From patchwork Fri Aug 31 14:37:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 964496 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=xs4all.nl Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42225d1vYgz9s3Z for ; Sat, 1 Sep 2018 00:37:56 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728594AbeHaSpf (ORCPT ); Fri, 31 Aug 2018 14:45:35 -0400 Received: from lb3-smtp-cloud8.xs4all.net ([194.109.24.29]:48633 "EHLO lb3-smtp-cloud8.xs4all.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728326AbeHaSpf (ORCPT ); Fri, 31 Aug 2018 14:45:35 -0400 Received: from marune.fritz.box ([80.101.105.217]) by smtp-cloud8.xs4all.net with ESMTPA id vkYSfoJHlaLLbvkYTf2rGF; Fri, 31 Aug 2018 16:37:45 +0200 From: Hans Verkuil To: linux-gpio@vger.kernel.org Cc: Linus Walleij , ilina@codeaurora.org, Marc Zyngier , Thomas Gleixner , Hans Verkuil Subject: [RFCv3 PATCH 1/4] gpiolib: add flag to indicate if the irq is disabled Date: Fri, 31 Aug 2018 16:37:41 +0200 Message-Id: <20180831143744.126063-2-hverkuil@xs4all.nl> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180831143744.126063-1-hverkuil@xs4all.nl> References: <20180831143744.126063-1-hverkuil@xs4all.nl> X-CMAE-Envelope: MS4wfLZM2z93Cms+7x+WCHN6qyw+juQAEipCF+n59aSVSeYwLeOqoKdXV+l3U3QhU8LcaNa8C2lnCSlq8uLRfU4Pf9R7aCNTC8oLoL9wt5S7GBNNU8c4rh/p UREPmVR22/K93fms1AjyWq3UubnVY8n7xdTVzUOx4MwMUgJHdvGJCdxxEIczIZb6/opqaTziDyr7fCFh3RVvV6YTy9OejHI+6xL4Jr/IJ3ytAnX22KMwvPrU CNBuf/6iXfn+WFtTc0vr7KB71qkOdFAC5FKAs+gCHISL4yoQlKmSN96U9IBdtsN0h4p6iY6j0lDvGPc1tKDRzfeC2XI+asWBVlrG8xX0lXZaaJngxXEeIYvB 3VSARrEC Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Hans Verkuil GPIO drivers call gpiochip_(un)lock_as_irq whenever they want to use a gpio as an interrupt. This is done when the irq is requested and it marks the gpio as in use by an interrupt. This is problematic for cases where a gpio pin is used as an interrupt pin, then, after the irq is disabled, is used as a regular gpio pin. Currently it is not possible to do this other than by first freeing the interrupt so gpiochip_unlock_as_irq is called, since an attempt to switch the gpio direction for output will fail since gpiolib believes that the gpio is in use for an interrupt and it does not know that it the irq is actually disabled. There are currently two drivers that would like to be able to do this: the tda998x_drv.c driver where a regular gpio pin needs to be temporarily reconfigured as an interrupt pin during CEC calibration, and the cec-gpio driver where you want to configure the gpio pin as an interrupt while waiting for traffic over the CEC bus, or as a regular pin when receiving or transmitting a CEC message. The solution is to add a new flag that is set when the irq is enabled, and have gpiod_direction_output check for that flag. We also add functions that drivers can call when they enable/disable the irq. Signed-off-by: Hans Verkuil --- drivers/gpio/gpiolib.c | 29 +++++++++++++++++++++++++++-- drivers/gpio/gpiolib.h | 1 + include/linux/gpio/driver.h | 2 ++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e8f8a1999393..8b6086fd4406 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2604,8 +2604,9 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) else value = !!value; - /* GPIOs used for IRQs shall not be set as output */ - if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) { + /* GPIOs used for enabled IRQs shall not be set as output */ + if (test_bit(FLAG_USED_AS_IRQ, &desc->flags) && + test_bit(FLAG_IRQ_IS_ENABLED, &desc->flags)) { gpiod_err(desc, "%s: tried to set a GPIO tied to an IRQ as output\n", __func__); @@ -3292,6 +3293,7 @@ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset) } set_bit(FLAG_USED_AS_IRQ, &desc->flags); + set_bit(FLAG_IRQ_IS_ENABLED, &desc->flags); /* * If the consumer has not set up a label (such as when the @@ -3322,6 +3324,7 @@ void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset) return; clear_bit(FLAG_USED_AS_IRQ, &desc->flags); + clear_bit(FLAG_IRQ_IS_ENABLED, &desc->flags); /* If we only had this marking, erase it */ if (desc->label && !strcmp(desc->label, "interrupt")) @@ -3329,6 +3332,28 @@ void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset) } EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq); +void gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset) +{ + struct gpio_desc *desc = gpiochip_get_desc(chip, offset); + + if (!IS_ERR(desc) && + !WARN_ON(!test_bit(FLAG_USED_AS_IRQ, &desc->flags))) + clear_bit(FLAG_IRQ_IS_ENABLED, &desc->flags); +} +EXPORT_SYMBOL_GPL(gpiochip_disable_irq); + +void gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset) +{ + struct gpio_desc *desc = gpiochip_get_desc(chip, offset); + + if (!IS_ERR(desc) && + !WARN_ON(!test_bit(FLAG_USED_AS_IRQ, &desc->flags))) { + WARN_ON(test_bit(FLAG_IS_OUT, &desc->flags)); + set_bit(FLAG_IRQ_IS_ENABLED, &desc->flags); + } +} +EXPORT_SYMBOL_GPL(gpiochip_enable_irq); + bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset) { if (offset >= chip->ngpio) diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index a7e49fef73d4..e9a86f4b00e3 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -214,6 +214,7 @@ struct gpio_desc { #define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */ #define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */ #define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */ +#define FLAG_IRQ_IS_ENABLED 10 /* GPIO is connected to an enabled IRQ */ #define FLAG_IS_HOGGED 11 /* GPIO is hogged */ #define FLAG_TRANSITORY 12 /* GPIO may lose value in sleep or reset */ diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 0ea328e71ec9..91108ac4fffd 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -395,6 +395,8 @@ extern struct gpio_chip *gpiochip_find(void *data, int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset); +void gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset); +void gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset); /* Line status inquiry for drivers */ bool gpiochip_line_is_open_drain(struct gpio_chip *chip, unsigned int offset); From patchwork Fri Aug 31 14:37:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 964497 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=xs4all.nl Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42225g5Lmrz9s47 for ; Sat, 1 Sep 2018 00:37:59 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728326AbeHaSpf (ORCPT ); Fri, 31 Aug 2018 14:45:35 -0400 Received: from lb1-smtp-cloud8.xs4all.net ([194.109.24.21]:50953 "EHLO lb1-smtp-cloud8.xs4all.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727563AbeHaSpf (ORCPT ); Fri, 31 Aug 2018 14:45:35 -0400 Received: from marune.fritz.box ([80.101.105.217]) by smtp-cloud8.xs4all.net with ESMTPA id vkYSfoJHlaLLbvkYTf2rGN; Fri, 31 Aug 2018 16:37:45 +0200 From: Hans Verkuil To: linux-gpio@vger.kernel.org Cc: Linus Walleij , ilina@codeaurora.org, Marc Zyngier , Thomas Gleixner , Hans Verkuil Subject: [RFCv3 PATCH 2/4] gpiolib: export gpiochip_irq_reqres/relres() Date: Fri, 31 Aug 2018 16:37:42 +0200 Message-Id: <20180831143744.126063-3-hverkuil@xs4all.nl> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180831143744.126063-1-hverkuil@xs4all.nl> References: <20180831143744.126063-1-hverkuil@xs4all.nl> X-CMAE-Envelope: MS4wfLZM2z93Cms+7x+WCHN6qyw+juQAEipCF+n59aSVSeYwLeOqoKdXV+l3U3QhU8LcaNa8C2lnCSlq8uLRfU4Pf9R7aCNTC8oLoL9wt5S7GBNNU8c4rh/p UREPmVR22/K93fms1AjyWq3UubnVY8n7xdTVzUOx4MwMUgJHdvGJCdxxEIczIZb6/opqaTziDyr7fCFh3RVvV6YTy9OejHI+6xL4Jr/IJ3ytAnX22KMwvPrU CNBuf/6iXfn+WFtTc0vr7KB71qkOdFAC5FKAs+gCHISL4yoQlKmSN96U9IBdtsN0h4p6iY6j0lDvGPc1tKDRzfeC2XI+asWBVlrG8xX0lXZaaJngxXEeIYvB 3VSARrEC Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Hans Verkuil GPIO drivers can hook these into the irq_request_resource and irq_release_resource callbacks of the irq_chip so they correctly 'get' the module and lock the gpio line for IRQ use. This will simplify driver code. Signed-off-by: Hans Verkuil --- drivers/gpio/gpiolib.c | 67 ++++++++++++++++++++++--------------- include/linux/gpio/driver.h | 2 ++ 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 8b6086fd4406..2ad58e63ce70 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -86,6 +86,8 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip); static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip); +static int gpiochip_irq_reqres(struct irq_data *d); +static void gpiochip_irq_relres(struct irq_data *d); static bool gpiolib_initialized; @@ -1804,33 +1806,6 @@ static const struct irq_domain_ops gpiochip_domain_ops = { .xlate = irq_domain_xlate_twocell, }; -static int gpiochip_irq_reqres(struct irq_data *d) -{ - struct gpio_chip *chip = irq_data_get_irq_chip_data(d); - int ret; - - if (!try_module_get(chip->gpiodev->owner)) - return -ENODEV; - - ret = gpiochip_lock_as_irq(chip, d->hwirq); - if (ret) { - chip_err(chip, - "unable to lock HW IRQ %lu for IRQ\n", - d->hwirq); - module_put(chip->gpiodev->owner); - return ret; - } - return 0; -} - -static void gpiochip_irq_relres(struct irq_data *d) -{ - struct gpio_chip *chip = irq_data_get_irq_chip_data(d); - - gpiochip_unlock_as_irq(chip, d->hwirq); - module_put(chip->gpiodev->owner); -} - static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) { if (!gpiochip_irqchip_irq_valid(chip, offset)) @@ -3363,6 +3338,44 @@ bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset) } EXPORT_SYMBOL_GPL(gpiochip_line_is_irq); +int gpiochip_reqres_irq(struct gpio_chip *chip, unsigned int offset) +{ + int ret; + + if (!try_module_get(chip->gpiodev->owner)) + return -ENODEV; + + ret = gpiochip_lock_as_irq(chip, offset); + if (ret) { + chip_err(chip, "unable to lock HW IRQ %u for IRQ\n", offset); + module_put(chip->gpiodev->owner); + return ret; + } + return 0; +} +EXPORT_SYMBOL_GPL(gpiochip_reqres_irq); + +void gpiochip_relres_irq(struct gpio_chip *chip, unsigned int offset) +{ + gpiochip_unlock_as_irq(chip, offset); + module_put(chip->gpiodev->owner); +} +EXPORT_SYMBOL_GPL(gpiochip_relres_irq); + +static int gpiochip_irq_reqres(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + + return gpiochip_reqres_irq(chip, d->hwirq); +} + +static void gpiochip_irq_relres(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + + gpiochip_relres_irq(chip, d->hwirq); +} + bool gpiochip_line_is_open_drain(struct gpio_chip *chip, unsigned int offset) { if (offset >= chip->ngpio) diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 91108ac4fffd..84449e95587a 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -397,6 +397,8 @@ void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset); void gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset); void gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset); +int gpiochip_reqres_irq(struct gpio_chip *chip, unsigned int offset); +void gpiochip_relres_irq(struct gpio_chip *chip, unsigned int offset); /* Line status inquiry for drivers */ bool gpiochip_line_is_open_drain(struct gpio_chip *chip, unsigned int offset); From patchwork Fri Aug 31 14:37:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 964498 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=xs4all.nl Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42225l1T3Xz9rvt for ; Sat, 1 Sep 2018 00:38:03 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727563AbeHaSpf (ORCPT ); Fri, 31 Aug 2018 14:45:35 -0400 Received: from lb3-smtp-cloud8.xs4all.net ([194.109.24.29]:57318 "EHLO lb3-smtp-cloud8.xs4all.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728627AbeHaSpf (ORCPT ); Fri, 31 Aug 2018 14:45:35 -0400 Received: from marune.fritz.box ([80.101.105.217]) by smtp-cloud8.xs4all.net with ESMTPA id vkYSfoJHlaLLbvkYTf2rGT; Fri, 31 Aug 2018 16:37:45 +0200 From: Hans Verkuil To: linux-gpio@vger.kernel.org Cc: Linus Walleij , ilina@codeaurora.org, Marc Zyngier , Thomas Gleixner , Hans Verkuil Subject: [RFCv3 PATCH 3/4] gpiolib: override irq_enable/disable Date: Fri, 31 Aug 2018 16:37:43 +0200 Message-Id: <20180831143744.126063-4-hverkuil@xs4all.nl> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180831143744.126063-1-hverkuil@xs4all.nl> References: <20180831143744.126063-1-hverkuil@xs4all.nl> X-CMAE-Envelope: MS4wfLZM2z93Cms+7x+WCHN6qyw+juQAEipCF+n59aSVSeYwLeOqoKdXV+l3U3QhU8LcaNa8C2lnCSlq8uLRfU4Pf9R7aCNTC8oLoL9wt5S7GBNNU8c4rh/p UREPmVR22/K93fms1AjyWq3UubnVY8n7xdTVzUOx4MwMUgJHdvGJCdxxEIczIZb6/opqaTziDyr7fCFh3RVvV6YTy9OejHI+6xL4Jr/IJ3ytAnX22KMwvPrU CNBuf/6iXfn+WFtTc0vr7KB71qkOdFAC5FKAs+gCHISL4yoQlKmSN96U9IBdtsN0h4p6iY6j0lDvGPc1tKDRzfeC2XI+asWBVlrG8xX0lXZaaJngxXEeIYvB 3VSARrEC Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Hans Verkuil When using the gpiolib irqchip helpers install irq_enable/disable hooks for the irqchip to ensure that gpiolib knows when the irq is enabled or disabled, allowing drivers to disable the irq and then use it as an output pin, and later switch the direction to input and re-enable the irq. Signed-off-by: Hans Verkuil --- drivers/gpio/gpiolib.c | 86 ++++++++++++++++++++++++++----------- include/linux/gpio/driver.h | 3 ++ 2 files changed, 65 insertions(+), 24 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2ad58e63ce70..49a32f45eac6 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -86,6 +86,8 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip); static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip); +static void gpiochip_irq_enable(struct irq_data *d); +static void gpiochip_irq_disable(struct irq_data *d); static int gpiochip_irq_reqres(struct irq_data *d); static void gpiochip_irq_relres(struct irq_data *d); @@ -1814,6 +1816,30 @@ static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) return irq_create_mapping(chip->irq.domain, offset); } +static void gpiochip_set_irq_hooks(struct gpio_chip *gpiochip) +{ + struct irq_chip *irqchip = gpiochip->irq.chip; + + if (WARN_ON(irqchip->irq_enable == gpiochip_irq_enable)) + return; + + /* + * It is possible for a driver to override this, but only if the + * alternative functions are both implemented. + */ + if (!irqchip->irq_request_resources && + !irqchip->irq_release_resources) { + irqchip->irq_request_resources = gpiochip_irq_reqres; + irqchip->irq_release_resources = gpiochip_irq_relres; + } + + gpiochip->irq.irq_enable = irqchip->irq_enable; + gpiochip->irq.irq_disable = irqchip->irq_disable; + + irqchip->irq_enable = gpiochip_irq_enable; + irqchip->irq_disable = gpiochip_irq_disable; +} + /** * gpiochip_add_irqchip() - adds an IRQ chip to a GPIO chip * @gpiochip: the GPIO chip to add the IRQ chip to @@ -1872,16 +1898,6 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, if (!gpiochip->irq.domain) return -EINVAL; - /* - * It is possible for a driver to override this, but only if the - * alternative functions are both implemented. - */ - if (!irqchip->irq_request_resources && - !irqchip->irq_release_resources) { - irqchip->irq_request_resources = gpiochip_irq_reqres; - irqchip->irq_release_resources = gpiochip_irq_relres; - } - if (gpiochip->irq.parent_handler) { void *data = gpiochip->irq.parent_handler_data ?: gpiochip; @@ -1897,6 +1913,8 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, } } + gpiochip_set_irq_hooks(gpiochip); + acpi_gpiochip_request_interrupts(gpiochip); return 0; @@ -1910,11 +1928,12 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, */ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) { + struct irq_chip *irqchip = gpiochip->irq.chip; unsigned int offset; acpi_gpiochip_free_interrupts(gpiochip); - if (gpiochip->irq.chip && gpiochip->irq.parent_handler) { + if (irqchip && gpiochip->irq.parent_handler) { struct gpio_irq_chip *irq = &gpiochip->irq; unsigned int i; @@ -1938,11 +1957,16 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) irq_domain_remove(gpiochip->irq.domain); } - if (gpiochip->irq.chip) { - gpiochip->irq.chip->irq_request_resources = NULL; - gpiochip->irq.chip->irq_release_resources = NULL; - gpiochip->irq.chip = NULL; + if (irqchip && + irqchip->irq_enable == gpiochip_irq_enable) { + irqchip->irq_request_resources = NULL; + irqchip->irq_release_resources = NULL; + irqchip->irq_enable = gpiochip->irq.irq_enable; + irqchip->irq_disable = gpiochip->irq.irq_disable; } + gpiochip->irq.irq_enable = NULL; + gpiochip->irq.irq_disable = NULL; + gpiochip->irq.chip = NULL; gpiochip_irqchip_free_valid_mask(gpiochip); } @@ -2031,15 +2055,7 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, return -EINVAL; } - /* - * It is possible for a driver to override this, but only if the - * alternative functions are both implemented. - */ - if (!irqchip->irq_request_resources && - !irqchip->irq_release_resources) { - irqchip->irq_request_resources = gpiochip_irq_reqres; - irqchip->irq_release_resources = gpiochip_irq_relres; - } + gpiochip_set_irq_hooks(gpiochip); acpi_gpiochip_request_interrupts(gpiochip); @@ -3329,6 +3345,28 @@ void gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset) } EXPORT_SYMBOL_GPL(gpiochip_enable_irq); +static void gpiochip_irq_enable(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + + gpiochip_enable_irq(chip, d->hwirq); + if (chip->irq.irq_enable) + chip->irq.irq_enable(d); + else + chip->irq.chip->irq_unmask(d); +} + +static void gpiochip_irq_disable(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + + if (chip->irq.irq_disable) + chip->irq.irq_disable(d); + else + chip->irq.chip->irq_mask(d); + gpiochip_disable_irq(chip, d->hwirq); +} + bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset) { if (offset >= chip->ngpio) diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 84449e95587a..46a896773448 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -138,6 +138,9 @@ struct gpio_irq_chip { * will allocate and map all IRQs during initialization. */ unsigned int first; + + void (*irq_enable)(struct irq_data *data); + void (*irq_disable)(struct irq_data *data); }; static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip) From patchwork Fri Aug 31 14:37:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 964493 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=xs4all.nl Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42225V4NtBz9rvt for ; Sat, 1 Sep 2018 00:37:50 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728647AbeHaSpe (ORCPT ); Fri, 31 Aug 2018 14:45:34 -0400 Received: from lb3-smtp-cloud8.xs4all.net ([194.109.24.29]:44870 "EHLO lb3-smtp-cloud8.xs4all.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728623AbeHaSpe (ORCPT ); Fri, 31 Aug 2018 14:45:34 -0400 Received: from marune.fritz.box ([80.101.105.217]) by smtp-cloud8.xs4all.net with ESMTPA id vkYSfoJHlaLLbvkYUf2rGa; Fri, 31 Aug 2018 16:37:46 +0200 From: Hans Verkuil To: linux-gpio@vger.kernel.org Cc: Linus Walleij , ilina@codeaurora.org, Marc Zyngier , Thomas Gleixner , Hans Verkuil Subject: [RFCv3 PATCH 4/4] gpio-bcm-kona: use new req/relres and dis/enable_irq funcs Date: Fri, 31 Aug 2018 16:37:44 +0200 Message-Id: <20180831143744.126063-5-hverkuil@xs4all.nl> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180831143744.126063-1-hverkuil@xs4all.nl> References: <20180831143744.126063-1-hverkuil@xs4all.nl> X-CMAE-Envelope: MS4wfPUZzgoaokfOvPU9tEiUIeJcncxPUZYNXbK4OxK47c3bSVewuCVUV2VPcebR6CiQcuYVTzUkey2NRT3Dxa95Y++nhHBE6bAui4UYXV+TO+FxUoipIq6D ecENO0dGhDx5BOJM174rcRe/WAe0amt1MzfCnlJoO0Ix0IzZ6mp+OOrXpGp4dGfWvOFSNxvXLcLK3CS+p41GFNi5AQsU7CwXl0vOEPvqeG8PQWVuKw7d/jZU kshTqAqleogXKYPkCriZRgv7rpsnkL9auNF/ta+68Pd5V8UMDewYQ+FMNAOjiXfiWNnfyXBS3hY7uzLCzUUVdWG23pDqwVK9HlyQ+DZtAmjIGxyWej7ZAzJU BBHfVnsm Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Hans Verkuil Since this driver does not use the gpiolib irqchip helpers it will have to allocate the irq resources and irq_en/disable itself. Use the new gpiochip_req/relres_irq helpers to request/release all the resources. Signed-off-by: Hans Verkuil --- drivers/gpio/gpio-bcm-kona.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index d0707fc23afd..c5536a509b59 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -373,6 +373,7 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d) val = readl(reg_base + GPIO_INT_MASK(bank_id)); val |= BIT(bit); writel(val, reg_base + GPIO_INT_MASK(bank_id)); + gpiochip_disable_irq(&kona_gpio->gpio_chip, gpio); raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } @@ -394,6 +395,7 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d) val = readl(reg_base + GPIO_INT_MSKCLR(bank_id)); val |= BIT(bit); writel(val, reg_base + GPIO_INT_MSKCLR(bank_id)); + gpiochip_enable_irq(&kona_gpio->gpio_chip, gpio); raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } @@ -485,23 +487,15 @@ static void bcm_kona_gpio_irq_handler(struct irq_desc *desc) static int bcm_kona_gpio_irq_reqres(struct irq_data *d) { struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d); - int ret; - ret = gpiochip_lock_as_irq(&kona_gpio->gpio_chip, d->hwirq); - if (ret) { - dev_err(kona_gpio->gpio_chip.parent, - "unable to lock HW IRQ %lu for IRQ\n", - d->hwirq); - return ret; - } - return 0; + return gpiochip_reqres_irq(&kona_gpio->gpio_chip, d->hwirq); } static void bcm_kona_gpio_irq_relres(struct irq_data *d) { struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d); - gpiochip_unlock_as_irq(&kona_gpio->gpio_chip, d->hwirq); + gpiochip_relres_irq(&kona_gpio->gpio_chip, d->hwirq); } static struct irq_chip bcm_gpio_irq_chip = {