get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2223123,
    "url": "http://patchwork.ozlabs.org/api/patches/2223123/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/patch/20260414-axiado-ax3000-sgpio-controller-v1-2-b5c7e4c2e69b@axiado.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": "<20260414-axiado-ax3000-sgpio-controller-v1-2-b5c7e4c2e69b@axiado.com>",
    "list_archive_url": null,
    "date": "2026-04-14T13:48:33",
    "name": "[2/3] gpio: axiado: add SGPIO controller support",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "a113d65f505d81121f87cfa76f280fe68ecbc30f",
    "submitter": {
        "id": 93145,
        "url": "http://patchwork.ozlabs.org/api/people/93145/?format=api",
        "name": "Petar Stepanovic",
        "email": "pstepanovic@axiado.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-gpio/patch/20260414-axiado-ax3000-sgpio-controller-v1-2-b5c7e4c2e69b@axiado.com/mbox/",
    "series": [
        {
            "id": 499848,
            "url": "http://patchwork.ozlabs.org/api/series/499848/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/list/?series=499848",
            "date": "2026-04-14T13:48:34",
            "name": "Subject: [PATCH 0/3] gpio: add support for Axiado SGPIO controller",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/499848/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2223123/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2223123/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linux-gpio+bounces-35150-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=axiado.com header.i=@axiado.com header.a=rsa-sha256\n header.s=selector1 header.b=QuiPLdj2;\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-35150-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=axiado.com header.i=@axiado.com\n header.b=\"QuiPLdj2\"",
            "smtp.subspace.kernel.org;\n arc=fail smtp.client-ip=40.107.201.112",
            "smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=axiado.com",
            "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=axiado.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 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fw5HD3MPNz1yDF\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 14 Apr 2026 23:49:28 +1000 (AEST)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id F02F53039C76\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 14 Apr 2026 13:49:00 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 317493E63BF;\n\tTue, 14 Apr 2026 13:48:59 +0000 (UTC)",
            "from CH4PR04CU002.outbound.protection.outlook.com\n (mail-northcentralusazon11023112.outbound.protection.outlook.com\n [40.107.201.112])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id C813B22D4E9;\n\tTue, 14 Apr 2026 13:48:56 +0000 (UTC)",
            "from SJ0PR13CA0136.namprd13.prod.outlook.com (2603:10b6:a03:2c6::21)\n by SA0PR18MB3662.namprd18.prod.outlook.com (2603:10b6:806:9e::21) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9769.48; Tue, 14 Apr\n 2026 13:48:53 +0000",
            "from SJ5PEPF000001D2.namprd05.prod.outlook.com\n (2603:10b6:a03:2c6:cafe::98) by SJ0PR13CA0136.outlook.office365.com\n (2603:10b6:a03:2c6::21) with Microsoft SMTP Server (version=TLS1_3,\n cipher=TLS_AES_256_GCM_SHA384) id 15.20.9769.48 via Frontend Transport; Tue,\n 14 Apr 2026 13:48:53 +0000",
            "from smtp.corp.axiado.com (50.233.182.194) by\n SJ5PEPF000001D2.mail.protection.outlook.com (10.167.242.54) with Microsoft\n SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.9769.17\n via Frontend Transport; Tue, 14 Apr 2026 13:48:52 +0000",
            "from axz-uw1-build-vm02.corp.axiado.com (unknown [10.14.1.22])\n\tby smtp.corp.axiado.com (Postfix) with ESMTP id 77A354186B5A;\n\tTue, 14 Apr 2026 06:48:51 -0700 (PDT)"
        ],
        "ARC-Seal": [
            "i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1776174538; cv=fail;\n b=hUGODAlPAKJF6czR+3hcUYxI/2YAx9Wb2ivRYrcfXBrLbfweHUJU+v48mwLELj1mZfTFVqNYgLRAdNAwWkmgiCL8eBEl58Tvjn2denTrKPOlJNBaf5euS/D1mXPNNcuIO54SrwcLFT4jyZBZm/IFmcGec5uu26q84qXwTUlq8fw=",
            "i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=k5+pp8jdyChKI+MkGc3kbNZZw7BDewo4RkzmHstwG7l2WtMy1LKQn42bRZFKB8K8xj7DPnddTJEb5caggjUWy9Y/SyDBixdQlFVzKA00jJBcVLSPiO/Uxe1DJZBzk1TjSy9cm4i+E+iCJkoiViS7tumXO5hXVbCJRvn/jOUotFMk6IMU7H3yD/1DdVgDfUFRUqrqqi5uZ4EDxELzRdyEwKsJgLRqsGLhjZjuGzw78gQohXSz4a8V4nEakXiPdNNFMfdN7+xQOQmT9kkRF6OOuvzlrubqP0Seerfx2gbM3cW+wyCuop9/3ps6BadcI7/2G+Uo6Tx1KHjbZ8mNPfvoCw=="
        ],
        "ARC-Message-Signature": [
            "i=2; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1776174538; c=relaxed/simple;\n\tbh=UctPww/5ghi9OTkK+5V0Zebvu20m6X4LR+bptf3MKpc=;\n\th=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:\n\t In-Reply-To:To:Cc;\n b=PQkKbKF9g4MVTDSzd5Cr6osCifUnwd8N9FEipvlXTwGjuNypGpLggpW56voQbyAA6/PptuGbEXSLt4IWkpD5kEgV4jn1tNdBWSlvvF7mZLAf/wot4NOs1DQcldG3TbqSIPcFi4cvQO1M6+TkERPczZcnh4xCq3VvXwHFolK0//U=",
            "i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector10001;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;\n bh=Uc0Cc5EnREDYCPbblIwAoMTbAbdhsP2yAQGul9ifjbw=;\n b=QcCBrSKcjhDaF2yQdPQdRgKvVY+qT0/BSHE0LmMQscqmZc89QxvU3xmiH5GtNOUnjyZLlYdgrTZj+B1HV/Pxy/et433iVWj3IRbclQPBvI/okYFjljlcLROw43l4/FrEBTS+uRRqX2sBSlq5/pCl1Fd+En6bHViIaGzyd7IZ1FU6Nlp91P3p8Y6LV4Mylqd4/9G5Bz+kMibhT6/5HYw1S+KsL25be6w+tn2AHnd2424qp8rZ47YNJLdovl5xoERn3u9XQS1NBjHxuQNBMHSSbRYAfzWagJtyec+Ga5NJSTnwZfz4skAvGmN42j6s7FMBUENPgGAXHWfeOEjmhgEnUA=="
        ],
        "ARC-Authentication-Results": [
            "i=2; smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=axiado.com;\n spf=pass smtp.mailfrom=axiado.com;\n dkim=pass (2048-bit key) header.d=axiado.com header.i=@axiado.com\n header.b=QuiPLdj2; arc=fail smtp.client-ip=40.107.201.112",
            "i=1; mx.microsoft.com 1; spf=fail (sender ip is\n 50.233.182.194) smtp.rcpttodomain=axiado.com smtp.mailfrom=axiado.com;\n dmarc=none action=none header.from=axiado.com; dkim=none (message not\n signed); arc=none (0)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=axiado.com;\n s=selector1;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=Uc0Cc5EnREDYCPbblIwAoMTbAbdhsP2yAQGul9ifjbw=;\n b=QuiPLdj2CgHVsub3AUkRVUFQOL2LLsSIC174wuNdXScTMnJGz0u3rxajVJMDXmOT0zfVyO5R+byxvd0Uu+o1HJUL5xUUpP4dhB/9MYKPFF8IEkF1N6SSXyzPU0OzPN7TGEXfUda0DzK8x5gwprb1khxcP62mfrqFx5p5N8qLL7OPpJRwgxp1lBCVbWzqaLF9jxZ6k18C4hAxGYXiXI35tsgaa9s5Z5j7Zb0JnPre6QWTojoMSyYotML04CKpVFB7ULXegh2AtJEgcf/h6vdyjiN2zYIxGpxLUdd/KDjeJIuK2bPeDdRMpiL6JUI9mIqxc+JnFCWt0uwY2crXm9FmYg==",
        "X-MS-Exchange-Authentication-Results": "spf=fail (sender IP is 50.233.182.194)\n smtp.mailfrom=axiado.com; dkim=none (message not signed)\n header.d=none;dmarc=none action=none header.from=axiado.com;",
        "Received-SPF": "Fail (protection.outlook.com: domain of axiado.com does not\n designate 50.233.182.194 as permitted sender)\n receiver=protection.outlook.com; client-ip=50.233.182.194;\n helo=smtp.corp.axiado.com;",
        "From": "Petar Stepanovic <pstepanovic@axiado.com>",
        "Date": "Tue, 14 Apr 2026 06:48:33 -0700",
        "Subject": "[PATCH 2/3] gpio: axiado: add SGPIO controller support",
        "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-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "\n <20260414-axiado-ax3000-sgpio-controller-v1-2-b5c7e4c2e69b@axiado.com>",
        "References": "\n <20260414-axiado-ax3000-sgpio-controller-v1-0-b5c7e4c2e69b@axiado.com>",
        "In-Reply-To": "\n <20260414-axiado-ax3000-sgpio-controller-v1-0-b5c7e4c2e69b@axiado.com>",
        "To": "Petar Stepanovic <pstepanovic@axiado.com>,\n Tzu-Hao Wei <twei@axiado.com>, Swark Yang <syang@axiado.com>,\n Prasad Bolisetty <pbolisetty@axiado.com>, Linus Walleij <linusw@kernel.org>,\n Bartosz Golaszewski <brgl@kernel.org>, Rob Herring <robh@kernel.org>,\n Krzysztof Kozlowski <krzk+dt@kernel.org>,\n Conor Dooley <conor+dt@kernel.org>, Harshit Shah <hshah@axiado.com>,\n SriNavmani A <srinavmani@axiado.com>",
        "Cc": "linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,\n linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org",
        "X-Mailer": "b4 0.14.3",
        "X-Developer-Signature": "v=1; a=ed25519-sha256; t=1776174532; l=21770;\n i=pstepanovic@axiado.com; s=20250916; h=from:subject:message-id;\n bh=UctPww/5ghi9OTkK+5V0Zebvu20m6X4LR+bptf3MKpc=;\n b=GjvMHTV63fcT2rH2/EsmLkSGlEyt/ODexKYpu7hRXLrW50tpgoeQYEchPAHDq5isHu+Qj34Kd\n fHQGES1/oVzDhX1WTUD00Xi6dLFgHpCN0ZuI0vIIcIIvrSfWZRtipiG",
        "X-Developer-Key": "i=pstepanovic@axiado.com; a=ed25519;\n pk=70f1UJOGT9U11ZK6o+ENXtv0I5wBE3e+Y9YWODzRsdI=",
        "X-EOPAttributedMessage": "0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "SJ5PEPF000001D2:EE_|SA0PR18MB3662:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "a1e8612c-4e18-47a5-82a4-08de9a2c90ab",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "\n\tBCL:0;ARA:13230040|1800799024|82310400026|36860700016|376014|921020|56012099003|18002099003|22082099003;",
        "X-Microsoft-Antispam-Message-Info": "\n\tmohtETSJD3bExUr0oVWWQkJ0gTgtgdd8+/RiiTKhBLvRQVg9XzK0oTalzai7/o+SAujnj2/QmmEP/U9Spd94QpVvVjuGx2c54WZSVM/SjTY4KiAmYrmCHUvSUm/vRZ0BSLoQbniUBtGzwR7gDuAW8jrVeC5KbmRJ1AVM1SPfAkTfx+p8FM5b+/BFajqbtdTkwkAzizNYdW31JdgxOb/eVPPEYVAW5FPWYV07hrNnp3baTUTXM5riUi/EuHh39U2OGlz3ULGNM3p+HE3OtmkgO193nGH/zykUYcXa7q1BIIKLGROFo1KZIkP3yWRh4W+YZIIhEEUZX1Nfgw/Jo/JGPX3ZdDseKowxE3f3Bf7tlasEjXcINHFB+NEtv6IKDgfVhl1ToTuy3OdwSr1OUabAEv48M+jzLhqxUNqdCA8ze7BZr+ozGjdi/Ajy5FamUI0UTeLlppz0Oqwe61nceb96tUbIqobiR0AyUpb74Dd/qxv+sLzjFhJTcZgQSU7jsTaSn3J+3GODiI7T1VS5yjnlp5lJrGTvb80NQHZ/CFUrqFBOCY3IcxJgQ6EWoIzviLiJmtRE7BGfPxt/angdCEerFZ65vI6D7I4xI8Th/ES/if9CmxNvWLAk2aEHoKbeAOOPuXfahcLx6+s3m8JTXC1XqQIDMIX5+ByKhhFOZ6zfzpq74eGoQP7JOM8ERuDHVekbglpAaEZae+gsmLv37tj5gJzOd0p3tSFT0maIJk4lZg+IPiEKL79llvuGYIU3VrMevQF/DA3Rkw80ysuXkTB2nRTN0RY/p3QWEpUe/YnIfeoHkUidKFhKemNmbUn+0815",
        "X-Forefront-Antispam-Report": "\n\tCIP:50.233.182.194;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:smtp.corp.axiado.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230040)(1800799024)(82310400026)(36860700016)(376014)(921020)(56012099003)(18002099003)(22082099003);DIR:OUT;SFP:1102;",
        "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1",
        "X-MS-Exchange-AntiSpam-MessageData-0": "\n\tfn8lvT9wBxwH3Filw1jh1vPasAfDmpNoPYXKFkKZPqhaj9FvScHZHUw0rjtMcqx3eR+ioFH2vuQELNakzFuHPhMgaybs61W0ypQL2fj1CgPMbfIwKDM8HUcUIcsvpbqYuRh48vnHdw9MTM2K/J6mqv6R+afFMBx/km6vC0TtHedd7cwqm5H/jiv0BC460EoPYf1z0nApUbVn3zV/6Swkj7m8DcO5bAAW+6OdfR4T18HjC2QcUQ1tXXG7avmFR644kbJLus+jYGr6dRQRlQ7rHotMC8vhuXOgXWfnXMxOdy7ASpSUZbV4nwrsH8nu8I28QqpvAuisvzKwUZ87OSVEh5Ar9/JH4/K5MXsORv/yV2LESf8nrZC41ukrD3drJeodm+shgs9/xuNiyM359D8cGNMxAhr9C3BF4kZmxi8dmr47xVQIB1M3IFTqyBb+jksn",
        "X-OriginatorOrg": "axiado.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "14 Apr 2026 13:48:52.9104\n (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n a1e8612c-4e18-47a5-82a4-08de9a2c90ab",
        "X-MS-Exchange-CrossTenant-Id": "ff2db17c-4338-408e-9036-2dee8e3e17d7",
        "X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp": "\n TenantId=ff2db17c-4338-408e-9036-2dee8e3e17d7;Ip=[50.233.182.194];Helo=[smtp.corp.axiado.com]",
        "X-MS-Exchange-CrossTenant-AuthSource": "\n\tSJ5PEPF000001D2.namprd05.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "SA0PR18MB3662"
    },
    "content": "Add support for the Axiado SGPIO controller.\n\nThe controller provides a serialized interface for GPIOs with\nconfigurable direction and interrupt support.\n\nThe driver registers the controller as a gpio_chip and uses\nregmap for register access.\n\nSigned-off-by: Petar Stepanovic <pstepanovic@axiado.com>\n---\n drivers/gpio/Kconfig             |  18 +\n drivers/gpio/Makefile            |   1 +\n drivers/gpio/gpio-axiado-sgpio.c | 780 +++++++++++++++++++++++++++++++++++++++\n 3 files changed, 799 insertions(+)",
    "diff": "diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig\nindex bd185482a7fd..42c56d157092 100644\n--- a/drivers/gpio/Kconfig\n+++ b/drivers/gpio/Kconfig\n@@ -198,6 +198,24 @@ config GPIO_ATH79\n \t  Select this option to enable GPIO driver for\n \t  Atheros AR71XX/AR724X/AR913X SoC devices.\n \n+config GPIO_AXIADO_SGPIO\n+\tbool \"Axiado SGPIO support\"\n+\tdepends on OF_GPIO\n+\tdepends on ARCH_AXIADO || COMPILE_TEST\n+\tselect GPIO_GENERIC\n+\tselect GPIOLIB_IRQCHIP\n+\tselect REGMAP\n+\thelp\n+\t  Enable support for the Axiado Serial GPIO (SGPIO) controller.\n+\n+\t  The SGPIO controller provides a serialized interface for\n+\t  controlling multiple GPIO signals over a limited number of\n+\t  physical lines. It supports configurable data direction and\n+\t  interrupt handling.\n+\n+\t  This driver integrates with the Linux GPIO subsystem and\n+\t  exposes the controller as a standard GPIO provider.\n+\n config GPIO_RASPBERRYPI_EXP\n \ttristate \"Raspberry Pi 3 GPIO Expander\"\n \tdefault RASPBERRYPI_FIRMWARE\ndiff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile\nindex 2421a8fd3733..909a97551807 100644\n--- a/drivers/gpio/Makefile\n+++ b/drivers/gpio/Makefile\n@@ -42,6 +42,7 @@ obj-$(CONFIG_GPIO_ARIZONA)\t\t+= gpio-arizona.o\n obj-$(CONFIG_GPIO_ASPEED)\t\t+= gpio-aspeed.o\n obj-$(CONFIG_GPIO_ASPEED_SGPIO)\t\t+= gpio-aspeed-sgpio.o\n obj-$(CONFIG_GPIO_ATH79)\t\t+= gpio-ath79.o\n+obj-$(CONFIG_GPIO_AXIADO_SGPIO)\t\t+= gpio-axiado-sgpio.o\n obj-$(CONFIG_GPIO_BCM_KONA)\t\t+= gpio-bcm-kona.o\n obj-$(CONFIG_GPIO_BCM_XGS_IPROC)\t+= gpio-xgs-iproc.o\n obj-$(CONFIG_GPIO_BD71815)\t\t+= gpio-bd71815.o\ndiff --git a/drivers/gpio/gpio-axiado-sgpio.c b/drivers/gpio/gpio-axiado-sgpio.c\nnew file mode 100644\nindex 000000000000..8cd349ec6f53\n--- /dev/null\n+++ b/drivers/gpio/gpio-axiado-sgpio.c\n@@ -0,0 +1,780 @@\n+// SPDX-License-Identifier: GPL-2.0-or-later\n+/*\n+ * Copyright (c) 2022-2026 Axiado Corporation\n+ */\n+#include <linux/types.h>\n+#include <linux/kernel.h>\n+#include <linux/init.h>\n+#include <linux/module.h>\n+\n+#include <linux/platform_device.h>\n+#include <linux/io.h>\n+#include <linux/spinlock.h>\n+\n+#include <linux/interrupt.h>\n+#include <linux/irq.h>\n+#include <linux/irqdomain.h>\n+\n+#include <linux/gpio/driver.h>\n+\n+#include <linux/of.h>\n+#include <linux/of_device.h>\n+#include <linux/of_irq.h>\n+\n+#include <linux/regmap.h>\n+\n+struct sgpio_reg_offsets {\n+\tu32 mux_0;\n+\tu32 preset_0;\n+\tu32 count_0;\n+\tu32 pos_0;\n+\n+\tu32 mux_1;\n+\tu32 ld;\n+\tu32 ld_ss;\n+\n+\tu32 preset_1;\n+\tu32 count_1;\n+\tu32 pos_1;\n+\n+\tu32 mux_2;\n+\tu32 dout;\n+\tu32 dout_ss;\n+\n+\tu32 preset_2;\n+\tu32 count_2;\n+\tu32 pos_2;\n+\n+\tu32 mux_3;\n+\tu32 preset_3;\n+\tu32 count_3;\n+\tu32 pos_3;\n+\n+\tu32 mux_4;\n+\tu32 oe;\n+\tu32 oe_ss;\n+\n+\tu32 preset_4;\n+\tu32 count_4;\n+\tu32 pos_4;\n+\n+\tu32 mask;\n+\tu32 ctrl_en;\n+\tu32 ctrl_en_pos;\n+\n+\tu32 din_ss;\n+\tu32 status;\n+};\n+\n+static const struct sgpio_reg_offsets sgpio_offsets_512 = {\n+\t.mux_0 = 0x000,\n+\t.preset_0 = 0x1dc,\n+\t.count_0 = 0x1f0,\n+\t.pos_0 = 0x204,\n+\n+\t.mux_1 = 0x004,\n+\t.ld = 0x014,\n+\t.ld_ss = 0x0d8,\n+\n+\t.preset_1 = 0x1e0,\n+\t.count_1 = 0x1f4,\n+\t.pos_1 = 0x208,\n+\n+\t.mux_2 = 0x008,\n+\t.dout = 0x054,\n+\t.dout_ss = 0x158,\n+\n+\t.preset_2 = 0x1e4,\n+\t.count_2 = 0x1f8,\n+\t.pos_2 = 0x20c,\n+\n+\t.mux_3 = 0x00c,\n+\t.preset_3 = 0x1e8,\n+\t.count_3 = 0x1fc,\n+\t.pos_3 = 0x210,\n+\n+\t.mux_4 = 0x010,\n+\t.oe = 0x0d4,\n+\t.oe_ss = 0x1d8,\n+\n+\t.preset_4 = 0x1ec,\n+\t.count_4 = 0x200,\n+\t.pos_4 = 0x214,\n+\n+\t.mask = 0x224,\n+\t.ctrl_en = 0x218,\n+\t.ctrl_en_pos = 0x21c,\n+\n+\t.din_ss = 0x198,\n+\t.status = 0x228,\n+};\n+\n+static const struct sgpio_reg_offsets sgpio_offsets_128 = {\n+\t.mux_0 = 0x000,\n+\t.preset_0 = 0x08c,\n+\t.count_0 = 0x0a0,\n+\t.pos_0 = 0x0b4,\n+\n+\t.mux_1 = 0x004,\n+\t.ld = 0x014,\n+\t.ld_ss = 0x048,\n+\n+\t.preset_1 = 0x090,\n+\t.count_1 = 0x0a4,\n+\t.pos_1 = 0x0b8,\n+\n+\t.mux_2 = 0x008,\n+\t.dout = 0x024,\n+\t.dout_ss = 0x068,\n+\n+\t.preset_2 = 0x094,\n+\t.count_2 = 0x0a8,\n+\t.pos_2 = 0x0bc,\n+\n+\t.mux_3 = 0x00c,\n+\t.preset_3 = 0x098,\n+\t.count_3 = 0x0ac,\n+\t.pos_3 = 0x0c0,\n+\n+\t.mux_4 = 0x010,\n+\t.oe = 0x044,\n+\t.oe_ss = 0x088,\n+\n+\t.preset_4 = 0x09c,\n+\t.count_4 = 0x0b0,\n+\t.pos_4 = 0x0c4,\n+\n+\t.mask = 0x0d4,\n+\t.ctrl_en = 0x0c8,\n+\t.ctrl_en_pos = 0x0cc,\n+\n+\t.din_ss = 0x078,\n+\t.status = 0x0d8,\n+};\n+\n+#define MAX_SGPIO_PINS 512\n+#define MAX_OFFSET_REG 16\n+#define MAX_SLICE_COUNT 5\n+\n+struct ax3000_slice_info {\n+\tu32 out_mux;\n+\tu32 sgpio_mux;\n+\tu32 slice_mux;\n+\tu32 reg[MAX_OFFSET_REG];\n+\tu32 reg_ss[MAX_OFFSET_REG];\n+\tu32 preset;\n+\tu32 count;\n+\tu32 pos;\n+};\n+\n+struct ax3000_sgpio {\n+\tu32 preset_value;\n+\tu32 count_value;\n+\tu32 pos_reg;\n+\tstruct ax3000_slice_info\n+\t\tslices[MAX_SLICE_COUNT]; /* 0=clk,1=load,2=out,3=in,4=oe */\n+\tspinlock_t lock;\n+\tint ngpios;\n+\tint max_sgpio_pins;\n+\tint max_offset_regs;\n+\tstruct gpio_chip chip;\n+\tu32 irq_unmasked[MAX_SGPIO_PINS];\n+\tint parent_irq;\n+\tstruct regmap *regmap;\n+\tu32 regmap_base_offset;\n+\tstruct sgpio_reg_offsets *regs;\n+};\n+\n+static int sgpio_set_irq_type(struct irq_data *d, unsigned int type);\n+static void sgpio_mask_irq(struct irq_data *d);\n+static void sgpio_unmask_irq(struct irq_data *d);\n+static void sgpio_irq_shutdown(struct irq_data *d);\n+\n+static const struct irq_chip axiado_sgpio_irqchip = {\n+\t.name = \"axiado-sgpio\",\n+\t.irq_mask = sgpio_mask_irq,\n+\t.irq_unmask = sgpio_unmask_irq,\n+\t.irq_set_type = sgpio_set_irq_type,\n+\t.irq_shutdown = sgpio_irq_shutdown,\n+\t.flags = IRQCHIP_IMMUTABLE | IRQCHIP_MASK_ON_SUSPEND,\n+};\n+\n+static void ax3000_sgpio_set(struct gpio_chip *chip, unsigned int offset,\n+\t\t\t     int value)\n+{\n+\tstruct ax3000_sgpio *sgpio = gpiochip_get_data(chip);\n+\tunsigned long flags;\n+\tu32 bank = (offset / 2) / 32;\n+\tu32 position = (offset / 2) % 32;\n+\n+\tspin_lock_irqsave(&sgpio->lock, flags);\n+\tif (value)\n+\t\tsgpio->slices[2].reg_ss[bank] |= BIT(position);\n+\telse\n+\t\tsgpio->slices[2].reg_ss[bank] &= ~BIT(position);\n+\n+\tspin_unlock_irqrestore(&sgpio->lock, flags);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->dout_ss +\n+\t\t\t     (bank * 4),\n+\t\t     sgpio->slices[2].reg_ss[bank]);\n+}\n+\n+static int ax3000_sgpio_get(struct gpio_chip *chip, unsigned int offset)\n+{\n+\tstruct ax3000_sgpio *sgpio = gpiochip_get_data(chip);\n+\tu32 bank = (offset / 2) / 32;\n+\tu32 position = (offset / 2) % 32;\n+\n+\tif (offset % 2 == 0)\n+\t\treturn !!(sgpio->slices[3].reg_ss[bank] & BIT(position));\n+\telse\n+\t\treturn !!(sgpio->slices[2].reg_ss[bank] & BIT(position));\n+}\n+\n+static int ax3000_sgpio_dir_in(struct gpio_chip *chip, unsigned int offset)\n+{\n+\tif (!(offset % 2))\n+\t\treturn 0;\n+\telse\n+\t\treturn -EINVAL;\n+}\n+\n+static int ax3000_sgpio_dir_out(struct gpio_chip *chip, unsigned int offset,\n+\t\t\t\tint value)\n+{\n+\tif (offset % 2) {\n+\t\tif (chip->set)\n+\t\t\tchip->set(chip, offset, value);\n+\t\treturn 0;\n+\t} else {\n+\t\treturn -EINVAL;\n+\t}\n+}\n+\n+static irqreturn_t sgpio_irq_handler(int irq, void *arg)\n+{\n+\tstruct ax3000_sgpio *sgpio = (struct ax3000_sgpio *)arg;\n+\tunsigned long flags;\n+\tu32 status, new_value;\n+\tu32 changed_value;\n+\tint i, bit, reg_ptr;\n+\n+\t/* Read-on-clear (ACK) parent cause */\n+\tregmap_read(sgpio->regmap,\n+\t\t    sgpio->regmap_base_offset + sgpio->regs->status, &status);\n+\tstatus >>= 16;\n+\n+\tbool has_shifted_layout = (sgpio->max_offset_regs == MAX_OFFSET_REG);\n+\n+\treg_ptr = has_shifted_layout ? 16 - DIV_ROUND_UP(sgpio->ngpios, 32) : 0;\n+\n+\tfor (i = 0; i < DIV_ROUND_UP(sgpio->ngpios, 32); i++, reg_ptr++) {\n+\t\tif (status & BIT(reg_ptr)) {\n+\t\t\tregmap_read(sgpio->regmap,\n+\t\t\t\t    sgpio->regmap_base_offset +\n+\t\t\t\t\t    sgpio->regs->din_ss + (reg_ptr * 4),\n+\t\t\t\t    &new_value);\n+\t\t\tspin_lock_irqsave(&sgpio->lock, flags);\n+\t\t\tchanged_value = sgpio->slices[3].reg_ss[i] ^ new_value;\n+\t\t\tsgpio->slices[3].reg_ss[i] = new_value;\n+\t\t\tspin_unlock_irqrestore(&sgpio->lock, flags);\n+\n+\t\t\twhile (changed_value) {\n+\t\t\t\tbit = __ffs(changed_value);\n+\t\t\t\tchanged_value &= ~BIT(bit);\n+\n+\t\t\t\tirq_hw_number_t hwirq = i * 32 + bit;\n+\n+\t\t\t\tif (sgpio->irq_unmasked[hwirq]) {\n+\t\t\t\t\tunsigned int child_irq;\n+\n+\t\t\t\t\tchild_irq = irq_find_mapping(sgpio->chip.irq.domain,\n+\t\t\t\t\t\t\t\t     hwirq);\n+\n+\t\t\t\t\tif (child_irq)\n+\t\t\t\t\t\thandle_nested_irq(child_irq);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\treturn IRQ_HANDLED;\n+}\n+\n+static void sgpio_hw_init(struct ax3000_sgpio *sgpio)\n+{\n+\tu32 bank;\n+\tu32 position;\n+\tint i = 0;\n+\tbool has_shifted_layout = (sgpio->max_offset_regs == MAX_OFFSET_REG);\n+\n+\t/* slice A0, Clock Pin - 0 */\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->mux_0, 0x306);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->preset_0,\n+\t\t     sgpio->preset_value);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->count_0,\n+\t\t     sgpio->count_value);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->pos_0, 0x1f001f);\n+\n+\t/* Slice B1, Data Load Pin - 1 */\n+\tbank = (sgpio->ngpios - 1) / 32;\n+\tposition = (sgpio->ngpios - 1) % 32;\n+\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->mux_1,\n+\t\t     has_shifted_layout ? 0x30c : 0x304);\n+\n+\tfor (i = 0; i < bank; i++) {\n+\t\tregmap_write(sgpio->regmap,\n+\t\t\t     sgpio->regmap_base_offset + sgpio->regs->ld +\n+\t\t\t\t     (i * 4),\n+\t\t\t     0xffffffff);\n+\t\tregmap_write(sgpio->regmap,\n+\t\t\t     sgpio->regmap_base_offset + sgpio->regs->ld_ss +\n+\t\t\t\t     (i * 4),\n+\t\t\t     0xffffffff);\n+\t}\n+\n+\tif (position) {\n+\t\tu32 val;\n+\n+\t\tval = sgpio->slices[1].reg_ss[i];\n+\t\tval |= GENMASK(position - 1, 0);\n+\n+\t\tregmap_write(sgpio->regmap,\n+\t\t\t     sgpio->regmap_base_offset + sgpio->regs->ld +\n+\t\t\t\t     (i * 4),\n+\t\t\t     val);\n+\t\tregmap_write(sgpio->regmap,\n+\t\t\t     sgpio->regmap_base_offset + sgpio->regs->ld_ss +\n+\t\t\t\t     (i * 4),\n+\t\t\t     val);\n+\t}\n+\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->preset_1,\n+\t\t     sgpio->preset_value);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->count_1,\n+\t\t     sgpio->count_value);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->pos_1,\n+\t\t     sgpio->pos_reg);\n+\n+\t/* Slice C2, Data Out Pin - 2 */\n+\tbank = sgpio->ngpios / 32;\n+\tposition = sgpio->ngpios % 32;\n+\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->mux_2,\n+\t\t     has_shifted_layout ? 0x30c : 0x304);\n+\n+\tfor (i = 0; i < bank; i++) {\n+\t\tregmap_write(sgpio->regmap,\n+\t\t\t     sgpio->regmap_base_offset + sgpio->regs->dout +\n+\t\t\t\t     (i * 4),\n+\t\t\t     sgpio->slices[2].reg_ss[i]);\n+\t\tregmap_write(sgpio->regmap,\n+\t\t\t     sgpio->regmap_base_offset + sgpio->regs->dout_ss +\n+\t\t\t\t     (i * 4),\n+\t\t\t     sgpio->slices[2].reg_ss[i]);\n+\t}\n+\n+\tif (position) {\n+\t\tregmap_write(sgpio->regmap,\n+\t\t\t     sgpio->regmap_base_offset + sgpio->regs->dout +\n+\t\t\t\t     (i * 4),\n+\t\t\t     sgpio->slices[2].reg_ss[i]);\n+\t\tregmap_write(sgpio->regmap,\n+\t\t\t     sgpio->regmap_base_offset + sgpio->regs->dout_ss +\n+\t\t\t\t     (i * 4),\n+\t\t\t     sgpio->slices[2].reg_ss[i]);\n+\t}\n+\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->preset_2,\n+\t\t     sgpio->preset_value);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->count_2,\n+\t\t     sgpio->count_value);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->pos_2,\n+\t\t     sgpio->pos_reg);\n+\n+\t/* Slice D3, Data In Pin - 3 */\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->mux_3, 0x14C);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->preset_3,\n+\t\t     sgpio->preset_value);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->count_3,\n+\t\t     sgpio->count_value);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->pos_3,\n+\t\t     sgpio->pos_reg);\n+\n+\t/* Slice E4, Output Enable for respective pins */\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->mux_4,\n+\t\t     has_shifted_layout ? 0x10c : 0x104);\n+\tregmap_write(sgpio->regmap, sgpio->regmap_base_offset + sgpio->regs->oe,\n+\t\t     0xffffffff);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->oe_ss,\n+\t\t     0xffffffff);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->preset_4,\n+\t\t     sgpio->preset_value);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->count_4,\n+\t\t     sgpio->count_value);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->pos_4, 0x1f001f);\n+\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->mask, 0xdfff);\n+\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->ctrl_en, 0xffff);\n+\tregmap_write(sgpio->regmap,\n+\t\t     sgpio->regmap_base_offset + sgpio->regs->ctrl_en_pos,\n+\t\t     0xffff);\n+}\n+\n+static int sgpio_set_irq_type(struct irq_data *d, unsigned int type)\n+{\n+\tswitch (type) {\n+\tcase IRQ_TYPE_EDGE_BOTH:\n+\tcase IRQ_TYPE_EDGE_RISING:\n+\tcase IRQ_TYPE_EDGE_FALLING:\n+\t\tirq_set_handler_locked(d, handle_edge_irq);\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static void sgpio_mask_irq(struct irq_data *d)\n+{\n+\tstruct gpio_chip *chip;\n+\tstruct ax3000_sgpio *sgpio;\n+\tu32 irq_num;\n+\n+\tchip = irq_data_get_irq_chip_data(d);\n+\tif (!chip) {\n+\t\tpr_err(\"Unable to get gpio_chip for IRQ\\n\");\n+\t\treturn;\n+\t}\n+\n+\tsgpio = gpiochip_get_data(chip);\n+\tif (!sgpio) {\n+\t\tpr_err(\"Unable to get chip data\\n\");\n+\t\treturn;\n+\t}\n+\n+\tirq_num = irqd_to_hwirq(d);\n+\tsgpio->irq_unmasked[irq_num / 2] = 0;\n+}\n+\n+static void sgpio_unmask_irq(struct irq_data *d)\n+{\n+\tstruct gpio_chip *chip;\n+\tstruct ax3000_sgpio *sgpio;\n+\tu32 irq_num;\n+\n+\tchip = irq_data_get_irq_chip_data(d);\n+\tif (!chip) {\n+\t\tpr_err(\"Unable to get gpio_chip for IRQ\\n\");\n+\t\treturn;\n+\t}\n+\n+\tsgpio = gpiochip_get_data(chip);\n+\tif (!sgpio) {\n+\t\tpr_err(\"Unable to get chip data\\n\");\n+\t\treturn;\n+\t}\n+\n+\tirq_num = irqd_to_hwirq(d);\n+\tsgpio->irq_unmasked[irq_num / 2] = 1;\n+}\n+\n+static void sgpio_irq_shutdown(struct irq_data *d)\n+{\n+\tsgpio_mask_irq(d);\n+}\n+\n+static int sgpio_probe(struct platform_device *pdev)\n+{\n+\tint rc;\n+\tint irq;\n+\tint i;\n+\tconst __be32 *prop;\n+\tstruct gpio_irq_chip *girq;\n+\tstruct ax3000_sgpio *sgpio;\n+\tu32 variant;\n+\tu32 dout_value;\n+\tu32 bus_frequency;\n+\tu32 apb_frequency;\n+\tint dout_reverse;\n+\n+\tvoid __iomem *base;\n+\n+\tconst struct regmap_config regmap_config = {\n+\t\t.reg_bits = 32,\n+\t\t.val_bits = 32,\n+\t\t.reg_stride = 4,\n+\t};\n+\n+\tsgpio = devm_kzalloc(&pdev->dev, sizeof(*sgpio), GFP_KERNEL);\n+\tif (!sgpio)\n+\t\treturn -ENOMEM;\n+\n+\tspin_lock_init(&sgpio->lock);\n+\n+\tsgpio->regmap = dev_get_regmap(pdev->dev.parent, NULL);\n+\n+\tif (sgpio->regmap) {\n+\t\trc = of_property_read_u32(pdev->dev.of_node, \"reg\",\n+\t\t\t\t\t  &sgpio->regmap_base_offset);\n+\t\tif (rc) {\n+\t\t\tdev_err(&pdev->dev, \"Failed to read reg property: %d\\n\",\n+\t\t\t\trc);\n+\t\t\treturn rc;\n+\t\t}\n+\t\tdev_info(&pdev->dev, \"Using regmap with base offset: 0x%x\\n\",\n+\t\t\t sgpio->regmap_base_offset);\n+\t} else {\n+\t\tbase = devm_platform_ioremap_resource(pdev, 0);\n+\t\tif (IS_ERR(base))\n+\t\t\treturn PTR_ERR(base);\n+\n+\t\tsgpio->regmap =\n+\t\t\tdevm_regmap_init_mmio(&pdev->dev, base, &regmap_config);\n+\n+\t\tif (IS_ERR(sgpio->regmap))\n+\t\t\treturn PTR_ERR(sgpio->regmap);\n+\n+\t\tsgpio->regmap_base_offset = 0;\n+\n+\t\tdev_info(&pdev->dev, \"Using MMIO regmap\\n\");\n+\t}\n+\n+\trc = device_property_read_u32(&pdev->dev, \"ngpios\", &sgpio->ngpios);\n+\tif (rc < 0) {\n+\t\tdev_err(&pdev->dev, \"Could not read ngpios property\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (device_property_read_u32(&pdev->dev, \"design-variant\", &variant)) {\n+\t\tdev_err(&pdev->dev, \"design-variant not specified in DT\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (variant == 128) {\n+\t\tsgpio->regs = &sgpio_offsets_128;\n+\t\tsgpio->max_sgpio_pins = 128;\n+\t\tsgpio->max_offset_regs = 4;\n+\t} else if (variant == 512) {\n+\t\tsgpio->regs = &sgpio_offsets_512;\n+\t\tsgpio->max_sgpio_pins = 512;\n+\t\tsgpio->max_offset_regs = 16;\n+\t} else {\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (sgpio->ngpios > sgpio->max_sgpio_pins) {\n+\t\tdev_err(&pdev->dev, \"ngpio is greater than 512 pins\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\trc = device_property_read_u32(&pdev->dev, \"bus-frequency\",\n+\t\t\t\t      &bus_frequency);\n+\tif (rc < 0) {\n+\t\tdev_err(&pdev->dev, \"Could not read bus-frequency property\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\trc = device_property_read_u32(&pdev->dev, \"apb-frequency\",\n+\t\t\t\t      &apb_frequency);\n+\tif (rc < 0) {\n+\t\tdev_err(&pdev->dev, \"Could not read apb-frequency property\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tsgpio->preset_value = (apb_frequency / bus_frequency) - 1;\n+\tsgpio->count_value = sgpio->preset_value;\n+\n+\tu32 pos;\n+\n+\tpos = sgpio->ngpios - 1;\n+\tsgpio->pos_reg = (pos << 16) | pos;\n+\n+\tprop = of_get_property(pdev->dev.of_node, \"dout-init\", NULL);\n+\tif (!prop) {\n+\t\tdev_err(&pdev->dev, \"Failed to get dout-init\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfor (i = 0; i < sgpio->max_offset_regs; i++) {\n+\t\tsgpio->slices[2].reg_ss[i] = 0;\n+\t\tdout_value = be32_to_cpu(prop[i]);\n+\n+\t\tfor (dout_reverse = 0; dout_reverse < 32; ++dout_reverse) {\n+\t\t\tsgpio->slices[2].reg_ss[i] <<= 1;\n+\t\t\tsgpio->slices[2].reg_ss[i] |= (dout_value & 1);\n+\t\t\tdout_value >>= 1;\n+\t\t}\n+\t}\n+\n+\tsgpio_hw_init(sgpio);\n+\n+\tirq = platform_get_irq(pdev, 0);\n+\n+\tif (irq < 0) {\n+\t\tdev_err(&pdev->dev, \"Failed to get parent IRQ: %d\\n\", irq);\n+\t\treturn irq;\n+\t}\n+\t/* Store parent IRQ for cleanup */\n+\tsgpio->parent_irq = irq;\n+\n+\trc = devm_request_threaded_irq(&pdev->dev, irq, NULL, sgpio_irq_handler,\n+\t\t\t\t       IRQF_ONESHOT, \"axiado-sgpio\", sgpio);\n+\n+\tif (rc < 0) {\n+\t\tdev_err(&pdev->dev, \"Failed to request threaded IRQ %d: %d\\n\",\n+\t\t\tirq, rc);\n+\t\treturn rc;\n+\t}\n+\n+\tsgpio->chip.parent = &pdev->dev;\n+\tsgpio->chip.ngpio = sgpio->ngpios * 2;\n+\tsgpio->chip.owner = THIS_MODULE;\n+\tsgpio->chip.direction_input = ax3000_sgpio_dir_in;\n+\tsgpio->chip.direction_output = ax3000_sgpio_dir_out;\n+\tsgpio->chip.get = ax3000_sgpio_get;\n+\tsgpio->chip.set = ax3000_sgpio_set;\n+\tsgpio->chip.label = dev_name(&pdev->dev);\n+\tsgpio->chip.base = -1;\n+\n+\tgirq = &sgpio->chip.irq;\n+\n+\tgirq->chip = &axiado_sgpio_irqchip;\n+\tgirq->handler = handle_edge_irq;\n+\tgirq->default_type = IRQ_TYPE_NONE;\n+\tgirq->num_parents = 1;\n+\tgirq->parents =\n+\t\tdevm_kcalloc(&pdev->dev, 1, sizeof(*girq->parents), GFP_KERNEL);\n+\tif (!girq->parents) {\n+\t\tdev_err(&pdev->dev, \"Failed to allocate parents array\\n\");\n+\t\treturn -ENOMEM;\n+\t}\n+\tgirq->parents[0] = irq;\n+\n+\trc = devm_gpiochip_add_data(&pdev->dev, &sgpio->chip, sgpio);\n+\tif (rc < 0) {\n+\t\tdev_err(&pdev->dev, \"Could not register gpiochip, %d\\n\", rc);\n+\t\treturn rc;\n+\t}\n+\n+\t/* Store driver data for remove() */\n+\tplatform_set_drvdata(pdev, sgpio);\n+\tdev_info(&pdev->dev, \"SGPIO registered with %d GPIOs\\n\",\n+\t\t sgpio->chip.ngpio);\n+\n+\treturn 0;\n+}\n+\n+static int sgpio_remove(struct platform_device *pdev)\n+{\n+\tstruct ax3000_sgpio *sgpio = platform_get_drvdata(pdev);\n+\tint i;\n+\n+\tif (!sgpio)\n+\t\treturn 0;\n+\n+\t/* Disable interrupts in hardware */\n+\tif (sgpio->regs) {\n+\t\tregmap_write(sgpio->regmap,\n+\t\t\t     sgpio->regmap_base_offset + sgpio->regs->mask,\n+\t\t\t     0x0);\n+\t\tregmap_write(sgpio->regmap,\n+\t\t\t     sgpio->regmap_base_offset + sgpio->regs->ctrl_en,\n+\t\t\t     0x0);\n+\t}\n+\n+\t/* Disable and synchronize parent IRQ to avoid races with handlers */\n+\tif (sgpio->parent_irq >= 0) {\n+\t\tdisable_irq(sgpio->parent_irq);\n+\t\tsynchronize_irq(sgpio->parent_irq);\n+\t}\n+\n+\t/* Ensure all GPIO IRQ handlers complete before removal */\n+\tif (sgpio->chip.irq.domain) {\n+\t\tstruct irq_domain *domain = sgpio->chip.irq.domain;\n+\t\tunsigned int irq;\n+\t\tint hwirq;\n+\n+\t\tfor (hwirq = 0; hwirq < sgpio->chip.ngpio; hwirq++) {\n+\t\t\tirq = irq_find_mapping(domain, hwirq);\n+\t\t\tif (irq) {\n+\t\t\t\tdisable_irq(irq);\n+\t\t\t\tsynchronize_irq(irq);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/* Clear internal IRQ state */\n+\tfor (i = 0; i < sgpio->max_sgpio_pins; i++)\n+\t\tsgpio->irq_unmasked[i] = 0;\n+\n+\treturn 0;\n+}\n+\n+static const struct of_device_id ax_sgpio_match[] = {\n+\t{ .compatible = \"axiado,sgpio\" },\n+\t{}\n+};\n+MODULE_DEVICE_TABLE(of, ax_sgpio_match);\n+\n+static struct platform_driver sgpio_driver = {\n+\t.driver = {\n+\t\t.name = \"sgpio\",\n+\t\t.owner = THIS_MODULE,\n+\t\t.of_match_table = ax_sgpio_match,\n+\t},\n+\t.probe = sgpio_probe,\n+\t.remove = sgpio_remove,\n+};\n+\n+static int __init ax_sgpio_init(void)\n+{\n+\tint ret;\n+\n+\tret = platform_driver_register(&sgpio_driver);\n+\tif (ret < 0) {\n+\t\tpr_err(\"Failed to register SGPIO driver\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static void __exit ax_sgpio_exit(void)\n+{\n+\tplatform_driver_unregister(&sgpio_driver);\n+}\n+\n+module_init(ax_sgpio_init);\n+module_exit(ax_sgpio_exit);\n+\n+MODULE_DESCRIPTION(\"Axiado Serial GPIO Driver\");\n+MODULE_AUTHOR(\"Axiado Corporation\");\n+MODULE_LICENSE(\"GPL\");\n",
    "prefixes": [
        "2/3"
    ]
}