get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2218093,
    "url": "http://patchwork.ozlabs.org/api/patches/2218093/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20260331113025.1566878-11-wei.fang@nxp.com/",
    "project": {
        "id": 2,
        "url": "http://patchwork.ozlabs.org/api/projects/2/?format=api",
        "name": "Linux PPC development",
        "link_name": "linuxppc-dev",
        "list_id": "linuxppc-dev.lists.ozlabs.org",
        "list_email": "linuxppc-dev@lists.ozlabs.org",
        "web_url": "https://github.com/linuxppc/wiki/wiki",
        "scm_url": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git",
        "webscm_url": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/",
        "list_archive_url": "https://lore.kernel.org/linuxppc-dev/",
        "list_archive_url_format": "https://lore.kernel.org/linuxppc-dev/{}/",
        "commit_url_format": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/commit/?id={}"
    },
    "msgid": "<20260331113025.1566878-11-wei.fang@nxp.com>",
    "list_archive_url": "https://lore.kernel.org/linuxppc-dev/20260331113025.1566878-11-wei.fang@nxp.com/",
    "date": "2026-03-31T11:30:21",
    "name": "[v4,net-next,10/14] net: dsa: netc: introduce NXP NETC switch driver for i.MX94",
    "commit_ref": null,
    "pull_url": null,
    "state": "handled-elsewhere",
    "archived": false,
    "hash": "59ee1c7632736f824d4a3ecd64bef3fcbddb2645",
    "submitter": {
        "id": 84380,
        "url": "http://patchwork.ozlabs.org/api/people/84380/?format=api",
        "name": "Wei Fang",
        "email": "wei.fang@nxp.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20260331113025.1566878-11-wei.fang@nxp.com/mbox/",
    "series": [
        {
            "id": 498181,
            "url": "http://patchwork.ozlabs.org/api/series/498181/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=498181",
            "date": "2026-03-31T11:30:11",
            "name": "Add preliminary NETC switch support for i.MX94",
            "version": 4,
            "mbox": "http://patchwork.ozlabs.org/series/498181/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2218093/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2218093/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linuxppc-dev+bounces-19075-incoming=patchwork.ozlabs.org@lists.ozlabs.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "linuxppc-dev@lists.ozlabs.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=hHQjZ+c1;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org\n (client-ip=112.213.38.117; helo=lists.ozlabs.org;\n envelope-from=linuxppc-dev+bounces-19075-incoming=patchwork.ozlabs.org@lists.ozlabs.org;\n receiver=patchwork.ozlabs.org)",
            "lists.ozlabs.org;\n arc=pass smtp.remote-ip=\"2a01:111:f403:c201::3\" arc.chain=microsoft.com",
            "lists.ozlabs.org;\n dmarc=pass (p=none dis=none) header.from=nxp.com",
            "lists.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=hHQjZ+c1;\n\tdkim-atps=neutral",
            "lists.ozlabs.org;\n spf=permerror (SPF Permanent Error: Void lookup limit of 2 exceeded)\n smtp.mailfrom=nxp.com (client-ip=2a01:111:f403:c201::3;\n helo=as8pr04cu009.outbound.protection.outlook.com;\n envelope-from=wei.fang@nxp.com; receiver=lists.ozlabs.org)",
            "dkim=none (message not signed)\n header.d=none;dmarc=none action=none header.from=nxp.com;"
        ],
        "Received": [
            "from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117])\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 4flQrz24g3z1xtJ\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 31 Mar 2026 22:30:11 +1100 (AEDT)",
            "from boromir.ozlabs.org (localhost [127.0.0.1])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 4flQry6pKLz2ygf;\n\tTue, 31 Mar 2026 22:30:10 +1100 (AEDT)",
            "from AS8PR04CU009.outbound.protection.outlook.com\n (mail-westeuropeazlp170110003.outbound.protection.outlook.com\n [IPv6:2a01:111:f403:c201::3])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange secp256r1 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 4flQrv09KCz2yft\n\tfor <linuxppc-dev@lists.ozlabs.org>; Tue, 31 Mar 2026 22:30:07 +1100 (AEDT)",
            "from AM8PR04MB7284.eurprd04.prod.outlook.com (2603:10a6:20b:1dc::8)\n by PA1PR04MB11406.eurprd04.prod.outlook.com (2603:10a6:102:4f1::22) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9769.15; Tue, 31 Mar\n 2026 11:29:43 +0000",
            "from AM8PR04MB7284.eurprd04.prod.outlook.com\n ([fe80::9cd6:51bd:82b:98dc]) by AM8PR04MB7284.eurprd04.prod.outlook.com\n ([fe80::9cd6:51bd:82b:98dc%5]) with mapi id 15.20.9745.027; Tue, 31 Mar 2026\n 11:29:43 +0000"
        ],
        "ARC-Seal": [
            "i=2; a=rsa-sha256; d=lists.ozlabs.org; s=201707; t=1774956610;\n\tcv=pass;\n b=Nt5H/wFX05X+/IBJfhJeVW2gThwxTPh8tnoCnDdHOGwe1ML5LsZgjlfskFiRjVUIJ94j+lfbDW7YHcH2Y85nKJ+wBWEfOw6tyoYV5oipHbcFvBR5fuYeOUQMyowLTIefU1lmQlxtpaWBUA/1IBTVMLUVqEkH+Z8S2qppXreexxiJMXS7VVn02GPyqMrEIkwHIoUGp6kpWILxjMqrCx+JQf1laetof4Zy92xTsJ38gBQsI+QG7yNka89/2WKyddz+f23YQwGlHEMZYDbLLDHc5O6Z2zAv+0/cLJ9FM2/D/30Nc6r0XZ5Nw9WcxM+cGMUXUaWhwcYoyRZLSM3SHVNY3w==",
            "i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=lPANFX30Iuf1dvAw5G46emjv9DDMPJSj+AWDTH0lzuFpD6xh3JGpVlLuW7ohiY68eBFQrDaej8oRtgNffjJQbY1/HjPPgoaJQ0zl04w5AVH7A1SXumx8kOuT3h0TIKxejC6dyIUx24oGG05pbozym654KQbVN3Ej6uhUXbfyu7ubz/dVyr1azuhmjrEn7S7lfmyLgx+Huyu8T+fc3uve2liVL1aS5MXiIG72KMCqxpQcC9nJLgaUK17HChHOakmYb9FjZZ8WIh4nKq21p+HATvUt+M2CEb6+3YFGzs7O9G9JSBt0imn4Rg2mjqxebDE6T/LBJWf6l6CCMTx50ZuguA=="
        ],
        "ARC-Message-Signature": [
            "i=2; a=rsa-sha256; d=lists.ozlabs.org; s=201707;\n\tt=1774956610; c=relaxed/relaxed;\n\tbh=X1dgHJxgvxB3sgkSaW5LAamd/8yMB2Fqr9LJeflLSdQ=;\n\th=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:\n\t Content-Type:MIME-Version;\n b=mUyGiilLxoabhN9+3BabYVetgI1bpO8nL2EOfNZguF8kuEvUOv8NeSPABGTmBFBq1L8ttobCUvOKsp/WdHyHngnkfPUmN3/+wf+EG7xVvkOJNdNFrW7BoIHQempqkyocMtVs2NGDkNCpIvQuPyAKyAtGvdBFH7OzE93AXruUWzgNEoIjGh6TRq+CCuHSdPp6VLLwOViXTB+ayuys+Z9SUhzSq4vnYoWIeaB3ojHpFC6AMMlkSXhxE1EckdqiZ8K2LllobDebNJWUy+GPkgvwPGIwxA3+7TA8RVnMsxRRSMqq74FOwZHWDDTlq3xJgC5DZs9KX+5EkgImGlZE738ldA==",
            "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=X1dgHJxgvxB3sgkSaW5LAamd/8yMB2Fqr9LJeflLSdQ=;\n b=P445ga8aGKe8iJUIF21HFxEmOeUJlBmEVS7w8imNz1WsvhbRC47uVlGHerHk5BRsJMCtZFAsZmDfZEr9LkucG4KD/NSX9LSpclxUtA2PohIQLmMSYqD01vVA+NnLVAOjV4n/NZtlTvjNOcp0LgWthYmIX0Qb1/4KNnQzhhmj6OoxH+ZnkYedWKS8ureuxyzuOXOGnHxbVXp09AeLkzroPtasVA9YS+KcEOIWzrWnIJVNcUyT44Gzi3lIF72D91LENc30lFxHFaLgcKEO6gihdnX/T/1rjidvyf4Z8ewGhjrUq0dH3ykDKIQDusvqJWhHjnzrYMlecldTQ+sDSJZn8Q=="
        ],
        "ARC-Authentication-Results": [
            "i=2; lists.ozlabs.org;\n dmarc=pass (p=none dis=none) header.from=nxp.com; dkim=pass (2048-bit key;\n unprotected) header.d=nxp.com header.i=@nxp.com header.a=rsa-sha256\n header.s=selector1 header.b=hHQjZ+c1; dkim-atps=neutral;\n spf=permerror (client-ip=2a01:111:f403:c201::3;\n helo=as8pr04cu009.outbound.protection.outlook.com;\n envelope-from=wei.fang@nxp.com;\n receiver=lists.ozlabs.org) smtp.mailfrom=nxp.com",
            "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=X1dgHJxgvxB3sgkSaW5LAamd/8yMB2Fqr9LJeflLSdQ=;\n b=hHQjZ+c12uYZSK2PzHbGESh/HMliRbeyjJLPRkM0XWsyLZVXhea04XFR6ULX3ucX8Te7FCi84HwYZKTHuHavhe97z5Ti3eev1a8Kwz/w/ocnmstkSkkY2mx+m6CPYkPQ/xwk7Hj0M61S/k/8mX6uOJcgG59f3+kRPuOOeElsAbWZT+ZEKVUVbWF4krDpcuD7702b07cMgwjpFsB7kG38tyOfozeVT3LV40VfTr73BN/TLZ8FMZMhVtxQNDfO05kBkLV1Xcbtob+fP2jfHFr2/GdHCCgnIGBRm2IvL3b2eUjuS/kkAO5ksAJjJlonKGbXxk0eeCNRdSIqUzAYEL6mAg==",
        "From": "Wei Fang <wei.fang@nxp.com>",
        "To": "claudiu.manoil@nxp.com,\n\tvladimir.oltean@nxp.com,\n\txiaoning.wang@nxp.com,\n\tandrew+netdev@lunn.ch,\n\tdavem@davemloft.net,\n\tedumazet@google.com,\n\tkuba@kernel.org,\n\tpabeni@redhat.com,\n\trobh@kernel.org,\n\tkrzk+dt@kernel.org,\n\tconor+dt@kernel.org,\n\tf.fainelli@gmail.com,\n\tfrank.li@nxp.com,\n\tchleroy@kernel.org,\n\thorms@kernel.org,\n\tlinux@armlinux.org.uk,\n\tandrew@lunn.ch",
        "Cc": "netdev@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org,\n\tdevicetree@vger.kernel.org,\n\tlinuxppc-dev@lists.ozlabs.org,\n\tlinux-arm-kernel@lists.infradead.org,\n\timx@lists.linux.dev",
        "Subject": "[PATCH v4 net-next 10/14] net: dsa: netc: introduce NXP NETC switch\n driver for i.MX94",
        "Date": "Tue, 31 Mar 2026 19:30:21 +0800",
        "Message-Id": "<20260331113025.1566878-11-wei.fang@nxp.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20260331113025.1566878-1-wei.fang@nxp.com>",
        "References": "<20260331113025.1566878-1-wei.fang@nxp.com>",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-ClientProxiedBy": "MA5P287CA0151.INDP287.PROD.OUTLOOK.COM\n (2603:1096:a01:1d7::14) To AM8PR04MB7284.eurprd04.prod.outlook.com\n (2603:10a6:20b:1dc::8)",
        "X-Mailing-List": "linuxppc-dev@lists.ozlabs.org",
        "List-Id": "<linuxppc-dev.lists.ozlabs.org>",
        "List-Help": "<mailto:linuxppc-dev+help@lists.ozlabs.org>",
        "List-Owner": "<mailto:linuxppc-dev+owner@lists.ozlabs.org>",
        "List-Post": "<mailto:linuxppc-dev@lists.ozlabs.org>",
        "List-Archive": "<https://lore.kernel.org/linuxppc-dev/>,\n  <https://lists.ozlabs.org/pipermail/linuxppc-dev/>",
        "List-Subscribe": "<mailto:linuxppc-dev+subscribe@lists.ozlabs.org>,\n  <mailto:linuxppc-dev+subscribe-digest@lists.ozlabs.org>,\n  <mailto:linuxppc-dev+subscribe-nomail@lists.ozlabs.org>",
        "List-Unsubscribe": "<mailto:linuxppc-dev+unsubscribe@lists.ozlabs.org>",
        "Precedence": "list",
        "MIME-Version": "1.0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "AM8PR04MB7284:EE_|PA1PR04MB11406:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "8360614a-8c01-406c-7bcb-08de8f18cdb3",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "\n\tBCL:0;ARA:13230040|19092799006|376014|52116014|366016|7416014|1800799024|18002099003|56012099003|22082099003|38350700014|921020;",
        "X-Microsoft-Antispam-Message-Info": "\n\tjehfegBzqcAZMn21t4fMN00lE0FV6SDIkHwE5ZOzIiuZZ8pr45t8HEIILwrEbh9Zt+ItX+tPCg5khzWMN86PMz0LyknOMmZuMdwnupwgIgJwu5PAYuCbaCuuMJIUuNvMCzs43yuqEUnw16rB9oSi2zwTVjlhYlSu5chAwe48LkU/iKsaqWGIvHJXB0a+z0pJgRH+kKZfs19HROz720OLzH+FJO269JiuyEeFq/GLyQIr4D/s/ARxVlSx1DBm/8W0pjl/wqsJ1ma1PCXLB5yeBto6axGDWtD6lu7JPxwnXskK90tg6/cZRVeB1+AZtFWxxReDqpqMysPkB5ofPdl/gvHgvP38uWGv8eqaOWEwAxR/OfRENY3ItGEtBISrFTTw7UhQfKV1NwkaT/gKZFuHbaSZhwch6ApY9mJQMKo2fJ5nOLEknlWAZQKMITXcHQBv9+J+TYmUvoGGnswTdslHrooaq9ci1qzho1mKfbT1q4h6sZB9HyMorYJUNDuLeEMuMBgg6FwUN8tPKiy6I05bkXDmMJhlocbucYWSefFNXSMYGouVyamkCdRVVS2rxsJypFGcwS4YGQ2cTAbJsUkqOlAZ+QanJGrc/8gzRKEgwEHLjxUwLbYAG6JM9sdD3LAz0RZiJz1M9Ji0+JubJuLvcM2Uy2xsWo1Jx4PPPtdr9gexJo+Esyc3EzzZmNhecjKddTQuYZJlq2mMF6BNxgiOJv0p25XMo3OTpXbanaycI8hGGqOHY7wLM8+EGSaULUf4KzSz7Blwn3NcF/G907mNH7IjS4HRSMz5yJlgav1vVYpWRDDbAfrv3BWAL/53h8ZP",
        "X-Forefront-Antispam-Report": "\n\tCIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:AM8PR04MB7284.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(19092799006)(376014)(52116014)(366016)(7416014)(1800799024)(18002099003)(56012099003)(22082099003)(38350700014)(921020);DIR:OUT;SFP:1101;",
        "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1",
        "X-MS-Exchange-AntiSpam-MessageData-0": "\n VH0tVd59lTcgump2r6DyFbruwBzBoHi2H//rfOWSPIw4xWZ7wBJamdWHEoYv09uw/SJQcpmymZYU013+3tE7+XVEV8swnJLML+xRByHmeA8jqhtpppBNnFjV2jZWsJooxOOGwFEqCZH+4fx9rEdvw9Com7xq7In7O62zLw+vriSo3eeSWMlPJFPiyN0cJaNTe2WNyCyKXvckJC73T1Y2lt1y6bKpa07i6HUWWkwDQyFCnsvcxuZ/tLacW17YG0u80y5r0YHZf5kDVAkqPuSk3+oZEgjZCLhA4k5PuPlNMjcRk5FXK3IY33BBGbTVn1OF1lIo72e+kFni7qPOkqlzgqR0QGU+TwW7WkJhbN47MDDzf5QfvW+tVVQIqaTEdOLs+MsXRqnOKDznAOHgikby4UCVpf17C9w1E+EK9QsN6kyvsnu8H4SFpal30FA17rb+oRt1X/0jQdYA2OFQl+7/lpfIDYUMNJOrSNfFPlQW3DGr5xqjG2356GYP8G1BAREPEZmqDiR7AtC73glFvIWnJT+uCkZeyVlo+y6SU1zU4r9ZxSxbkHAbn16Hx8uRcU4fehVheXBcYq5o7fK89wtswTbilT1qt3RquymN6lMHUT6AGQGX+tAPkzMBYjxvZDPEcU/ZmELQeihLRZrIe5QRna8p+FlnqslNgQ/Kpvpvek4zmEhNPotBswGseQKwDn2WDjHaQOfCbznYMZHLSk0DRuSklkgJ83Vy3dp4yQsyc0kseN2lBX2mJuTrywfB6uO8k+rCyOK1NlpkUhCRWFMV1tsZBAZzcSbr+PzRwUf6REbmp/Gc2qkwP/W7VB+TicUSZDSaT9+497PqE1G15rYRdyfeLJKUIPQZ8nqgyLoEQ/7lx71xYBSJqu7yYTcuxVpLPSoyB0PsXAM6xHv3uE7DQH8lLjT7gg34A3cjRXh+05acPwHlphgcL8x5rDYahOSZSmei9uRQ5HHbiNC/XnAv5w+keiEy1K62UxATnRo/C6KxmrF2NjO7HXcqgUjlCuPWRYjCnNp6+x5muMKVadVu1iy4qCUZj3/b0NAReplNinyIOl4qtJo4XelVDU62GCZmn1GsLkdNlxccV74aGG7/5uCWQj9vbHGdYVd4FDKdTmLy8DAMj0wwKLRW0bc6XOaYNcr81XB/nd0WIYpCzD+o2WULDE9RQgdJ0oiB5zTWh0CfXpZwW4VNlF5BiugFlsErmNyE8C0VBSbcdxvYlfu2s7VW8B3tXNRPaRslQ+T34MHmXTMPG/IfUr0olHiACr7H04K1tCu4ySuWbZ5JznXT/BwpYfLbZ7ZX4ea2ucReKVyj+f2YuG6PcNu4GBjkWXm3EeravDydnN656JUNMAU9wdypMz7h+5td0/1W4IuEEaZcujJl75fhalj3Ag4sehnw5WrRYqBB8teqPyY9TR7XpfMa8BcCGp2pof6XYK9l3XbhogwVlNtU/JAwyYFvbfUGF8JC0JSgAPdIbQT5gtEa6crnI8+cDAnuzqHsP7wQk0TVtddPPI0qMm08aLEE9Bj1SFsDQdS+TXrPglDyAzTyuaEHaR0tkZJdoVTBvGZWomA8HLAqtY+upoOnV1Pau+QorFpC0p0zaaB7qUoAMce4CKyLLnWfnL13dcSIEnZYAEJaHMBUHyB3DgzvsOlg5C27tN6qV5AlrMthggf9Ks5kZQT6btkchnR8GE4sy0Km0xc/kC32qsqnz/Qpy2W57zxFDpWoS/feY7X0fK39BlxDhQ==",
        "X-OriginatorOrg": "nxp.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 8360614a-8c01-406c-7bcb-08de8f18cdb3",
        "X-MS-Exchange-CrossTenant-AuthSource": "AM8PR04MB7284.eurprd04.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Internal",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "31 Mar 2026 11:29:42.9963\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 c5oBxX5VYJ8lFUN5RbzYPvpq4o+Aynaauejm0O/dcNdNddCga7vI5vCinEe5sMRGv58NDyFAK9SLzBmtvCOy7w==",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "PA1PR04MB11406",
        "X-Spam-Status": "No, score=0.8 required=3.0 tests=ARC_SIGNED,ARC_VALID,\n\tDKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_SPF_HELO,\n\tSPF_HELO_PASS,T_SPF_PERMERROR autolearn=disabled version=4.0.1 OzLabs 8",
        "X-Spam-Checker-Version": "SpamAssassin 4.0.1 (2024-03-25) on lists.ozlabs.org"
    },
    "content": "For i.MX94 series, the NETC IP provides full 802.1Q Ethernet switch\nfunctionality, advanced QoS with 8 traffic classes, and a full range of\nTSN standards capabilities. The switch has 3 user ports and 1 CPU port,\nthe CPU port is connected to an internal ENETC. Since the switch and the\ninternal ENETC are fully integrated within the NETC IP, no back-to-back\nMAC connection is required. Instead, a light-weight \"pseudo MAC\" is used\nbetween the switch and the ENETC. This translates to lower power (less\nlogic and memory) and lower delay (as there is no serialization delay\nacross this link).\n\nThis patch introduces the initial NETC switch driver. At this stage,\nonly basic probe and remove functionality is supported. More features\nwill be supported in the subsequent patches.\n\nSigned-off-by: Wei Fang <wei.fang@nxp.com>\n---\n MAINTAINERS                           |  11 +\n drivers/net/dsa/Kconfig               |   3 +\n drivers/net/dsa/Makefile              |   1 +\n drivers/net/dsa/netc/Kconfig          |  14 +\n drivers/net/dsa/netc/Makefile         |   3 +\n drivers/net/dsa/netc/netc_main.c      | 672 ++++++++++++++++++++++++++\n drivers/net/dsa/netc/netc_platform.c  |  49 ++\n drivers/net/dsa/netc/netc_switch.h    |  92 ++++\n drivers/net/dsa/netc/netc_switch_hw.h | 137 ++++++\n 9 files changed, 982 insertions(+)\n create mode 100644 drivers/net/dsa/netc/Kconfig\n create mode 100644 drivers/net/dsa/netc/Makefile\n create mode 100644 drivers/net/dsa/netc/netc_main.c\n create mode 100644 drivers/net/dsa/netc/netc_platform.c\n create mode 100644 drivers/net/dsa/netc/netc_switch.h\n create mode 100644 drivers/net/dsa/netc/netc_switch_hw.h",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex a09bf30a057d..fe744320b1e5 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -19083,6 +19083,17 @@ F:\tDocumentation/devicetree/bindings/clock/*imx*\n F:\tdrivers/clk/imx/\n F:\tinclude/dt-bindings/clock/*imx*\n \n+NXP NETC ETHERNET SWITCH DRIVER\n+M:\tWei Fang <wei.fang@nxp.com>\n+R:\tClark Wang <xiaoning.wang@nxp.com>\n+L:\timx@lists.linux.dev\n+L:\tnetdev@vger.kernel.org\n+S:\tMaintained\n+F:\tDocumentation/devicetree/bindings/net/dsa/nxp,netc-switch.yaml\n+F:\tdrivers/net/dsa/netc/\n+F:\tinclude/linux/dsa/tag_netc.h\n+F:\tnet/dsa/tag_netc.c\n+\n NXP NETC TIMER PTP CLOCK DRIVER\n M:\tWei Fang <wei.fang@nxp.com>\n M:\tClark Wang <xiaoning.wang@nxp.com>\ndiff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig\nindex 39fb8ead16b5..e9c7a6874791 100644\n--- a/drivers/net/dsa/Kconfig\n+++ b/drivers/net/dsa/Kconfig\n@@ -74,8 +74,11 @@ source \"drivers/net/dsa/microchip/Kconfig\"\n \n source \"drivers/net/dsa/mv88e6xxx/Kconfig\"\n \n+\n source \"drivers/net/dsa/mxl862xx/Kconfig\"\n \n+source \"drivers/net/dsa/netc/Kconfig\"\n+\n source \"drivers/net/dsa/ocelot/Kconfig\"\n \n source \"drivers/net/dsa/qca/Kconfig\"\ndiff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile\nindex f5a463b87ec2..d2975badffc0 100644\n--- a/drivers/net/dsa/Makefile\n+++ b/drivers/net/dsa/Makefile\n@@ -21,6 +21,7 @@ obj-y\t\t\t\t+= lantiq/\n obj-y\t\t\t\t+= microchip/\n obj-y\t\t\t\t+= mv88e6xxx/\n obj-y\t\t\t\t+= mxl862xx/\n+obj-y\t\t\t\t+= netc/\n obj-y\t\t\t\t+= ocelot/\n obj-y\t\t\t\t+= qca/\n obj-y\t\t\t\t+= realtek/\ndiff --git a/drivers/net/dsa/netc/Kconfig b/drivers/net/dsa/netc/Kconfig\nnew file mode 100644\nindex 000000000000..8824d30ed3ea\n--- /dev/null\n+++ b/drivers/net/dsa/netc/Kconfig\n@@ -0,0 +1,14 @@\n+# SPDX-License-Identifier: GPL-2.0-only\n+config NET_DSA_NETC_SWITCH\n+\ttristate \"NXP NETC Ethernet switch support\"\n+\tdepends on NET_DSA && PCI\n+\tselect NET_DSA_TAG_NETC\n+\tselect FSL_ENETC_MDIO\n+\tselect NXP_NTMP\n+\tselect NXP_NETC_LIB\n+\thelp\n+\t  This driver supports the NXP NETC Ethernet switch, which is embedded\n+\t  as a PCIe function of the NXP NETC IP. But note that this driver does\n+\t  only support switch versions greater than or equal to NETC v4.3.\n+\n+\t  If compiled as module (M), the module name is nxp-netc-switch.\ndiff --git a/drivers/net/dsa/netc/Makefile b/drivers/net/dsa/netc/Makefile\nnew file mode 100644\nindex 000000000000..4a5767562574\n--- /dev/null\n+++ b/drivers/net/dsa/netc/Makefile\n@@ -0,0 +1,3 @@\n+# SPDX-License-Identifier: GPL-2.0-only\n+obj-$(CONFIG_NET_DSA_NETC_SWITCH) += nxp-netc-switch.o\n+nxp-netc-switch-objs := netc_main.o netc_platform.o\ndiff --git a/drivers/net/dsa/netc/netc_main.c b/drivers/net/dsa/netc/netc_main.c\nnew file mode 100644\nindex 000000000000..5828fd3e342e\n--- /dev/null\n+++ b/drivers/net/dsa/netc/netc_main.c\n@@ -0,0 +1,672 @@\n+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)\n+/*\n+ * NXP NETC switch driver\n+ * Copyright 2025-2026 NXP\n+ */\n+\n+#include <linux/clk.h>\n+#include <linux/etherdevice.h>\n+#include <linux/fsl/enetc_mdio.h>\n+#include <linux/if_vlan.h>\n+#include <linux/of_mdio.h>\n+\n+#include \"netc_switch.h\"\n+\n+static enum dsa_tag_protocol\n+netc_get_tag_protocol(struct dsa_switch *ds, int port,\n+\t\t      enum dsa_tag_protocol mprot)\n+{\n+\treturn DSA_TAG_PROTO_NETC;\n+}\n+\n+static void netc_port_rmw(struct netc_port *np, u32 reg,\n+\t\t\t  u32 mask, u32 val)\n+{\n+\tu32 old, new;\n+\n+\tWARN_ON((mask | val) != mask);\n+\n+\told = netc_port_rd(np, reg);\n+\tnew = (old & ~mask) | val;\n+\tif (new == old)\n+\t\treturn;\n+\n+\tnetc_port_wr(np, reg, new);\n+}\n+\n+static void netc_mac_port_wr(struct netc_port *np, u32 reg, u32 val)\n+{\n+\tif (is_netc_pseudo_port(np))\n+\t\treturn;\n+\n+\tnetc_port_wr(np, reg, val);\n+\tif (np->caps.pmac)\n+\t\tnetc_port_wr(np, reg + NETC_PMAC_OFFSET, val);\n+}\n+\n+static void netc_mac_port_rmw(struct netc_port *np, u32 reg,\n+\t\t\t      u32 mask, u32 val)\n+{\n+\tu32 old, new;\n+\n+\tif (is_netc_pseudo_port(np))\n+\t\treturn;\n+\n+\tWARN_ON((mask | val) != mask);\n+\n+\told = netc_port_rd(np, reg);\n+\tnew = (old & ~mask) | val;\n+\tif (new == old)\n+\t\treturn;\n+\n+\tnetc_port_wr(np, reg, new);\n+\tif (np->caps.pmac)\n+\t\tnetc_port_wr(np, reg + NETC_PMAC_OFFSET, new);\n+}\n+\n+static void netc_port_get_capability(struct netc_port *np)\n+{\n+\tu32 val;\n+\n+\tval = netc_port_rd(np, NETC_PMCAPR);\n+\tif (val & PMCAPR_HD)\n+\t\tnp->caps.half_duplex = true;\n+\n+\tif (FIELD_GET(PMCAPR_FP, val) == FP_SUPPORT)\n+\t\tnp->caps.pmac = true;\n+\n+\tval = netc_port_rd(np, NETC_PCAPR);\n+\tif (val & PCAPR_LINK_TYPE)\n+\t\tnp->caps.pseudo_link = true;\n+}\n+\n+static int netc_port_get_info_from_dt(struct netc_port *np,\n+\t\t\t\t      struct device_node *node,\n+\t\t\t\t      struct device *dev)\n+{\n+\tif (of_find_property(node, \"clock-names\", NULL)) {\n+\t\tnp->ref_clk = devm_get_clk_from_child(dev, node, \"ref\");\n+\t\tif (IS_ERR(np->ref_clk)) {\n+\t\t\tdev_err(dev, \"Port %d cannot get reference clock\\n\",\n+\t\t\t\tnp->dp->index);\n+\t\t\treturn PTR_ERR(np->ref_clk);\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int netc_port_create_emdio_bus(struct netc_port *np,\n+\t\t\t\t      struct device_node *node)\n+{\n+\tstruct netc_switch *priv = np->switch_priv;\n+\tstruct enetc_mdio_priv *mdio_priv;\n+\tstruct device *dev = priv->dev;\n+\tstruct enetc_hw *hw;\n+\tstruct mii_bus *bus;\n+\tint err;\n+\n+\thw = enetc_hw_alloc(dev, np->iobase);\n+\tif (IS_ERR(hw))\n+\t\treturn dev_err_probe(dev, PTR_ERR(hw),\n+\t\t\t\t     \"Failed to allocate enetc_hw\\n\");\n+\n+\tbus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));\n+\tif (!bus)\n+\t\treturn -ENOMEM;\n+\n+\tbus->name = \"NXP NETC switch external MDIO Bus\";\n+\tbus->read = enetc_mdio_read_c22;\n+\tbus->write = enetc_mdio_write_c22;\n+\tbus->read_c45 = enetc_mdio_read_c45;\n+\tbus->write_c45 = enetc_mdio_write_c45;\n+\tbus->parent = dev;\n+\tmdio_priv = bus->priv;\n+\tmdio_priv->hw = hw;\n+\tmdio_priv->mdio_base = NETC_EMDIO_BASE;\n+\tsnprintf(bus->id, MII_BUS_ID_SIZE, \"%s-p%d-emdio\",\n+\t\t dev_name(dev), np->dp->index);\n+\n+\terr = devm_of_mdiobus_register(dev, bus, node);\n+\tif (err)\n+\t\treturn dev_err_probe(dev, err,\n+\t\t\t\t     \"Cannot register EMDIO bus\\n\");\n+\n+\tnp->emdio = bus;\n+\n+\treturn 0;\n+}\n+\n+static int netc_port_create_mdio_bus(struct netc_port *np,\n+\t\t\t\t     struct device_node *node)\n+{\n+\tstruct device_node *mdio_node;\n+\tint err;\n+\n+\tmdio_node = of_get_child_by_name(node, \"mdio\");\n+\tif (mdio_node) {\n+\t\terr = netc_port_create_emdio_bus(np, mdio_node);\n+\t\tof_node_put(mdio_node);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int netc_init_switch_id(struct netc_switch *priv)\n+{\n+\tstruct netc_switch_regs *regs = &priv->regs;\n+\tstruct dsa_switch *ds = priv->ds;\n+\n+\t/* The value of 0 is reserved for the VEPA switch and cannot\n+\t * be used.\n+\t */\n+\tif (ds->index > SWCR_SWID || !ds->index) {\n+\t\tdev_err(priv->dev, \"Switch index %d out of range\\n\",\n+\t\t\tds->index);\n+\t\treturn -ERANGE;\n+\t}\n+\n+\tnetc_base_wr(regs, NETC_SWCR, ds->index);\n+\n+\treturn 0;\n+}\n+\n+static int netc_init_all_ports(struct netc_switch *priv)\n+{\n+\tstruct device *dev = priv->dev;\n+\tstruct netc_port *np;\n+\tstruct dsa_port *dp;\n+\tint err;\n+\n+\tpriv->ports = devm_kcalloc(dev, priv->info->num_ports,\n+\t\t\t\t   sizeof(struct netc_port *),\n+\t\t\t\t   GFP_KERNEL);\n+\tif (!priv->ports)\n+\t\treturn -ENOMEM;\n+\n+\t/* Some DSA interfaces may set the port even it is disabled, such\n+\t * as .port_disable(), .port_stp_state_set() and so on. To avoid\n+\t * crash caused by accessing NULL port pointer, each port is\n+\t * allocated its own memory. Otherwise, we need to check whether\n+\t * the port pointer is NULL in these interfaces. The latter is\n+\t * difficult for us to cover.\n+\t */\n+\tfor (int i = 0; i < priv->info->num_ports; i++) {\n+\t\tnp = devm_kzalloc(dev, sizeof(*np), GFP_KERNEL);\n+\t\tif (!np)\n+\t\t\treturn -ENOMEM;\n+\n+\t\tnp->switch_priv = priv;\n+\t\tnp->iobase = priv->regs.port + PORT_IOBASE(i);\n+\t\tnetc_port_get_capability(np);\n+\t\tpriv->ports[i] = np;\n+\t}\n+\n+\tdsa_switch_for_each_available_port(dp, priv->ds) {\n+\t\tnp = priv->ports[dp->index];\n+\t\tnp->dp = dp;\n+\t\terr = netc_port_get_info_from_dt(np, dp->dn, dev);\n+\t\tif (err)\n+\t\t\treturn err;\n+\n+\t\tif (dsa_port_is_user(dp)) {\n+\t\t\terr = netc_port_create_mdio_bus(np, dp->dn);\n+\t\t\tif (err) {\n+\t\t\t\tdev_err(dev, \"Failed to create MDIO bus\\n\");\n+\t\t\t\treturn err;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static void netc_init_ntmp_tbl_versions(struct netc_switch *priv)\n+{\n+\tstruct ntmp_user *ntmp = &priv->ntmp;\n+\n+\t/* All tables default to version 0 */\n+\tmemset(&ntmp->tbl, 0, sizeof(ntmp->tbl));\n+}\n+\n+static int netc_init_all_cbdrs(struct netc_switch *priv)\n+{\n+\tstruct netc_switch_regs *regs = &priv->regs;\n+\tstruct ntmp_user *ntmp = &priv->ntmp;\n+\tint i, err;\n+\n+\tntmp->cbdr_num = NETC_CBDR_NUM;\n+\tntmp->dev = priv->dev;\n+\tntmp->ring = devm_kcalloc(ntmp->dev, ntmp->cbdr_num,\n+\t\t\t\t  sizeof(struct netc_cbdr),\n+\t\t\t\t  GFP_KERNEL);\n+\tif (!ntmp->ring)\n+\t\treturn -ENOMEM;\n+\n+\tfor (i = 0; i < ntmp->cbdr_num; i++) {\n+\t\tstruct netc_cbdr *cbdr = &ntmp->ring[i];\n+\t\tstruct netc_cbdr_regs cbdr_regs;\n+\n+\t\tcbdr_regs.pir = regs->base + NETC_CBDRPIR(i);\n+\t\tcbdr_regs.cir = regs->base + NETC_CBDRCIR(i);\n+\t\tcbdr_regs.mr = regs->base + NETC_CBDRMR(i);\n+\t\tcbdr_regs.bar0 = regs->base + NETC_CBDRBAR0(i);\n+\t\tcbdr_regs.bar1 = regs->base + NETC_CBDRBAR1(i);\n+\t\tcbdr_regs.lenr = regs->base + NETC_CBDRLENR(i);\n+\n+\t\terr = ntmp_init_cbdr(cbdr, ntmp->dev, &cbdr_regs);\n+\t\tif (err)\n+\t\t\tgoto free_cbdrs;\n+\t}\n+\n+\treturn 0;\n+\n+free_cbdrs:\n+\tfor (i--; i >= 0; i--)\n+\t\tntmp_free_cbdr(&ntmp->ring[i]);\n+\n+\treturn err;\n+}\n+\n+static void netc_remove_all_cbdrs(struct netc_switch *priv)\n+{\n+\tstruct ntmp_user *ntmp = &priv->ntmp;\n+\n+\tfor (int i = 0; i < NETC_CBDR_NUM; i++)\n+\t\tntmp_free_cbdr(&ntmp->ring[i]);\n+}\n+\n+static int netc_init_ntmp_user(struct netc_switch *priv)\n+{\n+\tnetc_init_ntmp_tbl_versions(priv);\n+\n+\treturn netc_init_all_cbdrs(priv);\n+}\n+\n+static void netc_free_ntmp_user(struct netc_switch *priv)\n+{\n+\tnetc_remove_all_cbdrs(priv);\n+}\n+\n+static void netc_switch_dos_default_config(struct netc_switch *priv)\n+{\n+\tstruct netc_switch_regs *regs = &priv->regs;\n+\tu32 val;\n+\n+\tval = DOSL2CR_SAMEADDR | DOSL2CR_MSAMCC;\n+\tnetc_base_wr(regs, NETC_DOSL2CR, val);\n+\n+\tval = DOSL3CR_SAMEADDR | DOSL3CR_IPSAMCC;\n+\tnetc_base_wr(regs, NETC_DOSL3CR, val);\n+}\n+\n+static void netc_switch_vfht_default_config(struct netc_switch *priv)\n+{\n+\tstruct netc_switch_regs *regs = &priv->regs;\n+\tu32 val;\n+\n+\tval = netc_base_rd(regs, NETC_VFHTDECR2);\n+\n+\t/* if no match is found in the VLAN Filter table, then VFHTDECR2[MLO]\n+\t * will take effect. VFHTDECR2[MLO] is set to \"Software MAC learning\n+\t * secure\" by default. Notice BPCR[MLO] will override VFHTDECR2[MLO]\n+\t * if its value is not zero.\n+\t */\n+\tval = u32_replace_bits(val, MLO_SW_SEC, VFHTDECR2_MLO);\n+\tval = u32_replace_bits(val, MFO_NO_MATCH_DISCARD, VFHTDECR2_MFO);\n+\tnetc_base_wr(regs, NETC_VFHTDECR2, val);\n+}\n+\n+static void netc_port_set_max_frame_size(struct netc_port *np,\n+\t\t\t\t\t u32 max_frame_size)\n+{\n+\tnetc_mac_port_wr(np, NETC_PM_MAXFRM(0),\n+\t\t\t PM_MAXFRAM & max_frame_size);\n+}\n+\n+static void netc_switch_fixed_config(struct netc_switch *priv)\n+{\n+\tnetc_switch_dos_default_config(priv);\n+\tnetc_switch_vfht_default_config(priv);\n+}\n+\n+static void netc_port_set_tc_max_sdu(struct netc_port *np,\n+\t\t\t\t     int tc, u32 max_sdu)\n+{\n+\tu32 val = max_sdu & PTCTMSDUR_MAXSDU;\n+\n+\tval |= FIELD_PREP(PTCTMSDUR_SDU_TYPE, SDU_TYPE_MPDU);\n+\tnetc_port_wr(np, NETC_PTCTMSDUR(tc), val);\n+}\n+\n+static void netc_port_set_all_tc_msdu(struct netc_port *np)\n+{\n+\tfor (int tc = 0; tc < NETC_TC_NUM; tc++)\n+\t\tnetc_port_set_tc_max_sdu(np, tc, NETC_MAX_FRAME_LEN);\n+}\n+\n+static void netc_port_set_mlo(struct netc_port *np, enum netc_mlo mlo)\n+{\n+\tnetc_port_rmw(np, NETC_BPCR, BPCR_MLO, FIELD_PREP(BPCR_MLO, mlo));\n+}\n+\n+static void netc_port_fixed_config(struct netc_port *np)\n+{\n+\t/* Default IPV and DR setting */\n+\tnetc_port_rmw(np, NETC_PQOSMR, PQOSMR_VS | PQOSMR_VE,\n+\t\t      PQOSMR_VS | PQOSMR_VE);\n+\n+\t/* Enable L2 and L3 DOS */\n+\tnetc_port_rmw(np, NETC_PCR, PCR_L2DOSE | PCR_L3DOSE,\n+\t\t      PCR_L2DOSE | PCR_L3DOSE);\n+}\n+\n+static void netc_port_default_config(struct netc_port *np)\n+{\n+\tnetc_port_fixed_config(np);\n+\n+\t/* Default VLAN unaware */\n+\tnetc_port_rmw(np, NETC_BPDVR, BPDVR_RXVAM, BPDVR_RXVAM);\n+\n+\tif (dsa_port_is_cpu(np->dp))\n+\t\t/* For CPU port, source port pruning is disabled and\n+\t\t * hardware MAC learning is enabled by default.\n+\t\t */\n+\t\tnetc_port_rmw(np, NETC_BPCR, BPCR_SRCPRND | BPCR_MLO,\n+\t\t\t      BPCR_SRCPRND | FIELD_PREP(BPCR_MLO, MLO_HW));\n+\telse\n+\t\tnetc_port_set_mlo(np, MLO_DISABLE);\n+\n+\tnetc_port_set_max_frame_size(np, NETC_MAX_FRAME_LEN);\n+\tnetc_port_set_all_tc_msdu(np);\n+\tnetc_mac_port_rmw(np, NETC_PM_CMD_CFG(0), PM_CMD_CFG_TX_EN,\n+\t\t\t  PM_CMD_CFG_TX_EN);\n+\tnetc_port_rmw(np, NETC_POR, PCR_TXDIS, 0);\n+}\n+\n+static int netc_setup(struct dsa_switch *ds)\n+{\n+\tstruct netc_switch *priv = ds->priv;\n+\tstruct dsa_port *dp;\n+\tint err;\n+\n+\terr = netc_init_switch_id(priv);\n+\tif (err)\n+\t\treturn err;\n+\n+\terr = netc_init_all_ports(priv);\n+\tif (err)\n+\t\treturn err;\n+\n+\terr = netc_init_ntmp_user(priv);\n+\tif (err)\n+\t\treturn err;\n+\n+\tnetc_switch_fixed_config(priv);\n+\n+\t/* default setting for ports */\n+\tdsa_switch_for_each_available_port(dp, ds)\n+\t\tnetc_port_default_config(priv->ports[dp->index]);\n+\n+\treturn 0;\n+}\n+\n+static void netc_teardown(struct dsa_switch *ds)\n+{\n+\tstruct netc_switch *priv = ds->priv;\n+\n+\tnetc_free_ntmp_user(priv);\n+}\n+\n+static struct device_node *netc_get_switch_ports(struct device_node *node)\n+{\n+\tstruct device_node *ports;\n+\n+\tports = of_get_child_by_name(node, \"ports\");\n+\tif (!ports)\n+\t\tports = of_get_child_by_name(node, \"ethernet-ports\");\n+\n+\treturn ports;\n+}\n+\n+static bool netc_port_is_emdio_consumer(struct device_node *node)\n+{\n+\tstruct device_node *mdio_node;\n+\n+\t/* If the port node has phy-handle property and it does\n+\t * not contain a mdio child node, then the port is the\n+\t * EMDIO consumer.\n+\t */\n+\tmdio_node = of_get_child_by_name(node, \"mdio\");\n+\tif (!mdio_node)\n+\t\treturn true;\n+\n+\tof_node_put(mdio_node);\n+\n+\treturn false;\n+}\n+\n+/* Currently, phylink_of_phy_connect() is called by dsa_user_create(),\n+ * so if the switch uses the external MDIO controller (like the EMDIO\n+ * function) to manage the external PHYs. The MDIO bus may not be\n+ * created when phylink_of_phy_connect() is called, so it will return\n+ * an error and cause the switch driver to fail to probe.\n+ * This workaround can be removed when DSA phylink_of_phy_connect()\n+ * calls are moved from probe() to ndo_open().\n+ */\n+static int netc_switch_check_emdio_is_ready(struct device *dev)\n+{\n+\tstruct device_node *ports, *phy_node;\n+\tstruct phy_device *phydev;\n+\tint err = 0;\n+\n+\tports = netc_get_switch_ports(dev->of_node);\n+\tif (!ports)\n+\t\treturn 0;\n+\n+\tfor_each_available_child_of_node_scoped(ports, child) {\n+\t\t/* If the node does not have phy-handle property, then\n+\t\t * the port does not connect to a PHY, so the port is\n+\t\t * not the EMDIO consumer.\n+\t\t */\n+\t\tphy_node = of_parse_phandle(child, \"phy-handle\", 0);\n+\t\tif (!phy_node)\n+\t\t\tcontinue;\n+\n+\t\tif (!netc_port_is_emdio_consumer(child)) {\n+\t\t\tof_node_put(phy_node);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tphydev = of_phy_find_device(phy_node);\n+\t\tof_node_put(phy_node);\n+\t\tif (!phydev) {\n+\t\t\terr = -EPROBE_DEFER;\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tput_device(&phydev->mdio.dev);\n+\t}\n+\n+out:\n+\tof_node_put(ports);\n+\n+\treturn err;\n+}\n+\n+static int netc_switch_pci_init(struct pci_dev *pdev)\n+{\n+\tstruct device *dev = &pdev->dev;\n+\tstruct netc_switch_regs *regs;\n+\tstruct netc_switch *priv;\n+\tint err;\n+\n+\tpcie_flr(pdev);\n+\terr = pci_enable_device_mem(pdev);\n+\tif (err)\n+\t\treturn dev_err_probe(dev, err, \"Failed to enable device\\n\");\n+\n+\t/* The command BD rings and NTMP tables need DMA. No need to check\n+\t * the return value, because it never returns fail when the mask is\n+\t * DMA_BIT_MASK(64), see dma-api-howto.rst.\n+\t */\n+\tdma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));\n+\terr = pci_request_mem_regions(pdev, KBUILD_MODNAME);\n+\tif (err) {\n+\t\tdev_err(dev, \"Failed to request memory regions, err: %pe\\n\",\n+\t\t\tERR_PTR(err));\n+\t\tgoto disable_pci_device;\n+\t}\n+\n+\tpci_set_master(pdev);\n+\tpriv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);\n+\tif (!priv) {\n+\t\terr = -ENOMEM;\n+\t\tgoto release_mem_regions;\n+\t}\n+\n+\tpriv->pdev = pdev;\n+\tpriv->dev = dev;\n+\n+\tregs = &priv->regs;\n+\tregs->base = pci_ioremap_bar(pdev, NETC_REGS_BAR);\n+\tif (!regs->base) {\n+\t\terr = -ENXIO;\n+\t\tdev_err(dev, \"pci_ioremap_bar() failed\\n\");\n+\t\tgoto release_mem_regions;\n+\t}\n+\n+\tregs->port = regs->base + NETC_REGS_PORT_BASE;\n+\tregs->global = regs->base + NETC_REGS_GLOBAL_BASE;\n+\tpci_set_drvdata(pdev, priv);\n+\n+\treturn 0;\n+\n+release_mem_regions:\n+\tpci_release_mem_regions(pdev);\n+disable_pci_device:\n+\tpci_disable_device(pdev);\n+\n+\treturn err;\n+}\n+\n+static void netc_switch_pci_destroy(struct pci_dev *pdev)\n+{\n+\tstruct netc_switch *priv = pci_get_drvdata(pdev);\n+\n+\tiounmap(priv->regs.base);\n+\tpci_release_mem_regions(pdev);\n+\tpci_disable_device(pdev);\n+}\n+\n+static void netc_switch_get_ip_revision(struct netc_switch *priv)\n+{\n+\tstruct netc_switch_regs *regs = &priv->regs;\n+\tu32 val = netc_glb_rd(regs, NETC_IPBRR0);\n+\n+\tpriv->revision = val & IPBRR0_IP_REV;\n+}\n+\n+static const struct dsa_switch_ops netc_switch_ops = {\n+\t.get_tag_protocol\t\t= netc_get_tag_protocol,\n+\t.setup\t\t\t\t= netc_setup,\n+\t.teardown\t\t\t= netc_teardown,\n+};\n+\n+static int netc_switch_probe(struct pci_dev *pdev,\n+\t\t\t     const struct pci_device_id *id)\n+{\n+\tstruct device_node *node = dev_of_node(&pdev->dev);\n+\tstruct device *dev = &pdev->dev;\n+\tstruct netc_switch *priv;\n+\tstruct dsa_switch *ds;\n+\tint err;\n+\n+\tif (!node)\n+\t\treturn dev_err_probe(dev, -ENODEV,\n+\t\t\t\t     \"No DT bindings, skipping\\n\");\n+\n+\terr = netc_switch_check_emdio_is_ready(dev);\n+\tif (err)\n+\t\treturn err;\n+\n+\terr = netc_switch_pci_init(pdev);\n+\tif (err)\n+\t\treturn err;\n+\n+\tpriv = pci_get_drvdata(pdev);\n+\tnetc_switch_get_ip_revision(priv);\n+\n+\terr = netc_switch_platform_probe(priv);\n+\tif (err)\n+\t\tgoto destroy_netc_switch;\n+\n+\tds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL);\n+\tif (!ds) {\n+\t\terr = -ENOMEM;\n+\t\tgoto destroy_netc_switch;\n+\t}\n+\n+\tds->dev = dev;\n+\tds->num_ports = priv->info->num_ports;\n+\tds->num_tx_queues = NETC_TC_NUM;\n+\tds->ops = &netc_switch_ops;\n+\tds->priv = priv;\n+\n+\tpriv->ds = ds;\n+\n+\terr = dsa_register_switch(ds);\n+\tif (err) {\n+\t\tdev_err_probe(dev, err, \"Failed to register DSA switch\\n\");\n+\t\tgoto destroy_netc_switch;\n+\t}\n+\n+\treturn 0;\n+\n+destroy_netc_switch:\n+\tnetc_switch_pci_destroy(pdev);\n+\n+\treturn err;\n+}\n+\n+static void netc_switch_remove(struct pci_dev *pdev)\n+{\n+\tstruct netc_switch *priv = pci_get_drvdata(pdev);\n+\n+\tif (!priv)\n+\t\treturn;\n+\n+\tdsa_unregister_switch(priv->ds);\n+\tnetc_switch_pci_destroy(pdev);\n+}\n+\n+static void netc_switch_shutdown(struct pci_dev *pdev)\n+{\n+\tstruct netc_switch *priv = pci_get_drvdata(pdev);\n+\n+\tif (!priv)\n+\t\treturn;\n+\n+\tdsa_switch_shutdown(priv->ds);\n+\tpci_set_drvdata(pdev, NULL);\n+}\n+\n+static const struct pci_device_id netc_switch_ids[] = {\n+\t{ PCI_DEVICE(NETC_SWITCH_VENDOR_ID, NETC_SWITCH_DEVICE_ID) },\n+\t{ }\n+};\n+MODULE_DEVICE_TABLE(pci, netc_switch_ids);\n+\n+static struct pci_driver netc_switch_driver = {\n+\t.name\t\t= KBUILD_MODNAME,\n+\t.id_table\t= netc_switch_ids,\n+\t.probe\t\t= netc_switch_probe,\n+\t.remove\t\t= netc_switch_remove,\n+\t.shutdown\t= netc_switch_shutdown,\n+};\n+module_pci_driver(netc_switch_driver);\n+\n+MODULE_DESCRIPTION(\"NXP NETC Switch driver\");\n+MODULE_LICENSE(\"Dual BSD/GPL\");\ndiff --git a/drivers/net/dsa/netc/netc_platform.c b/drivers/net/dsa/netc/netc_platform.c\nnew file mode 100644\nindex 000000000000..abd599ea9c8d\n--- /dev/null\n+++ b/drivers/net/dsa/netc/netc_platform.c\n@@ -0,0 +1,49 @@\n+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)\n+/*\n+ * NXP NETC switch driver\n+ * Copyright 2025-2026 NXP\n+ */\n+\n+#include \"netc_switch.h\"\n+\n+struct netc_switch_platform {\n+\tu16 revision;\n+\tconst struct netc_switch_info *info;\n+};\n+\n+static const struct netc_switch_info imx94_info = {\n+\t.num_ports = 4,\n+};\n+\n+static const struct netc_switch_platform netc_platforms[] = {\n+\t{ .revision = NETC_SWITCH_REV_4_3, .info = &imx94_info, },\n+\t{ }\n+};\n+\n+static const struct netc_switch_info *\n+netc_switch_get_info(struct netc_switch *priv)\n+{\n+\tint i;\n+\n+\t/* Matching based on IP revision */\n+\tfor (i = 0; i < ARRAY_SIZE(netc_platforms); i++) {\n+\t\tif (priv->revision == netc_platforms[i].revision)\n+\t\t\treturn netc_platforms[i].info;\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+int netc_switch_platform_probe(struct netc_switch *priv)\n+{\n+\tconst struct netc_switch_info *info = netc_switch_get_info(priv);\n+\n+\tif (!info) {\n+\t\tdev_err(priv->dev, \"Cannot find switch platform info\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tpriv->info = info;\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/dsa/netc/netc_switch.h b/drivers/net/dsa/netc/netc_switch.h\nnew file mode 100644\nindex 000000000000..dac19bfba02b\n--- /dev/null\n+++ b/drivers/net/dsa/netc/netc_switch.h\n@@ -0,0 +1,92 @@\n+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */\n+/*\n+ * Copyright 2025-2026 NXP\n+ */\n+\n+#ifndef _NETC_SWITCH_H\n+#define _NETC_SWITCH_H\n+\n+#include <linux/dsa/tag_netc.h>\n+#include <linux/fsl/netc_global.h>\n+#include <linux/fsl/ntmp.h>\n+#include <linux/of_device.h>\n+#include <linux/of_net.h>\n+#include <linux/pci.h>\n+\n+#include \"netc_switch_hw.h\"\n+\n+#define NETC_REGS_BAR\t\t\t0\n+#define NETC_MSIX_TBL_BAR\t\t2\n+#define NETC_REGS_PORT_BASE\t\t0x4000\n+/* register block size per port  */\n+#define NETC_REGS_PORT_SIZE\t\t0x4000\n+#define PORT_IOBASE(p)\t\t\t(NETC_REGS_PORT_SIZE * (p))\n+#define NETC_REGS_GLOBAL_BASE\t\t0x70000\n+\n+#define NETC_SWITCH_REV_4_3\t\t0x0403\n+\n+#define NETC_TC_NUM\t\t\t8\n+#define NETC_CBDR_NUM\t\t\t2\n+\n+#define NETC_MAX_FRAME_LEN\t\t9600\n+\n+struct netc_switch;\n+\n+struct netc_switch_info {\n+\tu32 num_ports;\n+};\n+\n+struct netc_port_caps {\n+\tu32 half_duplex:1; /* indicates whether the port support half-duplex */\n+\tu32 pmac:1;\t  /* indicates whether the port has preemption MAC */\n+\tu32 pseudo_link:1;\n+};\n+\n+struct netc_port {\n+\tvoid __iomem *iobase;\n+\tstruct netc_switch *switch_priv;\n+\tstruct netc_port_caps caps;\n+\tstruct dsa_port *dp;\n+\tstruct clk *ref_clk; /* RGMII/RMII reference clock */\n+\tstruct mii_bus *emdio;\n+};\n+\n+struct netc_switch_regs {\n+\tvoid __iomem *base;\n+\tvoid __iomem *port;\n+\tvoid __iomem *global;\n+};\n+\n+struct netc_switch {\n+\tstruct pci_dev *pdev;\n+\tstruct device *dev;\n+\tstruct dsa_switch *ds;\n+\tu16 revision;\n+\n+\tconst struct netc_switch_info *info;\n+\tstruct netc_switch_regs regs;\n+\tstruct netc_port **ports;\n+\n+\tstruct ntmp_user ntmp;\n+};\n+\n+/* Write/Read Switch base registers */\n+#define netc_base_rd(r, o)\t\tnetc_read((r)->base + (o))\n+#define netc_base_wr(r, o, v)\t\tnetc_write((r)->base + (o), v)\n+\n+/* Write/Read registers of Switch Port (including pseudo MAC port) */\n+#define netc_port_rd(p, o)\t\tnetc_read((p)->iobase + (o))\n+#define netc_port_wr(p, o, v)\t\tnetc_write((p)->iobase + (o), v)\n+\n+/* Write/Read Switch global registers */\n+#define netc_glb_rd(r, o)\t\tnetc_read((r)->global + (o))\n+#define netc_glb_wr(r, o, v)\t\tnetc_write((r)->global + (o), v)\n+\n+static inline bool is_netc_pseudo_port(struct netc_port *np)\n+{\n+\treturn np->caps.pseudo_link;\n+}\n+\n+int netc_switch_platform_probe(struct netc_switch *priv);\n+\n+#endif\ndiff --git a/drivers/net/dsa/netc/netc_switch_hw.h b/drivers/net/dsa/netc/netc_switch_hw.h\nnew file mode 100644\nindex 000000000000..11cb124ce4bf\n--- /dev/null\n+++ b/drivers/net/dsa/netc/netc_switch_hw.h\n@@ -0,0 +1,137 @@\n+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */\n+/*\n+ * Copyright 2025-2026 NXP\n+ */\n+\n+#ifndef _NETC_SWITCH_HW_H\n+#define _NETC_SWITCH_HW_H\n+\n+#include <linux/bitops.h>\n+\n+#define NETC_SWITCH_VENDOR_ID\t\t0x1131\n+#define NETC_SWITCH_DEVICE_ID\t\t0xeef2\n+\n+/* Definition of Switch base registers */\n+#define NETC_CBDRMR(a)\t\t\t(0x0800 + (a) * 0x30)\n+#define NETC_CBDRBAR0(a)\t\t(0x0810 + (a) * 0x30)\n+#define NETC_CBDRBAR1(a)\t\t(0x0814 + (a) * 0x30)\n+#define NETC_CBDRPIR(a)\t\t\t(0x0818 + (a) * 0x30)\n+#define NETC_CBDRCIR(a)\t\t\t(0x081c + (a) * 0x30)\n+#define NETC_CBDRLENR(a)\t\t(0x0820 + (a) * 0x30)\n+\n+#define NETC_SWCR\t\t\t0x1018\n+#define  SWCR_SWID\t\t\tGENMASK(2, 0)\n+\n+#define NETC_DOSL2CR\t\t\t0x1220\n+#define  DOSL2CR_SAMEADDR\t\tBIT(0)\n+#define  DOSL2CR_MSAMCC\t\t\tBIT(1)\n+\n+#define NETC_DOSL3CR\t\t\t0x1224\n+#define  DOSL3CR_SAMEADDR\t\tBIT(0)\n+#define  DOSL3CR_IPSAMCC\t\tBIT(1)\n+\n+#define NETC_VFHTDECR1\t\t\t0x2014\n+#define NETC_VFHTDECR2\t\t\t0x2018\n+#define  VFHTDECR2_ET_PORT(a)\t\tBIT((a))\n+#define  VFHTDECR2_MLO\t\t\tGENMASK(26, 24)\n+#define  VFHTDECR2_MFO\t\t\tGENMASK(28, 27)\n+\n+/* Definition of Switch port registers */\n+#define NETC_PCAPR\t\t\t0x0000\n+#define  PCAPR_LINK_TYPE\t\tBIT(4)\n+#define  PCAPR_NUM_TC\t\t\tGENMASK(15, 12)\n+#define  PCAPR_NUM_Q\t\t\tGENMASK(19, 16)\n+#define  PCAPR_NUM_CG\t\t\tGENMASK(27, 24)\n+#define  PCAPR_TGS\t\t\tBIT(28)\n+#define  PCAPR_CBS\t\t\tBIT(29)\n+\n+#define NETC_PMCAPR\t\t\t0x0004\n+#define  PMCAPR_HD\t\t\tBIT(8)\n+#define  PMCAPR_FP\t\t\tGENMASK(10, 9)\n+#define   FP_SUPPORT\t\t\t2\n+\n+#define NETC_PCR\t\t\t0x0010\n+#define  PCR_HDR_FMT\t\t\tBIT(0)\n+#define  PCR_NS_TAG_PORT\t\tBIT(3)\n+#define  PCR_L2DOSE\t\t\tBIT(4)\n+#define  PCR_L3DOSE\t\t\tBIT(5)\n+#define  PCR_TIMER_CS\t\t\tBIT(8)\n+#define  PCR_PSPEED\t\t\tGENMASK(29, 16)\n+#define   PSPEED_SET_VAL(s)\t\tFIELD_PREP(PCR_PSPEED, ((s) / 10 - 1))\n+\n+#define NETC_PQOSMR\t\t\t0x0054\n+#define  PQOSMR_VS\t\t\tBIT(0)\n+#define  PQOSMR_VE\t\t\tBIT(1)\n+#define  PQOSMR_DDR\t\t\tGENMASK(3, 2)\n+#define  PQOSMR_DIPV\t\t\tGENMASK(6, 4)\n+#define  PQOSMR_VQMP\t\t\tGENMASK(19, 16)\n+#define  PQOSMR_QVMP\t\t\tGENMASK(23, 20)\n+\n+#define NETC_POR\t\t\t0x100\n+#define  PCR_TXDIS\t\t\tBIT(0)\n+#define  PCR_RXDIS\t\t\tBIT(1)\n+\n+#define NETC_PTCTMSDUR(a)\t\t(0x208 + (a) * 0x20)\n+#define  PTCTMSDUR_MAXSDU\t\tGENMASK(15, 0)\n+#define  PTCTMSDUR_SDU_TYPE\t\tGENMASK(17, 16)\n+#define   SDU_TYPE_PPDU\t\t\t0\n+#define   SDU_TYPE_MPDU\t\t\t1\n+#define   SDU_TYPE_MSDU\t\t\t2\n+\n+#define NETC_BPCR\t\t\t0x500\n+#define  BPCR_DYN_LIMIT\t\t\tGENMASK(15, 0)\n+#define  BPCR_MLO\t\t\tGENMASK(22, 20)\n+#define  BPCR_UUCASTE\t\t\tBIT(24)\n+#define  BPCR_UMCASTE\t\t\tBIT(25)\n+#define  BPCR_MCASTE\t\t\tBIT(26)\n+#define  BPCR_BCASTE\t\t\tBIT(27)\n+#define  BPCR_STAMVD\t\t\tBIT(28)\n+#define  BPCR_SRCPRND\t\t\tBIT(29)\n+\n+/* MAC learning options, see BPCR[MLO], VFHTDECR2[MLO] and\n+ * VLAN Filter Table CFGE_DATA[MLO]\n+ */\n+enum netc_mlo {\n+\tMLO_NOT_OVERRIDE = 0,\n+\tMLO_DISABLE,\n+\tMLO_HW,\n+\tMLO_SW_SEC,\n+\tMLO_SW_UNSEC,\n+\tMLO_DISABLE_SMAC,\n+};\n+\n+/* MAC forwarding options, see VFHTDECR2[MFO] and VLAN\n+ * Filter Table CFGE_DATA[MFO]\n+ */\n+enum netc_mfo {\n+\tMFO_NO_FDB_LOOKUP = 1,\n+\tMFO_NO_MATCH_FLOOD,\n+\tMFO_NO_MATCH_DISCARD,\n+};\n+\n+#define NETC_BPDVR\t\t\t0x510\n+#define  BPDVR_VID\t\t\tGENMASK(11, 0)\n+#define  BPDVR_DEI\t\t\tBIT(12)\n+#define  BPDVR_PCP\t\t\tGENMASK(15, 13)\n+#define  BPDVR_TPID\t\t\tBIT(16)\n+#define  BPDVR_RXTAGA\t\t\tGENMASK(23, 20)\n+#define  BPDVR_RXVAM\t\t\tBIT(24)\n+#define  BPDVR_TXTAGA\t\t\tGENMASK(26, 25)\n+\n+/* Definition of Switch ethernet MAC port registers */\n+#define NETC_PMAC_OFFSET\t\t0x400\n+#define NETC_PM_CMD_CFG(a)\t\t(0x1008 + (a) * 0x400)\n+#define  PM_CMD_CFG_TX_EN\t\tBIT(0)\n+#define  PM_CMD_CFG_RX_EN\t\tBIT(1)\n+\n+#define NETC_PM_MAXFRM(a)\t\t(0x1014 + (a) * 0x400)\n+#define  PM_MAXFRAM\t\t\tGENMASK(15, 0)\n+\n+#define NETC_PEMDIOCR\t\t\t0x1c00\n+#define NETC_EMDIO_BASE\t\t\tNETC_PEMDIOCR\n+\n+/* Definition of global registers (read only) */\n+#define NETC_IPBRR0\t\t\t0x0bf8\n+#define  IPBRR0_IP_REV\t\t\tGENMASK(15, 0)\n+\n+#endif\n",
    "prefixes": [
        "v4",
        "net-next",
        "10/14"
    ]
}