Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/808978/?format=api
{ "id": 808978, "url": "http://patchwork.ozlabs.org/api/patches/808978/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/patch/20170901185736.28051-2-thierry.reding@gmail.com/", "project": { "id": 42, "url": "http://patchwork.ozlabs.org/api/projects/42/?format=api", "name": "Linux GPIO development", "link_name": "linux-gpio", "list_id": "linux-gpio.vger.kernel.org", "list_email": "linux-gpio@vger.kernel.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20170901185736.28051-2-thierry.reding@gmail.com>", "list_archive_url": null, "date": "2017-09-01T18:57:21", "name": "[01/16] gpio: Implement tighter IRQ chip integration", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "aaf5e06dac68184eeb1b13448c423ca2cd342351", "submitter": { "id": 26234, "url": "http://patchwork.ozlabs.org/api/people/26234/?format=api", "name": "Thierry Reding", "email": "thierry.reding@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-gpio/patch/20170901185736.28051-2-thierry.reding@gmail.com/mbox/", "series": [ { "id": 1098, "url": "http://patchwork.ozlabs.org/api/series/1098/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/list/?series=1098", "date": "2017-09-01T18:57:20", "name": "gpio: Tight IRQ chip integration and banked infrastructure", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/1098/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/808978/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/808978/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<linux-gpio-owner@vger.kernel.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": [ "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=linux-gpio-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"Yz7J19VJ\"; dkim-atps=neutral" ], "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xkTCS54m6z9sQl\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat, 2 Sep 2017 05:03:00 +1000 (AEST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1752673AbdIATB6 (ORCPT <rfc822;incoming@patchwork.ozlabs.org>);\n\tFri, 1 Sep 2017 15:01:58 -0400", "from mail-wr0-f193.google.com ([209.85.128.193]:37297 \"EHLO\n\tmail-wr0-f193.google.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1752131AbdIAS5l (ORCPT\n\t<rfc822; linux-gpio@vger.kernel.org>); Fri, 1 Sep 2017 14:57:41 -0400", "by mail-wr0-f193.google.com with SMTP id k9so478847wre.4;\n\tFri, 01 Sep 2017 11:57:40 -0700 (PDT)", "from localhost\n\t(p200300E41BD6D60076D02BFFFE273F51.dip0.t-ipconnect.de.\n\t[2003:e4:1bd6:d600:76d0:2bff:fe27:3f51])\n\tby smtp.gmail.com with ESMTPSA id\n\tp105sm907998wrc.64.2017.09.01.11.57.38\n\t(version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);\n\tFri, 01 Sep 2017 11:57:38 -0700 (PDT)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=gmail.com; s=20161025;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=Qn0BJh7I5Jze/UnGirJwTdrrxm7wrr/Bm28c51H/3TQ=;\n\tb=Yz7J19VJ9dko/ksG7AGDE8dQPVNNpTmf6zGeI4D2QxElvzgWnpknheyptRhLVZM1EJ\n\tL6dZywJMQmeQyncXPaKHAtyWNRDz/r/91UFIGO6VCJQBE47583MfijJsjPA4Czp+/DDU\n\t2WIQ2CviFITw7d8L9bYoampXebwn+BQBozjxuSyjCdwKVXJ72bSIwWwPgoSmCfBHmkCQ\n\tTXqxSbgnq7j2OV7QODjrw4kGLecTgmteWX+v8x38wXCsNgUsL3o3t7l2UP6rcnMr4H0H\n\tMHBBAkq03e0cib0XuC+ab2pYq3pP5vk3gZXzj9BvF1P5Y+E+cJJ7eHA1jhzNiSqcvULT\n\tl7Tg==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=Qn0BJh7I5Jze/UnGirJwTdrrxm7wrr/Bm28c51H/3TQ=;\n\tb=N7aczZcjOZtJdAL/boOitrtfZjGaRR+/7jC25uKBd2rbsMYUE32V/UNkNZTSeWzArx\n\tNtZ4MieCvcu5uqnB5wzxF7XwuDQRvjQCbU3pj6fSzoeaCO2AMVJFcGHGjTzKUqn/V05+\n\tXl1i/CX9MCuJCCtOXqPQADnGzLuhi5L+htMnMffdH6sg5Hkg7ehs+y4k4qXyh6tU4QTv\n\tEl/CTc5BC0dnCg7q33hFUI0gUmZu/hz1ZaEZ+0vo9N9i4EOOEhllryn3bVSUCakeUxE4\n\tHRkzvNwqCuHTz2RtXtfpx9FTrVRFoZsriLxVdEHJyk0dCA4Bvd1OMc6RVuu4W9Q2vDPg\n\tBirQ==", "X-Gm-Message-State": "AHPjjUjtJ8ajmA73g1znWVJgmigw7Y/MJKWHv6VIJ2w1veFdaMQYTrAW\n\tGLTIyXJrVlIizA==", "X-Google-Smtp-Source": "ADKCNb5A9kfOfzYTI+Hkw9YznpiKOnXmff6asoXMJc+VwYfnPf5k2xbvZnwCoC0nv4dk1cun4gIRkw==", "X-Received": "by 10.223.155.209 with SMTP id e17mr2068599wrc.298.1504292259953;\n\tFri, 01 Sep 2017 11:57:39 -0700 (PDT)", "From": "Thierry Reding <thierry.reding@gmail.com>", "To": "Linus Walleij <linus.walleij@linaro.org>", "Cc": "Jonathan Hunter <jonathanh@nvidia.com>, linux-gpio@vger.kernel.org,\n\tlinux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org", "Subject": "[PATCH 01/16] gpio: Implement tighter IRQ chip integration", "Date": "Fri, 1 Sep 2017 20:57:21 +0200", "Message-Id": "<20170901185736.28051-2-thierry.reding@gmail.com>", "X-Mailer": "git-send-email 2.13.3", "In-Reply-To": "<20170901185736.28051-1-thierry.reding@gmail.com>", "References": "<20170901185736.28051-1-thierry.reding@gmail.com>", "Sender": "linux-gpio-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<linux-gpio.vger.kernel.org>", "X-Mailing-List": "linux-gpio@vger.kernel.org" }, "content": "From: Thierry Reding <treding@nvidia.com>\n\nCurrently GPIO drivers are required to a GPIO chip and the corresponding\nIRQ chip separately, which can result in a lot of boilerplate. Introduce\na new struct gpio_irq_chip, embedded in a struct gpio_chip, that drivers\ncan fill in if they want the GPIO core to automatically register the IRQ\nchip associated with a GPIO chip.\n\nSigned-off-by: Thierry Reding <treding@nvidia.com>\n---\n drivers/gpio/gpiolib.c | 146 +++++++++++++++++++++++++++++++++++++++++++-\n include/linux/gpio/driver.h | 64 +++++++++++++++++++\n 2 files changed, 207 insertions(+), 3 deletions(-)", "diff": "diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c\nindex 18bba1748a35..abc0f72e9950 100644\n--- a/drivers/gpio/gpiolib.c\n+++ b/drivers/gpio/gpiolib.c\n@@ -72,6 +72,7 @@ static LIST_HEAD(gpio_lookup_list);\n LIST_HEAD(gpio_devices);\n \n static void gpiochip_free_hogs(struct gpio_chip *chip);\n+static int gpiochip_add_irqchip(struct gpio_chip *gpiochip);\n static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip);\n static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip);\n static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip);\n@@ -1271,6 +1272,10 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)\n \tif (status)\n \t\tgoto err_remove_from_list;\n \n+\tstatus = gpiochip_add_irqchip(chip);\n+\tif (status)\n+\t\tgoto err_remove_chip;\n+\n \tstatus = of_gpiochip_add(chip);\n \tif (status)\n \t\tgoto err_remove_chip;\n@@ -1637,8 +1642,8 @@ EXPORT_SYMBOL_GPL(gpiochip_set_nested_irqchip);\n * gpiochip by assigning the gpiochip as chip data, and using the irqchip\n * stored inside the gpiochip.\n */\n-static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,\n-\t\t\t irq_hw_number_t hwirq)\n+int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,\n+\t\t irq_hw_number_t hwirq)\n {\n \tstruct gpio_chip *chip = d->host_data;\n \n@@ -1666,8 +1671,9 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,\n \n \treturn 0;\n }\n+EXPORT_SYMBOL_GPL(gpiochip_irq_map);\n \n-static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)\n+void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)\n {\n \tstruct gpio_chip *chip = d->host_data;\n \n@@ -1676,6 +1682,7 @@ static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)\n \tirq_set_chip_and_handler(irq, NULL, NULL);\n \tirq_set_chip_data(irq, NULL);\n }\n+EXPORT_SYMBOL_GPL(gpiochip_irq_unmap);\n \n static const struct irq_domain_ops gpiochip_domain_ops = {\n \t.map\t= gpiochip_irq_map,\n@@ -1717,6 +1724,124 @@ static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)\n }\n \n /**\n+ * gpiochip_add_irqchip() - adds an IRQ chip to a GPIO chip\n+ * @gpiochip: the GPIO chip to add the IRQ chip to\n+ */\n+static int gpiochip_add_irqchip(struct gpio_chip *gpiochip)\n+{\n+\tstruct irq_chip *irqchip = gpiochip->irqchip;\n+\tconst struct irq_domain_ops *ops;\n+\tstruct device_node *np;\n+\tunsigned int type;\n+\tunsigned int i;\n+\n+\tif (!irqchip)\n+\t\treturn 0;\n+\n+\tif (gpiochip->irq.parent_handler && gpiochip->can_sleep) {\n+\t\tchip_err(gpiochip, \"you cannot have chained interrupts on a \"\n+\t\t\t \"chip that may sleep\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\ttype = gpiochip->irq_default_type;\n+\tnp = gpiochip->parent->of_node;\n+\n+#ifdef CONFIG_OF_GPIO\n+\t/*\n+\t * If the gpiochip has an assigned OF node this takes precedence\n+\t * FIXME: get rid of this and use gpiochip->parent->of_node\n+\t * everywhere\n+\t */\n+\tif (gpiochip->of_node)\n+\t\tnp = gpiochip->of_node;\n+#endif\n+\n+\t/*\n+\t * Specifying a default trigger is a terrible idea if DT or ACPI is\n+\t * used to configure the interrupts, as you may end up with\n+\t * conflicting triggers. Tell the user, and reset to NONE.\n+\t */\n+\tif (WARN(np && type != IRQ_TYPE_NONE,\n+\t\t \"%s: Ignoring %u default trigger\\n\", np->full_name, type))\n+\t\ttype = IRQ_TYPE_NONE;\n+\n+\tif (has_acpi_companion(gpiochip->parent) && type != IRQ_TYPE_NONE) {\n+\t\tacpi_handle_warn(ACPI_HANDLE(gpiochip->parent),\n+\t\t\t\t \"Ignoring %u default trigger\\n\", type);\n+\t\ttype = IRQ_TYPE_NONE;\n+\t}\n+\n+\tgpiochip->to_irq = gpiochip_to_irq;\n+\tgpiochip->irq_default_type = type;\n+\n+\tif (gpiochip->irq.domain_ops)\n+\t\tops = gpiochip->irq.domain_ops;\n+\telse\n+\t\tops = &gpiochip_domain_ops;\n+\n+\tgpiochip->irqdomain = irq_domain_add_simple(np, gpiochip->ngpio,\n+\t\t\t\t\t\t gpiochip->irq_base,\n+\t\t\t\t\t\t ops, gpiochip);\n+\tif (!gpiochip->irqdomain)\n+\t\treturn -EINVAL;\n+\n+\t/*\n+\t * It is possible for a driver to override this, but only if the\n+\t * alternative functions are both implemented.\n+\t */\n+\tif (!irqchip->irq_request_resources &&\n+\t !irqchip->irq_release_resources) {\n+\t\tirqchip->irq_request_resources = gpiochip_irq_reqres;\n+\t\tirqchip->irq_release_resources = gpiochip_irq_relres;\n+\t}\n+\n+\tif (gpiochip->irq.parent_handler) {\n+\t\tvoid *data = gpiochip->irq.parent_handler_data ?: gpiochip;\n+\n+\t\tfor (i = 0; i < gpiochip->irq.num_parents; i++) {\n+\t\t\t/*\n+\t\t\t * The parent IRQ chip is already using the chip_data\n+\t\t\t * for this IRQ chip, so our callbacks simply use the\n+\t\t\t * handler_data.\n+\t\t\t */\n+\t\t\tirq_set_chained_handler_and_data(gpiochip->irq.parents[i],\n+\t\t\t\t\t\t\t gpiochip->irq.parent_handler,\n+\t\t\t\t\t\t\t data);\n+\t\t}\n+\n+\t\tgpiochip->irq_nested = false;\n+\t} else {\n+\t\tgpiochip->irq_nested = true;\n+\t}\n+\n+\t/*\n+\t * Prepare the mapping since the IRQ chip shall be orthogonal to any\n+\t * GPIO chip calls.\n+\t */\n+\tfor (i = 0; i < gpiochip->ngpio; i++) {\n+\t\tunsigned int irq;\n+\n+\t\tif (!gpiochip_irqchip_irq_valid(gpiochip, i))\n+\t\t\tcontinue;\n+\n+\t\tirq = irq_create_mapping(gpiochip->irqdomain, i);\n+\t\tif (!irq) {\n+\t\t\tchip_err(gpiochip,\n+\t\t\t\t \"failed to create IRQ mapping for GPIO#%u\\n\",\n+\t\t\t\t i);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tirq_set_parent(irq, gpiochip->irq.map[i]);\n+\t}\n+\n+\tacpi_gpiochip_request_interrupts(gpiochip);\n+\n+\treturn 0;\n+}\n+\n+/**\n * gpiochip_irqchip_remove() - removes an irqchip added to a gpiochip\n * @gpiochip: the gpiochip to remove the irqchip from\n *\n@@ -1733,6 +1858,16 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)\n \t\tirq_set_handler_data(gpiochip->irq_chained_parent, NULL);\n \t}\n \n+\tif (gpiochip->irqchip) {\n+\t\tstruct gpio_irq_chip *irq = &gpiochip->irq;\n+\t\tunsigned int i;\n+\n+\t\tfor (i = 0; i < irq->num_parents; i++) {\n+\t\t\tirq_set_chained_handler(irq->parents[i], NULL);\n+\t\t\tirq_set_handler_data(irq->parents[i], NULL);\n+\t\t}\n+\t}\n+\n \t/* Remove all IRQ mappings and delete the domain */\n \tif (gpiochip->irqdomain) {\n \t\tfor (offset = 0; offset < gpiochip->ngpio; offset++) {\n@@ -1853,6 +1988,11 @@ EXPORT_SYMBOL_GPL(gpiochip_irqchip_add_key);\n \n #else /* CONFIG_GPIOLIB_IRQCHIP */\n \n+static inline int gpiochip_add_irqchip(struct gpio_chip *gpiochip)\n+{\n+\treturn 0;\n+}\n+\n static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}\n static inline int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip)\n {\ndiff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h\nindex c97f8325e8bf..6100b171817e 100644\n--- a/include/linux/gpio/driver.h\n+++ b/include/linux/gpio/driver.h\n@@ -19,6 +19,58 @@ struct module;\n \n #ifdef CONFIG_GPIOLIB\n \n+#ifdef CONFIG_GPIOLIB_IRQCHIP\n+/**\n+ * struct gpio_irq_chip - GPIO interrupt controller\n+ */\n+struct gpio_irq_chip {\n+\t/**\n+\t * @domain_ops:\n+\t *\n+\t * Table of interrupt domain operations for this IRQ chip.\n+\t */\n+\tconst struct irq_domain_ops *domain_ops;\n+\n+\t/**\n+\t * @parent_handler:\n+\t *\n+\t * The interrupt handler for the GPIO chip's parent interrupts, may be\n+\t * NULL if the parent interrupts are nested rather than cascaded.\n+\t */\n+\tirq_flow_handler_t parent_handler;\n+\n+\t/**\n+\t * @parent_handler_data:\n+\t *\n+\t * Data associated, and passed to, the handler for the parent\n+\t * interrupt.\n+\t */\n+\tvoid *parent_handler_data;\n+\n+\t/**\n+\t * @num_parents:\n+\t *\n+\t * The number of interrupt parents of a GPIO chip.\n+\t */\n+\tunsigned int num_parents;\n+\n+\t/**\n+\t * @parents:\n+\t *\n+\t * A list of interrupt parents of a GPIO chip. This is owned by the\n+\t * driver, so the core will only reference this list, not modify it.\n+\t */\n+\tunsigned int *parents;\n+\n+\t/**\n+\t * @map:\n+\t *\n+\t * A list of interrupt parents for each line of a GPIO chip.\n+\t */\n+\tunsigned int *map;\n+};\n+#endif\n+\n /**\n * struct gpio_chip - abstract a GPIO controller\n * @label: a functional name for the GPIO device, such as a part\n@@ -173,6 +225,14 @@ struct gpio_chip {\n \tbool\t\t\tirq_need_valid_mask;\n \tunsigned long\t\t*irq_valid_mask;\n \tstruct lock_class_key\t*lock_key;\n+\n+\t/**\n+\t * @irq:\n+\t *\n+\t * Integrates interrupt chip functionality with the GPIO chip. Can be\n+\t * used to handle IRQs for most practical cases.\n+\t */\n+\tstruct gpio_irq_chip irq;\n #endif\n \n #if defined(CONFIG_OF_GPIO)\n@@ -264,6 +324,10 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev,\n \n #ifdef CONFIG_GPIOLIB_IRQCHIP\n \n+int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,\n+\t\t irq_hw_number_t hwirq);\n+void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq);\n+\n void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,\n \t\tstruct irq_chip *irqchip,\n \t\tunsigned int parent_irq,\n", "prefixes": [ "01/16" ] }