get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/808957/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 808957,
    "url": "http://patchwork.ozlabs.org/api/patches/808957/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/patch/20170901185736.28051-12-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-12-thierry.reding@gmail.com>",
    "list_archive_url": null,
    "date": "2017-09-01T18:57:31",
    "name": "[11/16] gpio: Add Tegra186 support",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "e88c44ec5d6a15128274da11eae2d45ac728e0b9",
    "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-12-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/808957/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/808957/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=\"L8FhFdya\"; dkim-atps=neutral"
        ],
        "Received": [
            "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xkT7W636qz9sPt\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat,  2 Sep 2017 04:59:35 +1000 (AEST)",
            "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1752553AbdIAS6F (ORCPT <rfc822;incoming@patchwork.ozlabs.org>);\n\tFri, 1 Sep 2017 14:58:05 -0400",
            "from mail-wm0-f68.google.com ([74.125.82.68]:36004 \"EHLO\n\tmail-wm0-f68.google.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1752516AbdIAS6A (ORCPT\n\t<rfc822; linux-gpio@vger.kernel.org>); Fri, 1 Sep 2017 14:58:00 -0400",
            "by mail-wm0-f68.google.com with SMTP id p17so957740wmd.3;\n\tFri, 01 Sep 2017 11:57:59 -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\tb196sm718504wmd.29.2017.09.01.11.57.57\n\t(version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);\n\tFri, 01 Sep 2017 11:57:57 -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=N6CWoRL6vHcnr8x34qF160gQMJP546jyL3aQNGVCJ8E=;\n\tb=L8FhFdyal8gT/nNb3FBHV4pKI0cuwsM+huQ3EPNGr4vTlkiZSILtcXjf9qBUtdY+RD\n\t5gP0IY1oQF1OkN1Y/JQditDI+kWDmM48rnRgkLS8APPe1EGWQkvfxQ2+MbVYBt8LnbVR\n\t1fcpiSCqrUCCgETYpm5O4agxG4GWUVXg0cqq7qybo4AaMGzEI3Yi6ztLYVT3+rOyJ5PA\n\t9TVeCoGB31pJrazo+H1uVoH5YPbX/zyZWyeek0/7vFT7zIdFaqhsk049kfxG7wwthVjt\n\t2bFdMdFL7+c2aLwyf4fruJMy8VfSLc0T9ykJcTEV6EuAqSS4pJLJ1xQ7vIC4FyuTGzUT\n\tg4qg==",
        "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=N6CWoRL6vHcnr8x34qF160gQMJP546jyL3aQNGVCJ8E=;\n\tb=Ci9++yrO0YCj/fbaVQWCuTcKQC3bjxN7QixEC0NA8uqZxHzCF0D1LD7PNSGXeqrl8w\n\t1ySsK6rfTmBAMIRl7TtxLQbuevW86lo62hn/r02OFRV3siPbQFB/Y4GYZ0XV9w7gyEJz\n\txIq/Bd7uc7gdmDpearUvJECFYlRGxROLyuHDj5ai95wRwRovqKPNZcB9jFwRTm+6Jfsa\n\tuzlDBZP6/mvk7/KB/9nfsr7NjkaDvzP6soFahYY+WBRR6tTeOp05Dl/dcBDzkjj4/jhe\n\tIVNFCRPUV0zDvyg+6H3P5tmPj/aHgns78ERlGyapMXxazzjPkLtsM/3RYl8vw/u+0Ye0\n\tIs4Q==",
        "X-Gm-Message-State": "AHPjjUjM7le3QB3aG7BNkZ9AN+REZP4qdw2tP8mWBHSWmihF2p/sN8Kl\n\t8C9mq2J2KpbaWw==",
        "X-Google-Smtp-Source": "ADKCNb6kq/GPxjlOuYF2bV3jXBaEaPoA6yqUlcpxq+ZBipVFbPLDBtaS2yijcEmaiwYW5IeNbNqsdA==",
        "X-Received": "by 10.28.129.79 with SMTP id c76mr955558wmd.179.1504292278685;\n\tFri, 01 Sep 2017 11:57:58 -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 11/16] gpio: Add Tegra186 support",
        "Date": "Fri,  1 Sep 2017 20:57:31 +0200",
        "Message-Id": "<20170901185736.28051-12-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\nTegra186 has two GPIO controllers that are largely register compatible\nbetween one another but are completely different from the controller\nfound on earlier generations.\n\nSigned-off-by: Thierry Reding <treding@nvidia.com>\n---\nChanges in v4:\n- use platform_irq_count() instead of of_irq_count()\n\nChanges in v3:\n- make use of GPIOLIB_IRQCHIP for IRQ chip handling\n\nChanges in v2:\n- add pin names to allow easy lookup using the chardev interface\n- distinguish AON and main GPIO controllers by label\n- use gpiochip_get_data() instead of container_of()\n- use C99 initializers\n---\n drivers/gpio/Kconfig         |   9 +\n drivers/gpio/Makefile        |   1 +\n drivers/gpio/gpio-tegra186.c | 624 +++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 634 insertions(+)\n create mode 100644 drivers/gpio/gpio-tegra186.c",
    "diff": "diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig\nindex 3388d54ba114..f9e22c6fdd02 100644\n--- a/drivers/gpio/Kconfig\n+++ b/drivers/gpio/Kconfig\n@@ -442,6 +442,15 @@ config GPIO_TEGRA\n \thelp\n \t  Say yes here to support GPIO pins on NVIDIA Tegra SoCs.\n \n+config GPIO_TEGRA186\n+\ttristate \"NVIDIA Tegra186 GPIO support\"\n+\tdefault ARCH_TEGRA_186_SOC\n+\tdepends on ARCH_TEGRA_186_SOC || COMPILE_TEST\n+\tdepends on OF_GPIO\n+\tselect GPIOLIB_IRQCHIP\n+\thelp\n+\t  Say yes here to support GPIO pins on NVIDIA Tegra186 SoCs.\n+\n config GPIO_TS4800\n \ttristate \"TS-4800 DIO blocks and compatibles\"\n \tdepends on OF_GPIO\ndiff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile\nindex aeb70e9de6f2..4cb7c9b93215 100644\n--- a/drivers/gpio/Makefile\n+++ b/drivers/gpio/Makefile\n@@ -113,6 +113,7 @@ obj-$(CONFIG_GPIO_SYSCON)\t+= gpio-syscon.o\n obj-$(CONFIG_GPIO_TB10X)\t+= gpio-tb10x.o\n obj-$(CONFIG_GPIO_TC3589X)\t+= gpio-tc3589x.o\n obj-$(CONFIG_GPIO_TEGRA)\t+= gpio-tegra.o\n+obj-$(CONFIG_GPIO_TEGRA186)\t+= gpio-tegra186.o\n obj-$(CONFIG_GPIO_THUNDERX)\t+= gpio-thunderx.o\n obj-$(CONFIG_GPIO_TIMBERDALE)\t+= gpio-timberdale.o\n obj-$(CONFIG_GPIO_PALMAS)\t+= gpio-palmas.o\ndiff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c\nnew file mode 100644\nindex 000000000000..162dc6b41ae8\n--- /dev/null\n+++ b/drivers/gpio/gpio-tegra186.c\n@@ -0,0 +1,624 @@\n+/*\n+ * Copyright (c) 2016-2017 NVIDIA Corporation\n+ *\n+ * Author: Thierry Reding <treding@nvidia.com>\n+ *\n+ * This software is licensed under the terms of the GNU General Public\n+ * License version 2, as published by the Free Software Foundation, and\n+ * may be copied, distributed, and modified under those terms.\n+ */\n+\n+#include <linux/gpio/driver.h>\n+#include <linux/interrupt.h>\n+#include <linux/irq.h>\n+#include <linux/module.h>\n+#include <linux/of_device.h>\n+#include <linux/platform_device.h>\n+\n+#include <dt-bindings/gpio/tegra186-gpio.h>\n+\n+#define TEGRA186_GPIO_ENABLE_CONFIG 0x00\n+#define  TEGRA186_GPIO_ENABLE_CONFIG_ENABLE BIT(0)\n+#define  TEGRA186_GPIO_ENABLE_CONFIG_OUT BIT(1)\n+#define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_NONE (0x0 << 2)\n+#define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_LEVEL (0x1 << 2)\n+#define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE (0x2 << 2)\n+#define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_DOUBLE_EDGE (0x3 << 2)\n+#define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_MASK (0x3 << 2)\n+#define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL BIT(4)\n+#define  TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT BIT(6)\n+\n+#define TEGRA186_GPIO_DEBOUNCE_CONTROL 0x04\n+#define  TEGRA186_GPIO_DEBOUNCE_CONTROL_THRESHOLD(x) ((x) & 0xff)\n+\n+#define TEGRA186_GPIO_INPUT 0x08\n+#define  TEGRA186_GPIO_INPUT_HIGH BIT(0)\n+\n+#define TEGRA186_GPIO_OUTPUT_CONTROL 0x0c\n+#define  TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED BIT(0)\n+\n+#define TEGRA186_GPIO_OUTPUT_VALUE 0x10\n+#define  TEGRA186_GPIO_OUTPUT_VALUE_HIGH BIT(0)\n+\n+#define TEGRA186_GPIO_INTERRUPT_CLEAR 0x14\n+\n+#define TEGRA186_GPIO_INTERRUPT_STATUS(x) (0x100 + (x) * 4)\n+\n+struct tegra_gpio_port {\n+\tconst char *name;\n+\tunsigned int offset;\n+\tunsigned int pins;\n+\tunsigned int irq;\n+};\n+\n+struct tegra_gpio_soc {\n+\tconst struct tegra_gpio_port *ports;\n+\tunsigned int num_ports;\n+\tconst char *name;\n+};\n+\n+struct tegra_gpio {\n+\tstruct gpio_chip gpio;\n+\tstruct irq_chip intc;\n+\tunsigned int num_irq;\n+\tunsigned int *irq;\n+\n+\tconst struct tegra_gpio_soc *soc;\n+\n+\tvoid __iomem *base;\n+};\n+\n+static const struct tegra_gpio_port *\n+tegra186_gpio_get_port(struct tegra_gpio *gpio, unsigned int *pin)\n+{\n+\tunsigned int start = 0, i;\n+\n+\tfor (i = 0; i < gpio->soc->num_ports; i++) {\n+\t\tconst struct tegra_gpio_port *port = &gpio->soc->ports[i];\n+\n+\t\tif (*pin >= start && *pin < start + port->pins) {\n+\t\t\t*pin -= start;\n+\t\t\treturn port;\n+\t\t}\n+\n+\t\tstart += port->pins;\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+static void __iomem *tegra186_gpio_get_base(struct tegra_gpio *gpio,\n+\t\t\t\t\t    unsigned int pin)\n+{\n+\tconst struct tegra_gpio_port *port;\n+\n+\tport = tegra186_gpio_get_port(gpio, &pin);\n+\tif (!port)\n+\t\treturn NULL;\n+\n+\treturn gpio->base + port->offset + pin * 0x20;\n+}\n+\n+static int tegra186_gpio_get_direction(struct gpio_chip *chip,\n+\t\t\t\t       unsigned int offset)\n+{\n+\tstruct tegra_gpio *gpio = gpiochip_get_data(chip);\n+\tvoid __iomem *base;\n+\tu32 value;\n+\n+\tbase = tegra186_gpio_get_base(gpio, offset);\n+\tif (WARN_ON(base == NULL))\n+\t\treturn -ENODEV;\n+\n+\tvalue = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);\n+\tif (value & TEGRA186_GPIO_ENABLE_CONFIG_OUT)\n+\t\treturn 0;\n+\n+\treturn 1;\n+}\n+\n+static int tegra186_gpio_direction_input(struct gpio_chip *chip,\n+\t\t\t\t\t unsigned int offset)\n+{\n+\tstruct tegra_gpio *gpio = gpiochip_get_data(chip);\n+\tvoid __iomem *base;\n+\tu32 value;\n+\n+\tbase = tegra186_gpio_get_base(gpio, offset);\n+\tif (WARN_ON(base == NULL))\n+\t\treturn -ENODEV;\n+\n+\tvalue = readl(base + TEGRA186_GPIO_OUTPUT_CONTROL);\n+\tvalue |= TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED;\n+\twritel(value, base + TEGRA186_GPIO_OUTPUT_CONTROL);\n+\n+\tvalue = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);\n+\tvalue |= TEGRA186_GPIO_ENABLE_CONFIG_ENABLE;\n+\tvalue &= ~TEGRA186_GPIO_ENABLE_CONFIG_OUT;\n+\twritel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);\n+\n+\treturn 0;\n+}\n+\n+static int tegra186_gpio_direction_output(struct gpio_chip *chip,\n+\t\t\t\t\t  unsigned int offset, int level)\n+{\n+\tstruct tegra_gpio *gpio = gpiochip_get_data(chip);\n+\tvoid __iomem *base;\n+\tu32 value;\n+\n+\t/* configure output level first */\n+\tchip->set(chip, offset, level);\n+\n+\tbase = tegra186_gpio_get_base(gpio, offset);\n+\tif (WARN_ON(base == NULL))\n+\t\treturn -EINVAL;\n+\n+\t/* set the direction */\n+\tvalue = readl(base + TEGRA186_GPIO_OUTPUT_CONTROL);\n+\tvalue &= ~TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED;\n+\twritel(value, base + TEGRA186_GPIO_OUTPUT_CONTROL);\n+\n+\tvalue = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);\n+\tvalue |= TEGRA186_GPIO_ENABLE_CONFIG_ENABLE;\n+\tvalue |= TEGRA186_GPIO_ENABLE_CONFIG_OUT;\n+\twritel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);\n+\n+\treturn 0;\n+}\n+\n+static int tegra186_gpio_get(struct gpio_chip *chip, unsigned int offset)\n+{\n+\tstruct tegra_gpio *gpio = gpiochip_get_data(chip);\n+\tvoid __iomem *base;\n+\tu32 value;\n+\n+\tbase = tegra186_gpio_get_base(gpio, offset);\n+\tif (WARN_ON(base == NULL))\n+\t\treturn -ENODEV;\n+\n+\tvalue = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);\n+\tif (value & TEGRA186_GPIO_ENABLE_CONFIG_OUT)\n+\t\tvalue = readl(base + TEGRA186_GPIO_OUTPUT_VALUE);\n+\telse\n+\t\tvalue = readl(base + TEGRA186_GPIO_INPUT);\n+\n+\treturn value & BIT(0);\n+}\n+\n+static void tegra186_gpio_set(struct gpio_chip *chip, unsigned int offset,\n+\t\t\t      int level)\n+{\n+\tstruct tegra_gpio *gpio = gpiochip_get_data(chip);\n+\tvoid __iomem *base;\n+\tu32 value;\n+\n+\tbase = tegra186_gpio_get_base(gpio, offset);\n+\tif (WARN_ON(base == NULL))\n+\t\treturn;\n+\n+\tvalue = readl(base + TEGRA186_GPIO_OUTPUT_VALUE);\n+\tif (level == 0)\n+\t\tvalue &= ~TEGRA186_GPIO_OUTPUT_VALUE_HIGH;\n+\telse\n+\t\tvalue |= TEGRA186_GPIO_OUTPUT_VALUE_HIGH;\n+\n+\twritel(value, base + TEGRA186_GPIO_OUTPUT_VALUE);\n+}\n+\n+static int tegra186_gpio_of_xlate(struct gpio_chip *chip,\n+\t\t\t\t  const struct of_phandle_args *spec,\n+\t\t\t\t  u32 *flags)\n+{\n+\tstruct tegra_gpio *gpio = gpiochip_get_data(chip);\n+\tunsigned int port, pin, i, offset = 0;\n+\n+\tif (WARN_ON(chip->of_gpio_n_cells < 2))\n+\t\treturn -EINVAL;\n+\n+\tif (WARN_ON(spec->args_count < chip->of_gpio_n_cells))\n+\t\treturn -EINVAL;\n+\n+\tport = spec->args[0] / 8;\n+\tpin = spec->args[0] % 8;\n+\n+\tif (port >= gpio->soc->num_ports) {\n+\t\tdev_err(chip->parent, \"invalid port number: %u\\n\", port);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfor (i = 0; i < port; i++)\n+\t\toffset += gpio->soc->ports[i].pins;\n+\n+\tif (flags)\n+\t\t*flags = spec->args[1];\n+\n+\treturn offset + pin;\n+}\n+\n+static void tegra186_irq_ack(struct irq_data *data)\n+{\n+\tstruct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);\n+\tvoid __iomem *base;\n+\n+\tbase = tegra186_gpio_get_base(gpio, data->hwirq);\n+\tif (WARN_ON(base == NULL))\n+\t\treturn;\n+\n+\twritel(1, base + TEGRA186_GPIO_INTERRUPT_CLEAR);\n+}\n+\n+static void tegra186_irq_mask(struct irq_data *data)\n+{\n+\tstruct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);\n+\tvoid __iomem *base;\n+\tu32 value;\n+\n+\tbase = tegra186_gpio_get_base(gpio, data->hwirq);\n+\tif (WARN_ON(base == NULL))\n+\t\treturn;\n+\n+\tvalue = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);\n+\tvalue &= ~TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT;\n+\twritel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);\n+}\n+\n+static void tegra186_irq_unmask(struct irq_data *data)\n+{\n+\tstruct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);\n+\tvoid __iomem *base;\n+\tu32 value;\n+\n+\tbase = tegra186_gpio_get_base(gpio, data->hwirq);\n+\tif (WARN_ON(base == NULL))\n+\t\treturn;\n+\n+\tvalue = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);\n+\tvalue |= TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT;\n+\twritel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);\n+}\n+\n+static int tegra186_irq_set_type(struct irq_data *data, unsigned int flow)\n+{\n+\tstruct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);\n+\tvoid __iomem *base;\n+\tu32 value;\n+\n+\tbase = tegra186_gpio_get_base(gpio, data->hwirq);\n+\tif (WARN_ON(base == NULL))\n+\t\treturn -ENODEV;\n+\n+\tvalue = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);\n+\tvalue &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_MASK;\n+\tvalue &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL;\n+\n+\tswitch (flow & IRQ_TYPE_SENSE_MASK) {\n+\tcase IRQ_TYPE_NONE:\n+\t\tbreak;\n+\n+\tcase IRQ_TYPE_EDGE_RISING:\n+\t\tvalue |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE;\n+\t\tvalue |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL;\n+\t\tbreak;\n+\n+\tcase IRQ_TYPE_EDGE_FALLING:\n+\t\tvalue |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE;\n+\t\tbreak;\n+\n+\tcase IRQ_TYPE_EDGE_BOTH:\n+\t\tvalue |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_DOUBLE_EDGE;\n+\t\tbreak;\n+\n+\tcase IRQ_TYPE_LEVEL_HIGH:\n+\t\tvalue |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_LEVEL;\n+\t\tvalue |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL;\n+\t\tbreak;\n+\n+\tcase IRQ_TYPE_LEVEL_LOW:\n+\t\tvalue |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_LEVEL;\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\twritel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);\n+\n+\tif ((flow & IRQ_TYPE_EDGE_BOTH) == 0)\n+\t\tirq_set_handler_locked(data, handle_level_irq);\n+\telse\n+\t\tirq_set_handler_locked(data, handle_edge_irq);\n+\n+\treturn 0;\n+}\n+\n+static void tegra186_gpio_irq(struct irq_desc *desc)\n+{\n+\tstruct tegra_gpio *gpio = irq_desc_get_handler_data(desc);\n+\tstruct irq_domain *domain = gpio->gpio.irq.domain;\n+\tstruct irq_chip *chip = irq_desc_get_chip(desc);\n+\tunsigned int parent = irq_desc_get_irq(desc);\n+\tunsigned int i, offset = 0;\n+\n+\tchained_irq_enter(chip, desc);\n+\n+\tfor (i = 0; i < gpio->soc->num_ports; i++) {\n+\t\tconst struct tegra_gpio_port *port = &gpio->soc->ports[i];\n+\t\tvoid __iomem *base = gpio->base + port->offset;\n+\t\tunsigned int pin, irq;\n+\t\tunsigned long value;\n+\n+\t\t/* skip ports that are not associated with this controller */\n+\t\tif (parent != gpio->irq[port->irq])\n+\t\t\tgoto skip;\n+\n+\t\tvalue = readl(base + TEGRA186_GPIO_INTERRUPT_STATUS(1));\n+\n+\t\tfor_each_set_bit(pin, &value, port->pins) {\n+\t\t\tirq = irq_find_mapping(domain, offset + pin);\n+\t\t\tif (WARN_ON(irq == 0))\n+\t\t\t\tcontinue;\n+\n+\t\t\tgeneric_handle_irq(irq);\n+\t\t}\n+\n+skip:\n+\t\toffset += port->pins;\n+\t}\n+\n+\tchained_irq_exit(chip, desc);\n+}\n+\n+static int tegra186_gpio_irq_domain_xlate(struct irq_domain *domain,\n+\t\t\t\t\t  struct device_node *np,\n+\t\t\t\t\t  const u32 *spec, unsigned int size,\n+\t\t\t\t\t  unsigned long *hwirq,\n+\t\t\t\t\t  unsigned int *type)\n+{\n+\tstruct tegra_gpio *gpio = gpiochip_get_data(domain->host_data);\n+\tunsigned int port, pin, i, offset = 0;\n+\n+\tif (size < 2)\n+\t\treturn -EINVAL;\n+\n+\tport = spec[0] / 8;\n+\tpin = spec[0] % 8;\n+\n+\tif (port >= gpio->soc->num_ports) {\n+\t\tdev_err(gpio->gpio.parent, \"invalid port number: %u\\n\", port);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfor (i = 0; i < port; i++)\n+\t\toffset += gpio->soc->ports[i].pins;\n+\n+\t*type = spec[1] & IRQ_TYPE_SENSE_MASK;\n+\t*hwirq = offset + pin;\n+\n+\treturn 0;\n+}\n+\n+static const struct irq_domain_ops tegra186_gpio_irq_domain_ops = {\n+\t.map = gpiochip_irq_map,\n+\t.unmap = gpiochip_irq_unmap,\n+\t.xlate = tegra186_gpio_irq_domain_xlate,\n+};\n+\n+static struct lock_class_key tegra186_gpio_lock_class;\n+\n+static int tegra186_gpio_probe(struct platform_device *pdev)\n+{\n+\tunsigned int i, j, offset;\n+\tstruct gpio_irq_chip *irq;\n+\tstruct tegra_gpio *gpio;\n+\tstruct resource *res;\n+\tchar **names;\n+\tint err;\n+\n+\tgpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);\n+\tif (!gpio)\n+\t\treturn -ENOMEM;\n+\n+\tgpio->soc = of_device_get_match_data(&pdev->dev);\n+\n+\tres = platform_get_resource_byname(pdev, IORESOURCE_MEM, \"gpio\");\n+\tgpio->base = devm_ioremap_resource(&pdev->dev, res);\n+\tif (IS_ERR(gpio->base))\n+\t\treturn PTR_ERR(gpio->base);\n+\n+\terr = platform_irq_count(pdev);\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\tgpio->num_irq = err;\n+\n+\tgpio->irq = devm_kcalloc(&pdev->dev, gpio->num_irq, sizeof(*gpio->irq),\n+\t\t\t\t GFP_KERNEL);\n+\tif (!gpio->irq)\n+\t\treturn -ENOMEM;\n+\n+\tfor (i = 0; i < gpio->num_irq; i++) {\n+\t\terr = platform_get_irq(pdev, i);\n+\t\tif (err < 0)\n+\t\t\treturn err;\n+\n+\t\tgpio->irq[i] = err;\n+\t}\n+\n+\tgpio->gpio.label = gpio->soc->name;\n+\tgpio->gpio.parent = &pdev->dev;\n+\n+\tgpio->gpio.get_direction = tegra186_gpio_get_direction;\n+\tgpio->gpio.direction_input = tegra186_gpio_direction_input;\n+\tgpio->gpio.direction_output = tegra186_gpio_direction_output;\n+\tgpio->gpio.get = tegra186_gpio_get,\n+\tgpio->gpio.set = tegra186_gpio_set;\n+\n+\tgpio->gpio.base = -1;\n+\n+\tfor (i = 0; i < gpio->soc->num_ports; i++)\n+\t\tgpio->gpio.ngpio += gpio->soc->ports[i].pins;\n+\n+\tnames = devm_kcalloc(gpio->gpio.parent, gpio->gpio.ngpio,\n+\t\t\t     sizeof(*names), GFP_KERNEL);\n+\tif (!names)\n+\t\treturn -ENOMEM;\n+\n+\tfor (i = 0, offset = 0; i < gpio->soc->num_ports; i++) {\n+\t\tconst struct tegra_gpio_port *port = &gpio->soc->ports[i];\n+\t\tchar *name;\n+\n+\t\tfor (j = 0; j < port->pins; j++) {\n+\t\t\tname = devm_kasprintf(gpio->gpio.parent, GFP_KERNEL,\n+\t\t\t\t\t      \"P%s.%02x\", port->name, j);\n+\t\t\tif (!name)\n+\t\t\t\treturn -ENOMEM;\n+\n+\t\t\tnames[offset + j] = name;\n+\t\t}\n+\n+\t\toffset += port->pins;\n+\t}\n+\n+\tgpio->gpio.names = (const char * const *)names;\n+\n+\tgpio->gpio.of_node = pdev->dev.of_node;\n+\tgpio->gpio.of_gpio_n_cells = 2;\n+\tgpio->gpio.of_xlate = tegra186_gpio_of_xlate;\n+\n+\tgpio->intc.name = pdev->dev.of_node->name;\n+\tgpio->intc.irq_ack = tegra186_irq_ack;\n+\tgpio->intc.irq_mask = tegra186_irq_mask;\n+\tgpio->intc.irq_unmask = tegra186_irq_unmask;\n+\tgpio->intc.irq_set_type = tegra186_irq_set_type;\n+\n+\tirq = &gpio->gpio.irq;\n+\tirq->chip = &gpio->intc;\n+\tirq->first = 0;\n+\tirq->domain_ops = &tegra186_gpio_irq_domain_ops;\n+\tirq->handler = handle_simple_irq;\n+\tirq->lock_key = &tegra186_gpio_lock_class;\n+\tirq->default_type = IRQ_TYPE_NONE;\n+\tirq->parent_handler = tegra186_gpio_irq;\n+\tirq->parent_handler_data = gpio;\n+\tirq->num_parents = gpio->num_irq;\n+\tirq->parents = gpio->irq;\n+\n+\tirq->map = devm_kcalloc(&pdev->dev, gpio->gpio.ngpio,\n+\t\t\t\tsizeof(*irq->map), GFP_KERNEL);\n+\tif (!irq->map)\n+\t\treturn -ENOMEM;\n+\n+\tfor (i = 0, offset = 0; i < gpio->soc->num_ports; i++) {\n+\t\tconst struct tegra_gpio_port *port = &gpio->soc->ports[i];\n+\n+\t\tfor (j = 0; j < port->pins; j++)\n+\t\t\tirq->map[offset + j] = irq->parents[port->irq];\n+\n+\t\toffset += port->pins;\n+\t}\n+\n+\tplatform_set_drvdata(pdev, gpio);\n+\n+\terr = devm_gpiochip_add_data(&pdev->dev, &gpio->gpio, gpio);\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\treturn 0;\n+}\n+\n+static int tegra186_gpio_remove(struct platform_device *pdev)\n+{\n+\treturn 0;\n+}\n+\n+#define TEGRA_MAIN_GPIO_PORT(port, base, count, controller)\t\\\n+\t[TEGRA_MAIN_GPIO_PORT_##port] = {\t\t\t\\\n+\t\t.name = #port,\t\t\t\t\t\\\n+\t\t.offset = base,\t\t\t\t\t\\\n+\t\t.pins = count,\t\t\t\t\t\\\n+\t\t.irq = controller,\t\t\t\t\\\n+\t}\n+\n+static const struct tegra_gpio_port tegra186_main_ports[] = {\n+\tTEGRA_MAIN_GPIO_PORT( A, 0x2000, 7, 2),\n+\tTEGRA_MAIN_GPIO_PORT( B, 0x3000, 7, 3),\n+\tTEGRA_MAIN_GPIO_PORT( C, 0x3200, 7, 3),\n+\tTEGRA_MAIN_GPIO_PORT( D, 0x3400, 6, 3),\n+\tTEGRA_MAIN_GPIO_PORT( E, 0x2200, 8, 2),\n+\tTEGRA_MAIN_GPIO_PORT( F, 0x2400, 6, 2),\n+\tTEGRA_MAIN_GPIO_PORT( G, 0x4200, 6, 4),\n+\tTEGRA_MAIN_GPIO_PORT( H, 0x1000, 7, 1),\n+\tTEGRA_MAIN_GPIO_PORT( I, 0x0800, 8, 0),\n+\tTEGRA_MAIN_GPIO_PORT( J, 0x5000, 8, 5),\n+\tTEGRA_MAIN_GPIO_PORT( K, 0x5200, 1, 5),\n+\tTEGRA_MAIN_GPIO_PORT( L, 0x1200, 8, 1),\n+\tTEGRA_MAIN_GPIO_PORT( M, 0x5600, 6, 5),\n+\tTEGRA_MAIN_GPIO_PORT( N, 0x0000, 7, 0),\n+\tTEGRA_MAIN_GPIO_PORT( O, 0x0200, 4, 0),\n+\tTEGRA_MAIN_GPIO_PORT( P, 0x4000, 7, 4),\n+\tTEGRA_MAIN_GPIO_PORT( Q, 0x0400, 6, 0),\n+\tTEGRA_MAIN_GPIO_PORT( R, 0x0a00, 6, 0),\n+\tTEGRA_MAIN_GPIO_PORT( T, 0x0600, 4, 0),\n+\tTEGRA_MAIN_GPIO_PORT( X, 0x1400, 8, 1),\n+\tTEGRA_MAIN_GPIO_PORT( Y, 0x1600, 7, 1),\n+\tTEGRA_MAIN_GPIO_PORT(BB, 0x2600, 2, 2),\n+\tTEGRA_MAIN_GPIO_PORT(CC, 0x5400, 4, 5),\n+};\n+\n+static const struct tegra_gpio_soc tegra186_main_soc = {\n+\t.num_ports = ARRAY_SIZE(tegra186_main_ports),\n+\t.ports = tegra186_main_ports,\n+\t.name = \"tegra186-gpio\",\n+};\n+\n+#define TEGRA_AON_GPIO_PORT(port, base, count, controller)\t\\\n+\t[TEGRA_AON_GPIO_PORT_##port] = {\t\t\t\\\n+\t\t.name = #port,\t\t\t\t\t\\\n+\t\t.offset = base,\t\t\t\t\t\\\n+\t\t.pins = count,\t\t\t\t\t\\\n+\t\t.irq = controller,\t\t\t\t\\\n+\t}\n+\n+static const struct tegra_gpio_port tegra186_aon_ports[] = {\n+\tTEGRA_AON_GPIO_PORT( S, 0x0200, 5, 0),\n+\tTEGRA_AON_GPIO_PORT( U, 0x0400, 6, 0),\n+\tTEGRA_AON_GPIO_PORT( V, 0x0800, 8, 0),\n+\tTEGRA_AON_GPIO_PORT( W, 0x0a00, 8, 0),\n+\tTEGRA_AON_GPIO_PORT( Z, 0x0e00, 4, 0),\n+\tTEGRA_AON_GPIO_PORT(AA, 0x0c00, 8, 0),\n+\tTEGRA_AON_GPIO_PORT(EE, 0x0600, 3, 0),\n+\tTEGRA_AON_GPIO_PORT(FF, 0x0000, 5, 0),\n+};\n+\n+static const struct tegra_gpio_soc tegra186_aon_soc = {\n+\t.num_ports = ARRAY_SIZE(tegra186_aon_ports),\n+\t.ports = tegra186_aon_ports,\n+\t.name = \"tegra186-gpio-aon\",\n+};\n+\n+static const struct of_device_id tegra186_gpio_of_match[] = {\n+\t{\n+\t\t.compatible = \"nvidia,tegra186-gpio\",\n+\t\t.data = &tegra186_main_soc\n+\t}, {\n+\t\t.compatible = \"nvidia,tegra186-gpio-aon\",\n+\t\t.data = &tegra186_aon_soc\n+\t}, {\n+\t\t/* sentinel */\n+\t}\n+};\n+\n+static struct platform_driver tegra186_gpio_driver = {\n+\t.driver = {\n+\t\t.name = \"tegra186-gpio\",\n+\t\t.of_match_table = tegra186_gpio_of_match,\n+\t},\n+\t.probe = tegra186_gpio_probe,\n+\t.remove = tegra186_gpio_remove,\n+};\n+module_platform_driver(tegra186_gpio_driver);\n+\n+MODULE_DESCRIPTION(\"NVIDIA Tegra186 GPIO controller driver\");\n+MODULE_AUTHOR(\"Thierry Reding <treding@nvidia.com>\");\n+MODULE_LICENSE(\"GPL v2\");\n",
    "prefixes": [
        "11/16"
    ]
}