get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2196107,
    "url": "http://patchwork.ozlabs.org/api/patches/2196107/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/patch/20260212213656.662437-4-shenwei.wang@nxp.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": "<20260212213656.662437-4-shenwei.wang@nxp.com>",
    "list_archive_url": null,
    "date": "2026-02-12T21:36:55",
    "name": "[v8,3/4] gpio: rpmsg: add generic rpmsg GPIO driver",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "105fd90c1f4c73a61609bfedb38f9a040643c325",
    "submitter": {
        "id": 74153,
        "url": "http://patchwork.ozlabs.org/api/people/74153/?format=api",
        "name": "Shenwei Wang",
        "email": "shenwei.wang@nxp.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-gpio/patch/20260212213656.662437-4-shenwei.wang@nxp.com/mbox/",
    "series": [
        {
            "id": 492027,
            "url": "http://patchwork.ozlabs.org/api/series/492027/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/list/?series=492027",
            "date": "2026-02-12T21:36:52",
            "name": "Enable Remote GPIO over RPMSG on i.MX Platform",
            "version": 8,
            "mbox": "http://patchwork.ozlabs.org/series/492027/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2196107/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2196107/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linux-gpio+bounces-31643-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=nxp.com header.i=@nxp.com header.a=rsa-sha256\n header.s=selector1 header.b=l6eGBI1t;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c09:e001:a7::12fc:5321; helo=sto.lore.kernel.org;\n envelope-from=linux-gpio+bounces-31643-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=nxp.com header.i=@nxp.com\n header.b=\"l6eGBI1t\"",
            "smtp.subspace.kernel.org;\n arc=fail smtp.client-ip=52.101.72.49",
            "smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=nxp.com",
            "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=nxp.com",
            "dkim=none (message not signed)\n header.d=none;dmarc=none action=none header.from=nxp.com;"
        ],
        "Received": [
            "from sto.lore.kernel.org (sto.lore.kernel.org\n [IPv6:2600:3c09:e001:a7::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 4fBpZP6WV4z1xvQ\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 13 Feb 2026 08:38:21 +1100 (AEDT)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sto.lore.kernel.org (Postfix) with ESMTP id 43DFA301D10E\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 12 Feb 2026 21:38:10 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 6977935B130;\n\tThu, 12 Feb 2026 21:38:08 +0000 (UTC)",
            "from AM0PR02CU008.outbound.protection.outlook.com\n (mail-westeuropeazon11013049.outbound.protection.outlook.com [52.101.72.49])\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 38931330D5E;\n\tThu, 12 Feb 2026 21:38:06 +0000 (UTC)",
            "from PAXPR04MB9185.eurprd04.prod.outlook.com (2603:10a6:102:231::11)\n by PA4PR04MB7936.eurprd04.prod.outlook.com (2603:10a6:102:c6::21) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9611.10; Thu, 12 Feb\n 2026 21:38:03 +0000",
            "from PAXPR04MB9185.eurprd04.prod.outlook.com\n ([fe80::b4c0:6119:2228:2ceb]) by PAXPR04MB9185.eurprd04.prod.outlook.com\n ([fe80::b4c0:6119:2228:2ceb%4]) with mapi id 15.20.9611.008; Thu, 12 Feb 2026\n 21:38:03 +0000"
        ],
        "ARC-Seal": [
            "i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1770932288; cv=fail;\n b=fF3OYZ6wmm6lnKb/Q7BMzr07QG72wwS+OGNe8Ozbx4N9XtqYDCsuGUGxftfTq6r8+JPE4fWPZ1w/0jcX89sLOalGL2BpQ6GXKr/2+Jl10or+L+SYWMSUG7mMSaqeSMPfdxVKfyLFSLEWe38Q9aBicCEBnXBi6NP2ubgHS5Lrbus=",
            "i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=gjFa6GOfTlD7IrpyKepZHOv5Q6acBcixF1XVypA4wegYUT1SgZxfYjqWCsQfquGWyWxmcbZVS6Wto2U04tAx+19YjZCFg5CU2A3BdCnH0DEQzH7QB20wjhZ8yli07ND6binZoKr9uINFVDPHXhh5y0y23X+06GdipqARtclRJoNAztq40ael2muJr+t0Es8TYhZiwI50Q9vmfAP7QP6HXY/upxZ3EnqASI/zmEFcjDXl1x87AMgh1yIBW7w0sii2M7kdUqliOOje/soBleyid/K+Z4TA8Z3p/rp9zyVKL07c7IB5TzeCl5MRT0WyBHUUunslXQMe4qIPt8rrfOsIlA=="
        ],
        "ARC-Message-Signature": [
            "i=2; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1770932288; c=relaxed/simple;\n\tbh=cAkXTCQ1aIoOw7i2PW+KYYCsX5s9FwTt5BdHkVZ6pWU=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t Content-Type:MIME-Version;\n b=M5LcGuu3APaY6yIleiyKfginDAgZiGXRb56uHA/4K96WF9kXtOdrQFMkl7TE7fIbct7GcNnm5GMUEdAA/sOXbD8c2oXVVOWGh5ncESw9t2TBrij5SNo80AakEnO8QyEIy8Wa3A68zeBctBjs4ENAPltl3rrP61TFyP03Z2oUg38=",
            "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=L5FTZgkolnhiUg0Xosa+w8/3koKzmkYc03vOzLfJNVM=;\n b=ZVjlv+Q8my15tq4/S7dW3DpkA9lzV7GYbs5sAMbzOA7JrNeNu0+SvU7WGiZFl1wLfqq2IxvhXT/FhGNAV5S1z8Bd5ZOP4HGeyTdM5zfYBh59wGVM8YBc4xTbq6hKDi/OiKnudUJQ2fJ7OdD1MlqxcLrP/8zGvtA9C/ITzDGLZoeuW242M8O/gaDHAywHhNodLN/4ZOigHLONVAWi9bTR3D2zvfq0N61M0f+XloVdIbZiAqY2F9ppGh3MLMQKL2rmME5OQSMPh1kxAQN/ui6pquz9X7KclIE6SlwRb6nbK65RC+F/8fDydOoA5Y9XMm54PeajPRK8hbGZaX4Ib5pthA=="
        ],
        "ARC-Authentication-Results": [
            "i=2; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=nxp.com;\n spf=pass smtp.mailfrom=nxp.com;\n dkim=pass (2048-bit key) header.d=nxp.com header.i=@nxp.com\n header.b=l6eGBI1t; arc=fail smtp.client-ip=52.101.72.49",
            "i=1; mx.microsoft.com 1; spf=pass\n smtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com; dkim=pass\n header.d=nxp.com; arc=none"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=L5FTZgkolnhiUg0Xosa+w8/3koKzmkYc03vOzLfJNVM=;\n b=l6eGBI1tAZ86AM6ek5GimhY88IGFm35jl66a1YueCfQDakgtmFfo1UeKCMkVoinLZ2XpZVUoDWdsrPTJP+5I0SL3Da7OXtdQDibEz3DxxI/0Gyy95FwRZH6X0snZI0y2z09AQ97nZRfRlAEXosNLzv5BzTT7XcVBdScip9pe24+1cxnWIpJw8GIlMtPGpljkvBh+rvSurtOLMdm7TsF3FN8IYbkxRo1pwtzKYe4HS5cSt+pg+g5SfgUD2e/+yVSHaI+P0I8iwcmdg+upUQu3MOZsQk1iI35x8coIh5Qb8e7ew7jdDfLQ7wpqtL/rTk3SsZYb3fTKzCJ70tH3CwiSng==",
        "From": "Shenwei Wang <shenwei.wang@nxp.com>",
        "To": "Linus Walleij <linusw@kernel.org>,\n\tBartosz Golaszewski <brgl@kernel.org>,\n\tJonathan Corbet <corbet@lwn.net>,\n\tRob Herring <robh@kernel.org>,\n\tKrzysztof Kozlowski <krzk+dt@kernel.org>,\n\tConor Dooley <conor+dt@kernel.org>,\n\tBjorn Andersson <andersson@kernel.org>,\n\tMathieu Poirier <mathieu.poirier@linaro.org>,\n\tFrank Li <Frank.Li@nxp.com>,\n\tSascha Hauer <s.hauer@pengutronix.de>",
        "Cc": "Shuah Khan <skhan@linuxfoundation.org>,\n\tlinux-gpio@vger.kernel.org,\n\tlinux-doc@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org,\n\tPengutronix Kernel Team <kernel@pengutronix.de>,\n\tFabio Estevam <festevam@gmail.com>,\n\tShenwei Wang <shenwei.wang@nxp.com>,\n\tPeng Fan <peng.fan@nxp.com>,\n\tdevicetree@vger.kernel.org,\n\tlinux-remoteproc@vger.kernel.org,\n\timx@lists.linux.dev,\n\tlinux-arm-kernel@lists.infradead.org,\n\tlinux-imx@nxp.com,\n\tarnaud.pouliquen@foss.st.com,\n\tBartosz Golaszewski <brgl@bgdev.pl>,\n\tAndrew Lunn <andrew@lunn.ch>",
        "Subject": "[PATCH v8 3/4] gpio: rpmsg: add generic rpmsg GPIO driver",
        "Date": "Thu, 12 Feb 2026 15:36:55 -0600",
        "Message-ID": "<20260212213656.662437-4-shenwei.wang@nxp.com>",
        "X-Mailer": "git-send-email 2.43.0",
        "In-Reply-To": "<20260212213656.662437-1-shenwei.wang@nxp.com>",
        "References": "<20260212213656.662437-1-shenwei.wang@nxp.com>",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-ClientProxiedBy": "PH7P223CA0001.NAMP223.PROD.OUTLOOK.COM\n (2603:10b6:510:338::22) To PAXPR04MB9185.eurprd04.prod.outlook.com\n (2603:10a6:102:231::11)",
        "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",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "PAXPR04MB9185:EE_|PA4PR04MB7936:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "c2524540-3a86-42cf-2949-08de6a7f0026",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "\n\tBCL:0;ARA:13230040|19092799006|366016|7416014|52116014|376014|1800799024|921020|38350700014;",
        "X-Microsoft-Antispam-Message-Info": "\n gT4xm1st707P+NrK01+iyCXnEedovdtHtSu+ryJEmYUdM/sW5h2JkTAn+VakfZbwCzCnEPFd7sygQVH5kpWMMJ2Qe8EAe8kmpDmXu2SukNvGGkX3t2lQoHOQm2kLz0Q9jnpjCu7+xS5srcB0Ox5j72cEt38YyrLN7ty4d7lC40LFwfwj3YlkRkSIT4DWlpjqeFLq/JeRsLlTcl4etWNm2jwuZTTZJAlarEv1Te0ugPGq1WTR8CzhXye/LMSj8vuqojAR/322JHIuF3Z7+lZ7zvlT5rHff4Xu1wZlWNGyIsBzPkTdnb/vvpNH0pkX/hxBo9KoWuUzjRu9QVS6datNVBYjXeRLbuOqDONrHyyiqwYOwWCR2x576P4RKP38OejbklO+Ne2UDqgOHYrtKBGLhTf3+7BbmpZmgRlCMFnQbkr+/5aD6vlmqNrETlx7AGupfej4sEcuCHhWSSICxFL038XZCzuI4S9MmdySi/BTbyKCdNzgUlLzweQ99iSPnwmq52nQFIBD/QzezI9bf7qA5LejyuMqCyuq96JLsHQ75eaknrnB8rc0Lc5xWAbBHykEbXq5P95xQmXSgK023msTdwdnwKGblV6kF05kBGGDfxbk2dE2wYF8RSvLX1LTNZMPx0P63WsLm5q3254WqfWkec7cOVsN7vfoKuD7MhnAY8rqQKxul4S6XKQfkmj5/84nGxErQkNKmir/9Gnx317YXG92QDbfWxGJE15xCEMERQutl/bsAKqfm7hXe9494vm6ljz4DA/mlCvvfOJYaUqqW4T0fgz6tELjG6ZMVDJ0KLH5VR2JM2JhupVaSyN/usr2L/wjoIsxed/mzJT6EIVzLpVFTx+QJlnfVopzNAxKShORexsfDmmg2JBdF3C6FOggI0fUa7xKnr/rofRzxT0LwGkrgEXUMlH1RV0Hi4CfaJSK9yxaoHIay7vOG9uDDy4nwlYb2yGTdEDCt5Lfg6E7LNxsrhApRSg+8OwQ12//+jk4WVBFp7/NF3tr6bF9fgksIMwu+o6NG42tFDsbCCdcJvFctYwFU+0cOQS4I0lAkhSGv2Yh709ntnxa/XwEzhpBkCcGdsCZyuOFw8a5m1TjzdeFG41uGv+gE9pPUqFz2aW3SeyocejbtDFs2SvOljabPVz7Tlyrt9UxzJUOPEbmZY1pgASb0ncHGHspp8eZWqjCoDBAuvin6TFpM8Pq80r7lnAUry0bm8uViELWccgmvIYP/hqo2mGx0B9HheRE7fE5lDTAx7amL6vBUxyy8pjgYjaLmJ08mMFrUlhwehNLCCQCg4ECcdXT7XJHMAkPund/q/KFAukOnQpMSSZ07cMTEjolt2vGbmqSIeiFnG8j96BdSugfAKCr/hWuMhB+7dT5aDaZ4D+b3efKZPtBvT55IVVHTjvMFFZBV45nquPospcOary4UyURS7w3J20G2DVLOvs/lVLPrHOJ4FPTMEMpK7zD8OtJP50tEg2EH0cDDY0AUlIoreuEe9j73GiL4mRI2cnhrdqOVjvXm29F84Sn7Rwq6V8KKjtsvOm9GthUw5hXX06lP0wC6+bWUtGjAe0etLPerAI58Jkw8sd/YvPS+ZKeJWSdi9aocv6lfSPsmH8BVGjbDWcIjX3n31leKqlOAc4YGu+mFA6lV4o3ZD8r",
        "X-Forefront-Antispam-Report": "\n\tCIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PAXPR04MB9185.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(19092799006)(366016)(7416014)(52116014)(376014)(1800799024)(921020)(38350700014);DIR:OUT;SFP:1101;",
        "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1",
        "X-MS-Exchange-AntiSpam-MessageData-0": "\n f+s40sOzMBGwc/Q0bGtm1WW1UdJV8OMEq79lUI3Xsh9pjB3tViPt32XV7hezwWqullcbwnF8v7J2N2X86dh3yT/uTQEbTlopxnqcz6/bdJU3llaIMZxPu69OF+ffrbUpFUeoYZAz/choFieK/v4cMiAkvhXlTTJXWdORQhHryNWz/6hTiDn50U0kQ5YHC70Kj2ic8qLpdZ/mwRq5/MZM2Re93lK+E0Wr0aj5E1Mc0ElUrzmedhgdatb1gn01tAV78QALJiszJAeJ40qVtRHgth/TInlh2415vCmMzD2lU7KTqWOMHTJ759KLckV5RqUGRe9eE0y1crysf5NBYuPRDEfYgRddUJJn3ZZ+uqA4eG2Z+Sd99L4TFYpHnZWHLq/W5qdE3DOZSpgON7Mt8lYO4RMebMF9rQ8WtPDavNbp2VFRLp2QKtKXu1+PQTAIXNIVeEO3FaC6ZofA4Kh6kHVVcxJqzYQaLUgckDuP06tKp+LyutZXJ3vv6vAxgcxi0HWL353YIUPvInRXuNIskK7taQBo+2qyCaToxAC1Nc0sIvJlwLaftEAiYh3EBVDpBMS5xQ1ihHKXdj08L3Xq8VLecC3ve6+VPzZTNujc44xq1xYDKECNYcdM6L1GmEStmphy/SS1q3U/9uGZaEnZAhxIqOWeE35UIXobnNFbP73VwceI1EOIDkrPoUZ/JgRSFtGXZJ5sCl1+Xj3WVl/+JJU05reGYgVtznu3svKDFzGcctzYVQf2BHr4F3S18ShxfEjiZDAfcX+uOq/Zq6FLwzSff6ceq32ck9HZrdjJX6ICR3VtPAfO0jyNdEtOTHRFXSKtajBKOpDf30CT5vYj4RSu0LovPmCIDJLdxFvx4ANl6jFv5CXAlaxK3A5+MyWQhtFO3C2JEcJkgpe7BS2VRYCtopbDIoORa7aEL3PLY4hMKVoWsG/Bm7VEqRynDbhryj8cakrMYpfwBUqhl0Q4rehM18hfLw7sGpmI/xkWNcPmgSuJSD0u8QSLnbqvjSooHBgZWiBmwnZUm/zhbKKHRttesuii514v+bI1FUXFlaEaaOhD6Bv7J//8GZF79izyEaq8GSI5/CZDrC/t9/wvyKRIzS5riuNRsNPLn13N56u59PH9hxPeJvpxO36xM0q/0AQYXk7Y3HJ133OSKxWCXP9mAXvk/OTryyY7lvZmqUgOLyRBzhFQCpWpUIDmufIeG0MNvEUYZeoS2hns42cGRnDT8GFzt3fAVoi7h8u8WMkoOFu09h+tWg5DSsvSME+QK1O8oREb8SG5vtcKTQl1jejYG0y6UWlzcqbjQcqc3004alaOG0ZR1SJPB1RqNWHWP1D/VdtEV6OrBE8A51RXxk7afHKkii/1YwDkOEY92LTXk40z2du0rP580A2nDCTEPhkNO2dy9/k/MFrGMWooNcigYHnEWetes6mtuizAxDaIZLi+8X8ilIGFyjrgszzKmM1/gPjk02WXpxSkzjOEMAo7A0C3iw8/Q2zepEPHVZ6JR+jwHeyxHp4AF84jxNDMm1mUyzsTk0jbKd555ciBXg5gUsmaNuVVNTz6t6xwOfObXRKsUun6pTUFiN27eM09R0VimmTr8m1IaYZrCcNCx6wWOPmf+T9YvdFBAEwW9RKca7dJrOWtZogqhiBw8fm7VbJaLE6ozrDyQSKm/79Ittxa3SgvA1ijohB79Nul4Ds9orJSvnducDLJPrEBiSlp9evIpT0IFQYIaEOdtCM4Ew0K4Q==",
        "X-OriginatorOrg": "nxp.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n c2524540-3a86-42cf-2949-08de6a7f0026",
        "X-MS-Exchange-CrossTenant-AuthSource": "PAXPR04MB9185.eurprd04.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Internal",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "12 Feb 2026 21:38:03.2311\n (UTC)",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "Hosted",
        "X-MS-Exchange-CrossTenant-Id": "686ea1d3-bc2b-4c6f-a92c-d99c5c301635",
        "X-MS-Exchange-CrossTenant-MailboxType": "HOSTED",
        "X-MS-Exchange-CrossTenant-UserPrincipalName": "\n Zy3P4MF51SXkaOorn6MzoQaFAXTuf9DxfWlxU+d7AJjWg5lQO8hMfSoAEYxC1rS8jLoFn1K5ft5W13l6a3vrBw==",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "PA4PR04MB7936"
    },
    "content": "On an AMP platform, the system may include two processors:\n\t- An MCU running an RTOS\n\t- An MPU running Linux\n\nThese processors communicate via the RPMSG protocol.\nThe driver implements the standard GPIO interface, allowing\nthe Linux side to control GPIO controllers which reside in\nthe remote processor via RPMSG protocol.\n\nCc: Bartosz Golaszewski <brgl@bgdev.pl>\nCc: Andrew Lunn <andrew@lunn.ch>\nSigned-off-by: Shenwei Wang <shenwei.wang@nxp.com>\n---\n drivers/gpio/Kconfig      |  17 ++\n drivers/gpio/Makefile     |   1 +\n drivers/gpio/gpio-rpmsg.c | 588 ++++++++++++++++++++++++++++++++++++++\n 3 files changed, 606 insertions(+)\n create mode 100644 drivers/gpio/gpio-rpmsg.c",
    "diff": "diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig\nindex b45fb799e36c..3179a54f0634 100644\n--- a/drivers/gpio/Kconfig\n+++ b/drivers/gpio/Kconfig\n@@ -1892,6 +1892,23 @@ config GPIO_SODAVILLE\n \n endmenu\n \n+menu \"RPMSG GPIO drivers\"\n+\tdepends on RPMSG\n+\n+config GPIO_RPMSG\n+\ttristate \"Generic RPMSG GPIO support\"\n+\tdepends on REMOTEPROC\n+\tselect GPIOLIB_IRQCHIP\n+\tdefault REMOTEPROC\n+\thelp\n+\t  Say yes here to support the generic GPIO functions over the RPMSG\n+\t  bus. Currently supported devices: i.MX7ULP, i.MX8ULP, i.MX8x, and\n+\t  i.MX9x.\n+\n+\t  If unsure, say N.\n+\n+endmenu\n+\n menu \"SPI GPIO expanders\"\n \tdepends on SPI_MASTER\n \ndiff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile\nindex c05f7d795c43..501aba56ad68 100644\n--- a/drivers/gpio/Makefile\n+++ b/drivers/gpio/Makefile\n@@ -158,6 +158,7 @@ obj-$(CONFIG_GPIO_RDC321X)\t\t+= gpio-rdc321x.o\n 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_RPMSG)\t\t+= gpio-rpmsg.o\n obj-$(CONFIG_GPIO_RTD)\t\t\t+= gpio-rtd.o\n obj-$(CONFIG_ARCH_SA1100)\t\t+= gpio-sa1100.o\n obj-$(CONFIG_GPIO_SAMA5D2_PIOBU)\t+= gpio-sama5d2-piobu.o\ndiff --git a/drivers/gpio/gpio-rpmsg.c b/drivers/gpio/gpio-rpmsg.c\nnew file mode 100644\nindex 000000000000..163f51fd45b5\n--- /dev/null\n+++ b/drivers/gpio/gpio-rpmsg.c\n@@ -0,0 +1,588 @@\n+// SPDX-License-Identifier: GPL-2.0-only\n+/*\n+ * Copyright 2026 NXP\n+ *\n+ * The driver exports a standard gpiochip interface to control\n+ * the GPIO controllers via RPMSG on a remote processor.\n+ */\n+#include <linux/completion.h>\n+#include <linux/device.h>\n+#include <linux/err.h>\n+#include <linux/gpio/driver.h>\n+#include <linux/init.h>\n+#include <linux/irqdomain.h>\n+#include <linux/mod_devicetable.h>\n+#include <linux/module.h>\n+#include <linux/mutex.h>\n+#include <linux/of.h>\n+#include <linux/of_device.h>\n+#include <linux/of_platform.h>\n+#include <linux/platform_device.h>\n+#include <linux/remoteproc.h>\n+#include <linux/rpmsg.h>\n+\n+#define RPMSG_GPIO_ID\t\t5\n+#define RPMSG_VENDOR\t\t1\n+#define RPMSG_VERSION\t\t0\n+\n+#define GPIOS_PER_PORT_DEFAULT\t32\n+#define RPMSG_TIMEOUT\t\t1000\n+\n+/* GPIO RPMSG header type */\n+#define GPIO_RPMSG_SETUP\t0\n+#define GPIO_RPMSG_REPLY\t1\n+#define GPIO_RPMSG_NOTIFY\t2\n+\n+/* GPIO Interrupt trigger type */\n+#define GPIO_RPMSG_TRI_IGNORE\t\t0\n+#define GPIO_RPMSG_TRI_RISING\t\t1\n+#define GPIO_RPMSG_TRI_FALLING\t\t2\n+#define GPIO_RPMSG_TRI_BOTH_EDGE\t3\n+#define GPIO_RPMSG_TRI_LOW_LEVEL\t4\n+#define GPIO_RPMSG_TRI_HIGH_LEVEL\t5\n+\n+/* GPIO RPMSG commands */\n+#define GPIO_RPMSG_INPUT_INIT\t\t0\n+#define GPIO_RPMSG_OUTPUT_INIT\t\t1\n+#define GPIO_RPMSG_INPUT_GET\t\t2\n+#define GPIO_RPMSG_DIRECTION_GET\t3\n+\n+#define MAX_PORT_PER_CHANNEL    10\n+\n+/*\n+ * @rproc_name: the name of the remote proc.\n+ * @channel_devices: an array of the devices related to the rpdev.\n+ */\n+struct rpdev_drvdata {\n+\tconst char *rproc_name;\n+\tvoid *channel_devices[MAX_PORT_PER_CHANNEL];\n+};\n+\n+struct gpio_rpmsg_head {\n+\tu8 id;\t\t/* Message ID Code */\n+\tu8 vendor;\t/* Vendor ID number */\n+\tu8 version;\t/* Vendor-specific version number */\n+\tu8 type;\t/* Message type */\n+\tu8 cmd;\t\t/* Command code */\n+\tu8 reserved[5];\n+} __packed;\n+\n+struct gpio_rpmsg_packet {\n+\tstruct gpio_rpmsg_head header;\n+\tu8 pin_idx;\n+\tu8 port_idx;\n+\tunion {\n+\t\tu8 event;\n+\t\tu8 retcode;\n+\t\tu8 value;\n+\t} out;\n+\tunion {\n+\t\tu8 wakeup;\n+\t\tu8 value;\n+\t} in;\n+} __packed __aligned(8);\n+\n+struct gpio_rpmsg_pin {\n+\tu8 irq_shutdown;\n+\tu8 irq_unmask;\n+\tu8 irq_mask;\n+\tu32 irq_wake_enable;\n+\tu32 irq_type;\n+\tstruct gpio_rpmsg_packet msg;\n+};\n+\n+struct gpio_rpmsg_info {\n+\tstruct rpmsg_device *rpdev;\n+\tstruct gpio_rpmsg_packet *reply_msg;\n+\tstruct completion cmd_complete;\n+\tstruct mutex lock;\n+\tvoid **port_store;\n+};\n+\n+struct rpmsg_gpio_port {\n+\tstruct gpio_chip gc;\n+\tstruct gpio_rpmsg_pin gpio_pins[GPIOS_PER_PORT_DEFAULT];\n+\tstruct gpio_rpmsg_info info;\n+\tu32 ngpios;\n+\tu32 idx;\n+};\n+\n+static int gpio_send_message(struct rpmsg_gpio_port *port,\n+\t\t\t     struct gpio_rpmsg_packet *msg,\n+\t\t\t     bool sync)\n+{\n+\tstruct gpio_rpmsg_info *info = &port->info;\n+\tint err;\n+\n+\treinit_completion(&info->cmd_complete);\n+\terr = rpmsg_send(info->rpdev->ept, msg, sizeof(struct gpio_rpmsg_packet));\n+\tif (err) {\n+\t\tdev_err(&info->rpdev->dev, \"rpmsg_send failed: %d\\n\", err);\n+\t\treturn err;\n+\t}\n+\n+\tif (sync) {\n+\t\terr = wait_for_completion_timeout(&info->cmd_complete,\n+\t\t\t\t\t\t  msecs_to_jiffies(RPMSG_TIMEOUT));\n+\t\tif (err == 0) {\n+\t\t\tdev_err(&info->rpdev->dev, \"rpmsg_send timeout!\\n\");\n+\t\t\treturn -ETIMEDOUT;\n+\t\t}\n+\n+\t\tif (info->reply_msg->out.retcode != 0) {\n+\t\t\tdev_err(&info->rpdev->dev, \"remote core replies an error: %d!\\n\",\n+\t\t\t\tinfo->reply_msg->out.retcode);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\t/* copy the reply message */\n+\t\tmemcpy(&port->gpio_pins[info->reply_msg->pin_idx].msg,\n+\t\t       info->reply_msg, sizeof(*info->reply_msg));\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static struct gpio_rpmsg_packet *gpio_setup_msg_common(struct rpmsg_gpio_port *port,\n+\t\t\t\t\t\t       unsigned int offset,\n+\t\t\t\t\t\t       u8 cmd)\n+{\n+\tstruct gpio_rpmsg_packet *msg = &port->gpio_pins[offset].msg;\n+\n+\tmemset(msg, 0, sizeof(struct gpio_rpmsg_packet));\n+\tmsg->header.id = RPMSG_GPIO_ID;\n+\tmsg->header.vendor = RPMSG_VENDOR;\n+\tmsg->header.version = RPMSG_VERSION;\n+\tmsg->header.type = GPIO_RPMSG_SETUP;\n+\tmsg->header.cmd = cmd;\n+\tmsg->pin_idx = offset;\n+\tmsg->port_idx = port->idx;\n+\n+\treturn msg;\n+}\n+\n+static int rpmsg_gpio_get(struct gpio_chip *gc, unsigned int gpio)\n+{\n+\tstruct rpmsg_gpio_port *port = gpiochip_get_data(gc);\n+\tstruct gpio_rpmsg_packet *msg;\n+\tint ret;\n+\n+\tguard(mutex)(&port->info.lock);\n+\n+\tmsg = gpio_setup_msg_common(port, gpio, GPIO_RPMSG_INPUT_GET);\n+\n+\tret = gpio_send_message(port, msg, true);\n+\tif (!ret)\n+\t\tret = !!port->gpio_pins[gpio].msg.in.value;\n+\n+\treturn ret;\n+}\n+\n+static int rpmsg_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)\n+{\n+\tstruct rpmsg_gpio_port *port = gpiochip_get_data(gc);\n+\tstruct gpio_rpmsg_packet *msg;\n+\tint ret;\n+\n+\tguard(mutex)(&port->info.lock);\n+\n+\tmsg = gpio_setup_msg_common(port, gpio, GPIO_RPMSG_DIRECTION_GET);\n+\n+\tret = gpio_send_message(port, msg, true);\n+\tif (!ret)\n+\t\tret = !!port->gpio_pins[gpio].msg.in.value;\n+\n+\treturn ret;\n+}\n+\n+static int rpmsg_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio)\n+{\n+\tstruct rpmsg_gpio_port *port = gpiochip_get_data(gc);\n+\tstruct gpio_rpmsg_packet *msg;\n+\n+\tguard(mutex)(&port->info.lock);\n+\n+\tmsg = gpio_setup_msg_common(port, gpio, GPIO_RPMSG_INPUT_INIT);\n+\n+\treturn gpio_send_message(port, msg, true);\n+}\n+\n+static int rpmsg_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)\n+{\n+\tstruct rpmsg_gpio_port *port = gpiochip_get_data(gc);\n+\tstruct gpio_rpmsg_packet *msg;\n+\n+\tguard(mutex)(&port->info.lock);\n+\n+\tmsg = gpio_setup_msg_common(port, gpio, GPIO_RPMSG_OUTPUT_INIT);\n+\tmsg->out.value = val;\n+\n+\treturn gpio_send_message(port, msg, true);\n+}\n+\n+static int rpmsg_gpio_direction_output(struct gpio_chip *gc,\n+\t\t\t\t       unsigned int gpio,\n+\t\t\t\t       int val)\n+{\n+\treturn rpmsg_gpio_set(gc, gpio, val);\n+}\n+\n+static int gpio_rpmsg_irq_set_type(struct irq_data *d, u32 type)\n+{\n+\tstruct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);\n+\tu32 gpio_idx = d->hwirq;\n+\tint edge = 0;\n+\tint ret = 0;\n+\n+\tswitch (type) {\n+\tcase IRQ_TYPE_EDGE_RISING:\n+\t\tedge = GPIO_RPMSG_TRI_RISING;\n+\t\tirq_set_handler_locked(d, handle_simple_irq);\n+\t\tbreak;\n+\tcase IRQ_TYPE_EDGE_FALLING:\n+\t\tedge = GPIO_RPMSG_TRI_FALLING;\n+\t\tirq_set_handler_locked(d, handle_simple_irq);\n+\t\tbreak;\n+\tcase IRQ_TYPE_EDGE_BOTH:\n+\t\tedge = GPIO_RPMSG_TRI_BOTH_EDGE;\n+\t\tirq_set_handler_locked(d, handle_simple_irq);\n+\t\tbreak;\n+\tcase IRQ_TYPE_LEVEL_LOW:\n+\t\tedge = GPIO_RPMSG_TRI_LOW_LEVEL;\n+\t\tirq_set_handler_locked(d, handle_level_irq);\n+\t\tbreak;\n+\tcase IRQ_TYPE_LEVEL_HIGH:\n+\t\tedge = GPIO_RPMSG_TRI_HIGH_LEVEL;\n+\t\tirq_set_handler_locked(d, handle_level_irq);\n+\t\tbreak;\n+\tdefault:\n+\t\tret = -EINVAL;\n+\t\tirq_set_handler_locked(d, handle_bad_irq);\n+\t\tbreak;\n+\t}\n+\n+\tport->gpio_pins[gpio_idx].irq_type = edge;\n+\n+\treturn ret;\n+}\n+\n+static int gpio_rpmsg_irq_set_wake(struct irq_data *d, u32 enable)\n+{\n+\tstruct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);\n+\tu32 gpio_idx = d->hwirq;\n+\n+\tport->gpio_pins[gpio_idx].irq_wake_enable = enable;\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * This unmask/mask function is invoked in two situations:\n+ *   - when an interrupt is being set up, and\n+ *   - after an interrupt has occurred.\n+ *\n+ * The GPIO driver does not access hardware registers directly.\n+ * Instead, it caches all relevant information locally, and then sends\n+ * the accumulated state to the remote system at this stage.\n+ */\n+static void gpio_rpmsg_unmask_irq(struct irq_data *d)\n+{\n+\tstruct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);\n+\tu32 gpio_idx = d->hwirq;\n+\n+\tport->gpio_pins[gpio_idx].irq_unmask = 1;\n+}\n+\n+static void gpio_rpmsg_mask_irq(struct irq_data *d)\n+{\n+\tstruct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);\n+\tu32 gpio_idx = d->hwirq;\n+\n+\t/*\n+\t * When an interrupt occurs, the remote system masks the interrupt\n+\t * and then sends a notification to Linux. After Linux processes\n+\t * that notification, it sends an RPMsg command back to the remote\n+\t * system to unmask the interrupt again.\n+\t */\n+\tport->gpio_pins[gpio_idx].irq_mask = 1;\n+}\n+\n+static void gpio_rpmsg_irq_shutdown(struct irq_data *d)\n+{\n+\tstruct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);\n+\tu32 gpio_idx = d->hwirq;\n+\n+\tport->gpio_pins[gpio_idx].irq_shutdown = 1;\n+}\n+\n+static void gpio_rpmsg_irq_bus_lock(struct irq_data *d)\n+{\n+\tstruct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);\n+\n+\tmutex_lock(&port->info.lock);\n+}\n+\n+static void gpio_rpmsg_irq_bus_sync_unlock(struct irq_data *d)\n+{\n+\tstruct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);\n+\tstruct gpio_rpmsg_packet *msg = NULL;\n+\tu32 gpio_idx = d->hwirq;\n+\n+\t/*\n+\t * For mask irq, do nothing here.\n+\t * The remote system will mask interrupt after an interrupt occurs,\n+\t * and then send a notify to Linux system.\n+\t * After Linux system dealt with the notify, it will send an rpmsg to\n+\t * the remote system to unmask this interrupt again.\n+\t */\n+\tif (port->gpio_pins[gpio_idx].irq_mask && !port->gpio_pins[gpio_idx].irq_unmask) {\n+\t\tport->gpio_pins[gpio_idx].irq_mask = 0;\n+\t\tmutex_unlock(&port->info.lock);\n+\t\treturn;\n+\t}\n+\n+\tmsg = gpio_setup_msg_common(port, gpio_idx, GPIO_RPMSG_INPUT_INIT);\n+\n+\tif (port->gpio_pins[gpio_idx].irq_shutdown) {\n+\t\tmsg->out.event = GPIO_RPMSG_TRI_IGNORE;\n+\t\tmsg->in.wakeup = 0;\n+\t\tport->gpio_pins[gpio_idx].irq_shutdown = 0;\n+\t} else {\n+\t\t/* if not set irq type, then use low level as trigger type */\n+\t\tmsg->out.event = port->gpio_pins[gpio_idx].irq_type;\n+\t\tif (!msg->out.event)\n+\t\t\tmsg->out.event = GPIO_RPMSG_TRI_LOW_LEVEL;\n+\t\tif (port->gpio_pins[gpio_idx].irq_unmask) {\n+\t\t\tmsg->in.wakeup = 0;\n+\t\t\tport->gpio_pins[gpio_idx].irq_unmask = 0;\n+\t\t} else /* irq set wake */\n+\t\t\tmsg->in.wakeup = port->gpio_pins[gpio_idx].irq_wake_enable;\n+\t}\n+\n+\tgpio_send_message(port, msg, false);\n+\tmutex_unlock(&port->info.lock);\n+}\n+\n+static const struct irq_chip gpio_rpmsg_irq_chip = {\n+\t.irq_mask = gpio_rpmsg_mask_irq,\n+\t.irq_unmask = gpio_rpmsg_unmask_irq,\n+\t.irq_set_wake = gpio_rpmsg_irq_set_wake,\n+\t.irq_set_type = gpio_rpmsg_irq_set_type,\n+\t.irq_shutdown = gpio_rpmsg_irq_shutdown,\n+\t.irq_bus_lock = gpio_rpmsg_irq_bus_lock,\n+\t.irq_bus_sync_unlock = gpio_rpmsg_irq_bus_sync_unlock,\n+\t.flags = IRQCHIP_IMMUTABLE,\n+};\n+\n+static void rpmsg_gpio_remove_action(void *data)\n+{\n+\tstruct rpmsg_gpio_port *port = data;\n+\n+\tport->info.port_store[port->idx] = NULL;\n+}\n+\n+static int rpmsg_gpiochip_register(struct rpmsg_device *rpdev, struct device_node *np)\n+{\n+\tstruct rpdev_drvdata *drvdata = dev_get_drvdata(&rpdev->dev);\n+\tstruct rpmsg_gpio_port *port;\n+\tstruct gpio_irq_chip *girq;\n+\tstruct gpio_chip *gc;\n+\tint ret;\n+\n+\tport = devm_kzalloc(&rpdev->dev, sizeof(*port), GFP_KERNEL);\n+\tif (!port)\n+\t\treturn -ENOMEM;\n+\n+\tret = of_property_read_u32(np, \"reg\", &port->idx);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (port->idx >= MAX_PORT_PER_CHANNEL)\n+\t\treturn -EINVAL;\n+\n+\tret = devm_mutex_init(&rpdev->dev, &port->info.lock);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = of_property_read_u32(np, \"ngpios\", &port->ngpios);\n+\tif (ret)\n+\t\tport->ngpios = GPIOS_PER_PORT_DEFAULT;\n+\n+\tinit_completion(&port->info.cmd_complete);\n+\tport->info.reply_msg = devm_kzalloc(&rpdev->dev,\n+\t\t\t\t\t    sizeof(struct gpio_rpmsg_packet),\n+\t\t\t\t\t    GFP_KERNEL);\n+\tport->info.port_store = drvdata->channel_devices;\n+\tport->info.port_store[port->idx] = port;\n+\tport->info.rpdev = rpdev;\n+\n+\tgc = &port->gc;\n+\tgc->owner = THIS_MODULE;\n+\tgc->parent = &rpdev->dev;\n+\tgc->fwnode = of_fwnode_handle(np);\n+\tgc->ngpio = port->ngpios;\n+\tgc->base = -1;\n+\tgc->label = devm_kasprintf(&rpdev->dev, GFP_KERNEL, \"%s-gpio%d\",\n+\t\t\t\t   drvdata->rproc_name, port->idx);\n+\n+\tgc->direction_input = rpmsg_gpio_direction_input;\n+\tgc->direction_output = rpmsg_gpio_direction_output;\n+\tgc->get_direction = rpmsg_gpio_get_direction;\n+\tgc->get = rpmsg_gpio_get;\n+\tgc->set = rpmsg_gpio_set;\n+\n+\tgirq = &gc->irq;\n+\tgpio_irq_chip_set_chip(girq, &gpio_rpmsg_irq_chip);\n+\tgirq->parent_handler = NULL;\n+\tgirq->num_parents = 0;\n+\tgirq->parents = NULL;\n+\tgirq->chip->name = devm_kasprintf(&rpdev->dev, GFP_KERNEL, \"%s-gpio%d\",\n+\t\t\t\t\t  drvdata->rproc_name, port->idx);\n+\n+\tret = devm_add_action_or_reset(&rpdev->dev, rpmsg_gpio_remove_action, port);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn devm_gpiochip_add_data(&rpdev->dev, gc, port);\n+}\n+\n+static const char *rpmsg_get_rproc_node_name(struct rpmsg_device *rpdev)\n+{\n+\tconst char *name = NULL;\n+\tstruct device_node *np;\n+\tstruct rproc *rproc;\n+\n+\trproc = rproc_get_by_child(&rpdev->dev);\n+\n+\tif (!rproc)\n+\t\treturn NULL;\n+\n+\tnp = of_node_get(rproc->dev.of_node);\n+\tif (!np && rproc->dev.parent)\n+\t\tnp = of_node_get(rproc->dev.parent->of_node);\n+\n+\tif (np) {\n+\t\tname = devm_kstrdup(&rpdev->dev, np->name, GFP_KERNEL);\n+\t\tof_node_put(np);\n+\t}\n+\n+\treturn name;\n+}\n+\n+static struct device_node *\n+rpmsg_get_channel_ofnode(struct rpmsg_device *rpdev, char *chan_name)\n+{\n+\tstruct device_node *np_chan = NULL, *np;\n+\tstruct rproc *rproc;\n+\n+\trproc = rproc_get_by_child(&rpdev->dev);\n+\tif (!rproc)\n+\t\treturn NULL;\n+\n+\tnp = of_node_get(rproc->dev.of_node);\n+\tif (!np && rproc->dev.parent)\n+\t\tnp = of_node_get(rproc->dev.parent->of_node);\n+\n+\tif (np) {\n+\t\t/* Balance the of_node_put() performed by of_find_node_by_name(). */\n+\t\tof_node_get(np);\n+\t\tnp_chan = of_find_node_by_name(np, chan_name);\n+\t\tof_node_put(np);\n+\t}\n+\n+\treturn np_chan;\n+}\n+\n+static int\n+rpmsg_gpio_channel_callback(struct rpmsg_device *rpdev, void *data,\n+\t\t\t    int len, void *priv, u32 src)\n+{\n+\tstruct gpio_rpmsg_packet *msg = data;\n+\tstruct rpmsg_gpio_port *port = NULL;\n+\tstruct rpdev_drvdata *drvdata;\n+\n+\tdrvdata = dev_get_drvdata(&rpdev->dev);\n+\tif (drvdata && msg && msg->port_idx < MAX_PORT_PER_CHANNEL)\n+\t\tport = drvdata->channel_devices[msg->port_idx];\n+\n+\tif (!port)\n+\t\treturn -ENODEV;\n+\n+\tif (msg->header.type == GPIO_RPMSG_REPLY) {\n+\t\t*port->info.reply_msg = *msg;\n+\t\tcomplete(&port->info.cmd_complete);\n+\t} else if (msg->header.type == GPIO_RPMSG_NOTIFY) {\n+\t\tgeneric_handle_domain_irq_safe(port->gc.irq.domain, msg->pin_idx);\n+\t} else\n+\t\tdev_err(&rpdev->dev, \"wrong command type!\\n\");\n+\n+\treturn 0;\n+}\n+\n+static int rpmsg_gpio_channel_probe(struct rpmsg_device *rpdev)\n+{\n+\tstruct device *dev = &rpdev->dev;\n+\tstruct rpdev_drvdata *drvdata;\n+\tstruct device_node *np;\n+\tint ret;\n+\n+\tif (!dev->of_node) {\n+\t\tnp = rpmsg_get_channel_ofnode(rpdev, rpdev->id.name);\n+\t\tif (np) {\n+\t\t\tdev->of_node = np;\n+\t\t\tset_primary_fwnode(dev, of_fwnode_handle(np));\n+\t\t}\n+\t\treturn -EPROBE_DEFER;\n+\t}\n+\n+\tdrvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);\n+\tif (!drvdata)\n+\t\treturn -ENOMEM;\n+\n+\tdrvdata->rproc_name = rpmsg_get_rproc_node_name(rpdev);\n+\tdev_set_drvdata(dev, drvdata);\n+\n+\tfor_each_child_of_node_scoped(dev->of_node, child) {\n+\t\tif (!of_device_is_available(child))\n+\t\t\tcontinue;\n+\n+\t\tif (!of_match_node(dev->driver->of_match_table, child))\n+\t\t\tcontinue;\n+\n+\t\tret = rpmsg_gpiochip_register(rpdev, child);\n+\t\tif (ret < 0)\n+\t\t\tdev_err(dev, \"Failed to register: %pOF\\n\", child);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static void rpmsg_gpio_channel_remove(struct rpmsg_device *rpdev)\n+{\n+\tdev_info(&rpdev->dev, \"rpmsg gpio channel driver is removed\\n\");\n+}\n+\n+static const struct of_device_id rpmsg_gpio_dt_ids[] = {\n+\t{ .compatible = \"rpmsg-gpio\" },\n+\t{ /* sentinel */ }\n+};\n+\n+static struct rpmsg_device_id rpmsg_gpio_channel_id_table[] = {\n+\t{ .name\t= \"rpmsg-io-channel\" },\n+\t{ },\n+};\n+MODULE_DEVICE_TABLE(rpmsg, rpmsg_gpio_channel_id_table);\n+\n+static struct rpmsg_driver rpmsg_gpio_channel_client = {\n+\t.drv.name\t= KBUILD_MODNAME,\n+\t.drv.of_match_table = rpmsg_gpio_dt_ids,\n+\t.id_table\t= rpmsg_gpio_channel_id_table,\n+\t.probe\t\t= rpmsg_gpio_channel_probe,\n+\t.callback\t= rpmsg_gpio_channel_callback,\n+\t.remove\t\t= rpmsg_gpio_channel_remove,\n+};\n+module_rpmsg_driver(rpmsg_gpio_channel_client);\n+\n+MODULE_AUTHOR(\"Shenwei Wang <shenwei.wang@nxp.com>\");\n+MODULE_DESCRIPTION(\"generic rpmsg gpio driver\");\n+MODULE_LICENSE(\"GPL\");\n",
    "prefixes": [
        "v8",
        "3/4"
    ]
}