get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2218098,
    "url": "http://patchwork.ozlabs.org/api/patches/2218098/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/patch/20260331113835.3510341-4-eleanor.lin@realtek.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": "<20260331113835.3510341-4-eleanor.lin@realtek.com>",
    "list_archive_url": null,
    "date": "2026-03-31T11:38:35",
    "name": "[3/3] gpio: realtek: Add driver for Realtek DHC RTD1625 SoC",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "1d267b68ab02d3140f9490f64db076dc5eca6180",
    "submitter": {
        "id": 92797,
        "url": "http://patchwork.ozlabs.org/api/people/92797/?format=api",
        "name": "Yu-Chun Lin",
        "email": "eleanor.lin@realtek.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-gpio/patch/20260331113835.3510341-4-eleanor.lin@realtek.com/mbox/",
    "series": [
        {
            "id": 498182,
            "url": "http://patchwork.ozlabs.org/api/series/498182/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/list/?series=498182",
            "date": "2026-03-31T11:38:35",
            "name": "gpio: realtek: Add support for Realtek DHC RTD1625",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/498182/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2218098/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2218098/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linux-gpio+bounces-34474-incoming=patchwork.ozlabs.org@vger.kernel.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "linux-gpio@vger.kernel.org"
        ],
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=realtek.com header.i=@realtek.com header.a=rsa-sha256\n header.s=dkim header.b=hPuTmksP;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org;\n envelope-from=linux-gpio+bounces-34474-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com\n header.b=\"hPuTmksP\"",
            "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=211.75.126.72",
            "smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=realtek.com",
            "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=realtek.com"
        ],
        "Received": [
            "from tor.lore.kernel.org (tor.lore.kernel.org\n [IPv6:2600:3c04:e001:36c::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4flRFm6gkMz1xtJ\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 31 Mar 2026 22:48:12 +1100 (AEDT)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id 27151301D96C\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 31 Mar 2026 11:41:50 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id CD9C33E1205;\n\tTue, 31 Mar 2026 11:41:36 +0000 (UTC)",
            "from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 5562C3D9027;\n\tTue, 31 Mar 2026 11:41:34 +0000 (UTC)",
            "from mail.realtek.com (rtkexhmbs03.realtek.com.tw[10.21.1.53])\n\tby rtits2.realtek.com.tw (8.15.2/3.26/5.94) with ESMTPS id 62VBcZAM13149089\n\t(version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK);\n\tTue, 31 Mar 2026 19:38:35 +0800",
            "from RTKEXHMBS06.realtek.com.tw (10.21.1.56) by\n RTKEXHMBS03.realtek.com.tw (10.21.1.53) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.2.1748.10; Tue, 31 Mar 2026 19:38:36 +0800",
            "from RTKEXHMBS04.realtek.com.tw (10.21.1.54) by\n RTKEXHMBS06.realtek.com.tw (10.21.1.56) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.2.1748.10; Tue, 31 Mar 2026 19:38:35 +0800",
            "from cn1dhc-k02 (172.21.252.101) by RTKEXHMBS04.realtek.com.tw\n (10.21.1.54) with Microsoft SMTP Server id 15.2.1748.10 via Frontend\n Transport; Tue, 31 Mar 2026 19:38:35 +0800"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1774957296; cv=none;\n b=YInVCanjSDYX9T2N2wBJ45i7cUy/C46ijfugvHWB1y2pnhMBg/OqeUqkWfUh1eG7EOWJwZ6q6mxGRjfDEqfvYIGN8yoOEKc1xKAOe9R8ebSimF6P6zbmpIIYBgaKrgZ8YPuJ+B/aWOugKRXNQWWiXGLBtMw6NJhM1EuhrXDGtwM=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1774957296; c=relaxed/simple;\n\tbh=G33wzhqL7kCwwcVllXYG5XwQw6sdRf+w3WWWqvP/sLs=;\n\th=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version:Content-Type;\n b=i+wz051uhwuymP0RzXgFzrHQ9F78gSSC5+q8SJsh6A+aKeRUhUaZ3QEhhjbCIQfDF3+CkJAdRqE31UPoWqqz2wKk/63FjRZQeZeXe/fnGkoFL5fsOQRk18Lj3+W5V0qgnzPDb8OTIYVzSKd7ade/OCAYF6b7fr9aMP9ftrujHqM=",
        "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=realtek.com;\n spf=pass smtp.mailfrom=realtek.com;\n dkim=pass (2048-bit key) header.d=realtek.com header.i=@realtek.com\n header.b=hPuTmksP; arc=none smtp.client-ip=211.75.126.72",
        "X-SpamFilter-By": "ArmorX SpamTrap 5.80 with qID 62VBcZAM13149089,\n This message is accepted by code: ctloc85258",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=realtek.com; s=dkim;\n\tt=1774957115; bh=fp+gIfN0XfLllbGp+ZUFko52O+545pk/PSdxsFVOVHs=;\n\th=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version:Content-Transfer-Encoding:Content-Type;\n\tb=hPuTmksPEr0J53GZ5lyG3j4ln2xIbHJp2OqpmLrenSx4pEjD2WvrPqZzi/Tq5F0W/\n\t kP4wLgMTSCMpVYLvJAwJak8n40gztWgP4Rr2AMZDIVgKdTg6pGYHNzEjbe6PAcJVQE\n\t JRR49ljFxlB9quDuJSNefAJ9M6FeSoQouBRdxOs6xxUwqlK9f3W/bm1ooC+7GEBpo6\n\t RdMev5CdENEuB2KpiVF7X/IegAZpozvLz3UvZeE6BybsZurmoNc2eofSOYF7X0ch8o\n\t lD8NlOouSUg2wXmpo0baft8+o4lfhA+UejpomNoImTkDLGpTHqyDykYv2KLQ28h8+K\n\t OULstreHQE8/Q==",
        "From": "Yu-Chun Lin <eleanor.lin@realtek.com>",
        "To": "<linusw@kernel.org>, <brgl@kernel.org>, <robh@kernel.org>,\n        <krzk+dt@kernel.org>, <conor+dt@kernel.org>, <afaerber@suse.com>,\n        <tychang@realtek.com>",
        "CC": "<linux-gpio@vger.kernel.org>, <devicetree@vger.kernel.org>,\n        <linux-kernel@vger.kernel.org>,\n <linux-arm-kernel@lists.infradead.org>,\n        <linux-realtek-soc@lists.infradead.org>, <cy.huang@realtek.com>,\n        <stanley_chang@realtek.com>, <eleanor.lin@realtek.com>,\n        <james.tai@realtek.com>",
        "Subject": "[PATCH 3/3] gpio: realtek: Add driver for Realtek DHC RTD1625 SoC",
        "Date": "Tue, 31 Mar 2026 19:38:35 +0800",
        "Message-ID": "<20260331113835.3510341-4-eleanor.lin@realtek.com>",
        "X-Mailer": "git-send-email 2.50.1",
        "In-Reply-To": "<20260331113835.3510341-1-eleanor.lin@realtek.com>",
        "References": "<20260331113835.3510341-1-eleanor.lin@realtek.com>",
        "Precedence": "bulk",
        "X-Mailing-List": "linux-gpio@vger.kernel.org",
        "List-Id": "<linux-gpio.vger.kernel.org>",
        "List-Subscribe": "<mailto:linux-gpio+subscribe@vger.kernel.org>",
        "List-Unsubscribe": "<mailto:linux-gpio+unsubscribe@vger.kernel.org>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain"
    },
    "content": "From: Tzuyi Chang <tychang@realtek.com>\n\nAdd support for the GPIO controller found on Realtek DHC RTD1625 SoCs.\n\nUnlike the existing Realtek GPIO driver (drivers/gpio/gpio-rtd.c),\nwhich manages pins via shared bank registers, the RTD1625 introduces\na per-pin register architecture. Each GPIO line now has its own\ndedicated 32-bit control register to manage configuration independently,\nincluding direction, output value, input value, interrupt enable, and\ndebounce. Therefore, this distinct hardware design requires a separate\ndriver.\n\nSigned-off-by: Tzuyi Chang <tychang@realtek.com>\nSigned-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>\n---\n drivers/gpio/Kconfig        |  12 +\n drivers/gpio/Makefile       |   1 +\n drivers/gpio/gpio-rtd1625.c | 581 ++++++++++++++++++++++++++++++++++++\n 3 files changed, 594 insertions(+)\n create mode 100644 drivers/gpio/gpio-rtd1625.c",
    "diff": "diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig\nindex b45fb799e36c..6ffc95e02cb9 100644\n--- a/drivers/gpio/Kconfig\n+++ b/drivers/gpio/Kconfig\n@@ -639,6 +639,18 @@ config GPIO_RTD\n \t  Say yes here to support GPIO functionality and GPIO interrupt on\n \t  Realtek DHC SoCs.\n \n+config GPIO_RTD1625\n+\ttristate \"Realtek DHC RTD1625 GPIO support\"\n+\tdepends on ARCH_REALTEK || COMPILE_TEST\n+\tdefault y\n+\tselect GPIOLIB_IRQCHIP\n+\thelp\n+\t  This option enables support for the GPIO controller on Realtek\n+\t  DHC (Digital Home Center) RTD1625 SoC.\n+\n+\t  Say yes here to support both basic GPIO line functionality\n+\t  and GPIO interrupt handling capabilities for this platform.\n+\n config GPIO_SAMA5D2_PIOBU\n \ttristate \"SAMA5D2 PIOBU GPIO support\"\n \tdepends on MFD_SYSCON\ndiff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile\nindex c05f7d795c43..c95ba218d53a 100644\n--- a/drivers/gpio/Makefile\n+++ b/drivers/gpio/Makefile\n@@ -159,6 +159,7 @@ obj-$(CONFIG_GPIO_REALTEK_OTTO)\t\t+= gpio-realtek-otto.o\n obj-$(CONFIG_GPIO_REG)\t\t\t+= gpio-reg.o\n obj-$(CONFIG_GPIO_ROCKCHIP)\t+= gpio-rockchip.o\n obj-$(CONFIG_GPIO_RTD)\t\t\t+= gpio-rtd.o\n+obj-$(CONFIG_GPIO_RTD1625)\t\t+= gpio-rtd1625.o\n obj-$(CONFIG_ARCH_SA1100)\t\t+= gpio-sa1100.o\n obj-$(CONFIG_GPIO_SAMA5D2_PIOBU)\t+= gpio-sama5d2-piobu.o\n obj-$(CONFIG_GPIO_SCH311X)\t\t+= gpio-sch311x.o\ndiff --git a/drivers/gpio/gpio-rtd1625.c b/drivers/gpio/gpio-rtd1625.c\nnew file mode 100644\nindex 000000000000..10559a892c06\n--- /dev/null\n+++ b/drivers/gpio/gpio-rtd1625.c\n@@ -0,0 +1,581 @@\n+// SPDX-License-Identifier: GPL-2.0-or-later\n+/*\n+ * Realtek DHC RTD1625 gpio driver\n+ *\n+ * Copyright (c) 2023 Realtek Semiconductor Corp.\n+ */\n+\n+#include <linux/bitfield.h>\n+#include <linux/bitops.h>\n+#include <linux/gpio/driver.h>\n+#include <linux/interrupt.h>\n+#include <linux/irqchip.h>\n+#include <linux/irqchip/chained_irq.h>\n+#include <linux/irqdomain.h>\n+#include <linux/module.h>\n+#include <linux/platform_device.h>\n+#include <linux/property.h>\n+#include <linux/spinlock.h>\n+#include <linux/types.h>\n+\n+#define RTD1625_GPIO_DIR BIT(0)\n+#define RTD1625_GPIO_OUT BIT(2)\n+#define RTD1625_GPIO_IN BIT(4)\n+#define RTD1625_GPIO_EDGE_INT_DP BIT(6)\n+#define RTD1625_GPIO_EDGE_INT_EN BIT(8)\n+#define RTD1625_GPIO_LEVEL_INT_EN BIT(16)\n+#define RTD1625_GPIO_LEVEL_INT_DP BIT(18)\n+#define RTD1625_GPIO_DEBOUNCE GENMASK(30, 28)\n+#define RTD1625_GPIO_DEBOUNCE_WREN BIT(31)\n+\n+#define RTD1625_GPIO_WREN(x) ((x) << 1)\n+\n+/* Write-enable masks for all GPIO configs and reserved hardware bits */\n+#define RTD1625_ISO_GPIO_WREN_ALL 0x8000aa8a\n+#define RTD1625_ISOM_GPIO_WREN_ALL 0x800aaa8a\n+\n+#define RTD1625_GPIO_DEBOUNCE_1US 0\n+#define RTD1625_GPIO_DEBOUNCE_10US 1\n+#define RTD1625_GPIO_DEBOUNCE_100US 2\n+#define RTD1625_GPIO_DEBOUNCE_1MS 3\n+#define RTD1625_GPIO_DEBOUNCE_10MS 4\n+#define RTD1625_GPIO_DEBOUNCE_20MS 5\n+#define RTD1625_GPIO_DEBOUNCE_30MS 6\n+#define RTD1625_GPIO_DEBOUNCE_50MS 7\n+\n+#define GPIO_CONTROL(gpio) ((gpio) * 4)\n+\n+/**\n+ * struct rtd1625_gpio_info - Specific GPIO register information\n+ * @num_gpios: The number of GPIOs\n+ * @irq_type_support: Supported IRQ types\n+ * @gpa_offset: Offset for GPIO assert interrupt status registers\n+ * @gpda_offset: Offset for GPIO deassert interrupt status registers\n+ * @level_offset: Offset of level interrupt status register\n+ * @write_en_all: Write-enable mask for all configurable bits\n+ */\n+struct rtd1625_gpio_info {\n+\tunsigned int\tnum_gpios;\n+\tunsigned int\tirq_type_support;\n+\tunsigned int\tgpa_offset;\n+\tunsigned int\tgpda_offset;\n+\tunsigned int\tlevel_offset;\n+\tunsigned int\twrite_en_all;\n+};\n+\n+struct rtd1625_gpio {\n+\tstruct gpio_chip\t\tgpio_chip;\n+\tconst struct rtd1625_gpio_info\t*info;\n+\tvoid __iomem\t\t\t*base;\n+\tvoid __iomem\t\t\t*irq_base;\n+\tunsigned int\t\t\tirqs[3];\n+\traw_spinlock_t\t\t\tlock;\n+\tunsigned int\t\t\t*save_regs;\n+};\n+\n+static unsigned int rtd1625_gpio_gpa_offset(struct rtd1625_gpio *data, unsigned int offset)\n+{\n+\treturn data->info->gpa_offset + ((offset / 32) * 4);\n+}\n+\n+static unsigned int rtd1625_gpio_gpda_offset(struct rtd1625_gpio *data, unsigned int offset)\n+{\n+\treturn data->info->gpda_offset + ((offset / 32) * 4);\n+}\n+\n+static unsigned int rtd1625_gpio_level_offset(struct rtd1625_gpio *data, unsigned int offset)\n+{\n+\treturn data->info->level_offset + ((offset / 32) * 4);\n+}\n+\n+static unsigned int rtd1625_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,\n+\t\t\t\t\t      unsigned int debounce)\n+{\n+\tstruct rtd1625_gpio *data = gpiochip_get_data(chip);\n+\tu8 deb_val;\n+\tu32 val;\n+\n+\tswitch (debounce) {\n+\tcase 1:\n+\t\tdeb_val = RTD1625_GPIO_DEBOUNCE_1US;\n+\t\tbreak;\n+\tcase 10:\n+\t\tdeb_val = RTD1625_GPIO_DEBOUNCE_10US;\n+\t\tbreak;\n+\tcase 100:\n+\t\tdeb_val = RTD1625_GPIO_DEBOUNCE_100US;\n+\t\tbreak;\n+\tcase 1000:\n+\t\tdeb_val = RTD1625_GPIO_DEBOUNCE_1MS;\n+\t\tbreak;\n+\tcase 10000:\n+\t\tdeb_val = RTD1625_GPIO_DEBOUNCE_10MS;\n+\t\tbreak;\n+\tcase 20000:\n+\t\tdeb_val = RTD1625_GPIO_DEBOUNCE_20MS;\n+\t\tbreak;\n+\tcase 30000:\n+\t\tdeb_val = RTD1625_GPIO_DEBOUNCE_30MS;\n+\t\tbreak;\n+\tcase 50000:\n+\t\tdeb_val = RTD1625_GPIO_DEBOUNCE_50MS;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -ENOTSUPP;\n+\t}\n+\n+\tval = FIELD_PREP(RTD1625_GPIO_DEBOUNCE, deb_val) | RTD1625_GPIO_DEBOUNCE_WREN;\n+\n+\tguard(raw_spinlock_irqsave)(&data->lock);\n+\twritel_relaxed(val, data->base + GPIO_CONTROL(offset));\n+\n+\treturn 0;\n+}\n+\n+static int rtd1625_gpio_set_config(struct gpio_chip *chip, unsigned int offset,\n+\t\t\t\t   unsigned long config)\n+{\n+\tint debounce;\n+\n+\tif (pinconf_to_config_param(config) == PIN_CONFIG_INPUT_DEBOUNCE) {\n+\t\tdebounce = pinconf_to_config_argument(config);\n+\t\treturn rtd1625_gpio_set_debounce(chip, offset, debounce);\n+\t}\n+\n+\treturn gpiochip_generic_config(chip, offset, config);\n+}\n+\n+static int rtd1625_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)\n+{\n+\tstruct rtd1625_gpio *data = gpiochip_get_data(chip);\n+\tu32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_OUT);\n+\n+\tif (value)\n+\t\tval |= RTD1625_GPIO_OUT;\n+\n+\tguard(raw_spinlock_irqsave)(&data->lock);\n+\twritel_relaxed(val, data->base + GPIO_CONTROL(offset));\n+\n+\treturn 0;\n+}\n+\n+static int rtd1625_gpio_get(struct gpio_chip *chip, unsigned int offset)\n+{\n+\tstruct rtd1625_gpio *data = gpiochip_get_data(chip);\n+\tu32 val;\n+\n+\tguard(raw_spinlock_irqsave)(&data->lock);\n+\tval = readl_relaxed(data->base + GPIO_CONTROL(offset));\n+\n+\tif (val & RTD1625_GPIO_DIR)\n+\t\treturn !!(val & RTD1625_GPIO_OUT);\n+\telse\n+\t\treturn !!(val & RTD1625_GPIO_IN);\n+}\n+\n+static int rtd1625_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)\n+{\n+\tstruct rtd1625_gpio *data = gpiochip_get_data(chip);\n+\tu32 val;\n+\n+\tguard(raw_spinlock_irqsave)(&data->lock);\n+\tval = readl_relaxed(data->base + GPIO_CONTROL(offset));\n+\n+\tif (val & RTD1625_GPIO_DIR)\n+\t\treturn GPIO_LINE_DIRECTION_OUT;\n+\n+\treturn GPIO_LINE_DIRECTION_IN;\n+}\n+\n+static int rtd1625_gpio_set_direction(struct gpio_chip *chip, unsigned int offset, bool out)\n+{\n+\tstruct rtd1625_gpio *data = gpiochip_get_data(chip);\n+\tu32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_DIR);\n+\n+\tif (out)\n+\t\tval |= RTD1625_GPIO_DIR;\n+\n+\tguard(raw_spinlock_irqsave)(&data->lock);\n+\twritel_relaxed(val, data->base + GPIO_CONTROL(offset));\n+\n+\treturn 0;\n+}\n+\n+static int rtd1625_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)\n+{\n+\treturn rtd1625_gpio_set_direction(chip, offset, false);\n+}\n+\n+static int rtd1625_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value)\n+{\n+\trtd1625_gpio_set(chip, offset, value);\n+\n+\treturn rtd1625_gpio_set_direction(chip, offset, true);\n+}\n+\n+static void rtd1625_gpio_irq_handle(struct irq_desc *desc)\n+{\n+\tunsigned int (*get_reg_offset)(struct rtd1625_gpio *gpio, unsigned int offset);\n+\tstruct rtd1625_gpio *data = irq_desc_get_handler_data(desc);\n+\tstruct irq_domain *domain = data->gpio_chip.irq.domain;\n+\tstruct irq_chip *chip = irq_desc_get_chip(desc);\n+\tunsigned int irq = irq_desc_get_irq(desc);\n+\tunsigned long status;\n+\tunsigned int reg_offset, i, j;\n+\tunsigned int girq;\n+\tirq_hw_number_t hwirq;\n+\tu32 irq_type;\n+\n+\tif (irq == data->irqs[0])\n+\t\tget_reg_offset = &rtd1625_gpio_gpa_offset;\n+\telse if (irq == data->irqs[1])\n+\t\tget_reg_offset = &rtd1625_gpio_gpda_offset;\n+\telse if (irq == data->irqs[2])\n+\t\tget_reg_offset = &rtd1625_gpio_level_offset;\n+\telse\n+\t\treturn;\n+\n+\tchained_irq_enter(chip, desc);\n+\n+\tfor (i = 0; i < data->info->num_gpios; i += 32) {\n+\t\treg_offset = get_reg_offset(data, i);\n+\t\tstatus = readl_relaxed(data->irq_base + reg_offset);\n+\n+\t\t/* Clear edge interrupts; level interrupts are cleared in ->irq_ack() */\n+\t\tif (irq != data->irqs[2])\n+\t\t\twritel_relaxed(status, data->irq_base + reg_offset);\n+\n+\t\tfor_each_set_bit(j, &status, 32) {\n+\t\t\thwirq = i + j;\n+\t\t\tgirq = irq_find_mapping(domain, hwirq);\n+\t\t\tirq_type = irq_get_trigger_type(girq);\n+\n+\t\t\tif (irq == data->irqs[1] && irq_type != IRQ_TYPE_EDGE_BOTH)\n+\t\t\t\tcontinue;\n+\n+\t\t\tgeneric_handle_domain_irq(domain, hwirq);\n+\t\t}\n+\t}\n+\n+\tchained_irq_exit(chip, desc);\n+}\n+\n+static void rtd1625_gpio_ack_irq(struct irq_data *d)\n+{\n+\tstruct rtd1625_gpio *data = irq_data_get_irq_chip_data(d);\n+\tirq_hw_number_t hwirq = irqd_to_hwirq(d);\n+\tu32 irq_type = irqd_get_trigger_type(d);\n+\tu32 bit_mask = BIT(hwirq % 32);\n+\tint reg_offset;\n+\n+\tif (irq_type & IRQ_TYPE_LEVEL_MASK) {\n+\t\treg_offset = rtd1625_gpio_level_offset(data, hwirq);\n+\t\twritel_relaxed(bit_mask, data->irq_base + reg_offset);\n+\t}\n+}\n+\n+static void rtd1625_gpio_enable_edge_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)\n+{\n+\tint gpda_reg_offset = rtd1625_gpio_gpda_offset(data, hwirq);\n+\tint gpa_reg_offset = rtd1625_gpio_gpa_offset(data, hwirq);\n+\tu32 clr_mask = BIT(hwirq % 32);\n+\tu32 val;\n+\n+\tguard(raw_spinlock_irqsave)(&data->lock);\n+\twritel_relaxed(clr_mask, data->irq_base + gpa_reg_offset);\n+\twritel_relaxed(clr_mask, data->irq_base + gpda_reg_offset);\n+\tval = RTD1625_GPIO_EDGE_INT_EN | RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_EN);\n+\twritel_relaxed(val, data->base + GPIO_CONTROL(hwirq));\n+}\n+\n+static void rtd1625_gpio_disable_edge_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)\n+{\n+\tu32 val;\n+\n+\tguard(raw_spinlock_irqsave)(&data->lock);\n+\tval = RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_EN);\n+\twritel_relaxed(val, data->base + GPIO_CONTROL(hwirq));\n+}\n+\n+static void rtd1625_gpio_enable_level_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)\n+{\n+\tint level_reg_offset = rtd1625_gpio_level_offset(data, hwirq);\n+\tu32 clr_mask = BIT(hwirq % 32);\n+\tu32 val;\n+\n+\tguard(raw_spinlock_irqsave)(&data->lock);\n+\twritel_relaxed(clr_mask, data->irq_base + level_reg_offset);\n+\tval = RTD1625_GPIO_LEVEL_INT_EN | RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_EN);\n+\twritel_relaxed(val, data->base + GPIO_CONTROL(hwirq));\n+}\n+\n+static void rtd1625_gpio_disable_level_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)\n+{\n+\tu32 val;\n+\n+\tguard(raw_spinlock_irqsave)(&data->lock);\n+\tval = RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_EN);\n+\twritel_relaxed(val, data->base + GPIO_CONTROL(hwirq));\n+}\n+\n+static void rtd1625_gpio_enable_irq(struct irq_data *d)\n+{\n+\tstruct gpio_chip *gc = irq_data_get_irq_chip_data(d);\n+\tstruct rtd1625_gpio *data = gpiochip_get_data(gc);\n+\tirq_hw_number_t hwirq = irqd_to_hwirq(d);\n+\tu32 irq_type = irqd_get_trigger_type(d);\n+\n+\tgpiochip_enable_irq(gc, hwirq);\n+\n+\tif (irq_type & IRQ_TYPE_EDGE_BOTH)\n+\t\trtd1625_gpio_enable_edge_irq(data, hwirq);\n+\telse if (irq_type & IRQ_TYPE_LEVEL_MASK)\n+\t\trtd1625_gpio_enable_level_irq(data, hwirq);\n+}\n+\n+static void rtd1625_gpio_disable_irq(struct irq_data *d)\n+{\n+\tstruct gpio_chip *gc = irq_data_get_irq_chip_data(d);\n+\tstruct rtd1625_gpio *data = gpiochip_get_data(gc);\n+\tirq_hw_number_t hwirq = irqd_to_hwirq(d);\n+\tu32 irq_type = irqd_get_trigger_type(d);\n+\n+\tif (irq_type & IRQ_TYPE_EDGE_BOTH)\n+\t\trtd1625_gpio_disable_edge_irq(data, hwirq);\n+\telse if (irq_type & IRQ_TYPE_LEVEL_MASK)\n+\t\trtd1625_gpio_disable_level_irq(data, hwirq);\n+\n+\tgpiochip_disable_irq(gc, hwirq);\n+}\n+\n+static int rtd1625_gpio_irq_set_level_type(struct irq_data *d, bool level)\n+{\n+\tstruct gpio_chip *gc = irq_data_get_irq_chip_data(d);\n+\tstruct rtd1625_gpio *data = gpiochip_get_data(gc);\n+\tirq_hw_number_t hwirq = irqd_to_hwirq(d);\n+\tu32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_DP);\n+\n+\tif (!(data->info->irq_type_support & IRQ_TYPE_LEVEL_MASK))\n+\t\treturn -EINVAL;\n+\n+\tscoped_guard(raw_spinlock_irqsave, &data->lock) {\n+\t\tif (level)\n+\t\t\tval |= RTD1625_GPIO_LEVEL_INT_DP;\n+\t\twritel_relaxed(val, data->base + GPIO_CONTROL(hwirq));\n+\t}\n+\n+\tirq_set_handler_locked(d, handle_level_irq);\n+\n+\treturn 0;\n+}\n+\n+static int rtd1625_gpio_irq_set_edge_type(struct irq_data *d, bool polarity)\n+{\n+\tstruct gpio_chip *gc = irq_data_get_irq_chip_data(d);\n+\tstruct rtd1625_gpio *data = gpiochip_get_data(gc);\n+\tirq_hw_number_t hwirq = irqd_to_hwirq(d);\n+\tu32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_DP);\n+\n+\tif (!(data->info->irq_type_support & IRQ_TYPE_EDGE_BOTH))\n+\t\treturn -EINVAL;\n+\n+\tscoped_guard(raw_spinlock_irqsave, &data->lock) {\n+\t\tif (polarity)\n+\t\t\tval |= RTD1625_GPIO_EDGE_INT_DP;\n+\t\twritel_relaxed(val, data->base + GPIO_CONTROL(hwirq));\n+\t}\n+\n+\tirq_set_handler_locked(d, handle_edge_irq);\n+\n+\treturn 0;\n+}\n+\n+static int rtd1625_gpio_irq_set_type(struct irq_data *d, unsigned int type)\n+{\n+\tint ret;\n+\n+\tswitch (type & IRQ_TYPE_SENSE_MASK) {\n+\tcase IRQ_TYPE_EDGE_RISING:\n+\t\tret = rtd1625_gpio_irq_set_edge_type(d, 1);\n+\t\tbreak;\n+\tcase IRQ_TYPE_EDGE_FALLING:\n+\t\tret = rtd1625_gpio_irq_set_edge_type(d, 0);\n+\t\tbreak;\n+\tcase IRQ_TYPE_EDGE_BOTH:\n+\t\tret = rtd1625_gpio_irq_set_edge_type(d, 1);\n+\t\tbreak;\n+\tcase IRQ_TYPE_LEVEL_HIGH:\n+\t\tret = rtd1625_gpio_irq_set_level_type(d, 0);\n+\t\tbreak;\n+\tcase IRQ_TYPE_LEVEL_LOW:\n+\t\tret = rtd1625_gpio_irq_set_level_type(d, 1);\n+\t\tbreak;\n+\tdefault:\n+\t\tret = -EINVAL;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static struct irq_chip rtd1625_iso_gpio_irq_chip = {\n+\t.name = \"rtd1625-gpio\",\n+\t.irq_ack = rtd1625_gpio_ack_irq,\n+\t.irq_mask = rtd1625_gpio_disable_irq,\n+\t.irq_unmask = rtd1625_gpio_enable_irq,\n+\t.irq_set_type = rtd1625_gpio_irq_set_type,\n+\t.flags = IRQCHIP_IMMUTABLE | IRQCHIP_SKIP_SET_WAKE,\n+\tGPIOCHIP_IRQ_RESOURCE_HELPERS,\n+};\n+\n+static int rtd1625_gpio_setup_irq(struct platform_device *pdev, struct rtd1625_gpio *data)\n+{\n+\tstruct gpio_irq_chip *irq_chip;\n+\tint num_irqs;\n+\tint irq;\n+\tint i;\n+\n+\tirq = platform_get_irq_optional(pdev, 0);\n+\tif (irq == -ENXIO)\n+\t\treturn 0;\n+\tif (irq < 0)\n+\t\treturn irq;\n+\n+\tnum_irqs = (data->info->irq_type_support & IRQ_TYPE_LEVEL_MASK) ? 3 : 2;\n+\tdata->irqs[0] = irq;\n+\n+\tfor (i = 1; i < num_irqs; i++) {\n+\t\tirq = platform_get_irq(pdev, i);\n+\t\tif (irq < 0)\n+\t\t\treturn irq;\n+\t\tdata->irqs[i] = irq;\n+\t}\n+\n+\tirq_chip = &data->gpio_chip.irq;\n+\tirq_chip->handler = handle_bad_irq;\n+\tirq_chip->default_type = IRQ_TYPE_NONE;\n+\tirq_chip->parent_handler = rtd1625_gpio_irq_handle;\n+\tirq_chip->parent_handler_data = data;\n+\tirq_chip->num_parents = num_irqs;\n+\tirq_chip->parents = data->irqs;\n+\n+\tgpio_irq_chip_set_chip(irq_chip, &rtd1625_iso_gpio_irq_chip);\n+\n+\treturn 0;\n+}\n+\n+static int rtd1625_gpio_probe(struct platform_device *pdev)\n+{\n+\tstruct device *dev = &pdev->dev;\n+\tstruct rtd1625_gpio *data;\n+\tint ret;\n+\n+\tdata = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);\n+\tif (!data)\n+\t\treturn -ENOMEM;\n+\n+\tdata->info = device_get_match_data(dev);\n+\tif (!data->info)\n+\t\treturn -EINVAL;\n+\n+\traw_spin_lock_init(&data->lock);\n+\n+\tdata->base = devm_platform_ioremap_resource(pdev, 0);\n+\tif (IS_ERR(data->base))\n+\t\treturn PTR_ERR(data->base);\n+\n+\tdata->irq_base = devm_platform_ioremap_resource(pdev, 1);\n+\tif (IS_ERR(data->irq_base))\n+\t\treturn PTR_ERR(data->irq_base);\n+\n+\tdata->save_regs = devm_kzalloc(dev, data->info->num_gpios *\n+\t\t\t\t       sizeof(*data->save_regs), GFP_KERNEL);\n+\tif (!data->save_regs)\n+\t\treturn -ENOMEM;\n+\n+\tdata->gpio_chip.label = dev_name(dev);\n+\tdata->gpio_chip.base = -1;\n+\tdata->gpio_chip.ngpio = data->info->num_gpios;\n+\tdata->gpio_chip.request = gpiochip_generic_request;\n+\tdata->gpio_chip.free = gpiochip_generic_free;\n+\tdata->gpio_chip.get_direction = rtd1625_gpio_get_direction;\n+\tdata->gpio_chip.direction_input = rtd1625_gpio_direction_input;\n+\tdata->gpio_chip.direction_output = rtd1625_gpio_direction_output;\n+\tdata->gpio_chip.set = rtd1625_gpio_set;\n+\tdata->gpio_chip.get = rtd1625_gpio_get;\n+\tdata->gpio_chip.set_config = rtd1625_gpio_set_config;\n+\tdata->gpio_chip.parent = dev;\n+\n+\tret = rtd1625_gpio_setup_irq(pdev, data);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tplatform_set_drvdata(pdev, data);\n+\n+\treturn devm_gpiochip_add_data(dev, &data->gpio_chip, data);\n+}\n+\n+static const struct rtd1625_gpio_info rtd1625_iso_gpio_info = {\n+\t.num_gpios\t\t= 166,\n+\t.irq_type_support\t= IRQ_TYPE_EDGE_BOTH,\n+\t.gpa_offset\t\t= 0x0,\n+\t.gpda_offset\t\t= 0x20,\n+\t.write_en_all\t\t= RTD1625_ISO_GPIO_WREN_ALL,\n+};\n+\n+static const struct rtd1625_gpio_info rtd1625_isom_gpio_info = {\n+\t.num_gpios\t\t= 4,\n+\t.irq_type_support\t= IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_LOW |\n+\t\t\t\t  IRQ_TYPE_LEVEL_HIGH,\n+\t.gpa_offset\t\t= 0x0,\n+\t.gpda_offset\t\t= 0x4,\n+\t.level_offset\t\t= 0x18,\n+\t.write_en_all\t\t= RTD1625_ISOM_GPIO_WREN_ALL,\n+};\n+\n+static const struct of_device_id rtd1625_gpio_of_matches[] = {\n+\t{ .compatible = \"realtek,rtd1625-iso-gpio\", .data = &rtd1625_iso_gpio_info },\n+\t{ .compatible = \"realtek,rtd1625-isom-gpio\", .data = &rtd1625_isom_gpio_info },\n+\t{ }\n+};\n+MODULE_DEVICE_TABLE(of, rtd1625_gpio_of_matches);\n+\n+static int rtd1625_gpio_suspend(struct device *dev)\n+{\n+\tstruct rtd1625_gpio *data = dev_get_drvdata(dev);\n+\tconst struct rtd1625_gpio_info *info = data->info;\n+\tint i;\n+\n+\tfor (i = 0; i < info->num_gpios; i++)\n+\t\tdata->save_regs[i] = readl_relaxed(data->base + GPIO_CONTROL(i));\n+\n+\treturn 0;\n+}\n+\n+static int rtd1625_gpio_resume(struct device *dev)\n+{\n+\tstruct rtd1625_gpio *data = dev_get_drvdata(dev);\n+\tconst struct rtd1625_gpio_info *info = data->info;\n+\tint i;\n+\n+\tfor (i = 0; i < info->num_gpios; i++)\n+\t\twritel_relaxed(data->save_regs[i] | info->write_en_all,\n+\t\t\t       data->base + GPIO_CONTROL(i));\n+\n+\treturn 0;\n+}\n+\n+DEFINE_NOIRQ_DEV_PM_OPS(rtd1625_gpio_pm_ops, rtd1625_gpio_suspend, rtd1625_gpio_resume);\n+\n+static struct platform_driver rtd1625_gpio_platform_driver = {\n+\t.driver = {\n+\t\t.name = \"gpio-rtd1625\",\n+\t\t.of_match_table = rtd1625_gpio_of_matches,\n+\t\t.pm = pm_sleep_ptr(&rtd1625_gpio_pm_ops),\n+\t},\n+\t.probe = rtd1625_gpio_probe,\n+};\n+module_platform_driver(rtd1625_gpio_platform_driver);\n+\n+MODULE_LICENSE(\"GPL\");\n+MODULE_AUTHOR(\"Realtek Semiconductor Corporation\");\n+MODULE_DESCRIPTION(\"Realtek DHC SoC RTD1625 gpio driver\");\n",
    "prefixes": [
        "3/3"
    ]
}