get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 130834,
    "url": "http://patches.dpdk.org/api/patches/130834/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20230829101723.1295814-2-mko-plv@napatech.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20230829101723.1295814-2-mko-plv@napatech.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230829101723.1295814-2-mko-plv@napatech.com",
    "date": "2023-08-29T10:17:17",
    "name": "[v9,2/8] net/ntnic: adds core registers and fpga functionality",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "8adf0f575c3d2fd6f7652466bd3d8e4f6e4df484",
    "submitter": {
        "id": 3153,
        "url": "http://patches.dpdk.org/api/people/3153/?format=api",
        "name": "Mykola Kostenok",
        "email": "mko-plv@napatech.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20230829101723.1295814-2-mko-plv@napatech.com/mbox/",
    "series": [
        {
            "id": 29360,
            "url": "http://patches.dpdk.org/api/series/29360/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=29360",
            "date": "2023-08-29T10:17:19",
            "name": "[v9,1/8] net/ntnic: initial commit which adds register defines",
            "version": 9,
            "mbox": "http://patches.dpdk.org/series/29360/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/130834/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/130834/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 9A44841F54;\n\tTue, 29 Aug 2023 12:18:19 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 4E34C409FA;\n\tTue, 29 Aug 2023 12:17:25 +0200 (CEST)",
            "from egress-ip27b.ess.de.barracuda.com\n (egress-ip27b.ess.de.barracuda.com [18.185.115.231])\n by mails.dpdk.org (Postfix) with ESMTP id B1086402C4\n for <dev@dpdk.org>; Tue, 29 Aug 2023 12:17:18 +0200 (CEST)",
            "from EUR05-DB8-obe.outbound.protection.outlook.com\n (mail-db8eur05lp2106.outbound.protection.outlook.com [104.47.17.106]) by\n mx-outbound19-169.eu-central-1b.ess.aws.cudaops.com (version=TLSv1.2\n cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO);\n Tue, 29 Aug 2023 10:17:16 +0000",
            "from AS4P189CA0044.EURP189.PROD.OUTLOOK.COM (2603:10a6:20b:5dd::13)\n by AM8P190MB0834.EURP190.PROD.OUTLOOK.COM (2603:10a6:20b:1d8::15)\n with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.35; Tue, 29 Aug\n 2023 10:16:55 +0000",
            "from AMS1EPF00000045.eurprd04.prod.outlook.com\n (2603:10a6:20b:5dd:cafe::cf) by AS4P189CA0044.outlook.office365.com\n (2603:10a6:20b:5dd::13) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.35 via Frontend\n Transport; Tue, 29 Aug 2023 10:16:55 +0000",
            "from k8s-node.default.svc.cluster.local (178.72.21.4) by\n AMS1EPF00000045.mail.protection.outlook.com (10.167.16.42) with Microsoft\n SMTP Server id 15.20.6745.16 via Frontend Transport; Tue, 29 Aug 2023\n 10:16:55 +0000"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=lj3zIogBKVUfmJZvQwvvnzRhoBltJtl4MIZlzT0fVqiJuxya09Akpx76AYnCUb0bzsnlKBpp7UGRN8wwW8jslXAr8hGtPUQgBEUAfy6clDbYGOX88BXll9dSn+Ewu0rqSHMLtGGe/fXheFfxbf2F9RoVqvuIwHD8+0nbrOS29W5m4lRUfqOhrOM+1uvulGNNO4sO2/sil2kYK8RjzklCyu9ZdnbhHZfwMeBONz4dbxT3hcHIXWDsrgqscQgOx1cvexXII0ST68M7ac6EGfFOi7bX2fBPdBrDTliJKrrxnT8n/uyo3LgtALr1wKdpSzb8G5dcr0fBJ5mHrEP50n4EzQ==",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector9901;\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=coaSWDzaaKevc53tnjLZCjyrixItwk0PKdKMoAXdpgc=;\n b=SPSwfAcm3o9sou+NBjwqDRi8HbyHsRPkzCFzPaPQOqe3NocuCosI1TBFl21jRs88dtsS+WDwfBYRR5OF0lZNDWW7WzasObOjwknSxZy7NH2Pq+jtT/2ifxpbYHtbu2JFqdnkuu/ZpDZjfxTUAqJ+r2Y3usGIteUHT5+ZH5qkOiOwEjvj3kmvt3XCz15PYStDOhOFlgmgc9VielUlrFafdpYoO4gYuUKQ4XYSwAupMZrMJ1vktkNSoy5uPCTo4hx1x3MUWHPeL7zmcJ33u7eDYxMnIHVBHLeOVs/P8PUOe6pPzG98TnR/ucl1fB+Y0G1GG9BCQtCDYRh0MUDycNzjRQ==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=fail (sender ip is\n 178.72.21.4) smtp.rcpttodomain=dpdk.org smtp.mailfrom=napatech.com;\n dmarc=fail (p=none sp=none pct=100) action=none header.from=napatech.com;\n dkim=none (message not signed); arc=none",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=napatech.com;\n s=selector1;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=coaSWDzaaKevc53tnjLZCjyrixItwk0PKdKMoAXdpgc=;\n b=EjWpuo/Mtg6ZqUcmeJRcIldyWlxt2L6lV+waOTPaIAvDDGY4WCEXJBmNp0YMdL7BkOt7ygr8Ap+P/KlFt4c5qjY9IfDLUKuy0Yc+EzdeExD4HsT68o3V3e7vGK2WecwGM5YCKorDP29puDYes8bNN5OXqldKBlh3G+MjqCrH428=",
        "X-MS-Exchange-Authentication-Results": "spf=fail (sender IP is 178.72.21.4)\n smtp.mailfrom=napatech.com; dkim=none (message not signed)\n header.d=none;dmarc=fail action=none header.from=napatech.com;",
        "Received-SPF": "Fail (protection.outlook.com: domain of napatech.com does not\n designate 178.72.21.4 as permitted sender) receiver=protection.outlook.com;\n client-ip=178.72.21.4; helo=k8s-node.default.svc.cluster.local;",
        "From": "Mykola Kostenok <mko-plv@napatech.com>",
        "To": "dev@dpdk.org,\n\tmko-plv@napatech.com,\n\tthomas@monjalon.net",
        "Cc": "ckm@napatech.com",
        "Subject": "[PATCH v9 2/8] net/ntnic: adds core registers and fpga functionality",
        "Date": "Tue, 29 Aug 2023 12:17:17 +0200",
        "Message-Id": "<20230829101723.1295814-2-mko-plv@napatech.com>",
        "X-Mailer": "git-send-email 2.39.3",
        "In-Reply-To": "<20230829101723.1295814-1-mko-plv@napatech.com>",
        "References": "<20230816132552.2483752-1-mko-plv@napatech.com>\n <20230829101723.1295814-1-mko-plv@napatech.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-EOPAttributedMessage": "0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "AMS1EPF00000045:EE_|AM8P190MB0834:EE_",
        "Content-Type": "text/plain",
        "X-MS-Office365-Filtering-Correlation-Id": "46be6e6d-a1da-4a57-740a-08dba8791267",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n rBkXLNKV++ybx312V2m1t8vPYeZdx7S5CIx/aNIdt8q7h4GJGX72Tvy3YvU4XuWtIogkDt8jdwL8C0y6ezW0g/XdYswBVHUoZiaC+GdlC7DuoD3MfQr1M7KczK+eaTdjmWd90hQRAW1bekeL6BNfNNvay86K+vONpPMIc/2RqlJNon02bOe+1mvF/6OZLOcd5WzCccZVyvbBDw00i6gxr7Ya5jv8NpzGPk5KmlUqPCFvR5417sLcX6Mbn64iHZ0mrB/yXq5J49DReV22FLzhU6J09tewjAf7dyyK9HS4qgoib9iD3HltoYRhYOtKUhFPZvW/49BynZOviJ6cCbmyksyJJXYWnB14ySyNBNsw0BIMWlj3QkOGHqTNH643T6WiseFvnv5Swz/lX5jFzqAdYEr7UmspYD2luMUkxrEZ5GKHpMAykRmm8LKZN8ugsbFblv/PIz75EhqkjBF4A77dOIZqhJFWgEmkIaPIoc/8uCXqjBl3nD9wAVN8dIV0zT/mxCQ/ZCZm2DEXyYV5ILg887Amd3M5KrdPkRckSQV2KS8SmAwCYFuP1a299t4dRoCCgKzY9lpexvAVCdQB8vVkZFQwFejivAyYMrgpSNXzASgZom8uVzFbAsBz3OJXFCnuEKVSxJUD29cbYfZI4iBMpLOxlgTPlLOWnNfiHlpO0eZyGasfE5pGSq9+UNbTu9VkKIm8JhjkUATWX9XuxEvCdgrOrcHsi8jmnNh594mxxzMQRK3CwmbOU26fE28JSVQL",
        "X-Forefront-Antispam-Report": "CIP:178.72.21.4; CTRY:DK; LANG:en; SCL:1; SRV:;\n IPV:NLI; SFV:NSPM; H:k8s-node.default.svc.cluster.local;\n PTR:InfoDomainNonexistent; CAT:NONE;\n SFS:(13230031)(376002)(39840400004)(346002)(396003)(136003)(82310400011)(186009)(451199024)(1800799009)(36840700001)(46966006)(6512007)(6506007)(6666004)(6486002)(19627235002)(478600001)(83380400001)(107886003)(956004)(336012)(1076003)(26005)(2906002)(30864003)(2616005)(36736006)(316002)(41300700001)(70206006)(70586007)(9316004)(8936002)(5660300002)(8676002)(4326008)(36756003)(40480700001)(47076005)(36860700001)(86362001)(15974865002)(81166007)(356005)(21314003)(36900700001)(579004)(559001);\n DIR:OUT; SFP:1101;",
        "X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount": "1",
        "X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0": "\n iHD31pM/wtCC/z2OM3fSX8QWQW+0uOxlWgNN+6dl2IQNHT6NDfJbuMilE3RpZQ/bwOBNAaam9Syg8hNd+ZpX6Bpjd2ICjcyw5X3xaeWbCeZQfx2SfOX+uSWcup4kyGYLeGGTfOTPmCboApNqiLKF/NqA3VxVtNB17/Sq17hd1+Jai4Bk4A+ojlovb28tfYqPSrYndziw9HdOIdvks/os/+8lJYl7iAMIhvK/G14wcYGmIpQVoN/KDx2Eqc1joTXfQF1Qruenq2apz461jOdDWtWMTHBAWRkQ7Wr+8YClekh3Ql1bwBnZCTa5M0GfYmJaJ0cWGToyeyypzzxv+ZLgkiIVjylvk0HEtXfAdCyRQMB9JK/vEYOeYwWdJFrzRa0v3x/vhGE9Kamwsj/Blj6Z/IfhJdpLXS2rulDlLaruJqXbahQYSyBq9/rLmcopdmF0ZoeDfzj/zVscISrYgyRXzsw3o05QwEiw+ihLadbLWcuLOuxjAnpL+OvsVwifExM3yXS4X2FJ35hIecyl1PgDBQFfVMS1nr3BwIE+JAqvg680FRU4iTfTVXSxSqZTbynfRxdxGtnXPZs/rPXd2AQWOiidiwh39zG98eoSKsxo9G0SmPPBXtUdGiDlpb/0H6MxZCfSmNWkxCquU8pkd2LowW8conPACdFReD5pnGEmRQ/jUO8z8BkRY6TZHr6ZE8vS9pSrniVF0wIbllnLXVGckcGGfglvAWEj0tKEXsS2mYCbibwrKuE4d+k8usBKbpTEde9jGiD84JA07OwOk3gzn3qAfap3io/u2nmpHRp0wOQ=",
        "X-OriginatorOrg": "napatech.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "29 Aug 2023 10:16:55.5242 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 46be6e6d-a1da-4a57-740a-08dba8791267",
        "X-MS-Exchange-CrossTenant-Id": "c4540d0b-728a-4233-9da5-9ea30c7ec3ed",
        "X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp": "\n TenantId=c4540d0b-728a-4233-9da5-9ea30c7ec3ed; Ip=[178.72.21.4];\n Helo=[k8s-node.default.svc.cluster.local]",
        "X-MS-Exchange-CrossTenant-AuthSource": "\n AMS1EPF00000045.eurprd04.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "AM8P190MB0834",
        "X-BESS-ID": "1693304231-305033-12339-16306-2",
        "X-BESS-VER": "2019.1_20230822.1529",
        "X-BESS-Apparent-Source-IP": "104.47.17.106",
        "X-BESS-Parts": "H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKVqaGhmYmZkB2BlDYKCUxycwkNd\n HIzDgx2TTRKCXZ1NgyJcUsLdnMItHIwlKpNhYAcGvTrkMAAAA=",
        "X-BESS-Outbound-Spam-Score": "0.00",
        "X-BESS-Outbound-Spam-Report": "Code version 3.2,\n rules version 3.2.2.250465 [from\n cloudscan22-3.eu-central-1b.ess.aws.cudaops.com]\n Rule breakdown below\n pts rule name              description\n ---- ---------------------- --------------------------------\n 0.00 LARGE_BODY_SHORTCUT    META:  ",
        "X-BESS-Outbound-Spam-Status": "SCORE=0.00 using account:ESS113687 scores of\n KILL_LEVEL=7.0 tests=LARGE_BODY_SHORTCUT",
        "X-BESS-BRTS-Status": "1",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "From: Christian Koue Muf <ckm@napatech.com>\n\nIncludes functionality to reset, initialize, program, and collect\nstats for the NTNIC FPGA.\n\nSigned-off-by: Christian Koue Muf <ckm@napatech.com>\nReviewed-by: Mykola Kostenok <mko-plv@napatech.com>\n---\nv2:\n* Fixed WARNING:TYPO_SPELLING\n* Fix compilation for Fedora38\nv3:\n* Fixed WARNING:TYPO_SPELLING\n* Fix compilation for Fedora38\nv9:\n* Add missing header\n---\n drivers/net/ntnic/include/nthw_bus.h          |   10 +\n drivers/net/ntnic/meson.build                 |   32 +\n .../net/ntnic/nthw/core/nthw_clock_profiles.c |    9 +\n .../net/ntnic/nthw/core/nthw_clock_profiles.h |   39 +\n drivers/net/ntnic/nthw/core/nthw_core.h       |   31 +\n drivers/net/ntnic/nthw/core/nthw_fpga.c       |  914 +++++++++\n drivers/net/ntnic/nthw/core/nthw_fpga.h       |   47 +\n .../net/ntnic/nthw/core/nthw_fpga_nt200a0x.c  |   46 +\n .../net/ntnic/nthw/core/nthw_fpga_nt200a0x.h  |   14 +\n drivers/net/ntnic/nthw/core/nthw_fpga_rst.c   |   10 +\n drivers/net/ntnic/nthw/core/nthw_fpga_rst.h   |   17 +\n .../net/ntnic/nthw/core/nthw_fpga_rst9563.c   |  241 +++\n .../ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c  |  674 +++++++\n .../ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h  |   89 +\n drivers/net/ntnic/nthw/core/nthw_gpio_phy.c   |  271 +++\n drivers/net/ntnic/nthw/core/nthw_gpio_phy.h   |   57 +\n drivers/net/ntnic/nthw/core/nthw_hif.c        |  342 ++++\n drivers/net/ntnic/nthw/core/nthw_hif.h        |  156 ++\n drivers/net/ntnic/nthw/core/nthw_iic.c        |  570 ++++++\n drivers/net/ntnic/nthw/core/nthw_iic.h        |  101 +\n drivers/net/ntnic/nthw/core/nthw_mac_pcs.c    | 1034 ++++++++++\n drivers/net/ntnic/nthw/core/nthw_mac_pcs.h    |  261 +++\n .../net/ntnic/nthw/core/nthw_mac_pcs_xxv.c    | 1631 ++++++++++++++++\n .../net/ntnic/nthw/core/nthw_mac_pcs_xxv.h    |  291 +++\n drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c  |  121 ++\n drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h  |   51 +\n drivers/net/ntnic/nthw/core/nthw_pci_ta.c     |   99 +\n drivers/net/ntnic/nthw/core/nthw_pci_ta.h     |   40 +\n drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c  |  127 ++\n drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h  |   55 +\n drivers/net/ntnic/nthw/core/nthw_pcie3.c      |  274 +++\n drivers/net/ntnic/nthw/core/nthw_pcie3.h      |  100 +\n drivers/net/ntnic/nthw/core/nthw_sdc.c        |  177 ++\n drivers/net/ntnic/nthw/core/nthw_sdc.h        |   43 +\n drivers/net/ntnic/nthw/core/nthw_si5340.c     |  206 ++\n drivers/net/ntnic/nthw/core/nthw_si5340.h     |   34 +\n drivers/net/ntnic/nthw/core/nthw_spi_v3.c     |  380 ++++\n drivers/net/ntnic/nthw/core/nthw_spi_v3.h     |  106 ++\n drivers/net/ntnic/nthw/core/nthw_spim.c       |  117 ++\n drivers/net/ntnic/nthw/core/nthw_spim.h       |   52 +\n drivers/net/ntnic/nthw/core/nthw_spis.c       |  147 ++\n drivers/net/ntnic/nthw/core/nthw_spis.h       |   63 +\n drivers/net/ntnic/nthw/core/nthw_tsm.c        |  179 ++\n drivers/net/ntnic/nthw/core/nthw_tsm.h        |   53 +\n drivers/net/ntnic/nthw/nthw_dbs.c             | 1301 +++++++++++++\n drivers/net/ntnic/nthw/nthw_dbs.h             |  313 +++\n drivers/net/ntnic/nthw/nthw_drv.h             |   82 +\n drivers/net/ntnic/nthw/nthw_epp.c             |  335 ++++\n drivers/net/ntnic/nthw/nthw_epp.h             |   99 +\n drivers/net/ntnic/nthw/nthw_fpga_model.c      | 1677 +++++++++++++++++\n drivers/net/ntnic/nthw/nthw_fpga_model.h      |  308 +++\n drivers/net/ntnic/nthw/nthw_helper.h          |   21 +\n drivers/net/ntnic/nthw/nthw_platform.c        |   35 +\n drivers/net/ntnic/nthw/nthw_platform_drv.h    |   42 +\n drivers/net/ntnic/nthw/nthw_profile.h         |   15 +\n drivers/net/ntnic/nthw/nthw_rac.c             |  976 ++++++++++\n drivers/net/ntnic/nthw/nthw_rac.h             |  161 ++\n drivers/net/ntnic/nthw/nthw_register.h        |    2 +\n drivers/net/ntnic/nthw/nthw_stat.c            |  266 +++\n drivers/net/ntnic/nthw/nthw_stat.h            |   72 +\n drivers/net/ntnic/ntlog/include/ntlog.h       |  162 ++\n drivers/net/ntnic/ntlog/ntlog.c               |  115 ++\n drivers/net/ntnic/ntutil/include/nt_util.h    |   72 +\n drivers/net/ntnic/ntutil/nt_util.c            |   77 +\n 64 files changed, 15442 insertions(+)\n create mode 100644 drivers/net/ntnic/include/nthw_bus.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_clock_profiles.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_clock_profiles.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_core.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_gpio_phy.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_gpio_phy.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_hif.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_hif.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_iic.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_iic.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_ta.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_ta.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcie3.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcie3.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_sdc.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_sdc.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_si5340.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_si5340.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_spi_v3.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_spi_v3.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_spim.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_spim.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_spis.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_spis.h\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_tsm.c\n create mode 100644 drivers/net/ntnic/nthw/core/nthw_tsm.h\n create mode 100644 drivers/net/ntnic/nthw/nthw_dbs.c\n create mode 100644 drivers/net/ntnic/nthw/nthw_dbs.h\n create mode 100644 drivers/net/ntnic/nthw/nthw_drv.h\n create mode 100644 drivers/net/ntnic/nthw/nthw_epp.c\n create mode 100644 drivers/net/ntnic/nthw/nthw_epp.h\n create mode 100644 drivers/net/ntnic/nthw/nthw_fpga_model.c\n create mode 100644 drivers/net/ntnic/nthw/nthw_fpga_model.h\n create mode 100644 drivers/net/ntnic/nthw/nthw_helper.h\n create mode 100644 drivers/net/ntnic/nthw/nthw_platform.c\n create mode 100644 drivers/net/ntnic/nthw/nthw_platform_drv.h\n create mode 100644 drivers/net/ntnic/nthw/nthw_profile.h\n create mode 100644 drivers/net/ntnic/nthw/nthw_rac.c\n create mode 100644 drivers/net/ntnic/nthw/nthw_rac.h\n create mode 100644 drivers/net/ntnic/nthw/nthw_stat.c\n create mode 100644 drivers/net/ntnic/nthw/nthw_stat.h\n create mode 100644 drivers/net/ntnic/ntlog/include/ntlog.h\n create mode 100644 drivers/net/ntnic/ntlog/ntlog.c\n create mode 100644 drivers/net/ntnic/ntutil/include/nt_util.h\n create mode 100644 drivers/net/ntnic/ntutil/nt_util.c",
    "diff": "diff --git a/drivers/net/ntnic/include/nthw_bus.h b/drivers/net/ntnic/include/nthw_bus.h\nnew file mode 100644\nindex 0000000000..975cc95e78\n--- /dev/null\n+++ b/drivers/net/ntnic/include/nthw_bus.h\n@@ -0,0 +1,10 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_BUS_H__\n+#define __NTHW_BUS_H__\n+\n+typedef uint8_t rab_bus_id_t;\n+\n+#endif /* __NTHW_BUS_H__ */\ndiff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build\nindex 1194ce6aea..428fc7af98 100644\n--- a/drivers/net/ntnic/meson.build\n+++ b/drivers/net/ntnic/meson.build\n@@ -11,13 +11,45 @@ endif\n includes = [\n     include_directories('.'),\n     include_directories('include'),\n+    include_directories('ntlog/include'),\n+    include_directories('ntutil/include'),\n     include_directories('nthw'),\n+    include_directories('nthw/core'),\n     include_directories('nthw/supported'),\n ]\n \n # all sources\n sources = files(\n+    'nthw/core/nthw_clock_profiles.c',\n+    'nthw/core/nthw_fpga.c',\n+    'nthw/core/nthw_fpga_nt200a0x.c',\n+    'nthw/core/nthw_fpga_rst.c',\n+    'nthw/core/nthw_fpga_rst9563.c',\n+    'nthw/core/nthw_fpga_rst_nt200a0x.c',\n+    'nthw/core/nthw_gpio_phy.c',\n+    'nthw/core/nthw_hif.c',\n+    'nthw/core/nthw_iic.c',\n+    'nthw/core/nthw_mac_pcs.c',\n+    'nthw/core/nthw_mac_pcs_xxv.c',\n+    'nthw/core/nthw_pci_rd_tg.c',\n+    'nthw/core/nthw_pci_ta.c',\n+    'nthw/core/nthw_pci_wr_tg.c',\n+    'nthw/core/nthw_pcie3.c',\n+    'nthw/core/nthw_sdc.c',\n+    'nthw/core/nthw_si5340.c',\n+    'nthw/core/nthw_spi_v3.c',\n+    'nthw/core/nthw_spim.c',\n+    'nthw/core/nthw_spis.c',\n+    'nthw/core/nthw_tsm.c',\n+    'nthw/nthw_fpga_model.c',\n+    'nthw/nthw_dbs.c',\n+    'nthw/nthw_epp.c',\n+    'nthw/nthw_platform.c',\n+    'nthw/nthw_rac.c',\n+    'nthw/nthw_stat.c',\n     'nthw/supported/nthw_fpga_9563_055_024_0000.c',\n+    'ntlog/ntlog.c',\n+    'ntutil/nt_util.c',\n )\n \n if is_variable('default_cflags')\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c\nnew file mode 100644\nindex 0000000000..efdcc222a8\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.c\n@@ -0,0 +1,9 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"nthw_clock_profiles.h\"\n+\n+/* Clock profile for NT200A02 2x40G, 2x100G */\n+const int n_data_si5340_nt200a02_u23_v5;\n+const clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5;\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_clock_profiles.h b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.h\nnew file mode 100644\nindex 0000000000..4252f69e92\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_clock_profiles.h\n@@ -0,0 +1,39 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_CLOCK_PROFILES_H__\n+#define __NTHW_CLOCK_PROFILES_H__\n+\n+#include <stdint.h>\n+\n+#include \"nthw_helper.h\"\n+\n+#define clk_profile_size_error_msg \"size test failed\"\n+\n+typedef struct {\n+\tunsigned char reg_addr;\n+\tunsigned char reg_val;\n+\tunsigned char reg_mask;\n+} clk_profile_data_fmt0_t;\n+\n+typedef struct {\n+\tuint16_t reg_addr;\n+\tuint8_t reg_val;\n+} clk_profile_data_fmt1_t;\n+\n+typedef struct {\n+\tunsigned int reg_addr;\n+\tunsigned char reg_val;\n+} clk_profile_data_fmt2_t;\n+\n+typedef enum {\n+\tCLK_PROFILE_DATA_FMT_0,\n+\tCLK_PROFILE_DATA_FMT_1,\n+\tCLK_PROFILE_DATA_FMT_2\n+} clk_profile_data_fmt_t;\n+\n+extern const int n_data_si5340_nt200a02_u23_v5;\n+extern const  clk_profile_data_fmt2_t *p_data_si5340_nt200a02_u23_v5;\n+\n+#endif /* __NTHW_CLOCK_PROFILES_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_core.h b/drivers/net/ntnic/nthw/core/nthw_core.h\nnew file mode 100644\nindex 0000000000..798a95d5cf\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_core.h\n@@ -0,0 +1,31 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_CORE_H__\n+#define __NTHW_CORE_H__\n+\n+#include \"nthw_helper.h\"\n+\n+#include \"nthw_platform_drv.h\"\n+#include \"nthw_fpga_model.h\"\n+#include \"nthw_hif.h\"\n+#include \"nthw_pcie3.h\"\n+#include \"nthw_pci_rd_tg.h\"\n+#include \"nthw_pci_wr_tg.h\"\n+#include \"nthw_pci_ta.h\"\n+#include \"nthw_iic.h\"\n+\n+#include \"nthw_gpio_phy.h\"\n+#include \"nthw_mac_pcs.h\"\n+#include \"nthw_mac_pcs_xxv.h\"\n+#include \"nthw_sdc.h\"\n+\n+#include \"nthw_spim.h\"\n+#include \"nthw_spis.h\"\n+\n+#include \"nthw_tsm.h\"\n+\n+#include \"nthw_si5340.h\"\n+\n+#endif /* __NTHW_CORE_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_fpga.c b/drivers/net/ntnic/nthw/core/nthw_fpga.c\nnew file mode 100644\nindex 0000000000..646d45b7eb\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_fpga.c\n@@ -0,0 +1,914 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_fpga.h\"\n+#include \"nthw_fpga_instances.h\"\n+\n+#include \"nthw_spi_v3.h\"\n+\n+#include <arpa/inet.h>\n+\n+int nthw_fpga_get_param_info(struct fpga_info_s *p_fpga_info, nt_fpga_t *p_fpga)\n+{\n+\tconst int n_nims = fpga_get_product_param(p_fpga, NT_NIMS, -1);\n+\tconst int n_phy_ports = fpga_get_product_param(p_fpga, NT_PHY_PORTS, -1);\n+\tconst int n_phy_quads = fpga_get_product_param(p_fpga, NT_PHY_QUADS, -1);\n+\tconst int n_rx_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS, -1);\n+\tconst int n_tx_ports = fpga_get_product_param(p_fpga, NT_TX_PORTS, -1);\n+\n+\tp_fpga_info->n_nims = n_nims;\n+\tp_fpga_info->n_phy_ports = n_phy_ports;\n+\tp_fpga_info->n_phy_quads = n_phy_quads;\n+\tp_fpga_info->n_rx_ports = n_rx_ports;\n+\tp_fpga_info->n_tx_ports = n_tx_ports;\n+\tp_fpga_info->profile = FPGA_INFO_PROFILE_UNKNOWN;\n+\n+\t/* Check for VSWITCH FPGA */\n+\tif (fpga_get_product_param(p_fpga, NT_NFV_OVS_PRODUCT, 0) != 0)\n+\t\tp_fpga_info->profile = FPGA_INFO_PROFILE_VSWITCH;\n+\t/* Check for VSWITCH FPGA - legacy */\n+\telse if (fpga_get_product_param(p_fpga, NT_IOA_PRESENT, 0) != 0)\n+\t\tp_fpga_info->profile = FPGA_INFO_PROFILE_VSWITCH;\n+\n+\telse if (fpga_get_product_param(p_fpga, NT_QM_PRESENT, 0) != 0)\n+\t\tp_fpga_info->profile = FPGA_INFO_PROFILE_CAPTURE;\n+\n+\telse\n+\t\tp_fpga_info->profile = FPGA_INFO_PROFILE_INLINE;\n+\n+\treturn 0;\n+}\n+\n+int nthw_fpga_iic_read_byte(nt_fpga_t *p_fpga, const int n_instance_no,\n+\t\t\t   const uint8_t n_dev_addr, const uint8_t n_reg_addr)\n+{\n+\tnthw_iic_t nthw_iic;\n+\tuint8_t val = 0;\n+\n+\tif (nthw_iic_init(&nthw_iic, p_fpga, n_instance_no, 8) != 0)\n+\t\treturn -1;\n+\n+\tif (nthw_iic_readbyte(&nthw_iic, n_dev_addr, n_reg_addr, 1, &val) == 0)\n+\t\treturn val;\n+\n+\telse\n+\t\treturn -1;\n+}\n+\n+int nthw_fpga_iic_write_byte(nt_fpga_t *p_fpga, const int n_instance_no,\n+\t\t\t    const uint8_t n_dev_addr, const uint8_t n_reg_addr,\n+\t\t\t    uint8_t val)\n+{\n+\tnthw_iic_t nthw_iic;\n+\n+\tif (nthw_iic_init(&nthw_iic, p_fpga, n_instance_no, 8) != 0)\n+\t\treturn -1;\n+\n+\tif (nthw_iic_writebyte(&nthw_iic, n_dev_addr, n_reg_addr, 1, &val) != 0)\n+\t\treturn -1;\n+\n+\treturn 0;\n+}\n+\n+int nthw_fpga_iic_scan(nt_fpga_t *p_fpga, const int n_instance_no_begin,\n+\t\t      const int n_instance_no_end)\n+{\n+\tint i;\n+\n+\tassert(n_instance_no_begin <= n_instance_no_end);\n+\n+\tfor (i = n_instance_no_begin; i <= n_instance_no_end; i++) {\n+\t\tnthw_iic_t *p_nthw_iic = nthw_iic_new();\n+\n+\t\tif (p_nthw_iic) {\n+\t\t\tconst int rc = nthw_iic_init(p_nthw_iic, p_fpga, i, 8);\n+\n+\t\t\tif (rc == 0) {\n+\t\t\t\tnthw_iic_set_retry_params(p_nthw_iic, -1, 100, 100,\n+\t\t\t\t\t\t       3, 3);\n+\t\t\t\tnthw_iic_scan(p_nthw_iic);\n+\t\t\t}\n+\t\t\tnthw_iic_delete(p_nthw_iic);\n+\t\t\tp_nthw_iic = NULL;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+int nthw_fpga_silabs_detect(nt_fpga_t *p_fpga, const int n_instance_no,\n+\t\t\t   const int n_dev_addr, const int n_page_reg_addr)\n+{\n+\tconst char *const p_adapter_id_str _unused =\n+\t\tp_fpga->p_fpga_info->mp_adapter_id_str;\n+\tuint64_t ident = -1;\n+\tint res = -1;\n+\n+\tnthw_iic_t *p_nthw_iic = nthw_iic_new();\n+\n+\tif (p_nthw_iic) {\n+\t\tuint8_t data;\n+\t\tuint8_t a_silabs_ident[8];\n+\n+\t\tnthw_iic_init(p_nthw_iic, p_fpga, n_instance_no, 8);\n+\n+\t\tdata = 0;\n+\t\t/* switch to page 0 */\n+\t\tnthw_iic_write_data(p_nthw_iic, (uint8_t)n_dev_addr,\n+\t\t\t\t  (uint8_t)n_page_reg_addr, 1, &data);\n+\t\tres = nthw_iic_read_data(p_nthw_iic, (uint8_t)n_dev_addr, 0x00,\n+\t\t\t\t       sizeof(a_silabs_ident), a_silabs_ident);\n+\t\tif (res == 0) {\n+\t\t\tint i;\n+\n+\t\t\tfor (i = 0; i < (int)sizeof(a_silabs_ident); i++) {\n+\t\t\t\tident <<= 8;\n+\t\t\t\tident |= a_silabs_ident[i];\n+\t\t\t}\n+\t\t}\n+\t\tnthw_iic_delete(p_nthw_iic);\n+\t\tp_nthw_iic = NULL;\n+\n+\t\t/* Conclude SiLabs part */\n+\t\tif (res == 0) {\n+\t\t\tif (a_silabs_ident[3] == 0x53) {\n+\t\t\t\tif (a_silabs_ident[2] == 0x40)\n+\t\t\t\t\tres = 5340;\n+\t\t\t\telse if (a_silabs_ident[2] == 0x41)\n+\t\t\t\t\tres = 5341;\n+\t\t\t} else if (a_silabs_ident[2] == 38) {\n+\t\t\t\tres = 5338;\n+\t\t\t} else {\n+\t\t\t\tres = -1;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tNT_LOG(DBG, NTHW, \"%s: %016\" PRIX64 \": %d\\n\", p_adapter_id_str, ident,\n+\t       res);\n+\treturn res;\n+}\n+\n+/*\n+ * Calculate CRC-16-CCITT of passed data\n+ * CRC-16-CCITT ^16 + ^12 + ^5 + 1 (0x1021) (X.25, HDLC, XMODEM, Bluetooth,\n+ *   SD, many others; known as CRC-CCITT)\n+ */\n+static uint16_t crc16(uint8_t *buffer, size_t length)\n+{\n+\tuint16_t seed = 0;\n+\n+\twhile (length--) {\n+\t\tseed = (uint16_t)(seed >> 8 | seed << 8);\n+\t\tseed = (uint16_t)(seed ^ *buffer++);\n+\t\tseed = (uint16_t)(seed ^ (seed & 0xff) >> 4);\n+\t\tseed = (uint16_t)(seed ^ seed << 8 << 4);\n+\t\tseed = (uint16_t)(seed ^ (seed & 0xff) << 4 << 1);\n+\t}\n+\treturn seed;\n+}\n+\n+int nthw_fpga_avr_probe(nt_fpga_t *p_fpga, const int n_instance_no)\n+{\n+\tstruct fpga_info_s *p_fpga_info = p_fpga->p_fpga_info;\n+\tconst char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;\n+\tnthw_spi_v3_t *p_avr_spi;\n+\tint res = -1;\n+\n+\tp_avr_spi = nthw_spi_v3_new();\n+\tif (p_avr_spi) {\n+\t\tstruct avr_vpd_info_s {\n+\t\t\t/* avr info */\n+\t\t\tuint32_t n_avr_spi_version;\n+\t\t\tuint8_t n_avr_fw_ver_major;\n+\t\t\tuint8_t n_avr_fw_ver_minor;\n+\t\t\tuint8_t n_avr_fw_ver_micro;\n+\t\t\tuint8_t a_avr_fw_ver_str[50];\n+\t\t\tuint8_t a_avr_fw_plat_id_str[20];\n+\n+\t\t\t/* vpdEeprom_t */\n+\t\t\tuint8_t psu_hw_version;\n+\t\t\tuint8_t vpd_pn[GEN2_PN_SIZE];\n+\t\t\tuint8_t vpd_pba[GEN2_PBA_SIZE];\n+\t\t\tuint8_t vpd_sn[GEN2_SN_SIZE];\n+\t\t\tuint8_t vpd_board_name[GEN2_BNAME_SIZE];\n+\t\t\tuint8_t vpd_platform_section[GEN2_PLATFORM_SIZE];\n+\n+\t\t\t/* BoardInfo_t aka vpd_platform_section: */\n+\t\t\tuint32_t product_family; /* uint8_t 1: capture, 2: Inline, 3: analysis */\n+\t\t\tuint32_t feature_mask; /* Bit 0: OC192 capable */\n+\t\t\tuint32_t invfeature_mask;\n+\t\t\tuint8_t no_of_macs;\n+\t\t\tuint8_t mac_address[6];\n+\t\t\tuint16_t custom_id;\n+\t\t\tuint8_t user_id[8];\n+\t\t\t/*\n+\t\t\t * Reserved NT operations to monitor the reprogram count of userId with\n+\t\t\t * vpduser\n+\t\t\t */\n+\t\t\tuint16_t user_id_erase_write_count;\n+\n+\t\t\t/*\n+\t\t\t * AVR_OP_SYSINFO: struct version_sysinfo_request_container\n+\t\t\t * Which version of the sysinfo container to retrieve. Set to zero to fetch\n+\t\t\t * latest. offset zero of latest always contain an uint8_t version info\n+\t\t\t */\n+\t\t\tuint8_t sysinfo_container_version;\n+\n+\t\t\t/* AVR_OP_SYSINFO: struct AvrLibcVersion */\n+\t\t\tuint32_t sysinfo_avr_libc_version; /* The constant __AVR_LIBC_VERSION__ */\n+\n+\t\t\t/* AVR_OP_SYSINFO: struct AvrLibcSignature */\n+\t\t\tuint8_t sysinfo_signature_0; /* The constant SIGNATURE_0 */\n+\t\t\tuint8_t sysinfo_signature_1; /* The constant SIGNATURE_1 */\n+\t\t\tuint8_t sysinfo_signature_2; /* The constant SIGNATURE_2 */\n+\n+\t\t\t/* AVR_OP_SYSINFO: struct AvrOs */\n+\t\t\tuint8_t sysinfo_spi_version; /* SPI command layer version */\n+\t\t\t/*\n+\t\t\t * Hardware revision. Locked to eeprom address zero. Is also available via\n+\t\t\t * VPD read opcode (prior to v1.4b, this is required)\n+\t\t\t */\n+\t\t\tuint8_t sysinfo_hw_revision;\n+\t\t\t/*\n+\t\t\t * Number of ticks/second (Note: Be aware this may become zero if timer\n+\t\t\t * module is rewritten to a tickles system!)\n+\t\t\t */\n+\t\t\tuint8_t sysinfo_ticks_per_second;\n+\t\t\tuint32_t sysinfo_uptime; /* Uptime in seconds since last AVR reset */\n+\t\t\tuint8_t sysinfo_osccal; /* OSCCAL value */\n+\n+\t\t\t/*\n+\t\t\t * Meta data concluded/calculated from req/reply\n+\t\t\t */\n+\t\t\tbool b_feature_mask_valid;\n+\t\t\tbool b_crc16_valid;\n+\t\t\tuint16_t n_crc16_stored;\n+\t\t\tuint16_t n_crc16_calced;\n+\t\t\tuint64_t n_mac_val;\n+\t\t};\n+\n+\t\tstruct avr_vpd_info_s avr_vpd_info;\n+\t\tstruct tx_rx_buf tx_buf;\n+\t\tstruct tx_rx_buf rx_buf;\n+\t\tchar rx_data[MAX_AVR_CONTAINER_SIZE];\n+\t\tuint32_t u32;\n+\n+\t\tmemset(&avr_vpd_info, 0, sizeof(avr_vpd_info));\n+\n+\t\tnthw_spi_v3_init(p_avr_spi, p_fpga, n_instance_no);\n+\n+\t\t/* AVR_OP_SPI_VERSION */\n+\t\ttx_buf.size = 0;\n+\t\ttx_buf.p_buf = NULL;\n+\t\trx_buf.size = sizeof(u32);\n+\t\trx_buf.p_buf = &u32;\n+\t\tu32 = 0;\n+\t\tres = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SPI_VERSION, &tx_buf,\n+\t\t\t\t\t   &rx_buf);\n+\t\tavr_vpd_info.n_avr_spi_version = u32;\n+\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: SPI_VER: %d\\n\", p_adapter_id_str,\n+\t\t       n_instance_no, avr_vpd_info.n_avr_spi_version);\n+\n+\t\t/* AVR_OP_VERSION */\n+\t\ttx_buf.size = 0;\n+\t\ttx_buf.p_buf = NULL;\n+\t\trx_buf.size = sizeof(rx_data);\n+\t\trx_buf.p_buf = &rx_data;\n+\t\tres = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_VERSION, &tx_buf,\n+\t\t\t\t\t   &rx_buf);\n+\n+\t\tavr_vpd_info.n_avr_fw_ver_major = rx_data[0];\n+\t\tavr_vpd_info.n_avr_fw_ver_minor = rx_data[1];\n+\t\tavr_vpd_info.n_avr_fw_ver_micro = rx_data[2];\n+\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: FW_VER: %c.%c.%c\\n\",\n+\t\t       p_adapter_id_str, n_instance_no, avr_vpd_info.n_avr_fw_ver_major,\n+\t\t       avr_vpd_info.n_avr_fw_ver_minor,\n+\t\t       avr_vpd_info.n_avr_fw_ver_micro);\n+\n+\t\tmemcpy(avr_vpd_info.a_avr_fw_ver_str, &rx_data[0 + 3],\n+\t\t       sizeof(avr_vpd_info.a_avr_fw_ver_str));\n+\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: FW_VER_STR: '%.*s'\\n\",\n+\t\t       p_adapter_id_str, n_instance_no,\n+\t\t       (int)sizeof(avr_vpd_info.a_avr_fw_ver_str),\n+\t\t       avr_vpd_info.a_avr_fw_ver_str);\n+\n+\t\tmemcpy(avr_vpd_info.a_avr_fw_plat_id_str, &rx_data[0 + 3 + 50],\n+\t\t       sizeof(avr_vpd_info.a_avr_fw_plat_id_str));\n+\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: FW_HW_ID_STR: '%.*s'\\n\",\n+\t\t       p_adapter_id_str, n_instance_no,\n+\t\t       (int)sizeof(avr_vpd_info.a_avr_fw_plat_id_str),\n+\t\t       avr_vpd_info.a_avr_fw_plat_id_str);\n+\n+\t\trte_strscpy(p_fpga_info->nthw_hw_info.hw_plat_id_str,\n+\t\t\t(char *)avr_vpd_info.a_avr_fw_plat_id_str,\n+\t\t\tsizeof(p_fpga_info->nthw_hw_info.hw_plat_id_str));\n+\t\tp_fpga_info->nthw_hw_info.hw_plat_id_str\n+\t\t[sizeof(p_fpga_info->nthw_hw_info.hw_plat_id_str) - 1] =\n+\t\t\t0;\n+\n+\t\t/* AVR_OP_SYSINFO_2 */\n+\t\ttx_buf.size = 0;\n+\t\ttx_buf.p_buf = NULL;\n+\t\trx_buf.size = sizeof(rx_data);\n+\t\trx_buf.p_buf = &rx_data;\n+\t\tres = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SYSINFO_2, &tx_buf,\n+\t\t\t\t\t   &rx_buf);\n+\t\tif (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 &&\n+\t\t\t\trx_buf.size >= 16) {\n+\t\t\tif (rx_buf.size != 16) {\n+\t\t\t\tNT_LOG(WRN, NTHW,\n+\t\t\t\t       \"%s: AVR%d: SYSINFO2: reply is larger than expected: %04X %04X\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no, rx_buf.size,\n+\t\t\t\t       16);\n+\t\t\t} else {\n+\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t       \"%s: AVR%d: SYSINFO2: OK: res=%d sz=%d\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no, res,\n+\t\t\t\t       rx_buf.size);\n+\t\t\t}\n+\n+\t\t\tavr_vpd_info.sysinfo_container_version = rx_data[0];\n+\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: SYSINFO_REQ_VER: %d\\n\",\n+\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t       avr_vpd_info.sysinfo_container_version);\n+\n+\t\t\tmemcpy(&avr_vpd_info.sysinfo_avr_libc_version,\n+\t\t\t       &rx_data[0 + 1],\n+\t\t\t       sizeof(avr_vpd_info.sysinfo_avr_libc_version));\n+\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: LIBC_VER: %d\\n\",\n+\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t       avr_vpd_info.sysinfo_avr_libc_version);\n+\n+\t\t\tavr_vpd_info.sysinfo_signature_0 = rx_data[5];\n+\t\t\tavr_vpd_info.sysinfo_signature_1 = rx_data[6];\n+\t\t\tavr_vpd_info.sysinfo_signature_2 = rx_data[7];\n+\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t       \"%s: AVR%d: SIGNATURE: %02x%02x%02x\\n\",\n+\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t       avr_vpd_info.sysinfo_signature_0,\n+\t\t\t       avr_vpd_info.sysinfo_signature_1,\n+\t\t\t       avr_vpd_info.sysinfo_signature_2);\n+\n+\t\t\tavr_vpd_info.sysinfo_spi_version = rx_data[8];\n+\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: SPI_VER: %d\\n\",\n+\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t       avr_vpd_info.sysinfo_spi_version);\n+\n+\t\t\tavr_vpd_info.sysinfo_hw_revision = rx_data[9];\n+\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: HW_REV: %d\\n\",\n+\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t       avr_vpd_info.sysinfo_hw_revision);\n+\n+\t\t\tavr_vpd_info.sysinfo_ticks_per_second = rx_data[10];\n+\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: TICKS_PER_SEC: %d\\n\",\n+\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t       avr_vpd_info.sysinfo_ticks_per_second);\n+\n+\t\t\tmemcpy(&avr_vpd_info.sysinfo_uptime, &rx_data[11],\n+\t\t\t       sizeof(avr_vpd_info.sysinfo_uptime));\n+\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: UPTIME: %d\\n\",\n+\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t       avr_vpd_info.sysinfo_uptime);\n+\n+\t\t\tavr_vpd_info.sysinfo_osccal = rx_data[15];\n+\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: OSCCAL: %d\\n\",\n+\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t       avr_vpd_info.sysinfo_osccal);\n+\n+\t\t\t{\n+\t\t\t\tbool b_spi_ver_match _unused =\n+\t\t\t\t\t(avr_vpd_info.n_avr_spi_version ==\n+\t\t\t\t\t avr_vpd_info.sysinfo_spi_version);\n+\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t       \"%s: AVR%d: SPI_VER_TST: %s (%d %d)\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t       (b_spi_ver_match ? \"OK\" : \"MISMATCH\"),\n+\t\t\t\t       avr_vpd_info.n_avr_spi_version,\n+\t\t\t\t       avr_vpd_info.sysinfo_spi_version);\n+\t\t\t}\n+\t\t\t/* SYSINFO2: if response: only populate hw_id not hw_id_emulated */\n+\t\t\tp_fpga_info->nthw_hw_info.hw_id =\n+\t\t\t\tavr_vpd_info.sysinfo_hw_revision;\n+\t\t} else {\n+\t\t\t/* AVR_OP_SYSINFO */\n+\t\t\ttx_buf.size = 0;\n+\t\t\ttx_buf.p_buf = NULL;\n+\t\t\trx_buf.size = sizeof(rx_data);\n+\t\t\trx_buf.p_buf = &rx_data;\n+\t\t\tres = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SYSINFO,\n+\t\t\t\t\t\t   &tx_buf, &rx_buf);\n+\t\t\tif (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 &&\n+\t\t\t\t\trx_buf.size >= 16) {\n+\t\t\t\tif (rx_buf.size != 16) {\n+\t\t\t\t\tNT_LOG(WRN, NTHW,\n+\t\t\t\t\t       \"%s: AVR%d: SYSINFO: reply is larger than expected: %04X %04X\\n\",\n+\t\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t\t       rx_buf.size, 16);\n+\t\t\t\t} else {\n+\t\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t\t       \"%s: AVR%d: SYSINFO: OK: res=%d sz=%d\\n\",\n+\t\t\t\t\t       p_adapter_id_str, n_instance_no, res,\n+\t\t\t\t\t       rx_buf.size);\n+\t\t\t\t}\n+\n+\t\t\t\tavr_vpd_info.sysinfo_container_version =\n+\t\t\t\t\trx_data[0];\n+\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t       \"%s: AVR%d: SYSINFO_REQ_VER: %d\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t       avr_vpd_info.sysinfo_container_version);\n+\n+\t\t\t\tmemcpy(&avr_vpd_info.sysinfo_avr_libc_version,\n+\t\t\t\t       &rx_data[0 + 1],\n+\t\t\t\t       sizeof(avr_vpd_info\n+\t\t\t\t\t      .sysinfo_avr_libc_version));\n+\t\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: LIBC_VER: %d\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t       avr_vpd_info.sysinfo_avr_libc_version);\n+\n+\t\t\t\tavr_vpd_info.sysinfo_signature_0 = rx_data[5];\n+\t\t\t\tavr_vpd_info.sysinfo_signature_1 = rx_data[6];\n+\t\t\t\tavr_vpd_info.sysinfo_signature_2 = rx_data[7];\n+\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t       \"%s: AVR%d: SIGNATURE: %02x%02x%02x\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t       avr_vpd_info.sysinfo_signature_0,\n+\t\t\t\t       avr_vpd_info.sysinfo_signature_1,\n+\t\t\t\t       avr_vpd_info.sysinfo_signature_2);\n+\n+\t\t\t\tavr_vpd_info.sysinfo_spi_version = rx_data[8];\n+\t\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: SPI_VER: %d\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t       avr_vpd_info.sysinfo_spi_version);\n+\n+\t\t\t\tavr_vpd_info.sysinfo_hw_revision = rx_data[9];\n+\t\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: HW_REV: %d\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t       avr_vpd_info.sysinfo_hw_revision);\n+\t\t\t\tNT_LOG(INF, NTHW, \"%s: AVR%d: HW_REV: %d\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t       avr_vpd_info.sysinfo_hw_revision);\n+\n+\t\t\t\tavr_vpd_info.sysinfo_ticks_per_second =\n+\t\t\t\t\trx_data[10];\n+\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t       \"%s: AVR%d: TICKS_PER_SEC: %d\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t       avr_vpd_info.sysinfo_ticks_per_second);\n+\n+\t\t\t\tmemcpy(&avr_vpd_info.sysinfo_uptime,\n+\t\t\t\t       &rx_data[11],\n+\t\t\t\t       sizeof(avr_vpd_info.sysinfo_uptime));\n+\t\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: UPTIME: %d\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t       avr_vpd_info.sysinfo_uptime);\n+\n+\t\t\t\tavr_vpd_info.sysinfo_osccal = rx_data[15];\n+\t\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: OSCCAL: %d\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t       avr_vpd_info.sysinfo_osccal);\n+\n+\t\t\t\t{\n+\t\t\t\t\tbool b_spi_ver_match _unused =\n+\t\t\t\t\t\t(avr_vpd_info.n_avr_spi_version ==\n+\t\t\t\t\t\t avr_vpd_info\n+\t\t\t\t\t\t .sysinfo_spi_version);\n+\t\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t\t       \"%s: AVR%d: SPI_VER_TST: %s (%d %d)\\n\",\n+\t\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t\t       (b_spi_ver_match ? \"OK\" :\n+\t\t\t\t\t\t\"MISMATCH\"),\n+\t\t\t\t\t       avr_vpd_info.n_avr_spi_version,\n+\t\t\t\t\t       avr_vpd_info.sysinfo_spi_version);\n+\t\t\t\t}\n+\n+\t\t\t\tp_fpga_info->nthw_hw_info.hw_id =\n+\t\t\t\t\tavr_vpd_info.sysinfo_hw_revision;\n+\t\t\t\tp_fpga_info->nthw_hw_info.hw_id_emulated =\n+\t\t\t\t\tavr_vpd_info.sysinfo_hw_revision;\n+\t\t\t} else {\n+\t\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t\t       \"%s: AVR%d: SYSINFO: NA: res=%d sz=%d\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no, res,\n+\t\t\t\t       rx_buf.size);\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* AVR_OP_VPD_READ */\n+\t\ttx_buf.size = 0;\n+\t\ttx_buf.p_buf = NULL;\n+\t\trx_buf.size = sizeof(rx_data);\n+\t\trx_buf.p_buf = &rx_data;\n+\t\tres = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_VPD_READ, &tx_buf,\n+\t\t\t\t\t   &rx_buf);\n+\t\tif (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 &&\n+\t\t\t\trx_buf.size >= GEN2_VPD_SIZE_TOTAL) {\n+\t\t\tavr_vpd_info.n_crc16_calced =\n+\t\t\t\tcrc16(rx_buf.p_buf, rx_buf.size - 2);\n+\t\t\tmemcpy(&avr_vpd_info.n_crc16_stored,\n+\t\t\t       &rx_data[rx_buf.size - 2],\n+\t\t\t       sizeof(avr_vpd_info.n_crc16_stored));\n+\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: VPD_CRC: %04X %04X\\n\",\n+\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t       avr_vpd_info.n_crc16_stored,\n+\t\t\t       avr_vpd_info.n_crc16_calced);\n+\n+\t\t\tavr_vpd_info.b_crc16_valid = (avr_vpd_info.n_crc16_stored ==\n+\t\t\t\t\t\t    avr_vpd_info.n_crc16_calced);\n+\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: CRC_TST: %s\\n\",\n+\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t       (avr_vpd_info.b_crc16_valid ? \"OK\" : \"ERROR\"));\n+\n+\t\t\tif (avr_vpd_info.b_crc16_valid) {\n+\t\t\t\tmemcpy(&avr_vpd_info.psu_hw_version, &rx_data[0],\n+\t\t\t\t       sizeof(avr_vpd_info.psu_hw_version));\n+\t\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: PSU_HW_VER: %d\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t       avr_vpd_info.psu_hw_version);\n+\n+\t\t\t\tmemcpy(&avr_vpd_info.vpd_pn, &rx_data[0 + 1],\n+\t\t\t\t       sizeof(avr_vpd_info.vpd_pn));\n+\t\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: PN: '%.*s'\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no, GEN2_PN_SIZE,\n+\t\t\t\t       avr_vpd_info.vpd_pn);\n+\n+\t\t\t\tmemcpy(&avr_vpd_info.vpd_pba,\n+\t\t\t\t       &rx_data[0 + 1 + GEN2_PN_SIZE],\n+\t\t\t\t       sizeof(avr_vpd_info.vpd_pba));\n+\t\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: PBA: '%.*s'\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t       GEN2_PBA_SIZE, avr_vpd_info.vpd_pba);\n+\n+\t\t\t\tmemcpy(&avr_vpd_info.vpd_sn,\n+\t\t\t\t       &rx_data[0 + 1 + GEN2_PN_SIZE +\n+\t\t\t\t\t\t GEN2_PBA_SIZE],\n+\t\t\t\t       sizeof(avr_vpd_info.vpd_sn));\n+\t\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: SN: '%.*s'\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no, GEN2_SN_SIZE,\n+\t\t\t\t       avr_vpd_info.vpd_sn);\n+\n+\t\t\t\tmemcpy(&avr_vpd_info.vpd_board_name,\n+\t\t\t\t       &rx_data[0 + 1 + GEN2_PN_SIZE +\n+\t\t\t\t\t\t GEN2_PBA_SIZE + GEN2_SN_SIZE],\n+\t\t\t\t       sizeof(avr_vpd_info.vpd_board_name));\n+\t\t\t\tNT_LOG(DBG, NTHW, \"%s: AVR%d: BN: '%.*s'\\n\",\n+\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t       GEN2_BNAME_SIZE,\n+\t\t\t\t       avr_vpd_info.vpd_board_name);\n+\n+\t\t\t\t{\n+\t\t\t\t\tuint32_t u1;\n+\t\t\t\t\tunion mac_u {\n+\t\t\t\t\t\tuint8_t a_u8[8];\n+\t\t\t\t\t\tuint16_t a_u16[4];\n+\t\t\t\t\t\tuint32_t a_u32[2];\n+\t\t\t\t\t\tuint64_t a_u64[1];\n+\t\t\t\t\t} mac;\n+\n+\t\t\t\t\t /* vpd_platform_section */\n+\t\t\t\t\tuint8_t *p_vpd_board_info =\n+\t\t\t\t\t\t(uint8_t *)(&rx_data[1 +\n+\t\t\t\t\t\t\t\t      GEN2_PN_SIZE +\n+\t\t\t\t\t\t\t\t      GEN2_PBA_SIZE +\n+\t\t\t\t\t\t\t\t      GEN2_SN_SIZE +\n+\t\t\t\t\t\t\t\t      GEN2_BNAME_SIZE]);\n+\t\t\t\t\tmemcpy(&avr_vpd_info.product_family,\n+\t\t\t\t\t       &p_vpd_board_info[0],\n+\t\t\t\t\t       sizeof(avr_vpd_info\n+\t\t\t\t\t\t      .product_family));\n+\t\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t\t       \"%s: AVR%d: PROD_FAM: %d\\n\",\n+\t\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t\t       avr_vpd_info.product_family);\n+\n+\t\t\t\t\tmemcpy(&avr_vpd_info.feature_mask,\n+\t\t\t\t\t       &p_vpd_board_info[0 + 4],\n+\t\t\t\t\t       sizeof(avr_vpd_info.feature_mask));\n+\t\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t\t       \"%s: AVR%d: FMSK_VAL: 0x%08X\\n\",\n+\t\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t\t       avr_vpd_info.feature_mask);\n+\n+\t\t\t\t\tmemcpy(&avr_vpd_info.invfeature_mask,\n+\t\t\t\t\t       &p_vpd_board_info[0 + 4 + 4],\n+\t\t\t\t\t       sizeof(avr_vpd_info\n+\t\t\t\t\t\t      .invfeature_mask));\n+\t\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t\t       \"%s: AVR%d: FMSK_INV: 0x%08X\\n\",\n+\t\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t\t       avr_vpd_info.invfeature_mask);\n+\n+\t\t\t\t\tavr_vpd_info.b_feature_mask_valid =\n+\t\t\t\t\t\t(avr_vpd_info.feature_mask ==\n+\t\t\t\t\t\t ~avr_vpd_info.invfeature_mask);\n+\t\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t\t       \"%s: AVR%d: FMSK_TST: %s\\n\",\n+\t\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t\t       (avr_vpd_info.b_feature_mask_valid ?\n+\t\t\t\t\t\t\"OK\" :\n+\t\t\t\t\t\t\"ERROR\"));\n+\n+\t\t\t\t\tmemcpy(&avr_vpd_info.no_of_macs,\n+\t\t\t\t\t       &p_vpd_board_info[0 + 4 + 4 + 4],\n+\t\t\t\t\t       sizeof(avr_vpd_info.no_of_macs));\n+\t\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t\t       \"%s: AVR%d: NUM_MACS: %d\\n\",\n+\t\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t\t       avr_vpd_info.no_of_macs);\n+\n+\t\t\t\t\tmemcpy(&avr_vpd_info.mac_address,\n+\t\t\t\t\t       &p_vpd_board_info[0 + 4 + 4 + 4 + 1],\n+\t\t\t\t\t       sizeof(avr_vpd_info.mac_address));\n+\t\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t\t       \"%s: AVR%d: MAC_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\\n\",\n+\t\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t\t       avr_vpd_info.mac_address[0],\n+\t\t\t\t\t       avr_vpd_info.mac_address[1],\n+\t\t\t\t\t       avr_vpd_info.mac_address[2],\n+\t\t\t\t\t       avr_vpd_info.mac_address[3],\n+\t\t\t\t\t       avr_vpd_info.mac_address[4],\n+\t\t\t\t\t       avr_vpd_info.mac_address[5]);\n+\n+\t\t\t\t\tmac.a_u64[0] = 0;\n+\t\t\t\t\tmemcpy(&mac.a_u8[2],\n+\t\t\t\t\t       &avr_vpd_info.mac_address,\n+\t\t\t\t\t       sizeof(avr_vpd_info.mac_address));\n+\t\t\t\t\tu1 = ntohl(mac.a_u32[0]);\n+\t\t\t\t\tif (u1 != mac.a_u32[0]) {\n+\t\t\t\t\t\tconst uint32_t u0 = ntohl(mac.a_u32[1]);\n+\t\t\t\t\t\tmac.a_u32[0] = u0;\n+\t\t\t\t\t\tmac.a_u32[1] = u1;\n+\t\t\t\t\t}\n+\t\t\t\t\tavr_vpd_info.n_mac_val = mac.a_u64[0];\n+\t\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t\t       \"%s: AVR%d: MAC_U64: %012\" PRIX64\n+\t\t\t\t\t       \"\\n\",\n+\t\t\t\t\t       p_adapter_id_str, n_instance_no,\n+\t\t\t\t\t       avr_vpd_info.n_mac_val);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tp_fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_count =\n+\t\t\t\tavr_vpd_info.no_of_macs;\n+\t\t\tp_fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_value =\n+\t\t\t\tavr_vpd_info.n_mac_val;\n+\t\t\tmemcpy(p_fpga_info->nthw_hw_info.vpd_info.ma_mac_addr_octets,\n+\t\t\t       avr_vpd_info.mac_address,\n+\t\t\t       ARRAY_SIZE(p_fpga_info->nthw_hw_info.vpd_info\n+\t\t\t\t\t  .ma_mac_addr_octets));\n+\t\t} else {\n+\t\t\tNT_LOG(ERR, NTHW, \"%s:%u: res=%d\\n\", __func__, __LINE__,\n+\t\t\t       res);\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: AVR%d: SYSINFO2: NA: res=%d sz=%d\\n\",\n+\t\t\t       p_adapter_id_str, n_instance_no, res, rx_buf.size);\n+\t\t}\n+\t}\n+\n+\treturn res;\n+}\n+\n+/*\n+ * NT50B01, NT200A02, NT200A01-HWbuild2\n+ */\n+int nthw_fpga_si5340_clock_synth_init_fmt2(nt_fpga_t *p_fpga,\n+\tconst uint8_t n_iic_addr,\n+\tconst clk_profile_data_fmt2_t *p_clk_profile,\n+\tconst int n_clk_profile_rec_cnt)\n+{\n+\tint res;\n+\tnthw_iic_t *p_nthw_iic = nthw_iic_new();\n+\tnthw_si5340_t *p_nthw_si5340 = nthw_si5340_new();\n+\n+\tassert(p_nthw_iic);\n+\tassert(p_nthw_si5340);\n+\tnthw_iic_init(p_nthw_iic, p_fpga, 0, 8); /* I2C cycle time 125Mhz ~ 8ns */\n+\n+\tnthw_si5340_init(p_nthw_si5340, p_nthw_iic,\n+\t\t\tn_iic_addr); /* Si5340_U23_I2c_Addr_7bit */\n+\tres = nthw_si5340_config_fmt2(p_nthw_si5340, p_clk_profile,\n+\t\t\t\t    n_clk_profile_rec_cnt);\n+\tnthw_si5340_delete(p_nthw_si5340);\n+\tp_nthw_si5340 = NULL;\n+\n+\treturn res;\n+}\n+\n+int nthw_fpga_init(struct fpga_info_s *p_fpga_info)\n+{\n+\tconst char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;\n+\n+\tnthw_hif_t *p_nthw_hif = NULL;\n+\tnthw_pcie3_t *p_nthw_pcie3 = NULL;\n+\tnthw_rac_t *p_nthw_rac = NULL;\n+\tnthw_tsm_t *p_nthw_tsm = NULL;\n+\n+\tuint64_t n_fpga_ident = 0;\n+\tnt_fpga_mgr_t *p_fpga_mgr = NULL;\n+\tnt_fpga_t *p_fpga = NULL;\n+\n+\tchar s_fpga_prod_ver_rev_str[32] = { 0 };\n+\n+\tint res = 0;\n+\n+\tassert(p_fpga_info);\n+\n+\t{\n+\t\tint n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id, n_fpga_rev_id;\n+\t\tuint64_t n_fpga_ident;\n+\t\tuint32_t n_fpga_ident_low, n_fpga_ident_high, n_fpga_build_time;\n+\n+\t\tnthw_rac_reg_read32(p_fpga_info, 0x0, &n_fpga_ident_low);\n+\t\tnthw_rac_reg_read32(p_fpga_info, 0x8, &n_fpga_ident_high);\n+\t\tnthw_rac_reg_read32(p_fpga_info, 0x10, &n_fpga_build_time);\n+\n+\t\tn_fpga_ident = (((uint64_t)n_fpga_ident_high << 32) | n_fpga_ident_low);\n+\t\tn_fpga_type_id = FPGAID_TO_PRODUCTTYPE(n_fpga_ident);\n+\t\tn_fpga_prod_id = FPGAID_TO_PRODUCTCODE(n_fpga_ident);\n+\t\tn_fpga_ver_id = FPGAID_TO_VERSIONCODE(n_fpga_ident);\n+\t\tn_fpga_rev_id = FPGAID_TO_REVISIONCODE(n_fpga_ident);\n+\n+\t\tp_fpga_info->n_fpga_ident = n_fpga_ident;\n+\t\tp_fpga_info->n_fpga_type_id = n_fpga_type_id;\n+\t\tp_fpga_info->n_fpga_prod_id = n_fpga_prod_id;\n+\t\tp_fpga_info->n_fpga_ver_id = n_fpga_ver_id;\n+\t\tp_fpga_info->n_fpga_rev_id = n_fpga_rev_id;\n+\t\tp_fpga_info->n_fpga_build_time = n_fpga_build_time;\n+\n+\t\tsnprintf(s_fpga_prod_ver_rev_str, sizeof(s_fpga_prod_ver_rev_str),\n+\t\t\t \"%04d-%04d-%02d-%02d\", n_fpga_type_id, n_fpga_prod_id,\n+\t\t\t n_fpga_ver_id, n_fpga_rev_id);\n+\n+\t\tNT_LOG(INF, NTHW, \"%s: FPGA %s (%\" PRIX64 \") [%08X]\\n\",\n+\t\t       p_adapter_id_str, s_fpga_prod_ver_rev_str, n_fpga_ident,\n+\t\t       n_fpga_build_time);\n+\t}\n+\n+\tn_fpga_ident = p_fpga_info->n_fpga_ident;\n+\n+\tp_fpga_mgr = fpga_mgr_new();\n+\tfpga_mgr_init(p_fpga_mgr);\n+\tfpga_mgr_log_dump(p_fpga_mgr);\n+\tp_fpga = fpga_mgr_query_fpga(p_fpga_mgr, n_fpga_ident, p_fpga_info);\n+\tp_fpga_info->mp_fpga = p_fpga;\n+\tif (p_fpga == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: Unsupported FPGA: %s (%08X)\\n\",\n+\t\t       p_adapter_id_str, s_fpga_prod_ver_rev_str,\n+\t\t       p_fpga_info->n_fpga_build_time);\n+\t\treturn -1;\n+\t}\n+\n+\tif (p_fpga_mgr) {\n+\t\tfpga_mgr_delete(p_fpga_mgr);\n+\t\tp_fpga_mgr = NULL;\n+\t}\n+\n+\t/* Read Fpga param info */\n+\tnthw_fpga_get_param_info(p_fpga_info, p_fpga);\n+\n+\t/* debug: report params */\n+\tNT_LOG(DBG, NTHW, \"%s: NT_NIMS=%d\\n\", p_adapter_id_str, p_fpga_info->n_nims);\n+\tNT_LOG(DBG, NTHW, \"%s: NT_PHY_PORTS=%d\\n\", p_adapter_id_str,\n+\t       p_fpga_info->n_phy_ports);\n+\tNT_LOG(DBG, NTHW, \"%s: NT_PHY_QUADS=%d\\n\", p_adapter_id_str,\n+\t       p_fpga_info->n_phy_quads);\n+\tNT_LOG(DBG, NTHW, \"%s: NT_RX_PORTS=%d\\n\", p_adapter_id_str,\n+\t       p_fpga_info->n_rx_ports);\n+\tNT_LOG(DBG, NTHW, \"%s: NT_TX_PORTS=%d\\n\", p_adapter_id_str,\n+\t       p_fpga_info->n_tx_ports);\n+\tNT_LOG(DBG, NTHW, \"%s: nProfile=%d\\n\", p_adapter_id_str,\n+\t       (int)p_fpga_info->profile);\n+\n+\tp_nthw_rac = nthw_rac_new();\n+\tif (p_nthw_rac == NULL) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: Unsupported FPGA: RAC is not found: %s (%08X)\\n\",\n+\t\t       p_adapter_id_str, s_fpga_prod_ver_rev_str,\n+\t\t       p_fpga_info->n_fpga_build_time);\n+\t\treturn -1;\n+\t}\n+\n+\tnthw_rac_init(p_nthw_rac, p_fpga, p_fpga_info);\n+\tnthw_rac_rab_flush(p_nthw_rac);\n+\tp_fpga_info->mp_nthw_rac = p_nthw_rac;\n+\n+\t/* special case: values below 0x100 will disable debug on RAC communication */\n+\t{\n+\t\tconst int n_fpga_initial_debug_mode = p_fpga_info->n_fpga_debug_mode;\n+\n+\t\tfpga_set_debug_mode(p_fpga, n_fpga_initial_debug_mode);\n+\t}\n+\n+\tswitch (p_fpga_info->n_nthw_adapter_id) {\n+\tcase NT_HW_ADAPTER_ID_NT200A01: /* fallthrough */\n+\tcase NT_HW_ADAPTER_ID_NT200A02:\n+\t\tres = nthw_fpga_nt200a0x_init(p_fpga_info);\n+\t\tbreak;\n+\tdefault:\n+\t\tNT_LOG(ERR, NTHW, \"%s: Unsupported HW product id: %d\\n\",\n+\t\t       p_adapter_id_str, p_fpga_info->n_nthw_adapter_id);\n+\t\tres = -1;\n+\t\tbreak;\n+\t}\n+\n+\tif (res) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: status: 0x%08X\\n\", p_adapter_id_str, res);\n+\t\treturn res;\n+\t}\n+\n+\tres = nthw_pcie3_init(NULL, p_fpga, 0); /* Probe for module */\n+\tif (res == 0) {\n+\t\tp_nthw_pcie3 = nthw_pcie3_new();\n+\t\tif (p_nthw_pcie3) {\n+\t\t\tres = nthw_pcie3_init(p_nthw_pcie3, p_fpga, 0);\n+\t\t\tif (res == 0) {\n+\t\t\t\tNT_LOG(DBG, NTHW, \"%s: Pcie3 module found\\n\",\n+\t\t\t\t       p_adapter_id_str);\n+\t\t\t\tnthw_pcie3_trigger_sample_time(p_nthw_pcie3);\n+\t\t\t} else {\n+\t\t\t\tnthw_pcie3_delete(p_nthw_pcie3);\n+\t\t\t\tp_nthw_pcie3 = NULL;\n+\t\t\t}\n+\t\t}\n+\t\tp_fpga_info->mp_nthw_pcie3 = p_nthw_pcie3;\n+\t}\n+\n+\tif (p_nthw_pcie3 == NULL) {\n+\t\tp_nthw_hif = nthw_hif_new();\n+\t\tif (p_nthw_hif) {\n+\t\t\tres = nthw_hif_init(p_nthw_hif, p_fpga, 0);\n+\t\t\tif (res == 0) {\n+\t\t\t\tNT_LOG(DBG, NTHW, \"%s: Hif module found\\n\",\n+\t\t\t\t       p_adapter_id_str);\n+\t\t\t\tnthw_hif_trigger_sample_time(p_nthw_hif);\n+\t\t\t} else {\n+\t\t\t\tnthw_hif_delete(p_nthw_hif);\n+\t\t\t\tp_nthw_hif = NULL;\n+\t\t\t}\n+\t\t}\n+\t}\n+\tp_fpga_info->mp_nthw_hif = p_nthw_hif;\n+\n+\tp_nthw_tsm = nthw_tsm_new();\n+\tif (p_nthw_tsm) {\n+\t\tnthw_tsm_init(p_nthw_tsm, p_fpga, 0);\n+\n+\t\tnthw_tsm_set_config_ts_format(p_nthw_tsm,\n+\t\t\t\t\t  1); /* 1 = TSM: TS format native */\n+\n+\t\t/* Timer T0 - stat toggle timer */\n+\t\tnthw_tsm_set_timer_t0_enable(p_nthw_tsm, false);\n+\t\tnthw_tsm_set_timer_t0_max_count(p_nthw_tsm, 50 * 1000 * 1000); /* ns */\n+\t\tnthw_tsm_set_timer_t0_enable(p_nthw_tsm, true);\n+\n+\t\t/* Timer T1 - keep alive timer */\n+\t\tnthw_tsm_set_timer_t1_enable(p_nthw_tsm, false);\n+\t\tnthw_tsm_set_timer_t1_max_count(p_nthw_tsm,\n+\t\t\t\t\t   100 * 1000 * 1000); /* ns */\n+\t\tnthw_tsm_set_timer_t1_enable(p_nthw_tsm, true);\n+\t}\n+\tp_fpga_info->mp_nthw_tsm = p_nthw_tsm;\n+\n+\t/* TSM sample triggering: test validation... */\n+#if defined(DEBUG) && (1)\n+\t{\n+\t\tuint64_t n_time, n_ts;\n+\t\tint i;\n+\n+\t\tfor (i = 0; i < 4; i++) {\n+\t\t\tif (p_nthw_hif)\n+\t\t\t\tnthw_hif_trigger_sample_time(p_nthw_hif);\n+\n+\t\t\telse if (p_nthw_pcie3)\n+\t\t\t\tnthw_pcie3_trigger_sample_time(p_nthw_pcie3);\n+\t\t\tnthw_tsm_get_time(p_nthw_tsm, &n_time);\n+\t\t\tnthw_tsm_get_ts(p_nthw_tsm, &n_ts);\n+\n+\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t       \"%s: TSM time: %016\" PRIX64 \" %016\" PRIX64 \"\\n\",\n+\t\t\t       p_adapter_id_str, n_time, n_ts);\n+\n+\t\t\tNT_OS_WAIT_USEC(1000);\n+\t\t}\n+\t}\n+#endif\n+\n+\treturn res;\n+}\n+\n+int nthw_fpga_shutdown(struct fpga_info_s *p_fpga_info)\n+{\n+\tint res = -1;\n+\n+\tif (p_fpga_info) {\n+\t\tif (p_fpga_info && p_fpga_info->mp_nthw_rac)\n+\t\t\tres = nthw_rac_rab_reset(p_fpga_info->mp_nthw_rac);\n+\t}\n+\n+\treturn res;\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_fpga.h b/drivers/net/ntnic/nthw/core/nthw_fpga.h\nnew file mode 100644\nindex 0000000000..336d81f337\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_fpga.h\n@@ -0,0 +1,47 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_FPGA_H__\n+#define __NTHW_FPGA_H__\n+\n+#include \"nthw_drv.h\"\n+\n+#include \"nthw_fpga_model.h\"\n+\n+#include \"nthw_rac.h\"\n+#include \"nthw_iic.h\"\n+\n+#include \"nthw_stat.h\"\n+\n+#include \"nthw_fpga_rst.h\"\n+\n+#include \"nthw_fpga_nt200a0x.h\"\n+\n+#include \"nthw_dbs.h\"\n+\n+int nthw_fpga_init(struct fpga_info_s *p_fpga_info);\n+int nthw_fpga_shutdown(struct fpga_info_s *p_fpga_info);\n+\n+int nthw_fpga_get_param_info(struct fpga_info_s *p_fpga_info, nt_fpga_t *p_fpga);\n+\n+int nthw_fpga_avr_probe(nt_fpga_t *p_fpga, const int n_instance_no);\n+\n+int nthw_fpga_iic_scan(nt_fpga_t *p_fpga, const int n_instance_no_begin,\n+\t\t       const int n_instance_no_end);\n+\n+int nthw_fpga_iic_read_byte(nt_fpga_t *p_fpga, const int n_instance_no,\n+\t\t\t    const uint8_t n_dev_addr, const uint8_t n_reg_addr);\n+int nthw_fpga_iic_write_byte(nt_fpga_t *p_fpga, const int n_instance_no,\n+\t\t\t     const uint8_t n_dev_addr, const uint8_t n_reg_addr,\n+\t\t\t     uint8_t val);\n+\n+int nthw_fpga_silabs_detect(nt_fpga_t *p_fpga, const int n_instance_no,\n+\t\t\t    const int n_dev_addr, const int n_page_reg_addr);\n+\n+int nthw_fpga_si5340_clock_synth_init_fmt2(nt_fpga_t *p_fpga,\n+\tconst uint8_t n_iic_addr,\n+\tconst clk_profile_data_fmt2_t *p_clk_profile,\n+\tconst int n_clk_profile_rec_cnt);\n+\n+#endif /* __NTHW_FPGA_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c\nnew file mode 100644\nindex 0000000000..70338fdfd7\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.c\n@@ -0,0 +1,46 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_fpga.h\"\n+#include \"nthw_fpga_nt200a0x.h\"\n+\n+int nthw_fpga_nt200a0x_init(struct fpga_info_s *p_fpga_info)\n+{\n+\tassert(p_fpga_info);\n+\n+\tconst char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;\n+\tstruct nthw_fpga_rst_nt200a0x rst;\n+\tint res = -1;\n+\n+\t/* reset common */\n+\tres = nthw_fpga_rst_nt200a0x_init(p_fpga_info, &rst);\n+\tif (res) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: %s: loc=%u: FPGA=%04d res=%d\\n\",\n+\t\t       p_adapter_id_str, __func__, __LINE__,\n+\t\t       p_fpga_info->n_fpga_prod_id, res);\n+\t\treturn res;\n+\t}\n+\n+\t/* reset specific */\n+\tswitch (p_fpga_info->n_fpga_prod_id) {\n+\tcase 9563:\n+\t\tres = nthw_fpga_rst9563_init(p_fpga_info, &rst);\n+\t\tbreak;\n+\tdefault:\n+\t\tNT_LOG(ERR, NTHW, \"%s: Unsupported FPGA product: %04d\\n\",\n+\t\t       p_adapter_id_str, p_fpga_info->n_fpga_prod_id);\n+\t\tres = -1;\n+\t\tbreak;\n+\t}\n+\tif (res) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: %s: loc=%u: FPGA=%04d res=%d\\n\",\n+\t\t       p_adapter_id_str, __func__, __LINE__,\n+\t\t       p_fpga_info->n_fpga_prod_id, res);\n+\t\treturn res;\n+\t}\n+\n+\treturn res;\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h\nnew file mode 100644\nindex 0000000000..ff324bee39\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_nt200a0x.h\n@@ -0,0 +1,14 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_FPGA_NT200A0X_H__\n+#define __NTHW_FPGA_NT200A0X_H__\n+\n+int nthw_fpga_nt200a0x_init(struct fpga_info_s *p_fpga_info);\n+\n+/* NT200A02: 9563 */\n+int nthw_fpga_rst9563_init(struct fpga_info_s *p_fpga_info,\n+\t\t\t  struct nthw_fpga_rst_nt200a0x *const p);\n+\n+#endif /* __NTHW_FPGA_NT200A0X_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c\nnew file mode 100644\nindex 0000000000..66c148bab2\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.c\n@@ -0,0 +1,10 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_fpga.h\"\n+#include \"nthw_fpga_nt200a0x.h\"\n+\n+#include \"nthw_fpga_rst.h\"\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst.h b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.h\nnew file mode 100644\nindex 0000000000..2099c4b677\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst.h\n@@ -0,0 +1,17 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_FPGA_RST_H__\n+#define __NTHW_FPGA_RST_H__\n+\n+#include \"nthw_drv.h\"\n+\n+#include \"nthw_fpga_model.h\"\n+\n+#include \"nthw_rac.h\"\n+#include \"nthw_iic.h\"\n+\n+#include \"nthw_fpga_rst_nt200a0x.h\"\n+\n+#endif /* __NTHW_FPGA_RST_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c b/drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c\nnew file mode 100644\nindex 0000000000..077b043c60\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst9563.c\n@@ -0,0 +1,241 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+#include \"nthw_fpga.h\"\n+\n+#include \"nthw_clock_profiles.h\"\n+\n+static int nthw_fpga_rst9563_setup(nt_fpga_t *p_fpga,\n+\t\t\t\t  struct nthw_fpga_rst_nt200a0x *const p)\n+{\n+\tconst char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;\n+\tconst int n_fpga_product_id = p_fpga->m_product_id;\n+\tconst int n_fpga_version = p_fpga->m_fpga_version;\n+\tconst int n_fpga_revision = p_fpga->m_fpga_revision;\n+\n+\tnt_module_t *p_mod_rst;\n+\tnt_register_t *p_curr_reg;\n+\n+\tassert(p);\n+\tp->mn_fpga_product_id = n_fpga_product_id;\n+\tp->mn_fpga_version = n_fpga_version;\n+\tp->mn_fpga_revision = n_fpga_revision;\n+\n+\tNT_LOG(DBG, NTHW, \"%s: %s: FPGA reset setup: FPGA %04d-%02d-%02d\\n\",\n+\t       p_adapter_id_str, __func__, n_fpga_product_id, n_fpga_version,\n+\t       n_fpga_revision);\n+\n+\tp_mod_rst = fpga_query_module(p_fpga, MOD_RST9563, 0);\n+\tif (p_mod_rst == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: RST %d: no such instance\\n\",\n+\t\t       p_adapter_id_str, 0);\n+\t\treturn -1;\n+\t}\n+\n+\tp_mod_rst = fpga_query_module(p_fpga, MOD_RST9563, 0);\n+\tif (p_mod_rst == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: RST %d: no such instance\\n\",\n+\t\t       p_adapter_id_str, 0);\n+\t\treturn -1;\n+\t}\n+\n+\t/* RST register field pointers */\n+\tp_curr_reg = module_get_register(p_mod_rst, RST9563_RST);\n+\tp->mp_fld_rst_sys = register_get_field(p_curr_reg, RST9563_RST_SYS);\n+\tp->mp_fld_rst_sys_mmcm = register_get_field(p_curr_reg, RST9563_RST_SYS_MMCM);\n+\tp->mp_fld_rst_core_mmcm =\n+\t\tregister_get_field(p_curr_reg, RST9563_RST_CORE_MMCM);\n+\tp->mp_fld_rst_rpp = register_get_field(p_curr_reg, RST9563_RST_RPP);\n+\tp->mp_fld_rst_ddr4 = register_get_field(p_curr_reg, RST9563_RST_DDR4);\n+\tp->mp_fld_rst_sdc = register_get_field(p_curr_reg, RST9563_RST_SDC);\n+\tp->mp_fld_rst_phy = register_get_field(p_curr_reg, RST9563_RST_PHY);\n+\tp->mp_fld_rst_serdes_rx = NULL; /* Field not present on 9563 */\n+\tp->mp_fld_rst_serdes_tx = NULL; /* Field not present on 9563 */\n+\tp->mp_fld_rst_serdes_rx_datapath = NULL; /* Field not present on 9563 */\n+\tp->mp_fld_rst_pcs_rx = NULL; /* Field not present on 9563 */\n+\tp->mp_fld_rst_mac_rx = register_get_field(p_curr_reg, RST9563_RST_MAC_RX);\n+\tp->mp_fld_rst_mac_tx = NULL;\n+\tp->mp_fld_rst_ptp = register_get_field(p_curr_reg, RST9563_RST_PTP);\n+\tp->mp_fld_rst_ptp = register_get_field(p_curr_reg, RST9563_RST_PTP);\n+\tp->mp_fld_rst_ts = register_get_field(p_curr_reg, RST9563_RST_TS);\n+\tp->mp_fld_rst_ptp_mmcm = register_get_field(p_curr_reg, RST9563_RST_PTP_MMCM);\n+\tp->mp_fld_rst_ts_mmcm = register_get_field(p_curr_reg, RST9563_RST_TS_MMCM);\n+\t/* referenced in separate function */\n+\tp->mp_fld_rst_periph = register_get_field(p_curr_reg, RST9563_RST_PERIPH);\n+\tp->mp_fld_rst_tsm_ref_mmcm =\n+\t\tregister_query_field(p_curr_reg, RST9563_RST_TSM_REF_MMCM);\n+\tp->mp_fld_rst_tmc = register_query_field(p_curr_reg, RST9563_RST_TMC);\n+\n+\tif (!p->mp_fld_rst_tsm_ref_mmcm) {\n+\t\tNT_LOG(DBG, NTHW, \"%s: No RST9563_RST_TSM_REF_MMCM found\\n\",\n+\t\t       p_adapter_id_str);\n+\t}\n+\tif (!p->mp_fld_rst_tmc) {\n+\t\tNT_LOG(DBG, NTHW, \"%s: No RST9563_RST_TMC found\\n\",\n+\t\t       p_adapter_id_str);\n+\t}\n+\tregister_update(p_curr_reg);\n+\n+\t/* CTRL register field pointers */\n+\tp_curr_reg = module_get_register(p_mod_rst, RST9563_CTRL);\n+\tp->mp_fld_ctrl_ts_clk_sel_override =\n+\t\tregister_get_field(p_curr_reg, RST9563_CTRL_TS_CLKSEL_OVERRIDE);\n+\t/* Field not present on 9563 */\n+\tp->mp_fld_ctrl_ts_clk_sel =\n+\t\tregister_get_field(p_curr_reg, RST9563_CTRL_TS_CLKSEL);\n+\tp->mp_fld_ctrl_ts_clk_sel_ref = NULL; /* Field not present on 9563 */\n+\tp->mp_fld_ctrl_ptp_mmcm_clk_sel =\n+\t\tregister_get_field(p_curr_reg, RST9563_CTRL_PTP_MMCM_CLKSEL);\n+\tregister_update(p_curr_reg);\n+\n+\t/* STAT register field pointers */\n+\tp_curr_reg = module_get_register(p_mod_rst, RST9563_STAT);\n+\tp->mp_fld_stat_ddr4_mmcm_locked =\n+\t\tregister_get_field(p_curr_reg, RST9563_STAT_DDR4_MMCM_LOCKED);\n+\tp->mp_fld_stat_sys_mmcm_locked =\n+\t\tregister_get_field(p_curr_reg, RST9563_STAT_SYS_MMCM_LOCKED);\n+\tp->mp_fld_stat_core_mmcm_locked =\n+\t\tregister_get_field(p_curr_reg, RST9563_STAT_CORE_MMCM_LOCKED);\n+\tp->mp_fld_stat_ddr4_pll_locked =\n+\t\tregister_get_field(p_curr_reg, RST9563_STAT_DDR4_PLL_LOCKED);\n+\tp->mp_fld_stat_ptp_mmcm_locked =\n+\t\tregister_get_field(p_curr_reg, RST9563_STAT_PTP_MMCM_LOCKED);\n+\tp->mp_fld_stat_ts_mmcm_locked =\n+\t\tregister_get_field(p_curr_reg, RST9563_STAT_TS_MMCM_LOCKED);\n+\tp->mp_fld_stat_tsm_ref_mmcm_locked = NULL; /* Field not present on 9563 */\n+\n+\tif (!p->mp_fld_stat_tsm_ref_mmcm_locked) {\n+\t\tNT_LOG(DBG, NTHW,\n+\t\t       \"%s: No RST9563_STAT_TSM_REF_MMCM_LOCKED found\\n\",\n+\t\t       p_adapter_id_str);\n+\t}\n+\tregister_update(p_curr_reg);\n+\n+\t/* STICKY register field pointers */\n+\tp_curr_reg = module_get_register(p_mod_rst, RST9563_STICKY);\n+\tp->mp_fld_sticky_ptp_mmcm_unlocked =\n+\t\tregister_get_field(p_curr_reg, RST9563_STICKY_PTP_MMCM_UNLOCKED);\n+\tp->mp_fld_sticky_ts_mmcm_unlocked =\n+\t\tregister_get_field(p_curr_reg, RST9563_STICKY_TS_MMCM_UNLOCKED);\n+\tp->mp_fld_sticky_ddr4_mmcm_unlocked =\n+\t\tregister_get_field(p_curr_reg, RST9563_STICKY_DDR4_MMCM_UNLOCKED);\n+\tp->mp_fld_sticky_ddr4_pll_unlocked =\n+\t\tregister_get_field(p_curr_reg, RST9563_STICKY_DDR4_PLL_UNLOCKED);\n+\tp->mp_fld_sticky_core_mmcm_unlocked =\n+\t\tregister_get_field(p_curr_reg, RST9563_STICKY_CORE_MMCM_UNLOCKED);\n+\tp->mp_fld_sticky_pci_sys_mmcm_unlocked = NULL; /* Field not present on 9563 */\n+\tp->mp_fld_sticky_tsm_ref_mmcm_unlocked = NULL; /* Field not present on 9563 */\n+\n+\tif (!p->mp_fld_sticky_tsm_ref_mmcm_unlocked) {\n+\t\tNT_LOG(DBG, NTHW,\n+\t\t       \"%s: No RST9563_STICKY_TSM_REF_MMCM_UNLOCKED found\\n\",\n+\t\t       p_adapter_id_str);\n+\t}\n+\tregister_update(p_curr_reg);\n+\n+\t/* POWER register field pointers */\n+\tp_curr_reg = module_get_register(p_mod_rst, RST9563_POWER);\n+\tp->mp_fld_power_pu_phy = register_get_field(p_curr_reg, RST9563_POWER_PU_PHY);\n+\tp->mp_fld_power_pu_nseb =\n+\t\tregister_get_field(p_curr_reg, RST9563_POWER_PU_NSEB);\n+\tregister_update(p_curr_reg);\n+\n+\treturn 0;\n+}\n+\n+static int nthw_fpga_rst9563_periph_reset(nt_fpga_t *p_fpga)\n+{\n+\tconst char *const _unused p_adapter_id_str =\n+\t\tp_fpga->p_fpga_info->mp_adapter_id_str;\n+\tnt_module_t *p_mod_rst = fpga_query_module(p_fpga, MOD_RST9563, 0);\n+\n+\tif (p_mod_rst) {\n+\t\tnt_register_t *p_reg_rst;\n+\t\tnt_field_t *p_fld_rst_periph;\n+\n+\t\tNT_LOG(DBG, NTHW, \"%s: PERIPH RST\\n\", p_adapter_id_str);\n+\t\tp_reg_rst = module_get_register(p_mod_rst, RST9563_RST);\n+\t\tp_fld_rst_periph = register_get_field(p_reg_rst, RST9563_RST_PERIPH);\n+\t\tfield_set_flush(p_fld_rst_periph);\n+\t\tfield_clr_flush(p_fld_rst_periph);\n+\t} else {\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+nthw_fpga_rst9563_clock_synth_init(nt_fpga_t *p_fpga,\n+\t\t\t\t  const int n_si_labs_clock_synth_model,\n+\t\t\t\t  const uint8_t n_si_labs_clock_synth_i2c_addr)\n+{\n+\tconst char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;\n+\tconst int n_fpga_product_id = p_fpga->m_product_id;\n+\tint res;\n+\n+\tif (n_si_labs_clock_synth_model == 5340) {\n+\t\tres = nthw_fpga_si5340_clock_synth_init_fmt2(p_fpga,\n+\t\t\tn_si_labs_clock_synth_i2c_addr,\n+\t\t\tp_data_si5340_nt200a02_u23_v5,\n+\t\t\tn_data_si5340_nt200a02_u23_v5);\n+\t} else {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: Fpga %d: Unsupported clock synth model (%d)\\n\",\n+\t\t       p_adapter_id_str, n_fpga_product_id, n_si_labs_clock_synth_model);\n+\t\tres = -1;\n+\t}\n+\treturn res;\n+}\n+\n+int nthw_fpga_rst9563_init(struct fpga_info_s *p_fpga_info,\n+\t\t\t  struct nthw_fpga_rst_nt200a0x *p_rst)\n+{\n+\tassert(p_fpga_info);\n+\tassert(p_rst);\n+\n+\tconst char *const _unused p_adapter_id_str = p_fpga_info->mp_adapter_id_str;\n+\tint res = -1;\n+\tint n_si_labs_clock_synth_model;\n+\tuint8_t n_si_labs_clock_synth_i2c_addr;\n+\tnt_fpga_t *p_fpga = NULL;\n+\n+\tp_fpga = p_fpga_info->mp_fpga;\n+\tn_si_labs_clock_synth_model = p_rst->mn_si_labs_clock_synth_model;\n+\tn_si_labs_clock_synth_i2c_addr = p_rst->mn_si_labs_clock_synth_i2c_addr;\n+\n+\tres = nthw_fpga_rst9563_periph_reset(p_fpga);\n+\tif (res) {\n+\t\tNT_LOG(DBG, NTHW, \"%s: ERROR: res=%d [%s:%u]\\n\", p_adapter_id_str,\n+\t\t       res, __func__, __LINE__);\n+\t\treturn res;\n+\t}\n+\n+\tres = nthw_fpga_rst9563_clock_synth_init(p_fpga, n_si_labs_clock_synth_model,\n+\t\t\t\t\t\tn_si_labs_clock_synth_i2c_addr);\n+\tif (res) {\n+\t\tNT_LOG(DBG, NTHW, \"%s: ERROR: res=%d [%s:%u]\\n\", p_adapter_id_str,\n+\t\t       res, __func__, __LINE__);\n+\t\treturn res;\n+\t}\n+\n+\tres = nthw_fpga_rst9563_setup(p_fpga, p_rst);\n+\tif (res) {\n+\t\tNT_LOG(DBG, NTHW, \"%s: ERROR: res=%d [%s:%u]\\n\", p_adapter_id_str,\n+\t\t       res, __func__, __LINE__);\n+\t\treturn res;\n+\t}\n+\n+\tres = nthw_fpga_rst_nt200a0x_reset(p_fpga, p_rst);\n+\tif (res) {\n+\t\tNT_LOG(DBG, NTHW, \"%s: ERROR: res=%d [%s:%u]\\n\", p_adapter_id_str,\n+\t\t       res, __func__, __LINE__);\n+\t\treturn res;\n+\t}\n+\n+\treturn res;\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c\nnew file mode 100644\nindex 0000000000..ae63fefb09\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.c\n@@ -0,0 +1,674 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+#include \"nthw_fpga.h\"\n+\n+static const uint8_t si5338_u23_i2c_addr_7bit = 0x70;\n+static const uint8_t si5340_u23_i2c_addr_7bit = 0x74;\n+\n+/*\n+ * Wait until DDR4 PLL LOCKED\n+ */\n+static int nthw_fpga_rst_nt200a0x_wait_ddr4_pll_locked(nt_fpga_t *p_fpga,\n+\tconst struct nthw_fpga_rst_nt200a0x *p)\n+{\n+\tconst char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;\n+\tuint32_t locked;\n+\tuint32_t retrycount = 5;\n+\tuint32_t timeout = 50000; /* initial timeout must be set to 5 sec. */\n+\t/* 14: wait until DDR4 PLL LOCKED */\n+\tNT_LOG(DBG, NTHW, \"%s: Waiting for DDR4 PLL to lock\\n\", p_adapter_id_str);\n+\t/*\n+\t * The following retry count gives a total timeout of 1 * 5 + 5 * 8 = 45sec\n+\t * It has been observed that at least 21sec can be necessary\n+\t */\n+\twhile (true) {\n+\t\tint locked = field_wait_set_any32(p->mp_fld_stat_ddr4_pll_locked,\n+\t\t\t\t\t\t  timeout, 100);\n+\t\tif (locked == 0)\n+\t\t\tbreak;\n+\t\tNT_LOG(DBG, NTHW,\n+\t\t       \"%s: Waiting for DDR4 PLL to lock - timeout\\n\",\n+\t\t       p_adapter_id_str);\n+\t\tif (retrycount <= 0) {\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: Waiting for DDR4 PLL to lock failed (%d)\\n\",\n+\t\t\t       p_adapter_id_str, locked);\n+\t\t\tbreak;\n+\t\t}\n+\t\tfield_set_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */\n+\t\tfield_clr_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */\n+\t\tretrycount--;\n+\t\ttimeout =\n+\t\t\t80000; /* Increase timeout for second attempt to 8 sec. */\n+\t}\n+\n+\tNT_LOG(DBG, NTHW, \"%s: Waiting for DDR4 MMCM to lock\\n\", p_adapter_id_str);\n+\tlocked = field_wait_set_any32(p->mp_fld_stat_ddr4_mmcm_locked, -1, -1);\n+\tif (locked != 0) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: Waiting for DDR4 MMCM to lock failed (%d)\\n\",\n+\t\t       p_adapter_id_str, locked);\n+\t\treturn -1;\n+\t}\n+\n+\tif ((true) && p->mp_fld_stat_tsm_ref_mmcm_locked) {\n+\t\tNT_LOG(DBG, NTHW, \"%s: Waiting for TSM REF MMCM to lock\\n\",\n+\t\t       p_adapter_id_str);\n+\t\tlocked = field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked, -1,\n+\t\t\t\t\t    -1);\n+\t\tif (locked != 0) {\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: Waiting for TSM REF MMCM to lock failed (%d)\\n\",\n+\t\t\t       p_adapter_id_str, locked);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t/* 10: Clear all MMCM/PLL lock sticky bits before testing them */\n+\tNT_LOG(DBG, NTHW, \"%s: Clear sticky MMCM unlock bits\\n\", p_adapter_id_str);\n+\tfield_update_register(p->mp_fld_sticky_ptp_mmcm_unlocked);\n+\t/* Clear all sticky bits */\n+\tfield_set_flush(p->mp_fld_sticky_ptp_mmcm_unlocked);\n+\tfield_set_flush(p->mp_fld_sticky_ts_mmcm_unlocked);\n+\tfield_set_flush(p->mp_fld_sticky_ddr4_mmcm_unlocked);\n+\tfield_set_flush(p->mp_fld_sticky_ddr4_pll_unlocked);\n+\tfield_set_flush(p->mp_fld_sticky_core_mmcm_unlocked);\n+\tif (p->mp_fld_sticky_tsm_ref_mmcm_unlocked)\n+\t\tfield_set_flush(p->mp_fld_sticky_tsm_ref_mmcm_unlocked);\n+\tif (p->mp_fld_sticky_pci_sys_mmcm_unlocked)\n+\t\tfield_set_flush(p->mp_fld_sticky_pci_sys_mmcm_unlocked);\n+\n+\t/* 11: Ensure sticky bits are not unlocked except PTP MMCM and TS MMCM */\n+\tif (field_get_updated(p->mp_fld_sticky_ddr4_mmcm_unlocked)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: get_sticky_ddr4_mmcm_unlocked() returned true\\n\",\n+\t\t       p_adapter_id_str);\n+\t}\n+\n+\tif (field_get_updated(p->mp_fld_sticky_ddr4_pll_unlocked)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: get_sticky_ddr4_pll_unlocked() returned true\\n\",\n+\t\t       p_adapter_id_str);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Wait for SDRAM controller has been calibrated - On some adapters we have seen\n+ * calibration time of 2.3 seconds\n+ */\n+static int\n+nthw_fpga_rst_nt200a0x_wait_sdc_calibrated(nt_fpga_t *p_fpga,\n+\t\tconst struct nthw_fpga_rst_nt200a0x *p)\n+{\n+\tconst char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;\n+\tnthw_sdc_t *p_nthw_sdc = NULL;\n+\tconst int n_retry_cnt_max = 5;\n+\tint n_retry_cnt;\n+\tint res;\n+\n+\tres = nthw_sdc_init(NULL, p_fpga, 0); /* probe for module */\n+\tif (res == 0) {\n+\t\tp_nthw_sdc = nthw_sdc_new();\n+\t\tif (p_nthw_sdc) {\n+\t\t\tres = nthw_sdc_init(p_nthw_sdc, p_fpga, 0);\n+\t\t\tif (res) {\n+\t\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t\t       \"%s: SDC init failed: res=%d [%s:%d]\\n\",\n+\t\t\t\t       p_adapter_id_str, res, __func__, __LINE__);\n+\t\t\t\tnthw_sdc_delete(p_nthw_sdc);\n+\t\t\t\tp_nthw_sdc = NULL;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tnthw_sdc_delete(p_nthw_sdc);\n+\t\t\tp_nthw_sdc = NULL;\n+\t\t}\n+\t} else {\n+\t\tNT_LOG(DBG, NTHW, \"%s: No SDC found\\n\", p_adapter_id_str);\n+\t}\n+\tn_retry_cnt = 0;\n+\tres = -1;\n+\twhile ((res != 0) && (n_retry_cnt <= n_retry_cnt_max)) {\n+\t\t/* wait until DDR4 PLL LOCKED */\n+\t\tres = nthw_fpga_rst_nt200a0x_wait_ddr4_pll_locked(p_fpga, p);\n+\t\tif (res == 0) {\n+\t\t\tif (p_nthw_sdc) {\n+\t\t\t\t/*\n+\t\t\t\t * Wait for SDRAM controller has been calibrated\n+\t\t\t\t * On some adapters we have seen calibration time of 2.3 seconds\n+\t\t\t\t */\n+\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t       \"%s: Waiting for SDRAM to calibrate\\n\",\n+\t\t\t\t       p_adapter_id_str);\n+\t\t\t\tres = nthw_sdc_wait_states(p_nthw_sdc, 10000, 1000);\n+\t\t\t\t{\n+\t\t\t\t\tuint64_t n_result_mask;\n+\n+\t\t\t\t\tint n_state_code _unused =\n+\t\t\t\t\t\tnthw_sdc_get_states(p_nthw_sdc,\n+\t\t\t\t\t\t\t\t  &n_result_mask);\n+\t\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t\t       \"%s: SDRAM state=0x%08lX state_code=%d retry=%d code=%d\\n\",\n+\t\t\t\t\t       p_adapter_id_str, n_result_mask,\n+\t\t\t\t\t       n_state_code, n_retry_cnt, res);\n+\t\t\t\t}\n+\t\t\t\tif (res == 0)\n+\t\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\tif (n_retry_cnt >= n_retry_cnt_max) {\n+\t\t\t\tuint64_t n_result_mask;\n+\t\t\t\tint n_state_code _unused = nthw_sdc_get_states(p_nthw_sdc,\n+\t\t\t\t\t\t\t\t\t       &n_result_mask);\n+\n+\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t       \"%s: SDRAM state=0x%08lX state_code=%d retry=%d code=%d\\n\",\n+\t\t\t\t       p_adapter_id_str, n_result_mask, n_state_code,\n+\t\t\t\t       n_retry_cnt, res);\n+\t\t\t\tif (res != 0) {\n+\t\t\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t\t\t       \"%s: Timeout waiting for SDRAM controller calibration\\n\",\n+\t\t\t\t\t       p_adapter_id_str);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\n+\t\t/*\n+\t\t * SDRAM controller is not calibrated with DDR4 ram blocks:\n+\t\t * reset DDR and perform calibration retry\n+\t\t */\n+\t\tfield_set_flush(p->mp_fld_rst_ddr4); /* Reset DDR PLL */\n+\t\tNT_OS_WAIT_USEC(100);\n+\t\tfield_clr_flush(p->mp_fld_rst_ddr4);\n+\n+\t\tn_retry_cnt++;\n+\t}\n+\tnthw_sdc_delete(p_nthw_sdc);\n+\n+\treturn res;\n+}\n+\n+int nthw_fpga_rst_nt200a0x_reset(nt_fpga_t *p_fpga,\n+\t\t\t\tconst struct nthw_fpga_rst_nt200a0x *p)\n+{\n+\tconst char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;\n+\tconst fpga_info_t *const p_fpga_info = p_fpga->p_fpga_info;\n+\n+\tconst int n_fpga_product_id = p->mn_fpga_product_id;\n+\tconst int n_fpga_version = p->mn_fpga_version;\n+\tconst int n_fpga_revision = p->mn_fpga_revision;\n+\tconst int n_nthw_adapter_id = p_fpga_info->n_nthw_adapter_id;\n+\tconst bool b_is_nt200a01 = (n_nthw_adapter_id == NT_HW_ADAPTER_ID_NT200A01);\n+\tconst int n_hw_id = p_fpga_info->nthw_hw_info.hw_id;\n+\tconst uint8_t index = 0;\n+\tint locked;\n+\tint res = -1;\n+\n+\tNT_LOG(DBG, NTHW,\n+\t       \"%s: %s: FPGA reset sequence: FPGA %04d-%02d-%02d @ HWId%d\\n\",\n+\t       p_adapter_id_str, __func__, n_fpga_product_id, n_fpga_version,\n+\t       n_fpga_revision, n_hw_id);\n+\tassert(n_fpga_product_id == p_fpga->m_product_id);\n+\n+\t/*\n+\t * Reset all domains / modules except peripherals\n+\t * Set default reset values to ensure that all modules are reset correctly\n+\t * no matter if nic has been powercycled or ntservice has been reloaded\n+\t */\n+\n+\t/*\n+\t * Reset to defaults\n+\t * 1: Reset all domains\n+\t */\n+\tNT_LOG(DBG, NTHW, \"%s: RST defaults\\n\", p_adapter_id_str);\n+\n+\tfield_update_register(p->mp_fld_rst_sys);\n+\tfield_set_flush(p->mp_fld_rst_sys);\n+\tif (p->mp_fld_rst_tmc)\n+\t\tfield_set_flush(p->mp_fld_rst_tmc);\n+\tfield_set_flush(p->mp_fld_rst_rpp);\n+\tfield_set_flush(p->mp_fld_rst_ddr4); /* 0x07 3 banks */\n+\tfield_set_flush(p->mp_fld_rst_sdc);\n+\n+\t/* Reset port 0 and 1 in the following registers: */\n+\tfield_set_flush(p->mp_fld_rst_phy); /* 0x03 2 ports */\n+\tif (p->mp_fld_rst_mac_rx)\n+\t\tfield_set_flush(p->mp_fld_rst_mac_rx); /* 0x03 2 ports */\n+\n+\tif (p->mp_fld_rst_mac_tx)\n+\t\tfield_set_flush(p->mp_fld_rst_mac_tx); /* 0x03 2 ports */\n+\n+\tif (p->mp_fld_rst_pcs_rx)\n+\t\tfield_set_flush(p->mp_fld_rst_pcs_rx); /* 0x03 2 ports */\n+\n+\tif (p->mp_fld_rst_serdes_rx)\n+\t\tfield_set_flush(p->mp_fld_rst_serdes_rx); /* 0x03 2 ports */\n+\n+\tif (p->mp_fld_rst_serdes_rx_datapath) {\n+\t\tfield_set_flush(p->mp_fld_rst_serdes_rx_datapath);\n+\t\tfield_clr_flush(p->mp_fld_rst_serdes_rx);\n+\t}\n+\tif (p->mp_fld_rst_serdes_tx)\n+\t\tfield_set_flush(p->mp_fld_rst_serdes_tx);\n+\n+\tfield_set_flush(p->mp_fld_rst_ptp);\n+\tfield_set_flush(p->mp_fld_rst_ts);\n+\tfield_set_flush(p->mp_fld_rst_sys_mmcm);\n+\tfield_set_flush(p->mp_fld_rst_core_mmcm);\n+\tfield_set_flush(p->mp_fld_rst_ptp_mmcm);\n+\tfield_set_flush(p->mp_fld_rst_ts_mmcm);\n+\n+\tif ((true) && p->mp_fld_rst_tsm_ref_mmcm)\n+\t\tfield_set_flush(p->mp_fld_rst_tsm_ref_mmcm);\n+\n+\t/* Write all changes to register */\n+\tfield_flush_register(p->mp_fld_rst_sys);\n+\n+\tif (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */\n+\t\tif (p->mp_fld_rst_tsm_ref_mmcm) {\n+\t\t\tfield_update_register(p->mp_fld_rst_tsm_ref_mmcm);\n+\t\t\tfield_set_flush(p->mp_fld_rst_tsm_ref_mmcm);\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * 2: Force use of 50 MHz reference clock for timesync;\n+\t * NOTE: From 9508-05-18 this is a 20 MHz clock\n+\t */\n+\tNT_LOG(DBG, NTHW, \"%s: Setting TS CLK SEL OVERRIDE\\n\", p_adapter_id_str);\n+\tfield_update_register(p->mp_fld_ctrl_ts_clk_sel_override);\n+\tfield_set_flush(p->mp_fld_ctrl_ts_clk_sel_override);\n+\n+\tNT_LOG(DBG, NTHW, \"%s: Setting TS CLK SEL\\n\", p_adapter_id_str);\n+\tfield_update_register(p->mp_fld_ctrl_ts_clk_sel);\n+\tfield_set_flush(p->mp_fld_ctrl_ts_clk_sel);\n+\n+\tif (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */\n+\t\tNT_LOG(DBG, NTHW, \"%s: _selecting 20MHz TS CLK SEL REF\\n\",\n+\t\t       p_adapter_id_str);\n+\t\tif (p->mp_fld_ctrl_ts_clk_sel_ref) {\n+\t\t\tfield_update_register(p->mp_fld_ctrl_ts_clk_sel_ref);\n+\t\t\tfield_clr_flush(p->mp_fld_ctrl_ts_clk_sel_ref);\n+\t\t}\n+\t}\n+\n+\t/* 4: De-assert sys reset, CORE and SYS MMCM resets */\n+\tNT_LOG(DBG, NTHW, \"%s: De-asserting SYS, CORE and SYS MMCM resets\\n\",\n+\t       p_adapter_id_str);\n+\tfield_update_register(p->mp_fld_rst_sys);\n+\tfield_clr_flush(p->mp_fld_rst_sys);\n+\tfield_clr_flush(p->mp_fld_rst_sys_mmcm);\n+\tfield_clr_flush(p->mp_fld_rst_core_mmcm);\n+\n+\t/* 5: wait until CORE MMCM and SYS MMCM are LOCKED */\n+\tNT_LOG(DBG, NTHW, \"%s: Waiting for SYS MMCM to lock\\n\", p_adapter_id_str);\n+\tlocked = field_wait_set_any32(p->mp_fld_stat_sys_mmcm_locked, -1, -1);\n+\tif (locked != 0) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: Waiting for SYS MMCM to lock failed (%d)\\n\",\n+\t\t       p_adapter_id_str, locked);\n+\t}\n+\n+\tNT_LOG(DBG, NTHW, \"%s: Waiting for CORE MMCM to lock\\n\", p_adapter_id_str);\n+\tlocked = field_wait_set_any32(p->mp_fld_stat_core_mmcm_locked, -1, -1);\n+\tif (locked != 0) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: Waiting for CORE MMCM to lock failed (%d)\\n\",\n+\t\t       p_adapter_id_str, locked);\n+\t}\n+\n+\t/* RAC RAB bus \"flip/flip\" reset second stage - new impl (ref RMT#37020) */\n+\t/* RAC/RAB init - SYS/CORE MMCM is locked - pull the remaining RAB buses out of reset */\n+\t{\n+\t\tnthw_rac_t *p_nthw_rac = p_fpga_info->mp_nthw_rac;\n+\n+\t\tNT_LOG(DBG, NTHW, \"%s: De-asserting remaining RAB buses\\n\",\n+\t\t       p_adapter_id_str);\n+\t\tnthw_rac_rab_init(p_nthw_rac, 0);\n+\t}\n+\n+\tif ((true) && p->mp_fld_rst_tsm_ref_mmcm) {\n+\t\tNT_LOG(DBG, NTHW, \"%s: De-asserting TSM REF MMCM\\n\",\n+\t\t       p_adapter_id_str);\n+\t\tfield_clr_flush(p->mp_fld_rst_tsm_ref_mmcm);\n+\t\tif (p->mp_fld_stat_tsm_ref_mmcm_locked) {\n+\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t       \"%s: Waiting for TSM REF MMCM to lock\\n\",\n+\t\t\t       p_adapter_id_str);\n+\t\t\tlocked = field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked,\n+\t\t\t\t\t\t      -1, -1);\n+\t\t\tif (locked != 0) {\n+\t\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t\t       \"%s: Waiting for TSM REF MMCM to lock failed (%d)\\n\",\n+\t\t\t\t       p_adapter_id_str, locked);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * 5.2: Having ensured CORE MMCM and SYS MMCM are LOCKED,\n+\t * we need to select the alternative 20 MHz reference clock,\n+\t * the external TSM reference clock\n+\t * on NT200A01 - build 2 HW only (see SSF00024 p.32)\n+\t */\n+\tif (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */\n+\t\tNT_LOG(DBG, NTHW, \"%s: Setting TS CLK SEL REF\\n\",\n+\t\t       p_adapter_id_str);\n+\t\tif (p->mp_fld_ctrl_ts_clk_sel_ref)\n+\t\t\tfield_set_flush(p->mp_fld_ctrl_ts_clk_sel_ref);\n+\t\tif (p->mp_fld_rst_tsm_ref_mmcm) {\n+\t\t\tNT_LOG(DBG, NTHW, \"%s: De-asserting TSM REF MMCM\\n\",\n+\t\t\t       p_adapter_id_str);\n+\t\t\tfield_clr_flush(p->mp_fld_rst_tsm_ref_mmcm);\n+\t\t}\n+\t\tNT_LOG(DBG, NTHW, \"%s: Waiting for TSM REF MMCM to lock\\n\",\n+\t\t       p_adapter_id_str);\n+\t\tif (p->mp_fld_stat_tsm_ref_mmcm_locked) {\n+\t\t\tlocked = field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked,\n+\t\t\t\t\t\t      -1, -1);\n+\t\t\tif (locked != 0) {\n+\t\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t\t       \"%s: Waiting for TSM REF MMCM to lock failed (%d)\\n\",\n+\t\t\t\t       p_adapter_id_str, locked);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tNT_LOG(DBG, NTHW, \"%s: De-asserting all PHY resets\\n\", p_adapter_id_str);\n+\tfield_update_register(p->mp_fld_rst_phy);\n+\tfield_clr_flush(p->mp_fld_rst_phy);\n+\n+\t/* MAC_PCS_XXV 10G/25G: 9530 / 9544 */\n+\tif (n_fpga_product_id == 9530 || n_fpga_product_id == 9544) {\n+\t\t{\n+\t\t\t/* Based on nt200e3_2_ptp.cpp My25GbPhy::resetRx */\n+\t\t\tnthw_mac_pcs_xxv_t *p_nthw_mac_pcs_xxv0 = nthw_mac_pcs_xxv_new();\n+\n+\t\t\tassert(p_nthw_mac_pcs_xxv0);\n+\t\t\tnthw_mac_pcs_xxv_init(p_nthw_mac_pcs_xxv0, p_fpga, 0, 1);\n+\n+\t\t\tnthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv0, true,\n+\t\t\t\t\t\t    index);\n+\t\t\tNT_OS_WAIT_USEC(1000);\n+\n+\t\t\tnthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv0, false,\n+\t\t\t\t\t\t    index);\n+\t\t\tNT_OS_WAIT_USEC(1000);\n+\n+\t\t\tnthw_mac_pcs_xxv_delete(p_nthw_mac_pcs_xxv0);\n+\t\t}\n+\n+\t\t{\n+\t\t\t/* Based on nt200e3_2_ptp.cpp My25GbPhy::resetRx */\n+\t\t\tnthw_mac_pcs_xxv_t *p_nthw_mac_pcs_xxv1 = nthw_mac_pcs_xxv_new();\n+\n+\t\t\tassert(p_nthw_mac_pcs_xxv1);\n+\t\t\tnthw_mac_pcs_xxv_init(p_nthw_mac_pcs_xxv1, p_fpga, 1, 1);\n+\n+\t\t\tnthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv1, true,\n+\t\t\t\t\t\t    index);\n+\t\t\tNT_OS_WAIT_USEC(1000);\n+\n+\t\t\tnthw_mac_pcs_xxv_reset_rx_gt_data(p_nthw_mac_pcs_xxv1, false,\n+\t\t\t\t\t\t    index);\n+\t\t\tNT_OS_WAIT_USEC(1000);\n+\n+\t\t\tnthw_mac_pcs_xxv_delete(p_nthw_mac_pcs_xxv1);\n+\t\t}\n+\t\tNT_OS_WAIT_USEC(3000);\n+\t}\n+\n+\t/*\n+\t * 8: De-assert reset for remaining domains/modules resets except\n+\t * TS, PTP, PTP_MMCM and TS_MMCM\n+\t */\n+\tNT_LOG(DBG, NTHW, \"%s: De-asserting TMC RST\\n\", p_adapter_id_str);\n+\tif (p->mp_fld_rst_tmc) {\n+\t\tfield_update_register(p->mp_fld_rst_tmc);\n+\t\tfield_clr_flush(p->mp_fld_rst_tmc);\n+\t}\n+\n+\tNT_LOG(DBG, NTHW, \"%s: De-asserting RPP RST\\n\", p_adapter_id_str);\n+\tfield_update_register(p->mp_fld_rst_rpp);\n+\tfield_clr_flush(p->mp_fld_rst_rpp);\n+\n+\tNT_LOG(DBG, NTHW, \"%s: De-asserting DDR4 RST\\n\", p_adapter_id_str);\n+\tfield_update_register(p->mp_fld_rst_ddr4);\n+\tfield_clr_flush(p->mp_fld_rst_ddr4);\n+\n+\tNT_LOG(DBG, NTHW, \"%s: De-asserting SDC RST\\n\", p_adapter_id_str);\n+\tfield_update_register(p->mp_fld_rst_sdc);\n+\tfield_clr_flush(p->mp_fld_rst_sdc);\n+\n+\t/* NOTE: 9522 implements PHY10G_QPLL reset and lock at this stage in mac_rx_rst() */\n+\tNT_LOG(DBG, NTHW, \"%s: De-asserting MAC RX RST\\n\", p_adapter_id_str);\n+\tif (p->mp_fld_rst_mac_rx) {\n+\t\tfield_update_register(p->mp_fld_rst_mac_rx);\n+\t\tfield_clr_flush(p->mp_fld_rst_mac_rx);\n+\t}\n+\n+\t/* await until DDR4 PLL LOCKED and SDRAM controller has been calibrated */\n+\tres = nthw_fpga_rst_nt200a0x_wait_sdc_calibrated(p_fpga, p);\n+\tif (res) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: nthw_fpga_rst_nt200a0x_wait_sdc_calibrated() returned true\\n\",\n+\t\t       p_adapter_id_str);\n+\t\treturn -1;\n+\t}\n+\n+\tif (field_get_updated(p->mp_fld_sticky_core_mmcm_unlocked)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: get_sticky_core_mmcm_unlocked() returned true\\n\",\n+\t\t       p_adapter_id_str);\n+\t\treturn -1;\n+\t}\n+\n+\tif (p->mp_fld_sticky_pci_sys_mmcm_unlocked &&\n+\t\t\tfield_get_updated(p->mp_fld_sticky_pci_sys_mmcm_unlocked)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: get_sticky_pci_sys_mmcm_unlocked() returned true\\n\",\n+\t\t       p_adapter_id_str);\n+\t\treturn -1;\n+\t}\n+\n+\tif (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */\n+\t\tif (p->mp_fld_sticky_tsm_ref_mmcm_unlocked &&\n+\t\t\t\tfield_get_updated(p->mp_fld_sticky_tsm_ref_mmcm_unlocked)) {\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: get_sticky_tsm_ref_mmcm_unlocked returned true\\n\",\n+\t\t\t       p_adapter_id_str);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Timesync/PTP reset sequence\n+\t * De-assert TS_MMCM reset\n+\t */\n+\tNT_LOG(DBG, NTHW, \"%s: De-asserting TS MMCM RST\\n\", p_adapter_id_str);\n+\tfield_clr_flush(p->mp_fld_rst_ts_mmcm);\n+\n+\t/* Wait until TS_MMCM LOCKED (NT_RAB0_REG_P9508_RST9508_STAT_TS_MMCM_LOCKED=1); */\n+\tNT_LOG(DBG, NTHW, \"%s: Waiting for TS MMCM to lock\\n\", p_adapter_id_str);\n+\tlocked = field_wait_set_any32(p->mp_fld_stat_ts_mmcm_locked, -1, -1);\n+\tif (locked != 0) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: Waiting for TS MMCM to lock failed (%d)\\n\",\n+\t\t       p_adapter_id_str, locked);\n+\t}\n+\n+\tNT_LOG(DBG, NTHW, \"%s: Calling clear_sticky_mmcm_unlock_bits()\\n\",\n+\t       p_adapter_id_str);\n+\tfield_update_register(p->mp_fld_sticky_ptp_mmcm_unlocked);\n+\t/* Clear all sticky bits */\n+\tfield_set_flush(p->mp_fld_sticky_ptp_mmcm_unlocked);\n+\tfield_set_flush(p->mp_fld_sticky_ts_mmcm_unlocked);\n+\tfield_set_flush(p->mp_fld_sticky_ddr4_mmcm_unlocked);\n+\tfield_set_flush(p->mp_fld_sticky_ddr4_pll_unlocked);\n+\tfield_set_flush(p->mp_fld_sticky_core_mmcm_unlocked);\n+\tif (p->mp_fld_sticky_tsm_ref_mmcm_unlocked)\n+\t\tfield_set_flush(p->mp_fld_sticky_tsm_ref_mmcm_unlocked);\n+\tif (p->mp_fld_sticky_pci_sys_mmcm_unlocked)\n+\t\tfield_set_flush(p->mp_fld_sticky_pci_sys_mmcm_unlocked);\n+\n+\t/* De-assert TS reset bit */\n+\tNT_LOG(DBG, NTHW, \"%s: De-asserting TS RST\\n\", p_adapter_id_str);\n+\tfield_clr_flush(p->mp_fld_rst_ts);\n+\n+\tif (field_get_updated(p->mp_fld_sticky_ts_mmcm_unlocked)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: get_sticky_ts_mmcm_unlocked() returned true\\n\",\n+\t\t       p_adapter_id_str);\n+\t\treturn -1;\n+\t}\n+\n+\tif (field_get_updated(p->mp_fld_sticky_ddr4_mmcm_unlocked)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: get_sticky_ddr4_mmcm_unlocked() returned true\\n\",\n+\t\t       p_adapter_id_str);\n+\t\treturn -1;\n+\t}\n+\n+\tif (field_get_updated(p->mp_fld_sticky_ddr4_pll_unlocked)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: get_sticky_ddr4_pll_unlocked() returned true\\n\",\n+\t\t       p_adapter_id_str);\n+\t\treturn -1;\n+\t}\n+\n+\tif (field_get_updated(p->mp_fld_sticky_core_mmcm_unlocked)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: get_sticky_core_mmcm_unlocked() returned true\\n\",\n+\t\t       p_adapter_id_str);\n+\t\treturn -1;\n+\t}\n+\n+\tif (p->mp_fld_sticky_pci_sys_mmcm_unlocked &&\n+\t\t\tfield_get_updated(p->mp_fld_sticky_pci_sys_mmcm_unlocked)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: get_sticky_pci_sys_mmcm_unlocked() returned true\\n\",\n+\t\t       p_adapter_id_str);\n+\t\treturn -1;\n+\t}\n+\n+\tif (b_is_nt200a01 && n_hw_id == 2) { /* Not relevant to NT200A02 */\n+\t\tif (p->mp_fld_sticky_tsm_ref_mmcm_unlocked &&\n+\t\t\t\tfield_get_updated(p->mp_fld_sticky_tsm_ref_mmcm_unlocked)) {\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: get_sticky_tsm_ref_mmcm_unlocked() returned true\\n\",\n+\t\t\t       p_adapter_id_str);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\tif (false) {\n+\t\t/* Deassert PTP_MMCM */\n+\t\tNT_LOG(DBG, NTHW, \"%s: De-asserting PTP MMCM RST\\n\",\n+\t\t       p_adapter_id_str);\n+\t\tfield_clr_flush(p->mp_fld_rst_ptp_mmcm);\n+\n+\t\tif ((b_is_nt200a01 && n_fpga_version >= 9) || !b_is_nt200a01) {\n+\t\t\t/* Wait until PTP_MMCM LOCKED */\n+\t\t\tNT_LOG(DBG, NTHW, \"%s: Waiting for PTP MMCM to lock\\n\",\n+\t\t\t       p_adapter_id_str);\n+\t\t\tlocked = field_wait_set_any32(p->mp_fld_stat_ptp_mmcm_locked,\n+\t\t\t\t\t\t    -1, -1);\n+\t\t\tif (locked != 0) {\n+\t\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t\t       \"%s: Waiting for PTP MMCM to lock failed (%d)\\n\",\n+\t\t\t\t       p_adapter_id_str, locked);\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* Switch PTP MMCM sel to use ptp clk */\n+\t\tNT_LOG(DBG, NTHW, \"%s: Setting PTP MMCM CLK SEL\\n\",\n+\t\t       p_adapter_id_str);\n+\t\tfield_set_flush(p->mp_fld_ctrl_ptp_mmcm_clk_sel);\n+\n+\t\t/* Wait until TS_MMCM LOCKED (NT_RAB0_REG_P9508_RST9508_STAT_TS_MMCM_LOCKED=1); */\n+\t\tNT_LOG(DBG, NTHW, \"%s: Waiting for TS MMCM to re-lock\\n\",\n+\t\t       p_adapter_id_str);\n+\t\tlocked = field_wait_set_any32(p->mp_fld_stat_ts_mmcm_locked, -1, -1);\n+\t\tif (locked != 0) {\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: Waiting for TS MMCM to re-lock failed (%d)\\n\",\n+\t\t\t       p_adapter_id_str, locked);\n+\t\t}\n+\t}\n+\n+\tNT_LOG(DBG, NTHW, \"%s: De-asserting PTP RST\\n\", p_adapter_id_str);\n+\tfield_clr_flush(p->mp_fld_rst_ptp);\n+\n+\t/* POWER staging introduced in 9508-05-09 and always for 9512 */\n+\tif (n_fpga_product_id == 9508 && n_fpga_version <= 5 &&\n+\t\t\tn_fpga_revision <= 8) {\n+\t\tNT_LOG(DBG, NTHW, \"%s: No power staging\\n\", p_adapter_id_str);\n+\t} else {\n+\t\tNT_LOG(DBG, NTHW, \"%s: Staging power\\n\", p_adapter_id_str);\n+\t\tfield_set_flush(p->mp_fld_power_pu_phy); /* PHY power up */\n+\t\tfield_clr_flush(p->mp_fld_power_pu_nseb); /* NSEB power down */\n+\t}\n+\n+\tNT_LOG(DBG, NTHW, \"%s: %s: END\\n\", p_adapter_id_str, __func__);\n+\n+\treturn 0;\n+}\n+\n+int nthw_fpga_rst_nt200a0x_init(struct fpga_info_s *p_fpga_info,\n+\t\t\t       struct nthw_fpga_rst_nt200a0x *p_rst)\n+{\n+\tassert(p_fpga_info);\n+\n+\tconst char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;\n+\tint res = -1;\n+\tint n_si_labs_clock_synth_model = -1;\n+\tuint8_t n_si_labs_clock_synth_i2c_addr = 0;\n+\tnt_fpga_t *p_fpga = NULL;\n+\n+\tp_fpga = p_fpga_info->mp_fpga;\n+\n+\tNT_LOG(DBG, NTHW, \"%s: %s: RAB init/reset\\n\", p_adapter_id_str, __func__);\n+\tnthw_rac_rab_reset(p_fpga_info->mp_nthw_rac);\n+\tnthw_rac_rab_setup(p_fpga_info->mp_nthw_rac);\n+\n+\tres = nthw_fpga_avr_probe(p_fpga, 0);\n+\n+\tres = nthw_fpga_iic_scan(p_fpga, 0, 0);\n+\tres = nthw_fpga_iic_scan(p_fpga, 2, 3);\n+\n+\t/*\n+\t * Detect clock synth model\n+\t * check for NT200A02/NT200A01 HW-build2 - most commonly seen\n+\t */\n+\tn_si_labs_clock_synth_i2c_addr = si5340_u23_i2c_addr_7bit;\n+\tn_si_labs_clock_synth_model =\n+\t\tnthw_fpga_silabs_detect(p_fpga, 0, n_si_labs_clock_synth_i2c_addr, 1);\n+\tif (n_si_labs_clock_synth_model == -1) {\n+\t\t/* check for old NT200A01 HW-build1 */\n+\t\tn_si_labs_clock_synth_i2c_addr = si5338_u23_i2c_addr_7bit;\n+\t\tn_si_labs_clock_synth_model =\n+\t\t\tnthw_fpga_silabs_detect(p_fpga, 0,\n+\t\t\t\t\t\tn_si_labs_clock_synth_i2c_addr, 255);\n+\t\tif (n_si_labs_clock_synth_model == -1) {\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: Failed to detect clock synth model (%d)\\n\",\n+\t\t\t       p_adapter_id_str, n_si_labs_clock_synth_model);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\tp_rst->mn_si_labs_clock_synth_model = n_si_labs_clock_synth_model;\n+\tp_rst->mn_si_labs_clock_synth_i2c_addr = n_si_labs_clock_synth_i2c_addr;\n+\tp_rst->mn_hw_id = p_fpga_info->nthw_hw_info.hw_id;\n+\tNT_LOG(DBG, NTHW, \"%s: %s: Si%04d @ 0x%02x\\n\", p_adapter_id_str, __func__,\n+\t       p_rst->mn_si_labs_clock_synth_model, p_rst->mn_si_labs_clock_synth_i2c_addr);\n+\n+\treturn res;\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h\nnew file mode 100644\nindex 0000000000..1f192f5ecc\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_fpga_rst_nt200a0x.h\n@@ -0,0 +1,89 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_FPGA_RST_NT200A0X_H__\n+#define __NTHW_FPGA_RST_NT200A0X_H__\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_fpga_model.h\"\n+\n+struct nthw_fpga_rst_nt200a0x {\n+\tint mn_fpga_product_id;\n+\tint mn_fpga_version;\n+\tint mn_fpga_revision;\n+\n+\tint mn_hw_id;\n+\n+\tint mn_si_labs_clock_synth_model;\n+\tuint8_t mn_si_labs_clock_synth_i2c_addr;\n+\n+\tnt_field_t *mp_fld_rst_sys;\n+\tnt_field_t *mp_fld_rst_sys_mmcm;\n+\tnt_field_t *mp_fld_rst_core_mmcm;\n+\tnt_field_t *mp_fld_rst_rpp;\n+\tnt_field_t *mp_fld_rst_ddr4;\n+\tnt_field_t *mp_fld_rst_sdc;\n+\tnt_field_t *mp_fld_rst_phy;\n+\tnt_field_t *mp_fld_rst_serdes_rx;\n+\tnt_field_t *mp_fld_rst_serdes_tx;\n+\tnt_field_t *mp_fld_rst_serdes_rx_datapath;\n+\tnt_field_t *mp_fld_rst_pcs_rx;\n+\tnt_field_t *mp_fld_rst_mac_rx;\n+\tnt_field_t *mp_fld_rst_mac_tx;\n+\tnt_field_t *mp_fld_rst_ptp;\n+\tnt_field_t *mp_fld_rst_ts;\n+\tnt_field_t *mp_fld_rst_ptp_mmcm;\n+\tnt_field_t *mp_fld_rst_ts_mmcm;\n+\tnt_field_t *mp_fld_rst_periph;\n+\tnt_field_t *mp_fld_rst_tsm_ref_mmcm;\n+\tnt_field_t *mp_fld_rst_tmc;\n+\n+\t/* CTRL register field pointers */\n+\tnt_field_t *mp_fld_ctrl_ts_clk_sel_override;\n+\tnt_field_t *mp_fld_ctrl_ts_clk_sel;\n+\tnt_field_t *mp_fld_ctrl_ts_clk_sel_ref;\n+\tnt_field_t *mp_fld_ctrl_ptp_mmcm_clk_sel;\n+\n+\t/* STAT register field pointers */\n+\tnt_field_t *mp_fld_stat_ddr4_mmcm_locked;\n+\tnt_field_t *mp_fld_stat_sys_mmcm_locked;\n+\tnt_field_t *mp_fld_stat_core_mmcm_locked;\n+\tnt_field_t *mp_fld_stat_ddr4_pll_locked;\n+\tnt_field_t *mp_fld_stat_ptp_mmcm_locked;\n+\tnt_field_t *mp_fld_stat_ts_mmcm_locked;\n+\tnt_field_t *mp_fld_stat_tsm_ref_mmcm_locked;\n+\n+\t/* STICKY register field pointers */\n+\tnt_field_t *mp_fld_sticky_ptp_mmcm_unlocked;\n+\tnt_field_t *mp_fld_sticky_ts_mmcm_unlocked;\n+\tnt_field_t *mp_fld_sticky_ddr4_mmcm_unlocked;\n+\tnt_field_t *mp_fld_sticky_ddr4_pll_unlocked;\n+\tnt_field_t *mp_fld_sticky_core_mmcm_unlocked;\n+\tnt_field_t *mp_fld_sticky_pci_sys_mmcm_unlocked;\n+\tnt_field_t *mp_fld_sticky_tsm_ref_mmcm_unlocked;\n+\n+\t/* POWER register field pointers */\n+\tnt_field_t *mp_fld_power_pu_phy;\n+\tnt_field_t *mp_fld_power_pu_nseb;\n+\t/*  */\n+\n+\tvoid (*reset_serdes_rx)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no,\n+\t\t\t      uint32_t rst);\n+\tvoid (*pcs_rx_rst)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no,\n+\t\t\t   uint32_t rst);\n+\tvoid (*get_serdes_rx_rst)(struct nthw_fpga_rst_nt200a0x *p,\n+\t\t\t\t  uint32_t intf_no, uint32_t *p_set);\n+\tvoid (*get_pcs_rx_rst)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no,\n+\t\t\t       uint32_t *p_set);\n+\tbool (*is_rst_serdes_rx_datapath_implemented)(struct nthw_fpga_rst_nt200a0x *p);\n+};\n+\n+typedef struct nthw_fpga_rst_nt200a0x nthw_fpga_rst_nt200a0x_t;\n+\n+int nthw_fpga_rst_nt200a0x_init(struct fpga_info_s *p_fpga_info,\n+\t\t\t\tstruct nthw_fpga_rst_nt200a0x *p_rst);\n+int nthw_fpga_rst_nt200a0x_reset(nt_fpga_t *p_fpga,\n+\t\t\t\t const struct nthw_fpga_rst_nt200a0x *p);\n+\n+#endif /* __NTHW_FPGA_RST_NT200A0X_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_gpio_phy.c b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.c\nnew file mode 100644\nindex 0000000000..9b536726d0\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.c\n@@ -0,0 +1,271 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_gpio_phy.h\"\n+\n+nthw_gpio_phy_t *nthw_gpio_phy_new(void)\n+{\n+\tnthw_gpio_phy_t *p = malloc(sizeof(nthw_gpio_phy_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_gpio_phy_t));\n+\treturn p;\n+}\n+\n+void nthw_gpio_phy_delete(nthw_gpio_phy_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_gpio_phy_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+int nthw_gpio_phy_init(nthw_gpio_phy_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tnt_module_t *p_mod = fpga_query_module(p_fpga, MOD_GPIO_PHY, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn (p_mod == NULL ? -1 : 0);\n+\n+\tif (p_mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: GPIO_PHY %d: no such instance\\n\",\n+\t\t       p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_gpio_phy = p_mod;\n+\n+\t/* Registers */\n+\tp->mp_reg_config = module_get_register(p->mp_mod_gpio_phy, GPIO_PHY_CFG);\n+\tp->mp_reg_gpio = module_get_register(p->mp_mod_gpio_phy, GPIO_PHY_GPIO);\n+\n+\t/* PORT-0, config fields */\n+\tp->mpa_fields[0].cfg_fld_lp_mode =\n+\t\tregister_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_LPMODE);\n+\tp->mpa_fields[0].cfg_int =\n+\t\tregister_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_INT_B);\n+\tp->mpa_fields[0].cfg_reset =\n+\t\tregister_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_RESET_B);\n+\tp->mpa_fields[0].cfg_mod_prs =\n+\t\tregister_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_MODPRS_B);\n+\n+\t/* PORT-0, Non-mandatory fields (queryField) */\n+\tp->mpa_fields[0].cfg_pll_int =\n+\t\tregister_query_field(p->mp_reg_config, GPIO_PHY_CFG_PORT0_PLL_INTR);\n+\tp->mpa_fields[0].cfg_port_rxlos =\n+\t\tregister_query_field(p->mp_reg_config, GPIO_PHY_CFG_E_PORT0_RXLOS);\n+\n+\t/* PORT-1, config fields */\n+\tp->mpa_fields[1].cfg_fld_lp_mode =\n+\t\tregister_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_LPMODE);\n+\tp->mpa_fields[1].cfg_int =\n+\t\tregister_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_INT_B);\n+\tp->mpa_fields[1].cfg_reset =\n+\t\tregister_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_RESET_B);\n+\tp->mpa_fields[1].cfg_mod_prs =\n+\t\tregister_get_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_MODPRS_B);\n+\n+\t/* PORT-1, Non-mandatory fields (queryField) */\n+\tp->mpa_fields[1].cfg_pll_int =\n+\t\tregister_query_field(p->mp_reg_config, GPIO_PHY_CFG_PORT1_PLL_INTR);\n+\tp->mpa_fields[1].cfg_port_rxlos =\n+\t\tregister_query_field(p->mp_reg_config, GPIO_PHY_CFG_E_PORT1_RXLOS);\n+\n+\t/* PORT-0, gpio fields */\n+\tp->mpa_fields[0].gpio_fld_lp_mode =\n+\t\tregister_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_LPMODE);\n+\tp->mpa_fields[0].gpio_int =\n+\t\tregister_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_INT_B);\n+\tp->mpa_fields[0].gpio_reset =\n+\t\tregister_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_RESET_B);\n+\tp->mpa_fields[0].gpio_mod_prs =\n+\t\tregister_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_MODPRS_B);\n+\n+\t/* PORT-0, Non-mandatory fields (queryField) */\n+\tp->mpa_fields[0].gpio_pll_int =\n+\t\tregister_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT0_PLL_INTR);\n+\tp->mpa_fields[0].gpio_port_rxlos =\n+\t\tregister_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_E_PORT0_RXLOS);\n+\n+\t/* PORT-1, gpio fields */\n+\tp->mpa_fields[1].gpio_fld_lp_mode =\n+\t\tregister_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_LPMODE);\n+\tp->mpa_fields[1].gpio_int =\n+\t\tregister_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_INT_B);\n+\tp->mpa_fields[1].gpio_reset =\n+\t\tregister_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_RESET_B);\n+\tp->mpa_fields[1].gpio_mod_prs =\n+\t\tregister_get_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_MODPRS_B);\n+\n+\t/* PORT-1, Non-mandatory fields (queryField) */\n+\tp->mpa_fields[1].gpio_pll_int =\n+\t\tregister_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_PORT1_PLL_INTR);\n+\tp->mpa_fields[1].gpio_port_rxlos =\n+\t\tregister_query_field(p->mp_reg_gpio, GPIO_PHY_GPIO_E_PORT1_RXLOS);\n+\n+\tregister_update(p->mp_reg_config);\n+\n+\treturn 0;\n+}\n+\n+bool nthw_gpio_phy_is_low_power_enabled(nthw_gpio_phy_t *p, uint8_t if_no)\n+{\n+\tif (if_no >= ARRAY_SIZE(p->mpa_fields)) {\n+\t\tassert(false);\n+\t\treturn false;\n+\t}\n+\n+\tif (field_get_updated(p->mpa_fields[if_no].gpio_fld_lp_mode))\n+\t\treturn true;\n+\n+\telse\n+\t\treturn false;\n+}\n+\n+bool nthw_gpio_phy_is_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no)\n+{\n+\tif (if_no >= ARRAY_SIZE(p->mpa_fields)) {\n+\t\tassert(false);\n+\t\treturn false;\n+\t}\n+\n+\t/* NOTE: This is a negated GPIO PIN \"INT_B\" */\n+\tif (field_get_updated(p->mpa_fields[if_no].gpio_int))\n+\t\treturn false;\n+\n+\telse\n+\t\treturn true;\n+}\n+\n+bool nthw_gpio_phy_is_reset(nthw_gpio_phy_t *p, uint8_t if_no)\n+{\n+\tif (if_no >= ARRAY_SIZE(p->mpa_fields)) {\n+\t\tassert(false);\n+\t\treturn false;\n+\t}\n+\n+\t/* NOTE: This is a negated GPIO PIN \"RESET_B\" */\n+\tif (field_get_updated(p->mpa_fields[if_no].gpio_reset))\n+\t\treturn false;\n+\n+\telse\n+\t\treturn true;\n+}\n+\n+bool nthw_gpio_phy_is_module_present(nthw_gpio_phy_t *p, uint8_t if_no)\n+{\n+\tif (if_no >= ARRAY_SIZE(p->mpa_fields)) {\n+\t\tassert(false);\n+\t\treturn false;\n+\t}\n+\n+\t/* NOTE: This is a negated GPIO PIN \"MODPRS_B\" */\n+\treturn field_get_updated(p->mpa_fields[if_no].gpio_mod_prs) == 0U ? true :\n+\t       false;\n+}\n+\n+bool nthw_gpio_phy_is_pll_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no)\n+{\n+\tif (if_no >= ARRAY_SIZE(p->mpa_fields)) {\n+\t\tassert(false);\n+\t\treturn false;\n+\t}\n+\n+\t/* NOTE: This is a normal GPIO PIN \"PLL_INTR\" */\n+\tif (p->mpa_fields[if_no].gpio_pll_int) {\n+\t\tif (field_get_updated(p->mpa_fields[if_no].gpio_pll_int))\n+\t\t\treturn true;\n+\n+\t\telse\n+\t\t\treturn false;\n+\t} else {\n+\t\t/* this HW doesn't support \"PLL_INTR\" (INTR from SyncE jitter attenuater) */\n+\t\treturn false;\n+\t}\n+}\n+\n+bool nthw_gpio_phy_is_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no)\n+{\n+\tif (if_no >= ARRAY_SIZE(p->mpa_fields)) {\n+\t\tassert(false);\n+\t\treturn false;\n+\t}\n+\n+\tif (p->mpa_fields[if_no].gpio_port_rxlos) {\n+\t\tif (field_get_updated(p->mpa_fields[if_no].gpio_port_rxlos))\n+\t\t\treturn true;\n+\t\telse\n+\t\t\treturn false;\n+\t} else {\n+\t\treturn false;\n+\t}\n+}\n+\n+void nthw_gpio_phy_set_low_power(nthw_gpio_phy_t *p, uint8_t if_no, bool enable)\n+{\n+\tif (if_no >= ARRAY_SIZE(p->mpa_fields)) {\n+\t\tassert(false);\n+\t\treturn;\n+\t}\n+\n+\tif (enable)\n+\t\tfield_set_flush(p->mpa_fields[if_no].gpio_fld_lp_mode);\n+\n+\telse\n+\t\tfield_clr_flush(p->mpa_fields[if_no].gpio_fld_lp_mode);\n+\tfield_clr_flush(p->mpa_fields[if_no].cfg_fld_lp_mode); /* enable output */\n+}\n+\n+void nthw_gpio_phy_set_reset(nthw_gpio_phy_t *p, uint8_t if_no, bool enable)\n+{\n+\tif (if_no >= ARRAY_SIZE(p->mpa_fields)) {\n+\t\tassert(false);\n+\t\treturn;\n+\t}\n+\n+\tif (enable)\n+\t\tfield_clr_flush(p->mpa_fields[if_no].gpio_reset);\n+\n+\telse\n+\t\tfield_set_flush(p->mpa_fields[if_no].gpio_reset);\n+\tfield_clr_flush(p->mpa_fields[if_no].cfg_reset); /* enable output */\n+}\n+\n+void nthw_gpio_phy_set_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no, bool enable)\n+{\n+\tif (if_no >= ARRAY_SIZE(p->mpa_fields)) {\n+\t\tassert(false);\n+\t\treturn;\n+\t}\n+\n+\tif (p->mpa_fields[if_no].gpio_port_rxlos) {\n+\t\tif (enable)\n+\t\t\tfield_set_flush(p->mpa_fields[if_no].gpio_port_rxlos);\n+\n+\t\telse\n+\t\t\tfield_clr_flush(p->mpa_fields[if_no].gpio_port_rxlos);\n+\t}\n+}\n+\n+void nthw_gpio_phy_set_cfg_default_values(nthw_gpio_phy_t *p, uint8_t if_no)\n+{\n+\tif (if_no >= ARRAY_SIZE(p->mpa_fields)) {\n+\t\tassert(false);\n+\t\treturn;\n+\t}\n+\n+\tfield_set_flush(p->mpa_fields[if_no].cfg_fld_lp_mode); /* enable input */\n+\tfield_set_flush(p->mpa_fields[if_no].cfg_int); /* enable input */\n+\tfield_set_flush(p->mpa_fields[if_no].cfg_reset); /* enable input */\n+\tfield_set_flush(p->mpa_fields[if_no].cfg_mod_prs); /* enable input */\n+\tif (p->mpa_fields[if_no].cfg_port_rxlos)\n+\t\tfield_clr_flush(p->mpa_fields[if_no].cfg_port_rxlos); /* enable output */\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_gpio_phy.h b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.h\nnew file mode 100644\nindex 0000000000..1c6185150c\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_gpio_phy.h\n@@ -0,0 +1,57 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef NTHW_GPIO_PHY_H_\n+#define NTHW_GPIO_PHY_H_\n+\n+#define GPIO_PHY_INTERFACES (2)\n+\n+typedef struct {\n+\tnt_field_t *cfg_fld_lp_mode; /* Cfg Low Power Mode */\n+\tnt_field_t *cfg_int; /* Cfg Port Interrupt */\n+\tnt_field_t *cfg_reset; /* Cfg Reset */\n+\tnt_field_t *cfg_mod_prs; /* Cfg Module Present */\n+\tnt_field_t *cfg_pll_int; /* Cfg PLL Interrupt */\n+\tnt_field_t *cfg_port_rxlos; /* Emulate Cfg Port RXLOS */\n+\n+\tnt_field_t *gpio_fld_lp_mode; /* Gpio Low Power Mode */\n+\tnt_field_t *gpio_int; /* Gpio Port Interrupt */\n+\tnt_field_t *gpio_reset; /* Gpio Reset */\n+\tnt_field_t *gpio_mod_prs; /* Gpio Module Present */\n+\tnt_field_t *gpio_pll_int; /* Gpio PLL Interrupt */\n+\tnt_field_t *gpio_port_rxlos; /* Emulate Gpio Port RXLOS */\n+} gpio_phy_fields_t;\n+\n+struct nthw_gpio_phy {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_gpio_phy;\n+\tint mn_instance;\n+\n+\t/* Registers */\n+\tnt_register_t *mp_reg_config;\n+\tnt_register_t *mp_reg_gpio;\n+\n+\t/* Fields */\n+\tgpio_phy_fields_t mpa_fields[GPIO_PHY_INTERFACES];\n+};\n+\n+typedef struct nthw_gpio_phy nthw_gpio_phy_t;\n+typedef struct nthw_gpio_phy nthw_gpio_phy;\n+\n+nthw_gpio_phy_t *nthw_gpio_phy_new(void);\n+void nthw_gpio_phy_delete(nthw_gpio_phy_t *p);\n+int nthw_gpio_phy_init(nthw_gpio_phy_t *p, nt_fpga_t *p_fpga, int n_instance);\n+\n+bool nthw_gpio_phy_is_low_power_enabled(nthw_gpio_phy_t *p, uint8_t if_no);\n+bool nthw_gpio_phy_is_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no);\n+bool nthw_gpio_phy_is_reset(nthw_gpio_phy_t *p, uint8_t if_no);\n+bool nthw_gpio_phy_is_module_present(nthw_gpio_phy_t *p, uint8_t if_no);\n+bool nthw_gpio_phy_is_pll_interrupt_set(nthw_gpio_phy_t *p, uint8_t if_no);\n+bool nthw_gpio_phy_is_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no);\n+void nthw_gpio_phy_set_low_power(nthw_gpio_phy_t *p, uint8_t if_no, bool enable);\n+void nthw_gpio_phy_set_reset(nthw_gpio_phy_t *p, uint8_t if_no, bool enable);\n+void nthw_gpio_phy_set_port_rxlos(nthw_gpio_phy_t *p, uint8_t if_no, bool enable);\n+void nthw_gpio_phy_set_cfg_default_values(nthw_gpio_phy_t *p, uint8_t if_no);\n+\n+#endif /* NTHW_GPIO_PHY_H_ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_hif.c b/drivers/net/ntnic/nthw/core/nthw_hif.c\nnew file mode 100644\nindex 0000000000..7b7a919108\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_hif.c\n@@ -0,0 +1,342 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"nt_util.h\"\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_hif.h\"\n+\n+nthw_hif_t *nthw_hif_new(void)\n+{\n+\tnthw_hif_t *p = malloc(sizeof(nthw_hif_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_hif_t));\n+\treturn p;\n+}\n+\n+void nthw_hif_delete(nthw_hif_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_hif_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+int nthw_hif_init(nthw_hif_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tconst char *const p_adapter_id_str _unused =\n+\t\tp_fpga->p_fpga_info->mp_adapter_id_str;\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_HIF, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: HIF %d: no such instance\\n\",\n+\t\t       p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_hif = mod;\n+\n+\t/* default for (Xilinx-based) products until august 2022: (1e6/4000 = 250 MHz) */\n+\tp->mn_fpga_param_hif_per_ps =\n+\t\tfpga_get_product_param(p->mp_fpga, NT_HIF_PER_PS, 4000);\n+\tp->mn_fpga_hif_ref_clk_freq =\n+\t\t(uint32_t)(1000000000000ULL /\n+\t\t\t   (unsigned int)p->mn_fpga_param_hif_per_ps);\n+\n+\tp->mp_reg_prod_id_lsb = module_get_register(p->mp_mod_hif, HIF_PROD_ID_LSB);\n+\tp->mp_fld_prod_id_lsb_rev_id =\n+\t\tregister_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_REV_ID);\n+\tp->mp_fld_prod_id_lsb_ver_id =\n+\t\tregister_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_VER_ID);\n+\tp->mp_fld_prod_id_lsb_group_id =\n+\t\tregister_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_GROUP_ID);\n+\n+\tp->mp_reg_prod_id_msb = module_get_register(p->mp_mod_hif, HIF_PROD_ID_MSB);\n+\tp->mp_fld_prod_id_msb_type_id =\n+\t\tregister_get_field(p->mp_reg_prod_id_msb, HIF_PROD_ID_MSB_TYPE_ID);\n+\tp->mp_fld_prod_id_msb_build_no =\n+\t\tregister_get_field(p->mp_reg_prod_id_msb, HIF_PROD_ID_MSB_BUILD_NO);\n+\n+\tp->mp_reg_build_time = module_get_register(p->mp_mod_hif, HIF_BUILD_TIME);\n+\tp->mp_fld_build_time =\n+\t\tregister_get_field(p->mp_reg_build_time, HIF_BUILD_TIME_TIME);\n+\n+\tp->mn_fpga_id_prod = field_get_updated(p->mp_fld_prod_id_lsb_group_id);\n+\tp->mn_fpga_id_ver = field_get_updated(p->mp_fld_prod_id_lsb_ver_id);\n+\tp->mn_fpga_id_rev = field_get_updated(p->mp_fld_prod_id_lsb_rev_id);\n+\tp->mn_fpga_id_build_no = field_get_updated(p->mp_fld_prod_id_msb_build_no);\n+\tp->mn_fpga_id_item = field_get_updated(p->mp_fld_prod_id_msb_type_id);\n+\n+\tNT_LOG(DBG, NTHW, \"%s: HIF %d: %s: %d-%d-%d-%d-%d\\n\", p_adapter_id_str,\n+\t       p->mn_instance, __func__, p->mn_fpga_id_item, p->mn_fpga_id_prod,\n+\t       p->mn_fpga_id_ver, p->mn_fpga_id_rev, p->mn_fpga_id_build_no);\n+\tNT_LOG(DBG, NTHW,\n+\t       \"%s: HIF %d: %s: HIF ref clock: %d Hz (%d ticks/ps)\\n\",\n+\t       p_adapter_id_str, p->mn_instance, __func__, p->mn_fpga_hif_ref_clk_freq,\n+\t       p->mn_fpga_param_hif_per_ps);\n+\n+\tp->mp_reg_build_seed = NULL; /* Reg/Fld not present on HIF */\n+\tif (p->mp_reg_build_seed)\n+\t\tp->mp_fld_build_seed = NULL; /* Reg/Fld not present on HIF */\n+\telse\n+\t\tp->mp_fld_build_seed = NULL;\n+\n+\tp->mp_reg_core_speed = NULL; /* Reg/Fld not present on HIF */\n+\tif (p->mp_reg_core_speed) {\n+\t\tp->mp_fld_core_speed = NULL; /* Reg/Fld not present on HIF */\n+\t\tp->mp_fld_ddr3_speed = NULL; /* Reg/Fld not present on HIF */\n+\t} else {\n+\t\tp->mp_reg_core_speed = NULL;\n+\t\tp->mp_fld_core_speed = NULL;\n+\t\tp->mp_fld_ddr3_speed = NULL;\n+\t}\n+\n+\t/* Optional registers since: 2018-04-25 */\n+\tp->mp_reg_int_mask = NULL; /* Reg/Fld not present on HIF */\n+\tp->mp_reg_int_clr = NULL; /* Reg/Fld not present on HIF */\n+\tp->mp_reg_int_force = NULL; /* Reg/Fld not present on HIF */\n+\n+\tp->mp_fld_int_mask_timer = NULL;\n+\tp->mp_fld_int_clr_timer = NULL;\n+\tp->mp_fld_int_force_timer = NULL;\n+\n+\tp->mp_fld_int_mask_port = NULL;\n+\tp->mp_fld_int_clr_port = NULL;\n+\tp->mp_fld_int_force_port = NULL;\n+\n+\tp->mp_fld_int_mask_pps = NULL;\n+\tp->mp_fld_int_clr_pps = NULL;\n+\tp->mp_fld_int_force_pps = NULL;\n+\n+\tp->mp_reg_stat_ctrl = module_get_register(p->mp_mod_hif, HIF_STAT_CTRL);\n+\tp->mp_fld_stat_ctrl_ena =\n+\t\tregister_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_ENA);\n+\tp->mp_fld_stat_ctrl_req =\n+\t\tregister_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_REQ);\n+\n+\tp->mp_reg_stat_rx = module_get_register(p->mp_mod_hif, HIF_STAT_RX);\n+\tp->mp_fld_stat_rx_counter =\n+\t\tregister_get_field(p->mp_reg_stat_rx, HIF_STAT_RX_COUNTER);\n+\n+\tp->mp_reg_stat_tx = module_get_register(p->mp_mod_hif, HIF_STAT_TX);\n+\tp->mp_fld_stat_tx_counter =\n+\t\tregister_get_field(p->mp_reg_stat_tx, HIF_STAT_TX_COUNTER);\n+\n+\tp->mp_reg_stat_ref_clk = module_get_register(p->mp_mod_hif, HIF_STAT_REFCLK);\n+\tp->mp_fld_stat_ref_clk_ref_clk = register_get_field(p->mp_reg_stat_ref_clk,\n+\t\t\t\t   HIF_STAT_REFCLK_REFCLK250);\n+\n+\tp->mp_reg_status = module_query_register(p->mp_mod_hif, HIF_STATUS);\n+\tif (p->mp_reg_status) {\n+\t\tp->mp_fld_status_tags_in_use =\n+\t\t\tregister_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE);\n+\t\tp->mp_fld_status_wr_err =\n+\t\t\tregister_query_field(p->mp_reg_status, HIF_STATUS_WR_ERR);\n+\t\tp->mp_fld_status_rd_err =\n+\t\t\tregister_query_field(p->mp_reg_status, HIF_STATUS_RD_ERR);\n+\t} else {\n+\t\tp->mp_reg_status = module_query_register(p->mp_mod_hif, HIF_STATUS);\n+\t\tp->mp_fld_status_tags_in_use =\n+\t\t\tregister_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE);\n+\t\tp->mp_fld_status_wr_err = NULL;\n+\t\tp->mp_fld_status_rd_err = NULL;\n+\t}\n+\n+\tp->mp_reg_pci_test0 = module_get_register(p->mp_mod_hif, HIF_TEST0);\n+\tp->mp_fld_pci_test0 = register_get_field(p->mp_reg_pci_test0, HIF_TEST0_DATA);\n+\n+\tp->mp_reg_pci_test1 = module_get_register(p->mp_mod_hif, HIF_TEST1);\n+\tp->mp_fld_pci_test1 = register_get_field(p->mp_reg_pci_test1, HIF_TEST1_DATA);\n+\n+\t/* Required to run TSM */\n+\tp->mp_reg_sample_time = module_get_register(p->mp_mod_hif, HIF_SAMPLE_TIME);\n+\tif (p->mp_reg_sample_time) {\n+\t\tp->mp_fld_sample_time =\n+\t\t\tregister_get_field(p->mp_reg_sample_time, HIF_SAMPLE_TIME_SAMPLE_TIME);\n+\t} else {\n+\t\tp->mp_fld_sample_time = NULL;\n+\t}\n+\n+\t/* We need to optimize PCIe3 TLP-size read-request and extended tag usage */\n+\t{\n+\t\tp->mp_reg_config = module_query_register(p->mp_mod_hif, HIF_CONFIG);\n+\t\tif (p->mp_reg_config) {\n+\t\t\tp->mp_fld_max_tlp =\n+\t\t\t\tregister_get_field(p->mp_reg_config, HIF_CONFIG_MAX_TLP);\n+\t\t\tp->mp_fld_max_read =\n+\t\t\t\tregister_get_field(p->mp_reg_config, HIF_CONFIG_MAX_READ);\n+\t\t\tp->mp_fld_ext_tag =\n+\t\t\t\tregister_get_field(p->mp_reg_config, HIF_CONFIG_EXT_TAG);\n+\t\t} else {\n+\t\t\tp->mp_fld_max_tlp = NULL;\n+\t\t\tp->mp_fld_max_read = NULL;\n+\t\t\tp->mp_fld_ext_tag = NULL;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int nthw_hif_setup_config(nthw_hif_t *p)\n+{\n+\tconst char *const p_adapter_id_str _unused =\n+\t\tp->mp_fpga->p_fpga_info->mp_adapter_id_str;\n+\n+\t/*\n+\t * We need to optimize PCIe3 read-request and extended tag usage\n+\t * original check: HW_ADAPTER_ID_NT200A02 HW_ADAPTER_ID_NT100A01 HW_ADAPTER_ID_NT50B01\n+\t */\n+\tif (p->mp_fpga->p_fpga_info->n_nthw_adapter_id != NT_HW_ADAPTER_ID_NT40E3) {\n+\t\tif (p->mp_fld_max_read) {\n+\t\t\t/*\n+\t\t\t * NOTE: On Pandion DELL server, this param was negotiated to 4096\n+\t\t\t * (index=5), but the server crashed. For now we need to limit this value to\n+\t\t\t * 512 (index=2)\n+\t\t\t */\n+\t\t\tconst uint32_t n_max_read_req_size =\n+\t\t\t\tfield_get_updated(p->mp_fld_max_read);\n+\t\t\tif (n_max_read_req_size > 2) {\n+\t\t\t\tfield_set_val_flush32(p->mp_fld_max_read, 2);\n+\t\t\t\tNT_LOG(INF, NTHW,\n+\t\t\t\t       \"%s: %s: PCIe: MaxReadReqsize %d - changed to 2 (512B)\\n\",\n+\t\t\t\t       p_adapter_id_str, __func__,\n+\t\t\t\t       n_max_read_req_size);\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (p->mp_fld_ext_tag)\n+\t\t\tfield_set_val_flush32(p->mp_fld_ext_tag, 1);\n+\n+\t\tif (p->mp_fld_max_tlp && p->mp_fld_max_read && p->mp_fld_ext_tag) {\n+\t\t\tNT_LOG(INF, NTHW,\n+\t\t\t       \"%s: %s: PCIe config: MaxTlp = %d, MaxReadReqsize = %d, ExtTagEna = %d\\n\",\n+\t\t\t       p_adapter_id_str, __func__,\n+\t\t\t       field_get_updated(p->mp_fld_max_tlp),\n+\t\t\t       field_get_updated(p->mp_fld_max_read),\n+\t\t\t       field_get_updated(p->mp_fld_ext_tag));\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+int nthw_hif_trigger_sample_time(nthw_hif_t *p)\n+{\n+\tfield_set_val_flush32(p->mp_fld_sample_time, 0xfee1dead);\n+\n+\treturn 0;\n+}\n+\n+int nthw_hif_get_stat(nthw_hif_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt,\n+\t\t    uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size,\n+\t\t    uint32_t *p_tg_ref_freq, uint64_t *p_tags_in_use,\n+\t\t    uint64_t *p_rd_err, uint64_t *p_wr_err)\n+{\n+\t*p_rx_cnt = field_get_updated(p->mp_fld_stat_rx_counter);\n+\t*p_tx_cnt = field_get_updated(p->mp_fld_stat_tx_counter);\n+\n+\t*p_ref_clk_cnt = field_get_updated(p->mp_fld_stat_ref_clk_ref_clk);\n+\n+\t*p_tg_unit_size = NTHW_TG_CNT_SIZE;\n+\t*p_tg_ref_freq = p->mn_fpga_hif_ref_clk_freq;\n+\n+\t*p_tags_in_use = (p->mp_fld_status_tags_in_use ?\n+\t\t       field_get_updated(p->mp_fld_status_tags_in_use) :\n+\t\t       0);\n+\n+\t*p_rd_err = (p->mp_fld_status_rd_err ? field_get_updated(p->mp_fld_status_rd_err) :\n+\t\t   0);\n+\t*p_wr_err = (p->mp_fld_status_wr_err ? field_get_updated(p->mp_fld_status_wr_err) :\n+\t\t   0);\n+\n+\treturn 0;\n+}\n+\n+int nthw_hif_get_stat_rate(nthw_hif_t *p, uint64_t *p_pci_rx_rate,\n+\t\t\tuint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt,\n+\t\t\tuint64_t *p_tags_in_use, uint64_t *p_rd_err_cnt,\n+\t\t\tuint64_t *p_wr_err_cnt)\n+{\n+\tuint32_t rx_cnt, tx_cnt, ref_clk_cnt, tg_unit_size, tg_ref_freq;\n+\tuint64_t n_tags_in_use, n_rd_err, n_wr_err;\n+\n+\tnthw_hif_get_stat(p, &rx_cnt, &tx_cnt, &ref_clk_cnt, &tg_unit_size, &tg_ref_freq,\n+\t\t\t&n_tags_in_use, &n_rd_err, &n_wr_err);\n+\n+\t*p_tags_in_use = n_tags_in_use;\n+\tif (n_rd_err)\n+\t\t(*p_rd_err_cnt)++;\n+\tif (n_wr_err)\n+\t\t(*p_wr_err_cnt)++;\n+\n+\tif (ref_clk_cnt) {\n+\t\tuint64_t rx_rate;\n+\t\tuint64_t tx_rate;\n+\n+\t\t*p_ref_clk_cnt = ref_clk_cnt;\n+\n+\t\trx_rate = ((uint64_t)rx_cnt * tg_unit_size * tg_ref_freq) /\n+\t\t\t (uint64_t)ref_clk_cnt;\n+\t\t*p_pci_rx_rate = rx_rate;\n+\n+\t\ttx_rate = ((uint64_t)tx_cnt * tg_unit_size * tg_ref_freq) /\n+\t\t\t (uint64_t)ref_clk_cnt;\n+\t\t*p_pci_tx_rate = tx_rate;\n+\t} else {\n+\t\t*p_pci_rx_rate = 0;\n+\t\t*p_pci_tx_rate = 0;\n+\t\t*p_ref_clk_cnt = 0;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int nthw_hif_stat_req_enable(nthw_hif_t *p)\n+{\n+\tfield_set_all(p->mp_fld_stat_ctrl_ena);\n+\tfield_set_all(p->mp_fld_stat_ctrl_req);\n+\tfield_flush_register(p->mp_fld_stat_ctrl_req);\n+\treturn 0;\n+}\n+\n+int nthw_hif_stat_req_disable(nthw_hif_t *p)\n+{\n+\tfield_clr_all(p->mp_fld_stat_ctrl_ena);\n+\tfield_set_all(p->mp_fld_stat_ctrl_req);\n+\tfield_flush_register(p->mp_fld_stat_ctrl_req);\n+\treturn 0;\n+}\n+\n+int nthw_hif_stat_sample(nthw_hif_t *p, uint64_t *p_rx_rate, uint64_t *p_tx_rate,\n+\t\t       uint64_t *p_ref_clk_cnt, uint64_t *p_tags_in_use,\n+\t\t       uint64_t *p_rd_err_cnt, uint64_t *p_wr_err_cnt)\n+{\n+\tnthw_hif_stat_req_enable(p);\n+\tNT_OS_WAIT_USEC(100000);\n+\tnthw_hif_stat_req_disable(p);\n+\tnthw_hif_get_stat_rate(p, p_rx_rate, p_tx_rate, p_ref_clk_cnt, p_tags_in_use,\n+\t\t\t    p_rd_err_cnt, p_wr_err_cnt);\n+\n+\treturn 0;\n+}\n+\n+int nthw_hif_end_point_counters_sample(nthw_hif_t *p,\n+\t\t\t\t   struct nthw_hif_end_point_counters *epc)\n+{\n+\tassert(epc);\n+\n+\t/* Get stat rate and maintain rx/tx min/max */\n+\tnthw_hif_get_stat_rate(p, &epc->cur_tx, &epc->cur_rx, &epc->n_ref_clk_cnt,\n+\t\t\t    &epc->n_tags_in_use, &epc->n_rd_err, &epc->n_wr_err);\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_hif.h b/drivers/net/ntnic/nthw/core/nthw_hif.h\nnew file mode 100644\nindex 0000000000..2701e222b3\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_hif.h\n@@ -0,0 +1,156 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_HIF_H__\n+#define __NTHW_HIF_H__\n+\n+#define NTHW_TG_CNT_SIZE (4ULL)\n+\n+struct nthw_hif {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_hif;\n+\tint mn_instance;\n+\n+\tnt_register_t *mp_reg_prod_id_lsb;\n+\tnt_field_t *mp_fld_prod_id_lsb_rev_id;\n+\tnt_field_t *mp_fld_prod_id_lsb_ver_id;\n+\tnt_field_t *mp_fld_prod_id_lsb_group_id;\n+\n+\tnt_register_t *mp_reg_prod_id_msb;\n+\tnt_field_t *mp_fld_prod_id_msb_type_id;\n+\tnt_field_t *mp_fld_prod_id_msb_build_no;\n+\n+\tnt_register_t *mp_reg_build_time;\n+\tnt_field_t *mp_fld_build_time;\n+\n+\tnt_register_t *mp_reg_build_seed;\n+\tnt_field_t *mp_fld_build_seed;\n+\n+\tnt_register_t *mp_reg_core_speed;\n+\tnt_field_t *mp_fld_core_speed;\n+\tnt_field_t *mp_fld_ddr3_speed;\n+\n+\tnt_register_t *mp_reg_int_mask;\n+\tnt_field_t *mp_fld_int_mask_timer;\n+\tnt_field_t *mp_fld_int_mask_port;\n+\tnt_field_t *mp_fld_int_mask_pps;\n+\n+\tnt_register_t *mp_reg_int_clr;\n+\tnt_field_t *mp_fld_int_clr_timer;\n+\tnt_field_t *mp_fld_int_clr_port;\n+\tnt_field_t *mp_fld_int_clr_pps;\n+\n+\tnt_register_t *mp_reg_int_force;\n+\tnt_field_t *mp_fld_int_force_timer;\n+\tnt_field_t *mp_fld_int_force_port;\n+\tnt_field_t *mp_fld_int_force_pps;\n+\n+\tnt_register_t *mp_reg_sample_time;\n+\tnt_field_t *mp_fld_sample_time;\n+\n+\tnt_register_t *mp_reg_status;\n+\tnt_field_t *mp_fld_status_tags_in_use;\n+\tnt_field_t *mp_fld_status_wr_err;\n+\tnt_field_t *mp_fld_status_rd_err;\n+\n+\tnt_register_t *mp_reg_stat_ctrl;\n+\tnt_field_t *mp_fld_stat_ctrl_ena;\n+\tnt_field_t *mp_fld_stat_ctrl_req;\n+\n+\tnt_register_t *mp_reg_stat_rx;\n+\tnt_field_t *mp_fld_stat_rx_counter;\n+\n+\tnt_register_t *mp_reg_stat_tx;\n+\tnt_field_t *mp_fld_stat_tx_counter;\n+\n+\tnt_register_t *mp_reg_stat_ref_clk;\n+\tnt_field_t *mp_fld_stat_ref_clk_ref_clk;\n+\n+\tnt_register_t *mp_reg_pci_test0;\n+\tnt_field_t *mp_fld_pci_test0;\n+\n+\tnt_register_t *mp_reg_pci_test1;\n+\tnt_field_t *mp_fld_pci_test1;\n+\n+\tnt_register_t *mp_reg_pci_test2;\n+\tnt_field_t *mp_fld_pci_test2;\n+\n+\tnt_register_t *mp_reg_pci_test3;\n+\tnt_field_t *mp_fld_pci_test3;\n+\n+\tnt_register_t *mp_reg_config;\n+\tnt_field_t *mp_fld_max_tlp;\n+\tnt_field_t *mp_fld_max_read;\n+\tnt_field_t *mp_fld_ext_tag;\n+\n+\tint mn_fpga_id_item;\n+\tint mn_fpga_id_prod;\n+\tint mn_fpga_id_ver;\n+\tint mn_fpga_id_rev;\n+\tint mn_fpga_id_build_no;\n+\n+\tint mn_fpga_param_hif_per_ps;\n+\tuint32_t mn_fpga_hif_ref_clk_freq;\n+};\n+\n+typedef struct nthw_hif nthw_hif_t;\n+typedef struct nthw_hif nthw_hif;\n+\n+struct nthw_hif_end_point_err_counters {\n+\tuint32_t n_err_correctable, n_err_non_fatal, n_err_fatal;\n+};\n+\n+struct nthw_hif_end_point_counters {\n+\tint n_numa_node;\n+\n+\tint n_tg_direction;\n+\tint n_tg_pkt_size;\n+\tint n_tg_num_pkts;\n+\tint n_tg_delay;\n+\n+\tuint64_t cur_rx, cur_tx;\n+\tuint64_t cur_pci_nt_util, cur_pci_xil_util;\n+\tuint64_t n_ref_clk_cnt;\n+\n+\tuint64_t n_tags_in_use;\n+\tuint64_t n_rd_err;\n+\tuint64_t n_wr_err;\n+\n+\tstruct nthw_hif_end_point_err_counters s_rc_ep_pre, s_rc_ep_post, s_rc_ep_delta;\n+\tstruct nthw_hif_end_point_err_counters s_ep_rc_pre, s_ep_rc_post, s_ep_rc_delta;\n+\n+\tint bo_error;\n+};\n+\n+struct nthw_hif_end_points {\n+\tstruct nthw_hif_end_point_counters pri, sla;\n+};\n+\n+nthw_hif_t *nthw_hif_new(void);\n+void nthw_hif_delete(nthw_hif_t *p);\n+int nthw_hif_init(nthw_hif_t *p, nt_fpga_t *p_fpga, int n_instance);\n+\n+int nthw_hif_setup_config(nthw_hif_t *p);\n+\n+int nthw_hif_trigger_sample_time(nthw_hif_t *p);\n+\n+int nthw_hif_stat_req_enable(nthw_hif_t *p);\n+int nthw_hif_stat_req_disable(nthw_hif_t *p);\n+int nthw_hif_stat_sample(nthw_hif_t *p, uint64_t *p_rx_rate, uint64_t *p_tx_rate,\n+\t\t       uint64_t *p_ref_clk_cnt, uint64_t *p_tags_in_use,\n+\t\t       uint64_t *p_rd_err_cnt, uint64_t *p_wr_err_cnt);\n+\n+int nthw_hif_get_stat(nthw_hif_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt,\n+\t\t    uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size,\n+\t\t    uint32_t *p_tg_ref_freq, uint64_t *p_tags_in_use,\n+\t\t    uint64_t *p_rd_err, uint64_t *p_wr_err);\n+int nthw_hif_get_stat_rate(nthw_hif_t *p, uint64_t *p_pci_rx_rate,\n+\t\t\tuint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt,\n+\t\t\tuint64_t *p_tags_in_use, uint64_t *p_rd_err_cnt,\n+\t\t\tuint64_t *p_wr_err_cnt);\n+\n+int nthw_hif_end_point_counters_sample(nthw_hif_t *p,\n+\t\t\t\t   struct nthw_hif_end_point_counters *epc);\n+\n+#endif /* __NTHW_HIF_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_iic.c b/drivers/net/ntnic/nthw/core/nthw_iic.c\nnew file mode 100644\nindex 0000000000..14aee221ce\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_iic.c\n@@ -0,0 +1,570 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"nt_util.h\"\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_iic.h\"\n+\n+#define I2C_TRANSMIT_WR (0x00)\n+#define I2C_TRANSMIT_RD (0x01)\n+\n+#define I2C_WAIT_US(x) NT_OS_WAIT_USEC(x)\n+\n+/*\n+ * Minimum timing values for I2C for a Marvel 88E11111 Phy.\n+ * This Phy is used in many Trispeed NIMs.\n+ * In order to access this Phy, the I2C clock speed is needed to be set to 100KHz.\n+ */\n+static const uint32_t susta = 4700; /* ns */\n+static const uint32_t susto = 4000; /* ns */\n+static const uint32_t hdsta = 4000; /* ns */\n+static const uint32_t sudat = 250; /* ns */\n+static const uint32_t buf = 4700; /* ns */\n+static const uint32_t high = 4000; /* ns */\n+static const uint32_t low = 4700; /* ns */\n+static const uint32_t hddat = 300; /* ns */\n+\n+static int nthw_iic_reg_control_txfifo_reset(nthw_iic_t *p)\n+{\n+\tfield_update_register(p->mp_fld_cr_txfifo_reset);\n+\n+\tfield_set_all(p->mp_fld_cr_txfifo_reset);\n+\tfield_flush_register(p->mp_fld_cr_txfifo_reset);\n+\n+\tfield_clr_all(p->mp_fld_cr_txfifo_reset);\n+\tfield_flush_register(p->mp_fld_cr_txfifo_reset);\n+\n+\treturn 0;\n+}\n+\n+static int nthw_iic_reg_tx_fifo_write(nthw_iic_t *p, uint32_t data, bool start,\n+\t\t\t\t     bool stop)\n+{\n+\tif (start)\n+\t\tfield_set_all(p->mp_fld_tx_fifo_start);\n+\n+\telse\n+\t\tfield_clr_all(p->mp_fld_tx_fifo_start);\n+\n+\tif (stop)\n+\t\tfield_set_all(p->mp_fld_tx_fifo_stop);\n+\n+\telse\n+\t\tfield_clr_all(p->mp_fld_tx_fifo_stop);\n+\n+\tfield_set_val32(p->mp_fld_tx_fifo_txdata, data);\n+\n+\tregister_flush(p->mp_reg_tx_fifo, 1);\n+\n+\treturn 0;\n+}\n+\n+static int nthw_iic_reg_read_i2c_rx_fifo(nthw_iic_t *p, uint8_t *p_data)\n+{\n+\tassert(p_data);\n+\n+\t*p_data = (uint8_t)field_get_updated(p->mp_fld_rx_fifo_rxdata);\n+\n+\treturn 0;\n+}\n+\n+static int nthw_iic_reg_softr(nthw_iic_t *p)\n+{\n+\tfield_update_register(p->mp_fld_cr_en);\n+\tfield_set_val_flush32(p->mp_fld_softr_rkey, 0x0A);\n+\n+\treturn 0;\n+}\n+\n+static int nthw_iic_reg_enable(nthw_iic_t *p)\n+{\n+\tfield_update_register(p->mp_fld_cr_en);\n+\tfield_set_flush(p->mp_fld_cr_en);\n+\n+\treturn 0;\n+}\n+\n+static int nthw_iic_reg_busbusy(nthw_iic_t *p, bool *pb_flag)\n+{\n+\tassert(pb_flag);\n+\n+\t*pb_flag = field_get_updated(p->mp_fld_sr_bb) ? true : false;\n+\n+\treturn 0;\n+}\n+\n+static int nthw_iic_reg_rxfifo_empty(nthw_iic_t *p, bool *pb_flag)\n+{\n+\tassert(pb_flag);\n+\n+\t*pb_flag = field_get_updated(p->mp_fld_sr_rxfifo_empty) ? true : false;\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * nIicCycleTime is the I2C clock cycle time in ns ie 125MHz = 8ns\n+ */\n+static int nthw_iic_reg_set_timing(nthw_iic_t *p, uint32_t n_iic_cycle_time)\n+{\n+\tuint32_t val;\n+\n+\tval = susta / n_iic_cycle_time;\n+\tfield_set_val_flush(p->mp_fld_tsusta, &val, 1);\n+\n+\tval = susto / n_iic_cycle_time;\n+\tfield_set_val_flush(p->mp_fld_tsusto, &val, 1);\n+\n+\tval = hdsta / n_iic_cycle_time;\n+\tfield_set_val_flush(p->mp_fld_thdsta, &val, 1);\n+\n+\tval = sudat / n_iic_cycle_time;\n+\tfield_set_val_flush(p->mp_fld_tsudat, &val, 1);\n+\n+\tval = buf / n_iic_cycle_time;\n+\tfield_set_val_flush(p->mp_fld_tbuf, &val, 1);\n+\n+\tval = high / n_iic_cycle_time;\n+\tfield_set_val_flush(p->mp_fld_thigh, &val, 1);\n+\n+\tval = low / n_iic_cycle_time;\n+\tfield_set_val_flush(p->mp_fld_tlow, &val, 1);\n+\n+\tval = hddat / n_iic_cycle_time;\n+\tfield_set_val_flush(p->mp_fld_thddat, &val, 1);\n+\n+\treturn 0;\n+}\n+\n+nthw_iic_t *nthw_iic_new(void)\n+{\n+\tnthw_iic_t *p = malloc(sizeof(nthw_iic_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_iic_t));\n+\treturn p;\n+}\n+\n+int nthw_iic_init(nthw_iic_t *p, nt_fpga_t *p_fpga, int n_iic_instance,\n+\t\t uint32_t n_iic_cycle_time)\n+{\n+\tconst char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_IIC, n_iic_instance);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: I2C %d: no such instance\\n\",\n+\t\t       p_adapter_id_str, n_iic_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_iic_instance = n_iic_instance;\n+\n+\tp->mn_iic_cycle_time = n_iic_cycle_time;\n+\n+\tnthw_iic_set_retry_params(p, -1, -1, -1, -1, -1);\n+\n+\tp->mp_mod_iic = mod;\n+\n+\t/* I2C is a primary communication channel - turn off debug by default */\n+\tmodule_set_debug_mode(p->mp_mod_iic, 0x00);\n+\n+\tp->mp_reg_tsusta = module_get_register(p->mp_mod_iic, IIC_TSUSTA);\n+\tp->mp_fld_tsusta =\n+\t\tregister_get_field(p->mp_reg_tsusta, IIC_TSUSTA_TSUSTA_VAL);\n+\n+\tp->mp_reg_tsusto = module_get_register(p->mp_mod_iic, IIC_TSUSTO);\n+\tp->mp_fld_tsusto =\n+\t\tregister_get_field(p->mp_reg_tsusto, IIC_TSUSTO_TSUSTO_VAL);\n+\n+\tp->mp_reg_thdsta = module_get_register(p->mp_mod_iic, IIC_THDSTA);\n+\tp->mp_fld_thdsta =\n+\t\tregister_get_field(p->mp_reg_thdsta, IIC_THDSTA_THDSTA_VAL);\n+\n+\tp->mp_reg_tsudat = module_get_register(p->mp_mod_iic, IIC_TSUDAT);\n+\tp->mp_fld_tsudat =\n+\t\tregister_get_field(p->mp_reg_tsudat, IIC_TSUDAT_TSUDAT_VAL);\n+\n+\tp->mp_reg_tbuf = module_get_register(p->mp_mod_iic, IIC_TBUF);\n+\tp->mp_fld_tbuf = register_get_field(p->mp_reg_tbuf, IIC_TBUF_TBUF_VAL);\n+\n+\tp->mp_reg_thigh = module_get_register(p->mp_mod_iic, IIC_THIGH);\n+\tp->mp_fld_thigh = register_get_field(p->mp_reg_thigh, IIC_THIGH_THIGH_VAL);\n+\n+\tp->mp_reg_tlow = module_get_register(p->mp_mod_iic, IIC_TLOW);\n+\tp->mp_fld_tlow = register_get_field(p->mp_reg_tlow, IIC_TLOW_TLOW_VAL);\n+\n+\tp->mp_reg_thddat = module_get_register(p->mp_mod_iic, IIC_THDDAT);\n+\tp->mp_fld_thddat =\n+\t\tregister_get_field(p->mp_reg_thddat, IIC_THDDAT_THDDAT_VAL);\n+\n+\tp->mp_reg_cr = module_get_register(p->mp_mod_iic, IIC_CR);\n+\tp->mp_fld_cr_en = register_get_field(p->mp_reg_cr, IIC_CR_EN);\n+\tp->mp_fld_cr_msms = register_get_field(p->mp_reg_cr, IIC_CR_MSMS);\n+\tp->mp_fld_cr_txfifo_reset =\n+\t\tregister_get_field(p->mp_reg_cr, IIC_CR_TXFIFO_RESET);\n+\tp->mp_fld_cr_txak = register_get_field(p->mp_reg_cr, IIC_CR_TXAK);\n+\n+\tp->mp_reg_sr = module_get_register(p->mp_mod_iic, IIC_SR);\n+\tp->mp_fld_sr_bb = register_get_field(p->mp_reg_sr, IIC_SR_BB);\n+\tp->mp_fld_sr_rxfifo_full =\n+\t\tregister_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_FULL);\n+\tp->mp_fld_sr_rxfifo_empty =\n+\t\tregister_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_EMPTY);\n+\tp->mp_fld_sr_txfifo_full =\n+\t\tregister_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_FULL);\n+\tp->mp_fld_sr_txfifo_empty =\n+\t\tregister_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_EMPTY);\n+\n+\tp->mp_reg_tx_fifo = module_get_register(p->mp_mod_iic, IIC_TX_FIFO);\n+\tp->mp_fld_tx_fifo_txdata =\n+\t\tregister_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_TXDATA);\n+\tp->mp_fld_tx_fifo_start =\n+\t\tregister_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_START);\n+\tp->mp_fld_tx_fifo_stop =\n+\t\tregister_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_STOP);\n+\n+\tp->mp_reg_rx_fifo_pirq =\n+\t\tmodule_get_register(p->mp_mod_iic, IIC_RX_FIFO_PIRQ);\n+\tp->mp_fld_rx_fifo_pirq_cmp_val =\n+\t\tregister_get_field(p->mp_reg_rx_fifo_pirq, IIC_RX_FIFO_PIRQ_CMP_VAL);\n+\n+\tp->mp_reg_rx_fifo = module_get_register(p->mp_mod_iic, IIC_RX_FIFO);\n+\tp->mp_fld_rx_fifo_rxdata =\n+\t\tregister_get_field(p->mp_reg_rx_fifo, IIC_RX_FIFO_RXDATA);\n+\n+\tp->mp_reg_softr = module_get_register(p->mp_mod_iic, IIC_SOFTR);\n+\tp->mp_fld_softr_rkey = register_get_field(p->mp_reg_softr, IIC_SOFTR_RKEY);\n+\n+\t/*\n+\t * Initialize I2C controller by applying soft reset and enable the controller\n+\t */\n+\tnthw_iic_reg_softr(p);\n+\t/* Enable the controller */\n+\tnthw_iic_reg_enable(p);\n+\n+\t/* Setup controller timing */\n+\tif (p->mn_iic_cycle_time) {\n+\t\tNT_LOG(DBG, NTHW, \"%s: I2C%d: cycletime=%d\\n\", p_adapter_id_str,\n+\t\t       p->mn_iic_instance, p->mn_iic_cycle_time);\n+\t\tnthw_iic_reg_set_timing(p, p->mn_iic_cycle_time);\n+\t}\n+\n+\t/* Reset TX fifo - must be after enable */\n+\tnthw_iic_reg_control_txfifo_reset(p);\n+\tnthw_iic_reg_tx_fifo_write(p, 0, 0, 0);\n+\n+\treturn 0;\n+}\n+\n+void nthw_iic_delete(nthw_iic_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_iic_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+int nthw_iic_set_retry_params(nthw_iic_t *p, const int n_poll_delay,\n+\t\t\t   const int n_bus_ready_retry, const int n_data_ready_retry,\n+\t\t\t   const int n_read_data_retry, const int n_write_data_retry)\n+{\n+\tp->mn_poll_delay = n_poll_delay >= 0 ? n_poll_delay : 10;\n+\n+\tp->mn_bus_ready_retry = n_bus_ready_retry >= 0 ? n_bus_ready_retry : 1000;\n+\tp->mn_data_ready_retry = n_data_ready_retry >= 0 ? n_data_ready_retry : 1000;\n+\n+\tp->mn_read_data_retry = n_read_data_retry >= 0 ? n_read_data_retry : 10;\n+\tp->mn_write_data_retry = n_write_data_retry >= 0 ? n_write_data_retry : 10;\n+\n+\treturn 0;\n+}\n+\n+int nthw_iic_read_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,\n+\t\t     uint8_t data_len, void *p_void)\n+{\n+\tconst char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;\n+\tconst int n_debug_mode = module_get_debug_mode(p->mp_mod_iic);\n+\n+\tuint8_t *pb = (uint8_t *)p_void;\n+\tint retry = (p->mn_read_data_retry >= 0 ? p->mn_read_data_retry : 10);\n+\n+\tif (n_debug_mode == 0xff) {\n+\t\tNT_LOG(DBG, NTHW, \"%s: adr=0x%2.2x, reg=%d, len=%d\\n\",\n+\t\t       p_adapter_id_str, dev_addr, reg_addr, data_len);\n+\t}\n+\n+\twhile (nthw_iic_readbyte(p, dev_addr, reg_addr, data_len, pb) != 0) {\n+\t\tretry--;\n+\t\tif (retry <= 0) {\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: I2C%d: Read retry exhausted (dev_addr=%d reg_addr=%d)\\n\",\n+\t\t\t       p_adapter_id_str, p->mn_iic_instance, dev_addr,\n+\t\t\t       reg_addr);\n+\t\t\treturn -1;\n+\t\t}\n+#if defined(DEBUG)\n+\t\tNT_LOG(DBG, NTHW,\n+\t\t       \"%s: I2C%d: Read retry=%d (dev_addr=%d reg_addr=%d)\\n\",\n+\t\t       p_adapter_id_str, p->mn_iic_instance, retry, dev_addr,\n+\t\t       reg_addr);\n+#endif\n+\t}\n+\n+\tif (n_debug_mode == 0xff) {\n+\t\tNT_LOG(DBG, NTHW,\n+\t\t       \"%s: adr=0x%2.2x, reg=%d, len=%d, retries remaining: %d\\n\",\n+\t\t       p_adapter_id_str, dev_addr, reg_addr, data_len, retry);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int nthw_iic_readbyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,\n+\t\t     uint8_t data_len, uint8_t *p_byte)\n+{\n+\tconst char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;\n+\n+\tuint32_t value;\n+\tuint32_t i;\n+\n+\tif (nthw_iic_bus_ready(p)) {\n+\t\t/* Reset TX fifo */\n+\t\tnthw_iic_reg_control_txfifo_reset(p);\n+\n+\t\t/* Write device address to TX_FIFO and set start bit!! */\n+\t\tvalue = (dev_addr << 1) | I2C_TRANSMIT_WR;\n+\t\tnthw_iic_reg_tx_fifo_write(p, value, 1, 0);\n+\n+\t\t/* Write reg_addr to TX FIFO */\n+\t\tnthw_iic_reg_tx_fifo_write(p, reg_addr, 0, 1);\n+\n+\t\tif (!nthw_iic_bus_ready(p)) {\n+\t\t\tNT_LOG(ERR, NTHW, \"%s: error: (%s:%u)\\n\", p_adapter_id_str,\n+\t\t\t       __func__, __LINE__);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t/* Write device address + RD bit to TX_FIFO and set start bit!! */\n+\t\tvalue = (dev_addr << 1) | I2C_TRANSMIT_RD;\n+\t\tnthw_iic_reg_tx_fifo_write(p, value, 1, 0);\n+\n+\t\t/* Write DataLen to TX_FIFO and set stop bit!! */\n+\t\tnthw_iic_reg_tx_fifo_write(p, data_len, 0, 1);\n+\n+\t\tfor (i = 0; i < data_len; i++) {\n+\t\t\t/* Wait for RX FIFO not empty */\n+\t\t\tif (!nthw_iic_data_ready(p))\n+\t\t\t\treturn -1;\n+\n+\t\t\t/* Read DataLen bytes from RX_FIFO */\n+\t\t\tnthw_iic_reg_read_i2c_rx_fifo(p, p_byte);\n+\t\t\tp_byte++;\n+\t\t}\n+\n+\t\treturn 0;\n+\n+\t} else {\n+\t\tNT_LOG(ERR, NTHW, \"%s: error: (%s:%u)\\n\", p_adapter_id_str,\n+\t\t       __func__, __LINE__);\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n+\n+int nthw_iic_write_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,\n+\t\t      uint8_t data_len, void *p_void)\n+{\n+\tconst char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;\n+\tint retry = (p->mn_write_data_retry >= 0 ? p->mn_write_data_retry : 10);\n+\tuint8_t *pb = (uint8_t *)p_void;\n+\n+\twhile (nthw_iic_writebyte(p, dev_addr, reg_addr, data_len, pb) != 0) {\n+\t\tretry--;\n+\t\tif (retry <= 0) {\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: I2C%d: Write retry exhausted (dev_addr=%d reg_addr=%d)\\n\",\n+\t\t\t       p_adapter_id_str, p->mn_iic_instance, dev_addr,\n+\t\t\t       reg_addr);\n+\t\t\treturn -1;\n+\t\t}\n+#if defined(DEBUG)\n+\t\tNT_LOG(DBG, NTHW,\n+\t\t       \"%s: I2C%d: Write retry=%d (dev_addr=%d reg_addr=%d)\\n\",\n+\t\t       p_adapter_id_str, p->mn_iic_instance, retry, dev_addr,\n+\t\t       reg_addr);\n+#endif\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int nthw_iic_writebyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,\n+\t\t      uint8_t data_len, uint8_t *p_byte)\n+{\n+\tconst char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str;\n+\tuint32_t value;\n+\tint count;\n+\tint i;\n+\n+\tif (data_len == 0)\n+\t\treturn -1;\n+\n+\tcount = data_len - 1;\n+\tif (nthw_iic_bus_ready(p)) {\n+\t\t/* Reset TX fifo */\n+\t\tnthw_iic_reg_control_txfifo_reset(p);\n+\n+\t\t/* Write device address to TX_FIFO and set start bit!! */\n+\t\tvalue = (dev_addr << 1) | I2C_TRANSMIT_WR;\n+\t\tnthw_iic_reg_tx_fifo_write(p, value, 1, 0);\n+\n+\t\t/* Write reg_addr to TX FIFO */\n+\t\tnthw_iic_reg_tx_fifo_write(p, reg_addr, 0, 0);\n+\n+\t\tfor (i = 0; i < count; i++) {\n+\t\t\t/* Write data byte to TX fifo and set stop bit */\n+\t\t\tnthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 0);\n+\t\t\tp_byte++;\n+\t\t}\n+\n+\t\t/* Write data byte to TX fifo and set stop bit */\n+\t\tnthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 1);\n+\n+\t\tif (!nthw_iic_bus_ready(p)) {\n+\t\t\tNT_LOG(WRN, NTHW, \"%s: warn: !busReady (%s:%u)\\n\",\n+\t\t\t       p_adapter_id_str, __func__, __LINE__);\n+\t\t\twhile (true) {\n+\t\t\t\tif (nthw_iic_bus_ready(p)) {\n+\t\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t\t       \"%s: info: busReady (%s:%u)\\n\",\n+\t\t\t\t\t       p_adapter_id_str, __func__,\n+\t\t\t\t\t       __LINE__);\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\n+\t\treturn 0;\n+\n+\t} else {\n+\t\tNT_LOG(WRN, NTHW, \"%s: (%s:%u)\\n\", p_adapter_id_str, __func__,\n+\t\t       __LINE__);\n+\t\treturn -1;\n+\t}\n+}\n+\n+/*\n+ * Support function for read/write functions below. Waits for bus ready.\n+ */\n+bool nthw_iic_bus_ready(nthw_iic_t *p)\n+{\n+\tint count = (p->mn_bus_ready_retry >= 0 ? p->mn_bus_ready_retry : 1000);\n+\tbool b_bus_busy = true;\n+\n+\twhile (true) {\n+\t\tnthw_iic_reg_busbusy(p, &b_bus_busy);\n+\t\tif (!b_bus_busy)\n+\t\t\tbreak;\n+\n+\t\tcount--;\n+\t\tif (count <= 0)   /* Test for timeout */\n+\t\t\tbreak;\n+\n+\t\tif (p->mn_poll_delay != 0)\n+\t\t\tI2C_WAIT_US(p->mn_poll_delay);\n+\t}\n+\n+\tif (count == 0)\n+\t\treturn false;\n+\n+\treturn true;\n+}\n+\n+/*\n+ * Support function for read function. Waits for data ready.\n+ */\n+bool nthw_iic_data_ready(nthw_iic_t *p)\n+{\n+\tint count = (p->mn_data_ready_retry >= 0 ? p->mn_data_ready_retry : 1000);\n+\tbool b_rx_fifo_empty = true;\n+\n+\twhile (true) {\n+\t\tnthw_iic_reg_rxfifo_empty(p, &b_rx_fifo_empty);\n+\t\tif (!b_rx_fifo_empty)\n+\t\t\tbreak;\n+\n+\t\tcount--;\n+\t\tif (count <= 0)   /* Test for timeout */\n+\t\t\tbreak;\n+\n+\t\tif (p->mn_poll_delay != 0)\n+\t\t\tI2C_WAIT_US(p->mn_poll_delay);\n+\t}\n+\n+\tif (count == 0)\n+\t\treturn false;\n+\n+\treturn true;\n+}\n+\n+int nthw_iic_scan_dev_addr(nthw_iic_t *p, int n_dev_addr, int n_reg_addr)\n+{\n+\tconst char *const p_adapter_id_str _unused =\n+\t\tp->mp_fpga->p_fpga_info->mp_adapter_id_str;\n+\tint res;\n+\tuint8_t data_val = -1;\n+\n+\tres = nthw_iic_readbyte(p, (uint8_t)n_dev_addr, (uint8_t)n_reg_addr, 1,\n+\t\t\t       &data_val);\n+\tif (res == 0) {\n+\t\tNT_LOG(DBG, NTHW,\n+\t\t       \"%s: I2C%d: devaddr=0x%02X (%03d) regaddr=%02X val=%02X (%03d) res=%d\\n\",\n+\t\t       p_adapter_id_str, p->mn_iic_instance, n_dev_addr, n_dev_addr,\n+\t\t       n_reg_addr, data_val, data_val, res);\n+\t}\n+\treturn res;\n+}\n+\n+int nthw_iic_scan_find_dev(nthw_iic_t *p, int n_dev_addr_start, bool b_increate)\n+{\n+\tconst char *const p_adapter_id_str _unused =\n+\t\tp->mp_fpga->p_fpga_info->mp_adapter_id_str;\n+\n+\tint res = 0;\n+\tint i = 0;\n+\n+\tif (b_increate) {\n+\t\tfor (i = n_dev_addr_start; i < 128; i++) {\n+\t\t\tres = nthw_iic_scan_dev_addr(p, i, 0x00);\n+\t\t\tif (res == 0)\n+\t\t\t\tbreak;\n+\t\t}\n+\t} else {\n+\t\tfor (i = n_dev_addr_start; i >= 0; i--) {\n+\t\t\tres = nthw_iic_scan_dev_addr(p, i, 0x00);\n+\t\t\tif (res == 0)\n+\t\t\t\tbreak;\n+\t\t}\n+\t}\n+\tNT_LOG(DBG, NTHW, \"%s: I2C%d: FOUND: %d\\n\", p_adapter_id_str,\n+\t       p->mn_iic_instance, i);\n+\treturn (res == 0 ? i : -1);\n+}\n+\n+int nthw_iic_scan(nthw_iic_t *p)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < 128; i++)\n+\t\t(void)nthw_iic_scan_dev_addr(p, i, 0x00);\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_iic.h b/drivers/net/ntnic/nthw/core/nthw_iic.h\nnew file mode 100644\nindex 0000000000..e3bd313c88\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_iic.h\n@@ -0,0 +1,101 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_IIC_H__\n+#define __NTHW_IIC_H__\n+\n+#include \"nthw_fpga_model.h\"\n+\n+struct nthw_iic {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_iic;\n+\tint mn_iic_instance;\n+\n+\tuint32_t mn_iic_cycle_time;\n+\tint mn_poll_delay;\n+\tint mn_bus_ready_retry;\n+\tint mn_data_ready_retry;\n+\tint mn_read_data_retry;\n+\tint mn_write_data_retry;\n+\n+\tnt_register_t *mp_reg_tsusta;\n+\tnt_field_t *mp_fld_tsusta;\n+\n+\tnt_register_t *mp_reg_tsusto;\n+\tnt_field_t *mp_fld_tsusto;\n+\n+\tnt_register_t *mp_reg_thdsta;\n+\tnt_field_t *mp_fld_thdsta;\n+\n+\tnt_register_t *mp_reg_tsudat;\n+\tnt_field_t *mp_fld_tsudat;\n+\n+\tnt_register_t *mp_reg_tbuf;\n+\tnt_field_t *mp_fld_tbuf;\n+\n+\tnt_register_t *mp_reg_thigh;\n+\tnt_field_t *mp_fld_thigh;\n+\n+\tnt_register_t *mp_reg_tlow;\n+\tnt_field_t *mp_fld_tlow;\n+\n+\tnt_register_t *mp_reg_thddat;\n+\tnt_field_t *mp_fld_thddat;\n+\n+\tnt_register_t *mp_reg_cr;\n+\tnt_field_t *mp_fld_cr_en;\n+\tnt_field_t *mp_fld_cr_msms;\n+\tnt_field_t *mp_fld_cr_txfifo_reset;\n+\tnt_field_t *mp_fld_cr_txak;\n+\n+\tnt_register_t *mp_reg_sr;\n+\tnt_field_t *mp_fld_sr_bb;\n+\tnt_field_t *mp_fld_sr_rxfifo_full;\n+\tnt_field_t *mp_fld_sr_rxfifo_empty;\n+\tnt_field_t *mp_fld_sr_txfifo_full;\n+\tnt_field_t *mp_fld_sr_txfifo_empty;\n+\n+\tnt_register_t *mp_reg_tx_fifo;\n+\tnt_field_t *mp_fld_tx_fifo_txdata;\n+\tnt_field_t *mp_fld_tx_fifo_start;\n+\tnt_field_t *mp_fld_tx_fifo_stop;\n+\n+\tnt_register_t *mp_reg_rx_fifo_pirq;\n+\tnt_field_t *mp_fld_rx_fifo_pirq_cmp_val;\n+\n+\tnt_register_t *mp_reg_rx_fifo;\n+\tnt_field_t *mp_fld_rx_fifo_rxdata;\n+\n+\tnt_register_t *mp_reg_softr;\n+\tnt_field_t *mp_fld_softr_rkey;\n+};\n+\n+typedef struct nthw_iic nthw_iic_t;\n+typedef struct nthw_iic nthw_iic;\n+\n+nthw_iic_t *nthw_iic_new(void);\n+int nthw_iic_init(nthw_iic_t *p, nt_fpga_t *p_fpga, int n_iic_instance,\n+\t\t uint32_t n_iic_cycle_time);\n+void nthw_iic_delete(nthw_iic_t *p);\n+\n+int nthw_iic_set_retry_params(nthw_iic_t *p, const int n_poll_delay,\n+\t\t\t   const int n_bus_ready_retry, const int n_data_ready_retry,\n+\t\t\t   const int n_read_data_retry, const int n_write_data_retry);\n+\n+int nthw_iic_read_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,\n+\t\t     uint8_t data_len, void *p_void);\n+int nthw_iic_readbyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,\n+\t\t     uint8_t data_len, uint8_t *p_byte);\n+int nthw_iic_write_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,\n+\t\t      uint8_t data_len, void *p_void);\n+int nthw_iic_writebyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t reg_addr,\n+\t\t      uint8_t data_len, uint8_t *p_byte);\n+bool nthw_iic_bus_ready(nthw_iic_t *p);\n+bool nthw_iic_data_ready(nthw_iic_t *p);\n+\n+int nthw_iic_scan(nthw_iic_t *p);\n+int nthw_iic_scan_dev_addr(nthw_iic_t *p, int n_dev_addr, int n_reg_addr);\n+int nthw_iic_scan_find_dev(nthw_iic_t *p, int n_dev_addr_start, bool b_increate);\n+\n+#endif /* __NTHW_IIC_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c\nnew file mode 100644\nindex 0000000000..448caf1fd5\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.c\n@@ -0,0 +1,1034 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"nt_util.h\"\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_mac_pcs.h\"\n+\n+#define NTHW_MAC_PCS_LANES (20)\n+\n+static const uint8_t c_pcs_lanes = NTHW_MAC_PCS_LANES;\n+static const uint8_t c_mac_pcs_receiver_mode_dfe _unused;\n+\n+nthw_mac_pcs_t *nthw_mac_pcs_new(void)\n+{\n+\tnthw_mac_pcs_t *p = malloc(sizeof(nthw_mac_pcs_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_mac_pcs_t));\n+\treturn p;\n+}\n+\n+void nthw_mac_pcs_delete(nthw_mac_pcs_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_mac_pcs_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+/*\n+ * Parameters:\n+ *   p != NULL: init struct pointed to by p\n+ *   p == NULL: check fpga module(s) presence (but no struct to init)\n+ *\n+ * Return value:\n+ *  <0: if p == NULL then fpga module(s) is/are not present.\n+ *      if p != NULL then fpga module(s) is/are not present, struct undefined\n+ * ==0: if p == NULL then fpga module(s) is/are present (no struct to init)\n+ *    : if p != NULL then fpga module(s) is/are present and struct initialized\n+ */\n+int nthw_mac_pcs_init(nthw_mac_pcs_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_MAC_PCS, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: MAC_PCS %d: no such instance\\n\",\n+\t\t       p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_mac_pcs = mod;\n+\n+\tassert(n_instance >= 0 && n_instance <= 255);\n+\tnthw_mac_pcs_set_port_no(p, (uint8_t)n_instance);\n+\n+\t{\n+\t\tnt_register_t *p_reg_block_lock, *p_reg_stat_pcs_rx,\n+\t\t\t      *p_reg_stat_pcs_rx_latch;\n+\t\tnt_register_t *p_reg_vl_demuxed, *p_reg_gty_stat, *p_reg_pcs_config,\n+\t\t\t      *p_reg_phymac_misc;\n+\t\tconst int product_id = fpga_get_product_id(p_fpga);\n+\n+\t\tp_reg_block_lock =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_BLOCK_LOCK);\n+\t\tp->mp_reg_block_lock = p_reg_block_lock;\n+\t\tp->mp_fld_block_lock_lock =\n+\t\t\tregister_get_field(p_reg_block_lock, MAC_PCS_BLOCK_LOCK_LOCK);\n+\n+\t\tp_reg_stat_pcs_rx =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_STAT_PCS_RX);\n+\t\tp->mp_reg_stat_pcs_rx = p_reg_stat_pcs_rx;\n+\t\tp->mp_fld_stat_pcs_rx_status =\n+\t\t\tregister_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_STATUS);\n+\t\tp->mp_fld_stat_pcs_rx_aligned =\n+\t\t\tregister_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_ALIGNED);\n+\t\tp->mp_fld_stat_pcs_rx_aligned_err =\n+\t\t\tregister_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_ALIGNED_ERR);\n+\t\tp->mp_fld_stat_pcs_rx_misaligned =\n+\t\t\tregister_get_field(p_reg_stat_pcs_rx, MAC_PCS_STAT_PCS_RX_MISALIGNED);\n+\t\tp->mp_fld_stat_pcs_rx_internal_local_fault =\n+\t\t\tregister_get_field(p_reg_stat_pcs_rx,\n+\t\t\t\t\t   MAC_PCS_STAT_PCS_RX_INTERNAL_LOCAL_FAULT);\n+\t\tp->mp_fld_stat_pcs_rx_received_local_fault =\n+\t\t\tregister_get_field(p_reg_stat_pcs_rx,\n+\t\t\t\t\t   MAC_PCS_STAT_PCS_RX_RECEIVED_LOCAL_FAULT);\n+\t\tp->mp_fld_stat_pcs_rx_local_fault =\n+\t\t\tregister_get_field(p_reg_stat_pcs_rx,\n+\t\t\t\t\t   MAC_PCS_STAT_PCS_RX_LOCAL_FAULT);\n+\t\tp->mp_fld_stat_pcs_rx_remote_fault =\n+\t\t\tregister_get_field(p_reg_stat_pcs_rx,\n+\t\t\t\t\t   MAC_PCS_STAT_PCS_RX_REMOTE_FAULT);\n+\t\tp->mp_fld_stat_pcs_rx_hi_ber =\n+\t\t\tregister_get_field(p_reg_stat_pcs_rx,\n+\t\t\t\t\t   MAC_PCS_STAT_PCS_RX_HI_BER);\n+\n+\t\tp_reg_stat_pcs_rx_latch =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs,\n+\t\t\t\t\t    MAC_PCS_STAT_PCS_RX_LATCH);\n+\t\tp->mp_reg_stat_pcs_rx_latch = p_reg_stat_pcs_rx_latch;\n+\t\tp->mp_fld_stat_pcs_rx_latch_status =\n+\t\t\tregister_get_field(p_reg_stat_pcs_rx_latch,\n+\t\t\t\t\t   MAC_PCS_STAT_PCS_RX_LATCH_STATUS);\n+\n+\t\tp_reg_vl_demuxed =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_VL_DEMUXED);\n+\t\tp->mp_fld_vl_demuxed_lock =\n+\t\t\tregister_get_field(p_reg_vl_demuxed, MAC_PCS_VL_DEMUXED_LOCK);\n+\n+\t\tp_reg_gty_stat =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_STAT);\n+\t\tp->mp_fld_gty_stat_tx_rst_done0 =\n+\t\t\tregister_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_0);\n+\t\tp->mp_fld_gty_stat_tx_rst_done1 =\n+\t\t\tregister_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_1);\n+\t\tp->mp_fld_gty_stat_tx_rst_done2 =\n+\t\t\tregister_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_2);\n+\t\tp->mp_fld_gty_stat_tx_rst_done3 =\n+\t\t\tregister_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_TX_RST_DONE_3);\n+\t\tp->mp_fld_gty_stat_rx_rst_done0 =\n+\t\t\tregister_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_0);\n+\t\tp->mp_fld_gty_stat_rx_rst_done1 =\n+\t\t\tregister_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_1);\n+\t\tp->mp_fld_gty_stat_rx_rst_done2 =\n+\t\t\tregister_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_2);\n+\t\tp->mp_fld_gty_stat_rx_rst_done3 =\n+\t\t\tregister_get_field(p_reg_gty_stat, MAC_PCS_GTY_STAT_RX_RST_DONE_3);\n+\n+\t\tp->m_fld_block_lock_lock_mask = 0;\n+\t\tp->m_fld_vl_demuxed_lock_mask = 0;\n+\t\tp->m_fld_gty_stat_tx_rst_done_mask = 0;\n+\t\tp->m_fld_gty_stat_rx_rst_done_mask = 0;\n+\n+\t\tif (product_id == 9563) {\n+\t\t\t/* NT200A01_2X100 implements 20 virtual lanes */\n+\t\t\tp->m_fld_block_lock_lock_mask = (1 << 20) - 1;\n+\t\t\t/* NT200A01_2X100 implements 20 virtual lanes */\n+\t\t\tp->m_fld_vl_demuxed_lock_mask = (1 << 20) - 1;\n+\t\t\tp->m_fld_gty_stat_tx_rst_done_mask =\n+\t\t\t\t1; /* NT200A01_2X100 implements 4 GTY */\n+\t\t\tp->m_fld_gty_stat_rx_rst_done_mask =\n+\t\t\t\t1; /* NT200A01_2X100 implements 4 GTY */\n+\t\t} else {\n+\t\t\t/* Remember to add new productIds */\n+\t\t\tassert(0);\n+\t\t}\n+\n+\t\tp_reg_pcs_config = module_get_register(p->mp_mod_mac_pcs,\n+\t\t\t\t\t\t   MAC_PCS_MAC_PCS_CONFIG);\n+\t\tp->mp_fld_pcs_config_tx_path_rst =\n+\t\t\tregister_get_field(p_reg_pcs_config, MAC_PCS_MAC_PCS_CONFIG_TX_PATH_RST);\n+\t\tp->mp_fld_pcs_config_rx_path_rst =\n+\t\t\tregister_get_field(p_reg_pcs_config, MAC_PCS_MAC_PCS_CONFIG_RX_PATH_RST);\n+\t\tp->mp_fld_pcs_config_rx_enable =\n+\t\t\tregister_get_field(p_reg_pcs_config, MAC_PCS_MAC_PCS_CONFIG_RX_ENABLE);\n+\t\tp->mp_fld_pcs_config_rx_force_resync =\n+\t\t\tregister_get_field(p_reg_pcs_config,\n+\t\t\t\t\t   MAC_PCS_MAC_PCS_CONFIG_RX_FORCE_RESYNC);\n+\t\tp->mp_fld_pcs_config_rx_test_pattern =\n+\t\t\tregister_get_field(p_reg_pcs_config,\n+\t\t\t\t\t   MAC_PCS_MAC_PCS_CONFIG_RX_TEST_PATTERN);\n+\t\tp->mp_fld_pcs_config_tx_enable =\n+\t\t\tregister_get_field(p_reg_pcs_config,\n+\t\t\t\t\t   MAC_PCS_MAC_PCS_CONFIG_TX_ENABLE);\n+\t\tp->mp_fld_pcs_config_tx_send_idle =\n+\t\t\tregister_get_field(p_reg_pcs_config,\n+\t\t\t\t\t   MAC_PCS_MAC_PCS_CONFIG_TX_SEND_IDLE);\n+\t\tp->mp_fld_pcs_config_tx_send_rfi =\n+\t\t\tregister_get_field(p_reg_pcs_config,\n+\t\t\t\t\t   MAC_PCS_MAC_PCS_CONFIG_TX_SEND_RFI);\n+\t\tp->mp_fld_pcs_config_tx_test_pattern =\n+\t\t\tregister_get_field(p_reg_pcs_config,\n+\t\t\t\t\t   MAC_PCS_MAC_PCS_CONFIG_TX_TEST_PATTERN);\n+\n+\t\tp->mp_reg_gty_loop =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_LOOP);\n+\t\tp->mp_fld_gty_loop_gt_loop0 =\n+\t\t\tregister_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_0);\n+\t\tp->mp_fld_gty_loop_gt_loop1 =\n+\t\t\tregister_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_1);\n+\t\tp->mp_fld_gty_loop_gt_loop2 =\n+\t\t\tregister_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_2);\n+\t\tp->mp_fld_gty_loop_gt_loop3 =\n+\t\t\tregister_get_field(p->mp_reg_gty_loop, MAC_PCS_GTY_LOOP_GT_LOOP_3);\n+\n+\t\tp_reg_phymac_misc =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_PHYMAC_MISC);\n+\t\tp->mp_reg_phymac_misc = p_reg_phymac_misc;\n+\t\tp->mp_fld_phymac_misc_tx_sel_host =\n+\t\t\tregister_get_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TX_SEL_HOST);\n+\t\tp->mp_fld_phymac_misc_tx_sel_tfg =\n+\t\t\tregister_get_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TX_SEL_TFG);\n+\t\tp->mp_fld_phymac_misc_tx_sel_rx_loop =\n+\t\t\tregister_get_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TX_SEL_RX_LOOP);\n+\n+\t\t/* SOP or EOP TIMESTAMP */\n+\t\tp->mp_fld_phymac_misc_ts_eop =\n+\t\t\tregister_query_field(p_reg_phymac_misc, MAC_PCS_PHYMAC_MISC_TS_EOP);\n+\n+\t\tp->mp_reg_link_summary =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_LINK_SUMMARY);\n+\t\tp->mp_fld_link_summary_abs =\n+\t\t\tregister_get_field(p->mp_reg_link_summary, MAC_PCS_LINK_SUMMARY_ABS);\n+\t\tp->mp_fld_link_summary_nt_phy_link_state =\n+\t\t\tregister_get_field(p->mp_reg_link_summary,\n+\t\t\t\t\t   MAC_PCS_LINK_SUMMARY_NT_PHY_LINK_STATE);\n+\t\tp->mp_fld_link_summary_lh_abs =\n+\t\t\tregister_get_field(p->mp_reg_link_summary, MAC_PCS_LINK_SUMMARY_LH_ABS);\n+\t\tp->mp_fld_link_summary_ll_nt_phy_link_state =\n+\t\t\tregister_get_field(p->mp_reg_link_summary,\n+\t\t\t\t\t   MAC_PCS_LINK_SUMMARY_LL_PHY_LINK_STATE);\n+\t\tp->mp_fld_link_summary_link_down_cnt =\n+\t\t\tregister_get_field(p->mp_reg_link_summary,\n+\t\t\t\t\t   MAC_PCS_LINK_SUMMARY_LINK_DOWN_CNT);\n+\t\tp->mp_fld_link_summary_nim_interr =\n+\t\t\tregister_get_field(p->mp_reg_link_summary,\n+\t\t\t\t\t   MAC_PCS_LINK_SUMMARY_NIM_INTERR);\n+\t\tp->mp_fld_link_summary_lh_local_fault =\n+\t\t\tregister_get_field(p->mp_reg_link_summary,\n+\t\t\t\t\t   MAC_PCS_LINK_SUMMARY_LH_LOCAL_FAULT);\n+\t\tp->mp_fld_link_summary_lh_remote_fault =\n+\t\t\tregister_get_field(p->mp_reg_link_summary,\n+\t\t\t\t\t   MAC_PCS_LINK_SUMMARY_LH_REMOTE_FAULT);\n+\t\tp->mp_fld_link_summary_local_fault =\n+\t\t\tregister_get_field(p->mp_reg_link_summary,\n+\t\t\t\t\t   MAC_PCS_LINK_SUMMARY_LOCAL_FAULT);\n+\t\tp->mp_fld_link_summary_remote_fault =\n+\t\t\tregister_get_field(p->mp_reg_link_summary,\n+\t\t\t\t\t   MAC_PCS_LINK_SUMMARY_REMOTE_FAULT);\n+\n+\t\tp->mp_reg_bip_err =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_BIP_ERR);\n+\t\tp->mp_fld_reg_bip_err_bip_err =\n+\t\t\tregister_get_field(p->mp_reg_bip_err, MAC_PCS_BIP_ERR_BIP_ERR);\n+\n+\t\tp->mp_reg_fec_ctrl =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_CTRL);\n+\t\tp->mp_field_fec_ctrl_reg_rs_fec_ctrl_in =\n+\t\t\tregister_get_field(p->mp_reg_fec_ctrl, MAC_PCS_FEC_CTRL_RS_FEC_CTRL_IN);\n+\n+\t\tp->mp_reg_fec_stat =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_STAT);\n+\t\tp->mp_field_fec_stat_bypass =\n+\t\t\tregister_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_BYPASS);\n+\t\tp->mp_field_fec_stat_valid =\n+\t\t\tregister_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_VALID);\n+\t\tp->mp_field_fec_stat_am_lock0 =\n+\t\t\tregister_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_0);\n+\t\tp->mp_field_fec_stat_am_lock1 =\n+\t\t\tregister_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_1);\n+\t\tp->mp_field_fec_stat_am_lock2 =\n+\t\t\tregister_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_2);\n+\t\tp->mp_field_fec_stat_am_lock3 =\n+\t\t\tregister_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_AM_LOCK_3);\n+\t\tp->mp_field_fec_stat_fec_lane_algn =\n+\t\t\tregister_get_field(p->mp_reg_fec_stat, MAC_PCS_FEC_STAT_FEC_LANE_ALGN);\n+\n+\t\tp->mp_reg_fec_cw_cnt =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_CW_CNT);\n+\t\tp->mp_field_fec_cw_cnt_cw_cnt =\n+\t\t\tregister_get_field(p->mp_reg_fec_cw_cnt, MAC_PCS_FEC_CW_CNT_CW_CNT);\n+\n+\t\tp->mp_reg_fec_ucw_cnt =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_FEC_UCW_CNT);\n+\t\tp->mp_field_fec_ucw_cnt_ucw_cnt =\n+\t\t\tregister_get_field(p->mp_reg_fec_ucw_cnt, MAC_PCS_FEC_UCW_CNT_UCW_CNT);\n+\n+\t\t/* GTY_RX_BUF_STAT */\n+#ifdef RXBUFSTAT\n+\t\tp->mp_reg_gty_rx_buf_stat =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_RX_BUF_STAT);\n+\t\tp->mp_field_gty_rx_buf_stat_rx_buf_stat0 =\n+\t\t\tregister_get_field(p->mp_reg_gty_rx_buf_stat,\n+\t\t\t\t\t   MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_0);\n+\t\tp->mp_field_gty_rx_buf_stat_rx_buf_stat1 =\n+\t\t\tregister_get_field(p->mp_reg_gty_rx_buf_stat,\n+\t\t\t\t\t   MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_1);\n+\t\tp->mp_field_gty_rx_buf_stat_rx_buf_stat2 =\n+\t\t\tregister_get_field(p->mp_reg_gty_rx_buf_stat,\n+\t\t\t\t\t   MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_2);\n+\t\tp->mp_field_gty_rx_buf_stat_rx_buf_stat3 =\n+\t\t\tregister_get_field(p->mp_reg_gty_rx_buf_stat,\n+\t\t\t\t\t   MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_3);\n+\t\tp->mp_field_gty_rx_buf_stat_rx_buf_stat_changed0 =\n+\t\t\tregister_get_field(p->mp_reg_gty_rx_buf_stat,\n+\t\t\t\t\t   MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_0);\n+\t\tp->mp_field_gty_rx_buf_stat_rx_buf_stat_changed1 =\n+\t\t\tregister_get_field(p->mp_reg_gty_rx_buf_stat,\n+\t\t\t\t\t   MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_1);\n+\t\tp->mp_field_gty_rx_buf_stat_rx_buf_stat_changed2 =\n+\t\t\tregister_get_field(p->mp_reg_gty_rx_buf_stat,\n+\t\t\t\t\t   MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_2);\n+\t\tp->mp_field_gty_rx_buf_stat_rx_buf_stat_changed3 =\n+\t\t\tregister_get_field(p->mp_reg_gty_rx_buf_stat,\n+\t\t\t\t\t   MAC_PCS_GTY_RX_BUF_STAT_RX_BUF_STAT_CHANGED_3);\n+#endif\n+\n+\t\t/* GTY_PRE_CURSOR */\n+\t\tp->mp_reg_gty_pre_cursor =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_PRE_CURSOR);\n+\t\tp->mp_field_gty_pre_cursor_tx_pre_csr0 =\n+\t\t\tregister_get_field(p->mp_reg_gty_pre_cursor,\n+\t\t\t\t\t   MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_0);\n+\t\tp->mp_field_gty_pre_cursor_tx_pre_csr1 =\n+\t\t\tregister_get_field(p->mp_reg_gty_pre_cursor,\n+\t\t\t\t\t   MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_1);\n+\t\tp->mp_field_gty_pre_cursor_tx_pre_csr2 =\n+\t\t\tregister_get_field(p->mp_reg_gty_pre_cursor,\n+\t\t\t\t\t   MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_2);\n+\t\tp->mp_field_gty_pre_cursor_tx_pre_csr3 =\n+\t\t\tregister_get_field(p->mp_reg_gty_pre_cursor,\n+\t\t\t\t\t   MAC_PCS_GTY_PRE_CURSOR_TX_PRE_CSR_3);\n+\n+\t\t/* GTY_DIFF_CTL */\n+\t\tp->mp_reg_gty_diff_ctl =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_DIFF_CTL);\n+\t\tp->mp_field_gty_gty_diff_ctl_tx_diff_ctl0 =\n+\t\t\tregister_get_field(p->mp_reg_gty_diff_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_0);\n+\t\tp->mp_field_gty_gty_diff_ctl_tx_diff_ctl1 =\n+\t\t\tregister_get_field(p->mp_reg_gty_diff_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_1);\n+\t\tp->mp_field_gty_gty_diff_ctl_tx_diff_ctl2 =\n+\t\t\tregister_get_field(p->mp_reg_gty_diff_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_2);\n+\t\tp->mp_field_gty_gty_diff_ctl_tx_diff_ctl3 =\n+\t\t\tregister_get_field(p->mp_reg_gty_diff_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_DIFF_CTL_TX_DIFF_CTL_3);\n+\n+\t\t/* GTY_POST_CURSOR */\n+\t\tp->mp_reg_gty_post_cursor =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs,\n+\t\t\t\t\t    MAC_PCS_GTY_POST_CURSOR);\n+\t\tp->mp_field_gty_post_cursor_tx_post_csr0 =\n+\t\t\tregister_get_field(p->mp_reg_gty_post_cursor,\n+\t\t\t\t\t   MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_0);\n+\t\tp->mp_field_gty_post_cursor_tx_post_csr1 =\n+\t\t\tregister_get_field(p->mp_reg_gty_post_cursor,\n+\t\t\t\t\t   MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_1);\n+\t\tp->mp_field_gty_post_cursor_tx_post_csr2 =\n+\t\t\tregister_get_field(p->mp_reg_gty_post_cursor,\n+\t\t\t\t\t   MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_2);\n+\t\tp->mp_field_gty_post_cursor_tx_post_csr3 =\n+\t\t\tregister_get_field(p->mp_reg_gty_post_cursor,\n+\t\t\t\t\t   MAC_PCS_GTY_POST_CURSOR_TX_POST_CSR_3);\n+\n+\t\t/* GTY_CTL */\n+\t\tp->mp_reg_gty_ctl =\n+\t\t\tmodule_query_register(p->mp_mod_mac_pcs, MAC_PCS_GTY_CTL);\n+\t\tif (p->mp_reg_gty_ctl) {\n+\t\t\tp->mp_field_gty_ctl_tx_pol0 =\n+\t\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t\t   MAC_PCS_GTY_CTL_TX_POLARITY_0);\n+\t\t\tp->mp_field_gty_ctl_tx_pol1 =\n+\t\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t\t   MAC_PCS_GTY_CTL_TX_POLARITY_1);\n+\t\t\tp->mp_field_gty_ctl_tx_pol2 =\n+\t\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t\t   MAC_PCS_GTY_CTL_TX_POLARITY_2);\n+\t\t\tp->mp_field_gty_ctl_tx_pol3 =\n+\t\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t\t   MAC_PCS_GTY_CTL_TX_POLARITY_3);\n+\t\t} else {\n+\t\t\tp->mp_reg_gty_ctl =\n+\t\t\t\tmodule_get_register(p->mp_mod_mac_pcs,\n+\t\t\t\t\t\t    MAC_PCS_GTY_CTL_RX);\n+\t\t\tp->mp_reg_gty_ctl_tx =\n+\t\t\t\tmodule_get_register(p->mp_mod_mac_pcs,\n+\t\t\t\t\t\t    MAC_PCS_GTY_CTL_TX);\n+\t\t\tp->mp_field_gty_ctl_tx_pol0 =\n+\t\t\t\tregister_get_field(p->mp_reg_gty_ctl_tx,\n+\t\t\t\t\t\t   MAC_PCS_GTY_CTL_TX_POLARITY_0);\n+\t\t\tp->mp_field_gty_ctl_tx_pol1 =\n+\t\t\t\tregister_get_field(p->mp_reg_gty_ctl_tx,\n+\t\t\t\t\t\t   MAC_PCS_GTY_CTL_TX_POLARITY_1);\n+\t\t\tp->mp_field_gty_ctl_tx_pol2 =\n+\t\t\t\tregister_get_field(p->mp_reg_gty_ctl_tx,\n+\t\t\t\t\t\t   MAC_PCS_GTY_CTL_TX_POLARITY_2);\n+\t\t\tp->mp_field_gty_ctl_tx_pol3 =\n+\t\t\t\tregister_get_field(p->mp_reg_gty_ctl_tx,\n+\t\t\t\t\t\t   MAC_PCS_GTY_CTL_TX_POLARITY_3);\n+\t\t}\n+\t\tp->mp_field_gty_ctl_rx_pol0 =\n+\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_CTL_RX_POLARITY_0);\n+\t\tp->mp_field_gty_ctl_rx_pol1 =\n+\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_CTL_RX_POLARITY_1);\n+\t\tp->mp_field_gty_ctl_rx_pol2 =\n+\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_CTL_RX_POLARITY_2);\n+\t\tp->mp_field_gty_ctl_rx_pol3 =\n+\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_CTL_RX_POLARITY_3);\n+\t\tp->mp_field_gty_ctl_rx_lpm_en0 =\n+\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_CTL_RX_LPM_EN_0);\n+\t\tp->mp_field_gty_ctl_rx_lpm_en1 =\n+\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_CTL_RX_LPM_EN_1);\n+\t\tp->mp_field_gty_ctl_rx_lpm_en2 =\n+\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_CTL_RX_LPM_EN_2);\n+\t\tp->mp_field_gty_ctl_rx_lpm_en3 =\n+\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_CTL_RX_LPM_EN_3);\n+\t\tp->mp_field_gty_ctl_rx_equa_rst0 =\n+\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_CTL_RX_EQUA_RST_0);\n+\t\tp->mp_field_gty_ctl_rx_equa_rst1 =\n+\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_CTL_RX_EQUA_RST_1);\n+\t\tp->mp_field_gty_ctl_rx_equa_rst2 =\n+\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_CTL_RX_EQUA_RST_2);\n+\t\tp->mp_field_gty_ctl_rx_equa_rst3 =\n+\t\t\tregister_get_field(p->mp_reg_gty_ctl,\n+\t\t\t\t\t   MAC_PCS_GTY_CTL_RX_EQUA_RST_3);\n+\n+\t\t/* DEBOUNCE_CTRL */\n+\t\tp->mp_reg_debounce_ctrl =\n+\t\t\tmodule_get_register(p->mp_mod_mac_pcs,\n+\t\t\t\t\t    MAC_PCS_DEBOUNCE_CTRL);\n+\t\tp->mp_field_debounce_ctrl_nt_port_ctrl =\n+\t\t\tregister_get_field(p->mp_reg_debounce_ctrl,\n+\t\t\t\t\t   MAC_PCS_DEBOUNCE_CTRL_NT_PORT_CTRL);\n+\n+\t\tp->mp_reg_time_stamp_comp =\n+\t\t\tmodule_query_register(p->mp_mod_mac_pcs,\n+\t\t\t\t\t      MAC_PCS_TIMESTAMP_COMP);\n+\t\tif (p->mp_reg_time_stamp_comp) {\n+\t\t\t/* TIMESTAMP_COMP */\n+\t\t\tp->mp_field_time_stamp_comp_rx_dly =\n+\t\t\t\tregister_get_field(p->mp_reg_time_stamp_comp,\n+\t\t\t\t\t\t   MAC_PCS_TIMESTAMP_COMP_RX_DLY);\n+\t\t\tp->mp_field_time_stamp_comp_tx_dly =\n+\t\t\t\tregister_get_field(p->mp_reg_time_stamp_comp,\n+\t\t\t\t\t\t   MAC_PCS_TIMESTAMP_COMP_TX_DLY);\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+/* wrapper - for ease of use */\n+void nthw_mac_pcs_tx_host_enable(nthw_mac_pcs_t *p, bool enable)\n+{\n+\tnthw_mac_pcs_set_tx_sel_host(p, enable);\n+\tnthw_mac_pcs_set_tx_sel_tfg(p, !enable);\n+}\n+\n+void nthw_mac_pcs_set_rx_enable(nthw_mac_pcs_t *p, bool enable)\n+{\n+\tfield_get_updated(p->mp_fld_pcs_config_rx_enable);\n+\tif (enable)\n+\t\tfield_set_flush(p->mp_fld_pcs_config_rx_enable);\n+\n+\telse\n+\t\tfield_clr_flush(p->mp_fld_pcs_config_rx_enable);\n+}\n+\n+void nthw_mac_pcs_set_tx_enable(nthw_mac_pcs_t *p, bool enable)\n+{\n+\tfield_get_updated(p->mp_fld_pcs_config_tx_enable);\n+\tif (enable)\n+\t\tfield_set_flush(p->mp_fld_pcs_config_tx_enable);\n+\n+\telse\n+\t\tfield_clr_flush(p->mp_fld_pcs_config_tx_enable);\n+}\n+\n+void nthw_mac_pcs_set_tx_sel_host(nthw_mac_pcs_t *p, bool enable)\n+{\n+\tfield_get_updated(p->mp_fld_phymac_misc_tx_sel_host);\n+\tif (enable)\n+\t\tfield_set_flush(p->mp_fld_phymac_misc_tx_sel_host);\n+\n+\telse\n+\t\tfield_clr_flush(p->mp_fld_phymac_misc_tx_sel_host);\n+}\n+\n+void nthw_mac_pcs_set_tx_sel_tfg(nthw_mac_pcs_t *p, bool enable)\n+{\n+\tfield_get_updated(p->mp_fld_phymac_misc_tx_sel_tfg);\n+\tif (enable)\n+\t\tfield_set_flush(p->mp_fld_phymac_misc_tx_sel_tfg);\n+\n+\telse\n+\t\tfield_clr_flush(p->mp_fld_phymac_misc_tx_sel_tfg);\n+}\n+\n+void nthw_mac_pcs_set_ts_eop(nthw_mac_pcs_t *p, bool enable)\n+{\n+\tif (p->mp_fld_phymac_misc_ts_eop) {\n+\t\tfield_get_updated(p->mp_fld_phymac_misc_ts_eop);\n+\t\tif (enable)\n+\t\t\tfield_set_flush(p->mp_fld_phymac_misc_ts_eop);\n+\n+\t\telse\n+\t\t\tfield_clr_flush(p->mp_fld_phymac_misc_ts_eop);\n+\t}\n+}\n+\n+bool nthw_mac_pcs_is_block_and_lane_lock_locked(nthw_mac_pcs_t *p)\n+{\n+\tuint32_t block_lock;\n+\tuint32_t lane_lock;\n+\n+\tblock_lock = field_get_updated(p->mp_fld_block_lock_lock) &\n+\t\t    p->m_fld_block_lock_lock_mask;\n+\tlane_lock = field_get_updated(p->mp_fld_vl_demuxed_lock) &\n+\t\t   p->m_fld_vl_demuxed_lock_mask;\n+\tif (block_lock == p->m_fld_block_lock_lock_mask &&\n+\t\t\tlane_lock == p->m_fld_vl_demuxed_lock_mask)\n+\t\treturn true;\n+\n+\treturn false;\n+}\n+\n+void nthw_mac_pcs_tx_path_rst(nthw_mac_pcs_t *p, bool enable)\n+{\n+\tfield_get_updated(p->mp_fld_pcs_config_tx_path_rst);\n+\tif (enable)\n+\t\tfield_set_flush(p->mp_fld_pcs_config_tx_path_rst);\n+\n+\telse\n+\t\tfield_clr_flush(p->mp_fld_pcs_config_tx_path_rst);\n+}\n+\n+void nthw_mac_pcs_rx_path_rst(nthw_mac_pcs_t *p, bool enable)\n+{\n+\tfield_get_updated(p->mp_fld_pcs_config_rx_path_rst);\n+\tif (enable)\n+\t\tfield_set_flush(p->mp_fld_pcs_config_rx_path_rst);\n+\n+\telse\n+\t\tfield_clr_flush(p->mp_fld_pcs_config_rx_path_rst);\n+}\n+\n+bool nthw_mac_pcs_is_rx_path_rst(nthw_mac_pcs_t *p)\n+{\n+\treturn field_get_updated(p->mp_fld_pcs_config_rx_path_rst);\n+}\n+\n+void nthw_mac_pcs_tx_send_rfi(nthw_mac_pcs_t *p, bool enable)\n+{\n+\tfield_get_updated(p->mp_fld_pcs_config_tx_send_rfi);\n+\tif (enable)\n+\t\tfield_set_flush(p->mp_fld_pcs_config_tx_send_rfi);\n+\n+\telse\n+\t\tfield_clr_flush(p->mp_fld_pcs_config_tx_send_rfi);\n+}\n+\n+void nthw_mac_pcs_rx_force_resync(nthw_mac_pcs_t *p, bool enable)\n+{\n+\tfield_get_updated(p->mp_fld_pcs_config_rx_force_resync);\n+\tif (enable)\n+\t\tfield_set_flush(p->mp_fld_pcs_config_rx_force_resync);\n+\n+\telse\n+\t\tfield_clr_flush(p->mp_fld_pcs_config_rx_force_resync);\n+}\n+\n+bool nthw_mac_pcs_is_gt_fsm_rx_reset_done(nthw_mac_pcs_t *p)\n+{\n+\tif ((field_get_updated(p->mp_fld_gty_stat_rx_rst_done0) &\n+\t\t\tp->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask &&\n+\t\t\t(field_get_updated(p->mp_fld_gty_stat_rx_rst_done1) &\n+\t\t\tp->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask &&\n+\t\t\t(field_get_updated(p->mp_fld_gty_stat_rx_rst_done2) &\n+\t\t\tp->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask &&\n+\t\t\t(field_get_updated(p->mp_fld_gty_stat_rx_rst_done3) &\n+\t\t\tp->m_fld_gty_stat_rx_rst_done_mask) == p->m_fld_gty_stat_rx_rst_done_mask)\n+\t\treturn true;\n+\n+\telse\n+\t\treturn false;\n+}\n+\n+bool nthw_mac_pcs_is_gt_fsm_tx_reset_done(nthw_mac_pcs_t *p)\n+{\n+\tif ((field_get_updated(p->mp_fld_gty_stat_tx_rst_done0) &\n+\t\t\tp->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask &&\n+\t\t\t(field_get_updated(p->mp_fld_gty_stat_tx_rst_done1) &\n+\t\t\tp->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask &&\n+\t\t\t(field_get_updated(p->mp_fld_gty_stat_tx_rst_done2) &\n+\t\t\tp->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask &&\n+\t\t\t(field_get_updated(p->mp_fld_gty_stat_tx_rst_done3) &\n+\t\t\tp->m_fld_gty_stat_tx_rst_done_mask) == p->m_fld_gty_stat_tx_rst_done_mask)\n+\t\treturn true;\n+\n+\telse\n+\t\treturn false;\n+}\n+\n+void nthw_mac_pcs_set_host_loopback(nthw_mac_pcs_t *p, bool enable)\n+{\n+\tregister_update(p->mp_reg_gty_loop);\n+\tif (enable) {\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop0, 2);\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop1, 2);\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop2, 2);\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop3, 2);\n+\t} else {\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop0, 0);\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop1, 0);\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop2, 0);\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop3, 0);\n+\t}\n+\tregister_flush(p->mp_reg_gty_loop, 1);\n+}\n+\n+void nthw_mac_pcs_set_line_loopback(nthw_mac_pcs_t *p, bool enable)\n+{\n+\tregister_update(p->mp_reg_gty_loop);\n+\tif (enable) {\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop0, 4);\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop1, 4);\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop2, 4);\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop3, 4);\n+\t} else {\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop0, 0);\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop1, 0);\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop2, 0);\n+\t\tfield_set_val32(p->mp_fld_gty_loop_gt_loop3, 0);\n+\t}\n+\tregister_flush(p->mp_reg_gty_loop, 1);\n+}\n+\n+void nthw_mac_pcs_reset_bip_counters(nthw_mac_pcs_t *p)\n+{\n+\tuint32_t lane_bit_errors[NTHW_MAC_PCS_LANES];\n+\n+\tregister_update(p->mp_reg_bip_err);\n+\tfield_get_val(p->mp_fld_reg_bip_err_bip_err, (uint32_t *)lane_bit_errors,\n+\t\t     ARRAY_SIZE(lane_bit_errors));\n+\n+#if defined(DEBUG)\n+\t{\n+\t\tuint8_t lane;\n+\n+\t\tfor (lane = 0; lane < c_pcs_lanes; lane++) {\n+\t\t\tif (lane_bit_errors[lane]) {\n+\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t       \"Port %u: pcsLane %2u: BIP8 errors: %u\\n\",\n+\t\t\t\t       p->m_port_no, lane, lane_bit_errors[lane]);\n+\t\t\t}\n+\t\t}\n+\t}\n+#else\n+\t(void)c_pcs_lanes; /* unused - kill warning */\n+#endif\n+}\n+\n+void nthw_mac_pcs_get_status(nthw_mac_pcs_t *p, uint8_t *status)\n+{\n+\t*status = field_get_updated(p->mp_fld_stat_pcs_rx_status) & 0x01;\n+}\n+\n+bool nthw_mac_pcs_get_hi_ber(nthw_mac_pcs_t *p)\n+{\n+\treturn field_get_updated(p->mp_fld_stat_pcs_rx_hi_ber);\n+}\n+\n+void nthw_mac_pcs_get_link_summary(nthw_mac_pcs_t *p, uint32_t *p_abs,\n+\tuint32_t *p_nt_phy_link_state, uint32_t *p_lh_abs,\n+\tuint32_t *p_ll_nt_phy_link_state,\n+\tuint32_t *p_link_down_cnt, uint32_t *p_nim_interr,\n+\tuint32_t *p_lh_local_fault,\n+\tuint32_t *p_lh_remote_fault, uint32_t *p_local_fault,\n+\tuint32_t *p_remote_fault)\n+{\n+\tregister_update(p->mp_reg_link_summary);\n+\tif (p_abs)\n+\t\t*p_abs = field_get_val32(p->mp_fld_link_summary_abs);\n+\tif (p_nt_phy_link_state) {\n+\t\t*p_nt_phy_link_state =\n+\t\t\tfield_get_val32(p->mp_fld_link_summary_nt_phy_link_state);\n+\t}\n+\tif (p_lh_abs)\n+\t\t*p_lh_abs = field_get_val32(p->mp_fld_link_summary_lh_abs);\n+\tif (p_ll_nt_phy_link_state) {\n+\t\t*p_ll_nt_phy_link_state =\n+\t\t\tfield_get_val32(p->mp_fld_link_summary_ll_nt_phy_link_state);\n+\t}\n+\tif (p_link_down_cnt)\n+\t\t*p_link_down_cnt = field_get_val32(p->mp_fld_link_summary_link_down_cnt);\n+\tif (p_nim_interr)\n+\t\t*p_nim_interr = field_get_val32(p->mp_fld_link_summary_nim_interr);\n+\tif (p_lh_local_fault) {\n+\t\t*p_lh_local_fault =\n+\t\t\tfield_get_val32(p->mp_fld_link_summary_lh_local_fault);\n+\t}\n+\tif (p_lh_remote_fault) {\n+\t\t*p_lh_remote_fault =\n+\t\t\tfield_get_val32(p->mp_fld_link_summary_lh_remote_fault);\n+\t}\n+\tif (p_local_fault)\n+\t\t*p_local_fault = field_get_val32(p->mp_fld_link_summary_local_fault);\n+\tif (p_remote_fault)\n+\t\t*p_remote_fault = field_get_val32(p->mp_fld_link_summary_remote_fault);\n+}\n+\n+/*\n+ * Returns true if the lane/block lock bits indicate that a reset is required.\n+ * This is the case if Block/Lane lock is not all zero but not all set either.\n+ */\n+bool nthw_mac_pcs_reset_required(nthw_mac_pcs_t *p)\n+{\n+\tuint32_t block_lock = nthw_mac_pcs_get_fld_block_lock_lock(p);\n+\tuint32_t lane_lock = nthw_mac_pcs_get_fld_lane_lock_lock(p);\n+\tuint32_t block_lock_mask = nthw_mac_pcs_get_fld_block_lock_lock_mask(p);\n+\tuint32_t lane_lock_mask = nthw_mac_pcs_get_fld_lane_lock_lock_mask(p);\n+\n+\treturn ((block_lock != 0) && (block_lock != block_lock_mask)) ||\n+\t       ((lane_lock != 0) && (lane_lock != lane_lock_mask));\n+}\n+\n+void nthw_mac_pcs_set_fec(nthw_mac_pcs_t *p, bool enable)\n+{\n+\tNT_LOG(DBG, NTHW, \"Port %u: Set FEC: %u\\n\", p->m_port_no, enable);\n+\n+\tfield_get_updated(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in);\n+\tif (enable) {\n+\t\tfield_set_val_flush32(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in, 0);\n+\t} else {\n+\t\tfield_set_val_flush32(p->mp_field_fec_ctrl_reg_rs_fec_ctrl_in,\n+\t\t\t\t    (1 << 5) - 1);\n+\t}\n+\n+\t/* Both Rx and Tx must be reset for new FEC state to become active */\n+\tnthw_mac_pcs_rx_path_rst(p, true);\n+\tnthw_mac_pcs_tx_path_rst(p, true);\n+\tNT_OS_WAIT_USEC(10000); /* 10ms */\n+\n+\tnthw_mac_pcs_rx_path_rst(p, false);\n+\tnthw_mac_pcs_tx_path_rst(p, false);\n+\tNT_OS_WAIT_USEC(10000); /* 10ms */\n+\n+#ifdef DEBUG\n+\tif (enable) {\n+\t\tNT_LOG(DBG, NTHW, \"Port %u: FEC valid: %u\\n\", p->m_port_no,\n+\t\t       field_get_updated(p->mp_field_fec_stat_valid));\n+\t} else {\n+\t\tNT_LOG(DBG, NTHW, \"Port %u: FEC bypass: %u\\n\", p->m_port_no,\n+\t\t       field_get_updated(p->mp_field_fec_stat_bypass));\n+\t}\n+#endif\n+}\n+\n+bool nthw_mac_pcs_get_fec_bypass(nthw_mac_pcs_t *p)\n+{\n+\treturn field_get_updated(p->mp_field_fec_stat_bypass);\n+}\n+\n+bool nthw_mac_pcs_get_fec_valid(nthw_mac_pcs_t *p)\n+{\n+\treturn field_get_updated(p->mp_field_fec_stat_valid);\n+}\n+\n+bool nthw_mac_pcs_get_fec_aligned(nthw_mac_pcs_t *p)\n+{\n+\treturn field_get_updated(p->mp_field_fec_stat_fec_lane_algn);\n+}\n+\n+bool nthw_mac_pcs_get_fec_stat_any_am_locked(nthw_mac_pcs_t *p)\n+{\n+\tregister_update(p->mp_reg_fec_stat);\n+\tif ((field_get_val32(p->mp_field_fec_stat_am_lock0)) ||\n+\t\t\t(field_get_val32(p->mp_field_fec_stat_am_lock1)) ||\n+\t\t\t(field_get_val32(p->mp_field_fec_stat_am_lock2)) ||\n+\t\t\t(field_get_val32(p->mp_field_fec_stat_am_lock3)))\n+\t\treturn true;\n+\treturn false;\n+}\n+\n+bool nthw_mac_pcs_get_fec_stat_all_am_locked(nthw_mac_pcs_t *p)\n+{\n+\tregister_update(p->mp_reg_fec_stat);\n+\tif ((field_get_val32(p->mp_field_fec_stat_am_lock0)) &&\n+\t\t\t(field_get_val32(p->mp_field_fec_stat_am_lock1)) &&\n+\t\t\t(field_get_val32(p->mp_field_fec_stat_am_lock2)) &&\n+\t\t\t(field_get_val32(p->mp_field_fec_stat_am_lock3)))\n+\t\treturn true;\n+\treturn false;\n+}\n+\n+void nthw_mac_pcs_dump_fec_stat_fields(nthw_mac_pcs_t *p)\n+{\n+\tregister_update(p->mp_reg_fec_stat);\n+\tNT_LOG(DBG, NTHW,\n+\t       \"Port %u: FEC_STAT VALID: %u, AM_LOCK_0: %u, AM_LOCK_1: %u, AM_LOCK_2: %u, AM_LOCK_0: %u, FEC_LANE_ALGN: %u\\n\",\n+\t       p->m_port_no, field_get_val32(p->mp_field_fec_stat_valid),\n+\t       field_get_val32(p->mp_field_fec_stat_am_lock0),\n+\t       field_get_val32(p->mp_field_fec_stat_am_lock1),\n+\t       field_get_val32(p->mp_field_fec_stat_am_lock2),\n+\t       field_get_val32(p->mp_field_fec_stat_am_lock3),\n+\t       field_get_val32(p->mp_field_fec_stat_fec_lane_algn));\n+}\n+\n+void nthw_mac_pcs_reset_fec_counters(nthw_mac_pcs_t *p)\n+{\n+\tregister_update(p->mp_reg_fec_cw_cnt);\n+\tregister_update(p->mp_reg_fec_ucw_cnt);\n+\n+\tif (field_get_val32(p->mp_field_fec_cw_cnt_cw_cnt)) {\n+\t\tNT_LOG(DBG, NTHW, \"Port %u: FEC_CW_CNT: %u\\n\", p->m_port_no,\n+\t\t       field_get_val32(p->mp_field_fec_cw_cnt_cw_cnt));\n+\t}\n+\tif (field_get_val32(p->mp_field_fec_ucw_cnt_ucw_cnt)) {\n+\t\tNT_LOG(DBG, NTHW, \"Port %u: FEC_UCW_CNT: %u\\n\", p->m_port_no,\n+\t\t       field_get_val32(p->mp_field_fec_ucw_cnt_ucw_cnt));\n+\t}\n+}\n+\n+bool nthw_mac_pcs_get_gty_rx_buf_stat_error(nthw_mac_pcs_t *p)\n+{\n+\tregister_update(p->mp_reg_gty_rx_buf_stat);\n+\n+\tif (field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed0) ||\n+\t\t\tfield_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed1) ||\n+\t\t\tfield_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed2) ||\n+\t\t\tfield_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat_changed3)) {\n+\t\tif (field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat0) ||\n+\t\t\t\tfield_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat1) ||\n+\t\t\t\tfield_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat2) ||\n+\t\t\t\tfield_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat3)) {\n+\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t       \"Port %u: GTY RX_BUF_STAT_0: %u, RX_BUF_STAT_1: %u, RX_BUF_STAT_2: %u, RX_BUF_STAT_3: %u\\n\",\n+\t\t\t       p->m_port_no,\n+\t\t\t       field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat0),\n+\t\t\t       field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat1),\n+\t\t\t       field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat2),\n+\t\t\t       field_get_val32(p->mp_field_gty_rx_buf_stat_rx_buf_stat3));\n+\n+\t\t\treturn true;\n+\t\t}\n+\t}\n+\treturn false;\n+}\n+\n+void nthw_mac_pcs_set_gty_tx_tuning(nthw_mac_pcs_t *p, uint8_t lane, uint8_t tx_pre_csr,\n+\t\t\t       uint8_t tx_diff_ctl, uint8_t tx_post_csr)\n+{\n+\t/* GTY_PRE_CURSOR */\n+\tregister_update(p->mp_reg_gty_pre_cursor);\n+\tswitch (lane) {\n+\tcase 0:\n+\t\tfield_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr0,\n+\t\t\t\t    tx_pre_csr & 0x1F);\n+\t\tbreak;\n+\tcase 1:\n+\t\tfield_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr1,\n+\t\t\t\t    tx_pre_csr & 0x1F);\n+\t\tbreak;\n+\tcase 2:\n+\t\tfield_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr2,\n+\t\t\t\t    tx_pre_csr & 0x1F);\n+\t\tbreak;\n+\tcase 3:\n+\t\tfield_set_val_flush32(p->mp_field_gty_pre_cursor_tx_pre_csr3,\n+\t\t\t\t    tx_pre_csr & 0x1F);\n+\t\tbreak;\n+\t}\n+\n+\t/* GTY_DIFF_CTL */\n+\tregister_update(p->mp_reg_gty_diff_ctl);\n+\tswitch (lane) {\n+\tcase 0:\n+\t\tfield_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl0,\n+\t\t\t\t    tx_diff_ctl & 0x1F);\n+\t\tbreak;\n+\tcase 1:\n+\t\tfield_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl1,\n+\t\t\t\t    tx_diff_ctl & 0x1F);\n+\t\tbreak;\n+\tcase 2:\n+\t\tfield_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl2,\n+\t\t\t\t    tx_diff_ctl & 0x1F);\n+\t\tbreak;\n+\tcase 3:\n+\t\tfield_set_val_flush32(p->mp_field_gty_gty_diff_ctl_tx_diff_ctl3,\n+\t\t\t\t    tx_diff_ctl & 0x1F);\n+\t\tbreak;\n+\t}\n+\n+\t/* GTY_POST_CURSOR */\n+\tregister_update(p->mp_reg_gty_post_cursor);\n+\tswitch (lane) {\n+\tcase 0:\n+\t\tfield_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr0,\n+\t\t\t\t    tx_post_csr & 0x1F);\n+\t\tbreak;\n+\tcase 1:\n+\t\tfield_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr1,\n+\t\t\t\t    tx_post_csr & 0x1F);\n+\t\tbreak;\n+\tcase 2:\n+\t\tfield_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr2,\n+\t\t\t\t    tx_post_csr & 0x1F);\n+\t\tbreak;\n+\tcase 3:\n+\t\tfield_set_val_flush32(p->mp_field_gty_post_cursor_tx_post_csr3,\n+\t\t\t\t    tx_post_csr & 0x1F);\n+\t\tbreak;\n+\t}\n+\n+\tNT_LOG(DBG, NTHW,\n+\t       \"Port %u, lane %u: GTY txPreCsr: %d, txDiffCtl: %d, txPostCsr: %d\\n\",\n+\t       p->m_port_no, lane, tx_pre_csr, tx_diff_ctl, tx_post_csr);\n+}\n+\n+/*\n+ * Set receiver equalization mode\n+ *  0: enable DFE\n+ *  mode 1: enable LPM\n+ *\n+ * See UltraScale Architecture GTY Transceivers www.xilinx.com page 181,\n+ * UG578 (v1.1) November 24, 2015\n+ */\n+void nthw_mac_pcs_set_receiver_equalization_mode(nthw_mac_pcs_t *p, uint8_t mode)\n+{\n+\tregister_update(p->mp_reg_gty_ctl);\n+\tfield_set_val32(p->mp_field_gty_ctl_rx_lpm_en0, mode & 0x1);\n+\tfield_set_val32(p->mp_field_gty_ctl_rx_lpm_en1, mode & 0x1);\n+\tfield_set_val32(p->mp_field_gty_ctl_rx_lpm_en2, mode & 0x1);\n+\tfield_set_val_flush32(p->mp_field_gty_ctl_rx_lpm_en3, mode & 0x1);\n+\n+\t/* Toggle reset */\n+\tfield_set_val32(p->mp_field_gty_ctl_rx_equa_rst0, 1);\n+\tfield_set_val32(p->mp_field_gty_ctl_rx_equa_rst1, 1);\n+\tfield_set_val32(p->mp_field_gty_ctl_rx_equa_rst2, 1);\n+\tfield_set_val_flush32(p->mp_field_gty_ctl_rx_equa_rst3, 1);\n+\n+\tNT_OS_WAIT_USEC(1000); /* 1ms */\n+\n+\tfield_set_val32(p->mp_field_gty_ctl_rx_equa_rst0, 0);\n+\tfield_set_val32(p->mp_field_gty_ctl_rx_equa_rst1, 0);\n+\tfield_set_val32(p->mp_field_gty_ctl_rx_equa_rst2, 0);\n+\tfield_set_val_flush32(p->mp_field_gty_ctl_rx_equa_rst3, 0);\n+\n+\tNT_LOG(DBG, NTHW, \"Port %u: GTY receiver mode: %s\\n\", p->m_port_no,\n+\t       (mode == c_mac_pcs_receiver_mode_dfe ? \"DFE\" : \"LPM\"));\n+}\n+\n+void nthw_mac_pcs_swap_gty_tx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap)\n+{\n+\tregister_update(p->mp_reg_gty_ctl);\n+\tswitch (lane) {\n+\tcase 0:\n+\t\tfield_set_val_flush32(p->mp_field_gty_ctl_tx_pol0, swap);\n+\t\tbreak;\n+\tcase 1:\n+\t\tfield_set_val_flush32(p->mp_field_gty_ctl_tx_pol1, swap);\n+\t\tbreak;\n+\tcase 2:\n+\t\tfield_set_val_flush32(p->mp_field_gty_ctl_tx_pol2, swap);\n+\t\tbreak;\n+\tcase 3:\n+\t\tfield_set_val_flush32(p->mp_field_gty_ctl_tx_pol3, swap);\n+\t\tbreak;\n+\t}\n+\tNT_LOG(DBG, NTHW, \"Port %u: set GTY Tx lane (%d) polarity: %d\\n\",\n+\t       p->m_port_no, lane, swap);\n+}\n+\n+void nthw_mac_pcs_swap_gty_rx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap)\n+{\n+\tregister_update(p->mp_reg_gty_ctl);\n+\tswitch (lane) {\n+\tcase 0:\n+\t\tfield_set_val_flush32(p->mp_field_gty_ctl_rx_pol0, swap);\n+\t\tbreak;\n+\tcase 1:\n+\t\tfield_set_val_flush32(p->mp_field_gty_ctl_rx_pol1, swap);\n+\t\tbreak;\n+\tcase 2:\n+\t\tfield_set_val_flush32(p->mp_field_gty_ctl_rx_pol2, swap);\n+\t\tbreak;\n+\tcase 3:\n+\t\tfield_set_val_flush32(p->mp_field_gty_ctl_rx_pol3, swap);\n+\t\tbreak;\n+\t}\n+\tNT_LOG(DBG, NTHW, \"Port %u: set GTY Rx lane (%d) polarity: %d\\n\",\n+\t       p->m_port_no, lane, swap);\n+}\n+\n+void nthw_mac_pcs_set_led_mode(nthw_mac_pcs_t *p, uint8_t mode)\n+{\n+\tfield_get_updated(p->mp_field_debounce_ctrl_nt_port_ctrl);\n+\tfield_set_val_flush32(p->mp_field_debounce_ctrl_nt_port_ctrl, mode);\n+}\n+\n+void nthw_mac_pcs_set_timestamp_comp_rx(nthw_mac_pcs_t *p, uint16_t rx_dly)\n+{\n+\tif (p->mp_field_time_stamp_comp_rx_dly) {\n+\t\tfield_get_updated(p->mp_field_time_stamp_comp_rx_dly);\n+\t\tfield_set_val_flush32(p->mp_field_time_stamp_comp_rx_dly, rx_dly);\n+\t}\n+}\n+\n+void nthw_mac_pcs_set_port_no(nthw_mac_pcs_t *p, uint8_t port_no)\n+{\n+\tp->m_port_no = port_no;\n+}\n+\n+uint32_t nthw_mac_pcs_get_fld_block_lock_lock(nthw_mac_pcs_t *p)\n+{\n+\treturn field_get_updated(p->mp_fld_block_lock_lock);\n+}\n+\n+uint32_t nthw_mac_pcs_get_fld_block_lock_lock_mask(nthw_mac_pcs_t *p)\n+{\n+\treturn p->m_fld_block_lock_lock_mask;\n+}\n+\n+uint32_t nthw_mac_pcs_get_fld_lane_lock_lock(nthw_mac_pcs_t *p)\n+{\n+\treturn field_get_updated(p->mp_fld_vl_demuxed_lock);\n+}\n+\n+uint32_t nthw_mac_pcs_get_fld_lane_lock_lock_mask(nthw_mac_pcs_t *p)\n+{\n+\treturn p->m_fld_vl_demuxed_lock_mask;\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs.h b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.h\nnew file mode 100644\nindex 0000000000..08197f8b9e\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs.h\n@@ -0,0 +1,261 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef NTHW_MAC_PCS_H_\n+#define NTHW_MAC_PCS_H_\n+\n+enum nthw_mac_pcs_led_mode_e {\n+\tNTHW_MAC_PCS_LED_AUTO = 0x00,\n+\tNTHW_MAC_PCS_LED_ON = 0x01,\n+\tNTHW_MAC_PCS_LED_OFF = 0x02,\n+\tNTHW_MAC_PCS_LED_PORTID = 0x03,\n+};\n+\n+#define nthw_mac_pcs_receiver_mode_dfe (0)\n+#define nthw_mac_pcs_receiver_mode_lpm (1)\n+\n+struct nthw_mac_pcs {\n+\tuint8_t m_port_no;\n+\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_mac_pcs;\n+\tint mn_instance;\n+\n+\t/* Block lock status */\n+\tnt_field_t *mp_fld_block_lock_lock;\n+\tuint32_t m_fld_block_lock_lock_mask;\n+\n+\t/* Lane lock status */\n+\tnt_field_t *mp_fld_vl_demuxed_lock;\n+\tuint32_t m_fld_vl_demuxed_lock_mask;\n+\n+\t/* GTY_STAT */\n+\tnt_field_t *mp_fld_gty_stat_rx_rst_done0;\n+\tnt_field_t *mp_fld_gty_stat_rx_rst_done1;\n+\tnt_field_t *mp_fld_gty_stat_rx_rst_done2;\n+\tnt_field_t *mp_fld_gty_stat_rx_rst_done3;\n+\tnt_field_t *mp_fld_gty_stat_tx_rst_done0;\n+\tnt_field_t *mp_fld_gty_stat_tx_rst_done1;\n+\tnt_field_t *mp_fld_gty_stat_tx_rst_done2;\n+\tnt_field_t *mp_fld_gty_stat_tx_rst_done3;\n+\tuint32_t m_fld_gty_stat_rx_rst_done_mask;\n+\tuint32_t m_fld_gty_stat_tx_rst_done_mask;\n+\n+\t/* GTY_LOOP */\n+\tnt_register_t *mp_reg_gty_loop;\n+\tnt_field_t *mp_fld_gty_loop_gt_loop0;\n+\tnt_field_t *mp_fld_gty_loop_gt_loop1;\n+\tnt_field_t *mp_fld_gty_loop_gt_loop2;\n+\tnt_field_t *mp_fld_gty_loop_gt_loop3;\n+\n+\t/* MAC_PCS_CONFIG */\n+\tnt_field_t *mp_fld_pcs_config_tx_path_rst;\n+\tnt_field_t *mp_fld_pcs_config_rx_path_rst;\n+\tnt_field_t *mp_fld_pcs_config_rx_enable;\n+\tnt_field_t *mp_fld_pcs_config_rx_force_resync;\n+\tnt_field_t *mp_fld_pcs_config_rx_test_pattern;\n+\tnt_field_t *mp_fld_pcs_config_tx_enable;\n+\tnt_field_t *mp_fld_pcs_config_tx_send_idle;\n+\tnt_field_t *mp_fld_pcs_config_tx_send_rfi;\n+\tnt_field_t *mp_fld_pcs_config_tx_test_pattern;\n+\n+\t/* STAT PCS */\n+\tnt_field_t *mp_fld_stat_pcs_rx_status;\n+\tnt_field_t *mp_fld_stat_pcs_rx_aligned;\n+\tnt_field_t *mp_fld_stat_pcs_rx_aligned_err;\n+\tnt_field_t *mp_fld_stat_pcs_rx_misaligned;\n+\tnt_field_t *mp_fld_stat_pcs_rx_internal_local_fault;\n+\tnt_field_t *mp_fld_stat_pcs_rx_received_local_fault;\n+\tnt_field_t *mp_fld_stat_pcs_rx_local_fault;\n+\tnt_field_t *mp_fld_stat_pcs_rx_remote_fault;\n+\tnt_field_t *mp_fld_stat_pcs_rx_hi_ber;\n+\n+\t/* STAT_PCS_RX_LATCH */\n+\tnt_field_t *mp_fld_stat_pcs_rx_latch_status;\n+\n+\t/* PHYMAC_MISC */\n+\tnt_field_t *mp_fld_phymac_misc_tx_sel_host;\n+\tnt_field_t *mp_fld_phymac_misc_tx_sel_tfg;\n+\tnt_field_t *mp_fld_phymac_misc_tx_sel_rx_loop;\n+\tnt_field_t *mp_fld_phymac_misc_ts_eop;\n+\n+\t/* LINK_SUMMARY */\n+\tnt_register_t *mp_reg_link_summary;\n+\tnt_field_t *mp_fld_link_summary_abs;\n+\tnt_field_t *mp_fld_link_summary_nt_phy_link_state;\n+\tnt_field_t *mp_fld_link_summary_lh_abs;\n+\tnt_field_t *mp_fld_link_summary_ll_nt_phy_link_state;\n+\tnt_field_t *mp_fld_link_summary_link_down_cnt;\n+\tnt_field_t *mp_fld_link_summary_nim_interr;\n+\tnt_field_t *mp_fld_link_summary_lh_local_fault;\n+\tnt_field_t *mp_fld_link_summary_lh_remote_fault;\n+\tnt_field_t *mp_fld_link_summary_local_fault;\n+\tnt_field_t *mp_fld_link_summary_remote_fault;\n+\n+\t/* BIP_ERR */\n+\tnt_register_t *mp_reg_bip_err;\n+\tnt_field_t *mp_fld_reg_bip_err_bip_err;\n+\n+\t/* FEC_CTRL */\n+\tnt_register_t *mp_reg_fec_ctrl;\n+\tnt_field_t *mp_field_fec_ctrl_reg_rs_fec_ctrl_in;\n+\n+\t/* FEC_STAT */\n+\tnt_register_t *mp_reg_fec_stat;\n+\tnt_field_t *mp_field_fec_stat_bypass;\n+\tnt_field_t *mp_field_fec_stat_valid;\n+\tnt_field_t *mp_field_fec_stat_am_lock0;\n+\tnt_field_t *mp_field_fec_stat_am_lock1;\n+\tnt_field_t *mp_field_fec_stat_am_lock2;\n+\tnt_field_t *mp_field_fec_stat_am_lock3;\n+\tnt_field_t *mp_field_fec_stat_fec_lane_algn;\n+\n+\t/* FEC Corrected code word count */\n+\tnt_register_t *mp_reg_fec_cw_cnt;\n+\tnt_field_t *mp_field_fec_cw_cnt_cw_cnt;\n+\n+\t/* FEC Uncorrected code word count */\n+\tnt_register_t *mp_reg_fec_ucw_cnt;\n+\tnt_field_t *mp_field_fec_ucw_cnt_ucw_cnt;\n+\n+\t/* GTY_RX_BUF_STAT */\n+\tnt_register_t *mp_reg_gty_rx_buf_stat;\n+\tnt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat0;\n+\tnt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat1;\n+\tnt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat2;\n+\tnt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat3;\n+\tnt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed0;\n+\tnt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed1;\n+\tnt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed2;\n+\tnt_field_t *mp_field_gty_rx_buf_stat_rx_buf_stat_changed3;\n+\n+\t/* GTY_PRE_CURSOR */\n+\tnt_register_t *mp_reg_gty_pre_cursor;\n+\tnt_field_t *mp_field_gty_pre_cursor_tx_pre_csr0;\n+\tnt_field_t *mp_field_gty_pre_cursor_tx_pre_csr1;\n+\tnt_field_t *mp_field_gty_pre_cursor_tx_pre_csr2;\n+\tnt_field_t *mp_field_gty_pre_cursor_tx_pre_csr3;\n+\n+\t/* GTY_DIFF_CTL */\n+\tnt_register_t *mp_reg_gty_diff_ctl;\n+\tnt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl0;\n+\tnt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl1;\n+\tnt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl2;\n+\tnt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl3;\n+\n+\t/* GTY_POST_CURSOR */\n+\tnt_register_t *mp_reg_gty_post_cursor;\n+\tnt_field_t *mp_field_gty_post_cursor_tx_post_csr0;\n+\tnt_field_t *mp_field_gty_post_cursor_tx_post_csr1;\n+\tnt_field_t *mp_field_gty_post_cursor_tx_post_csr2;\n+\tnt_field_t *mp_field_gty_post_cursor_tx_post_csr3;\n+\n+\t/* GTY_CTL */\n+\tnt_register_t *mp_reg_gty_ctl;\n+\tnt_register_t *mp_reg_gty_ctl_tx;\n+\tnt_field_t *mp_field_gty_ctl_tx_pol0;\n+\tnt_field_t *mp_field_gty_ctl_tx_pol1;\n+\tnt_field_t *mp_field_gty_ctl_tx_pol2;\n+\tnt_field_t *mp_field_gty_ctl_tx_pol3;\n+\tnt_field_t *mp_field_gty_ctl_rx_pol0;\n+\tnt_field_t *mp_field_gty_ctl_rx_pol1;\n+\tnt_field_t *mp_field_gty_ctl_rx_pol2;\n+\tnt_field_t *mp_field_gty_ctl_rx_pol3;\n+\tnt_field_t *mp_field_gty_ctl_rx_lpm_en0;\n+\tnt_field_t *mp_field_gty_ctl_rx_lpm_en1;\n+\tnt_field_t *mp_field_gty_ctl_rx_lpm_en2;\n+\tnt_field_t *mp_field_gty_ctl_rx_lpm_en3;\n+\tnt_field_t *mp_field_gty_ctl_rx_equa_rst0;\n+\tnt_field_t *mp_field_gty_ctl_rx_equa_rst1;\n+\tnt_field_t *mp_field_gty_ctl_rx_equa_rst2;\n+\tnt_field_t *mp_field_gty_ctl_rx_equa_rst3;\n+\n+\t/* DEBOUNCE_CTRL */\n+\tnt_register_t *mp_reg_debounce_ctrl;\n+\tnt_field_t *mp_field_debounce_ctrl_nt_port_ctrl;\n+\n+\t/* TIMESTAMP_COMP */\n+\tnt_register_t *mp_reg_time_stamp_comp;\n+\tnt_field_t *mp_field_time_stamp_comp_rx_dly;\n+\tnt_field_t *mp_field_time_stamp_comp_tx_dly;\n+\n+\t/* STAT_PCS_RX */\n+\tnt_register_t *mp_reg_stat_pcs_rx;\n+\n+\t/* STAT_PCS_RX */\n+\tnt_register_t *mp_reg_stat_pcs_rx_latch;\n+\n+\t/* PHYMAC_MISC */\n+\tnt_register_t *mp_reg_phymac_misc;\n+\n+\t/* BLOCK_LOCK */\n+\tnt_register_t *mp_reg_block_lock;\n+};\n+\n+typedef struct nthw_mac_pcs nthw_mac_pcs_t;\n+typedef struct nthw_mac_pcs nthw_mac_pcs;\n+\n+nthw_mac_pcs_t *nthw_mac_pcs_new(void);\n+int nthw_mac_pcs_init(nthw_mac_pcs_t *p, nt_fpga_t *p_fpga, int n_instance);\n+void nthw_mac_pcs_delete(nthw_mac_pcs_t *p);\n+\n+bool nthw_mac_pcs_is_block_and_lane_lock_locked(nthw_mac_pcs_t *p);\n+bool nthw_mac_pcs_is_gt_fsm_rx_reset_done(nthw_mac_pcs_t *p);\n+bool nthw_mac_pcs_is_gt_fsm_tx_reset_done(nthw_mac_pcs_t *p);\n+void nthw_mac_pcs_tx_path_rst(nthw_mac_pcs_t *p, bool enable);\n+void nthw_mac_pcs_rx_path_rst(nthw_mac_pcs_t *p, bool enable);\n+bool nthw_mac_pcs_is_rx_path_rst(nthw_mac_pcs_t *p);\n+void nthw_mac_pcs_rx_force_resync(nthw_mac_pcs_t *p, bool enable);\n+void nthw_mac_pcs_tx_send_rfi(nthw_mac_pcs_t *p, bool enable);\n+bool nthw_mac_pcs_is_dd_r3_calib_done(nthw_mac_pcs_t *p);\n+void nthw_mac_pcs_tx_host_enable(nthw_mac_pcs_t *p,\n+\t\t\t     bool enable); /* wrapper - for ease of use */\n+void nthw_mac_pcs_set_rx_enable(nthw_mac_pcs_t *p, bool enable);\n+void nthw_mac_pcs_set_tx_enable(nthw_mac_pcs_t *p, bool enable);\n+void nthw_mac_pcs_set_tx_sel_host(nthw_mac_pcs_t *p, bool enable);\n+void nthw_mac_pcs_set_tx_sel_tfg(nthw_mac_pcs_t *p, bool enable);\n+void nthw_mac_pcs_set_ts_eop(nthw_mac_pcs_t *p, bool enable);\n+void nthw_mac_pcs_set_host_loopback(nthw_mac_pcs_t *p, bool enable);\n+void nthw_mac_pcs_set_line_loopback(nthw_mac_pcs_t *p, bool enable);\n+void nthw_mac_pcs_reset_bip_counters(nthw_mac_pcs_t *p);\n+void nthw_mac_pcs_get_status(nthw_mac_pcs_t *p, uint8_t *status);\n+bool nthw_mac_pcs_get_hi_ber(nthw_mac_pcs_t *p);\n+\n+void nthw_mac_pcs_get_link_summary1(nthw_mac_pcs_t *p, uint32_t *p_status,\n+\t\t\t\tuint32_t *p_status_latch, uint32_t *p_aligned,\n+\t\t\t\tuint32_t *p_local_fault, uint32_t *p_remote_fault);\n+\n+void nthw_mac_pcs_get_link_summary(nthw_mac_pcs_t *p, uint32_t *p_abs,\n+\t\t\t       uint32_t *p_nt_phy_link_state, uint32_t *p_lh_abs,\n+\t\t\t       uint32_t *p_ll_nt_phy_link_state,\n+\t\t\t       uint32_t *p_link_down_cnt, uint32_t *p_nim_interr,\n+\t\t\t       uint32_t *p_lh_local_fault,\n+\t\t\t       uint32_t *p_lh_remote_fault, uint32_t *p_local_fault,\n+\t\t\t       uint32_t *p_remote_fault);\n+\n+bool nthw_mac_pcs_reset_required(nthw_mac_pcs_t *p);\n+void nthw_mac_pcs_set_fec(nthw_mac_pcs_t *p, bool enable);\n+bool nthw_mac_pcs_get_fec_bypass(nthw_mac_pcs_t *p);\n+bool nthw_mac_pcs_get_fec_valid(nthw_mac_pcs_t *p);\n+bool nthw_mac_pcs_get_fec_aligned(nthw_mac_pcs_t *p);\n+bool nthw_mac_pcs_get_fec_stat_any_am_locked(nthw_mac_pcs_t *p);\n+bool nthw_mac_pcs_get_fec_stat_all_am_locked(nthw_mac_pcs_t *p);\n+void nthw_mac_pcs_dump_fec_stat_fields(nthw_mac_pcs_t *p);\n+void nthw_mac_pcs_reset_fec_counters(nthw_mac_pcs_t *p);\n+bool nthw_mac_pcs_get_gty_rx_buf_stat_error(nthw_mac_pcs_t *p);\n+void nthw_mac_pcs_set_gty_tx_tuning(nthw_mac_pcs_t *p, uint8_t lane, uint8_t tx_pre_csr,\n+\t\t\t       uint8_t tx_diff_ctl, uint8_t tx_post_csr);\n+void nthw_mac_pcs_swap_gty_tx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap);\n+void nthw_mac_pcs_swap_gty_rx_polarity(nthw_mac_pcs_t *p, uint8_t lane, bool swap);\n+void nthw_mac_pcs_set_receiver_equalization_mode(nthw_mac_pcs_t *p, uint8_t mode);\n+void nthw_mac_pcs_set_led_mode(nthw_mac_pcs_t *p, uint8_t mode);\n+void nthw_mac_pcs_set_timestamp_comp_rx(nthw_mac_pcs_t *p, uint16_t rx_dly);\n+void nthw_mac_pcs_set_port_no(nthw_mac_pcs_t *p, uint8_t port_no);\n+\n+uint32_t nthw_mac_pcs_get_fld_block_lock_lock(nthw_mac_pcs_t *p);\n+uint32_t nthw_mac_pcs_get_fld_block_lock_lock_mask(nthw_mac_pcs_t *p);\n+uint32_t nthw_mac_pcs_get_fld_lane_lock_lock(nthw_mac_pcs_t *p);\n+uint32_t nthw_mac_pcs_get_fld_lane_lock_lock_mask(nthw_mac_pcs_t *p);\n+\n+#endif /* NTHW_MAC_PCS_H_ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c\nnew file mode 100644\nindex 0000000000..d8e1f0de5d\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.c\n@@ -0,0 +1,1631 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_mac_pcs_xxv.h\"\n+\n+static void nthw_mac_pcs_xxv_field_set_or_clr_flush(const nt_field_t *f, bool set)\n+{\n+\tif (f) {\n+\t\tfield_get_updated(f);\n+\t\tif (set)\n+\t\t\tfield_set_flush(f);\n+\t\telse\n+\t\t\tfield_clr_flush(f);\n+\t}\n+}\n+\n+nthw_mac_pcs_xxv_t *nthw_mac_pcs_xxv_new(void)\n+{\n+\tnthw_mac_pcs_xxv_t *p = malloc(sizeof(nthw_mac_pcs_xxv_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_mac_pcs_xxv_t));\n+\treturn p;\n+}\n+\n+void nthw_mac_pcs_xxv_delete(nthw_mac_pcs_xxv_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_mac_pcs_xxv_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+uint8_t nthw_mac_pcs_xxv_get_port_no(const nthw_mac_pcs_xxv_t *p, uint8_t index)\n+{\n+\treturn index == 0 ? (uint8_t)p->mn_instance : index;\n+}\n+\n+void nthw_mac_pcs_xxv_set_port_no(nthw_mac_pcs_xxv_t *p, uint8_t port_no)\n+{\n+\tp->m_port_no = port_no;\n+}\n+\n+void nthw_mac_pcs_xxv_get_link_summary(nthw_mac_pcs_xxv_t *p,\n+\tuint32_t *p_abs, uint32_t *p_nt_phy_link_state,\n+\tuint32_t *p_lh_abs, uint32_t *p_ll_nt_phy_link_state, uint32_t *p_link_down_cnt,\n+\tuint32_t *p_nim_interr, uint32_t *p_lh_local_fault, uint32_t *p_lh_remote_fault,\n+\tuint32_t *p_lh_internal_local_fault, uint32_t *p_lh_received_local_fault,\n+\tuint8_t index)\n+{\n+\tstruct nthw_mac_pcs_xxv__registers_fields *r =\n+\t\t\t&p->regs[index]; /* register and fields */\n+\n+\tassert(p);\n+\n+\tregister_update(r->mp_reg_link_summary);\n+\tif (p_abs)\n+\t\t*p_abs = field_get_val32(r->mp_fld_link_summary_abs);\n+\tif (p_nt_phy_link_state) {\n+\t\t*p_nt_phy_link_state =\n+\t\t\tfield_get_val32(r->mp_fld_link_summary_nt_phy_link_state);\n+\t}\n+\tif (p_lh_abs)\n+\t\t*p_lh_abs = field_get_val32(r->mp_fld_link_summary_lh_abs);\n+\tif (p_ll_nt_phy_link_state) {\n+\t\t*p_ll_nt_phy_link_state =\n+\t\t\tfield_get_val32(r->mp_fld_link_summary_ll_nt_phy_link_state);\n+\t}\n+\tif (p_link_down_cnt)\n+\t\t*p_link_down_cnt = field_get_val32(r->mp_fld_link_summary_link_down_cnt);\n+\tif (p_nim_interr)\n+\t\t*p_nim_interr = field_get_val32(r->mp_fld_link_summary_nim_interr);\n+\tif (p_lh_local_fault) {\n+\t\t*p_lh_local_fault =\n+\t\t\tfield_get_val32(r->mp_fld_link_summary_lh_local_fault);\n+\t}\n+\tif (p_lh_remote_fault) {\n+\t\t*p_lh_remote_fault =\n+\t\t\tfield_get_val32(r->mp_fld_link_summary_lh_remote_fault);\n+\t}\n+\tif (p_lh_internal_local_fault) {\n+\t\t*p_lh_internal_local_fault =\n+\t\t\tfield_get_val32(r->mp_fld_link_summary_lh_internal_local_fault);\n+\t}\n+\tif (p_lh_received_local_fault) {\n+\t\t*p_lh_received_local_fault =\n+\t\t\tfield_get_val32(r->mp_fld_link_summary_lh_received_local_fault);\n+\t}\n+}\n+\n+void nthw_mac_pcs_xxv_set_tx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_enable;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_rx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_core_conf_rx_enable;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_rx_force_resync(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_core_conf_rx_force_resync;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_reset_rx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_sub_rst_rx_gt_data;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_reset_tx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_sub_rst_tx_gt_data;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_reset_an_lt(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_sub_rst_an_lt;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_reset_speed_ctrl(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t  uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_sub_rst_speed_ctrl;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_send_rfi;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_tx_send_lfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_send_lfi;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_tx_send_lfi_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable_lfi,\n+\t\tbool enable_rfi, uint8_t index)\n+{\n+\tregister_update(p->regs[index].mp_reg_core_conf);\n+\tfield_set_val32(p->regs[index].mp_fld_core_conf_tx_send_lfi, enable_lfi);\n+\tfield_set_val32(p->regs[index].mp_fld_core_conf_tx_send_rfi, enable_rfi);\n+\tregister_flush(p->regs[index].mp_reg_core_conf, 1);\n+}\n+\n+bool nthw_mac_pcs_xxv_is_dfe_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_rx_lpm_en;\n+\n+\t/* NOTE: DFE is enabled when LPM is disabled */\n+\treturn !field_get_updated(f);\n+}\n+\n+void nthw_mac_pcs_xxv_set_dfe(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)\n+{\n+\tconst nt_field_t *f = p->regs[index].mp_fld_gty_ctl_rx_lpm_en;\n+\tconst bool set_dfe =\n+\t\t!enable; /* NOTE: Enable DFE mode means setting LPM = 0 */\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, set_dfe);\n+\n+\t/* Toggle GTY_CTL_RX->EQUA_RST to 1 and 0 to assert new LPM_EN setting */\n+\tf = p->regs[index].mp_fld_gty_ctl_rx_equa_rst;\n+\tfield_get_updated(f);\n+\tfield_set_val_flush32(f, 1); /* Assert    GTH SOFT RESET */\n+\tfield_get_updated(f);\n+\tfield_set_val_flush32(f, 0); /* De-Assert GTH SOFT RESET */\n+\tfield_get_updated(f);\n+}\n+\n+void nthw_mac_pcs_xxv_set_rx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t    uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_rx_polarity;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_tx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t    uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_tx_polarity;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_tx_gty_inhibit(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t   uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_gty_ctl_tx_inhibit;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_host_loopback(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t   uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_gty_loop_gt_loop;\n+\n+\tfield_get_updated(f);\n+\tfield_set_val_flush32(f, enable ? 2U : 0U);\n+}\n+\n+void nthw_mac_pcs_xxv_set_line_loopback(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t   uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_core_conf_line_loopback;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+bool nthw_mac_pcs_xxv_is_user_rx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index)\n+{\n+\treturn field_get_updated(p->regs[index].mp_fld_sub_rst_status_user_rx_rst);\n+}\n+\n+bool nthw_mac_pcs_xxv_is_user_tx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index)\n+{\n+\treturn field_get_updated(p->regs[index].mp_fld_sub_rst_status_user_tx_rst);\n+}\n+\n+/*\n+ * QPLL lock signal.\n+ * For cores capable of 10G only, there are only 1 QPLL. For cores capable of\n+ * 10G/25G, there are 2 QPLLs.\n+ */\n+bool nthw_mac_pcs_xxv_is_qpll_lock(nthw_mac_pcs_xxv_t *p, uint8_t index)\n+{\n+\treturn (field_get_updated(p->regs[index].mp_fld_sub_rst_status_qpll_lock) ==\n+\t\t3);\n+}\n+\n+bool nthw_mac_pcs_xxv_is_sub_rst_ready(nthw_mac_pcs_xxv_t *p, uint8_t index)\n+{\n+\treturn (nthw_mac_pcs_xxv_is_qpll_lock(p, index) &&\n+\t\t!nthw_mac_pcs_xxv_is_user_rx_rst(p, index) &&\n+\t\t!nthw_mac_pcs_xxv_is_user_tx_rst(p, index));\n+}\n+\n+bool nthw_mac_pcs_xxv_is_aneg_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index)\n+{\n+\treturn field_get_updated(p->regs[index].mp_fld_aneg_config_enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_tx_send_idle(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_send_idle;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_tx_ins_fcs(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_core_conf_tx_ins_fcs;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+bool nthw_mac_pcs_xxv_get_link_speed10_g(nthw_mac_pcs_xxv_t *p, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_link_speed10_g;\n+\n+\treturn field_get_updated(f) != 0; /* 0 = 25g, 1 = 10g */\n+}\n+\n+void nthw_mac_pcs_xxv_set_link_speed10_g(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t   uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_link_speed10_g;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_link_speed_toggle(nthw_mac_pcs_xxv_t *p, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_link_speed_toggle;\n+\n+\tfield_get_updated(f);\n+\tfield_set_flush(f);\n+}\n+\n+void nthw_mac_pcs_xxv_set_rs_fec_conf_rs_fec_enable(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\tuint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_rs_fec_conf_rs_fec_enable;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_led_mode(nthw_mac_pcs_xxv_t *p, uint8_t mode, uint8_t index)\n+{\n+\tconst nt_field_t *const f =\n+\t\tp->regs[index].mp_field_debounce_ctrl_nt_port_ctrl;\n+\n+\tfield_get_updated(f);\n+\tfield_set_val_flush32(f, mode);\n+}\n+\n+void nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t  uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_sub_rst_rx_mac_pcs;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t  uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_sub_rst_tx_mac_pcs;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_reset_fec_counters(nthw_mac_pcs_xxv_t *p, uint8_t index)\n+{\n+\tregister_update(p->regs[index].mp_reg_rs_fec_ccw);\n+\tregister_update(p->regs[index].mp_reg_rs_fec_ucw);\n+\n+\tif (field_get_val32(p->regs[index].mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt)) {\n+\t\tNT_LOG(DBG, NTHW, \"Port %u: FEC_CW_CNT: %u\", p->m_port_no,\n+\t\t       field_get_val32(p->regs[index].mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt));\n+\t}\n+\tif (field_get_val32(p->regs[index].mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt)) {\n+\t\tNT_LOG(DBG, NTHW, \"Port %u: FEC_UCW_CNT: %u\", p->m_port_no,\n+\t\t       field_get_val32(p->regs[index].mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt));\n+\t}\n+}\n+\n+void nthw_mac_pcs_xxv_set_timestamp_comp_rx(nthw_mac_pcs_xxv_t *p, uint16_t rx_dly,\n+\t\t\t\t      uint8_t index)\n+{\n+\tfield_get_updated(p->regs[index].mp_field_timestamp_comp_rx_dly);\n+\tfield_set_val_flush32(p->regs[index].mp_field_timestamp_comp_rx_dly, rx_dly);\n+}\n+\n+void nthw_mac_pcs_xxv_set_timestamp_comp_tx(nthw_mac_pcs_xxv_t *p, uint16_t tx_dly,\n+\t\t\t\t      uint8_t index)\n+{\n+\tfield_get_updated(p->regs[index].mp_field_timestamp_comp_tx_dly);\n+\tfield_set_val_flush32(p->regs[index].mp_field_timestamp_comp_tx_dly, tx_dly);\n+}\n+\n+void nthw_mac_pcs_xxv_set_ts_at_eop(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_core_conf_ts_at_eop;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_gty_diff(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index)\n+{\n+\tfield_get_updated(p->regs[index].mp_field_gty_gty_diff_ctl_tx_diff_ctl);\n+\tfield_set_val_flush32(p->regs[index].mp_field_gty_gty_diff_ctl_tx_diff_ctl,\n+\t\t\t    value);\n+}\n+\n+void nthw_mac_pcs_xxv_set_gty_pre(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index)\n+{\n+\tfield_get_updated(p->regs[index].mp_field_gty_pre_cursor_tx_pre_csr);\n+\tfield_set_val_flush32(p->regs[index].mp_field_gty_pre_cursor_tx_pre_csr, value);\n+}\n+\n+void nthw_mac_pcs_xxv_set_gty_post(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index)\n+{\n+\tfield_get_updated(p->regs[index].mp_field_gty_post_cursor_tx_post_csr);\n+\tfield_set_val_flush32(p->regs[index].mp_field_gty_post_cursor_tx_post_csr,\n+\t\t\t    value);\n+}\n+\n+void nthw_mac_pcs_xxv_set_lt_conf_enable(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t   uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_lt_conf_enable;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_aneg_config_fec91_request(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\tuint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_aneg_config_fec91_request;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_aneg_config_rs_fec_request(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\tuint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_aneg_config_rs_fec_request;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_aneg_config_fec74_request(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\tuint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_aneg_config_fec74_request;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_aneg_config_enable(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t       uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_aneg_config_enable;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_aneg_config_bypass(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t       uint8_t index)\n+{\n+\tconst nt_field_t *const f = p->regs[index].mp_fld_aneg_config_bypass;\n+\n+\tnthw_mac_pcs_xxv_field_set_or_clr_flush(f, enable);\n+}\n+\n+void nthw_mac_pcs_xxv_set_dac_mode(nthw_mac_pcs_xxv_t *p, uint8_t dac_mode,\n+\t\t\t      uint8_t index)\n+{\n+\tif (dac_mode == NTHW_MAC_PCS_XXV_DAC_OFF) {\n+\t\tnthw_mac_pcs_xxv_reset_an_lt(p, false, index);\n+\t\tnthw_mac_pcs_xxv_set_aneg_config_enable(p, false, index);\n+\t\tnthw_mac_pcs_xxv_set_aneg_config_bypass(p, true, index);\n+\t\tnthw_mac_pcs_xxv_set_lt_conf_enable(p, false, index);\n+\t\tnthw_mac_pcs_xxv_set_rx_mac_pcs_rst(p, true, index);\n+\t\tnthw_mac_pcs_xxv_set_tx_mac_pcs_rst(p, true, index);\n+\t\tnthw_mac_pcs_xxv_reset_rx_gt_data(p, true, index);\n+\t\tnthw_mac_pcs_xxv_reset_tx_gt_data(p, true, index);\n+\t\tnthw_mac_pcs_xxv_set_rx_mac_pcs_rst(p, false, index);\n+\t\tnthw_mac_pcs_xxv_set_tx_mac_pcs_rst(p, false, index);\n+\t\tnthw_mac_pcs_xxv_reset_rx_gt_data(p, false, index);\n+\t\tnthw_mac_pcs_xxv_reset_tx_gt_data(p, false, index);\n+\n+\t\treturn;\n+\t}\n+\tassert(0); /* If you end up here you need to implement other DAC modes */\n+}\n+\n+bool nthw_mac_pcs_xxv_get_ll_rx_fec74_lock(nthw_mac_pcs_xxv_t *p, uint8_t index)\n+{\n+\treturn field_get_updated(p->regs[index].mp_fld_link_summary_ll_rx_fec74_lock);\n+}\n+\n+bool nthw_mac_pcs_xxv_get_ll_rx_rsfec_lane_alignment(nthw_mac_pcs_xxv_t *p, uint8_t index)\n+{\n+\treturn field_get_updated(p->regs[index].mp_fld_link_summary_ll_rx_rsfec_lane_alignment);\n+}\n+\n+int nthw_mac_pcs_xxv_init(nthw_mac_pcs_xxv_t *p, nt_fpga_t *p_fpga, int n_instance,\n+\t\t       int n_channels)\n+{\n+\tnt_module_t *p_mod = fpga_query_module(p_fpga, MOD_MAC_PCS_XXV, n_instance);\n+\tconst char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;\n+\tconst bool m_mac8x10_g = false;\n+\tnt_module_t *module = p_mod;\n+\tuint64_t n_module_version_packed64 = -1;\n+\tnt_register_t *r;\n+\tnt_register_t *(*get_register)(nt_module_t *, uint32_t) =\n+\t\tmodule_get_register;\n+\tnt_field_t *(*get_field)(const nt_register_t *, uint32_t) =\n+\t\tregister_get_field;\n+\tnt_field_t *(*query_field)(const nt_register_t *, uint32_t) =\n+\t\tregister_query_field;\n+\tstruct nthw_mac_pcs_xxv__registers_fields *rf;\n+\n+\tif (p == NULL)\n+\t\treturn (p_mod == NULL ? -1 : 0);\n+\n+\tif (p_mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: MAC_PCS_XXV instance=%d: no such instance\\n\",\n+\t\t       p_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_mac_pcs_xxv = p_mod;\n+\n+\tmemset(p->regs, 0, sizeof(p->regs));\n+\n+\tn_module_version_packed64 = module_get_version_packed64(p->mp_mod_mac_pcs_xxv);\n+\tswitch (n_module_version_packed64) {\n+\tcase (0UL << 32) | 0UL: /* 0.0 */\n+\tcase (0UL << 32) | 1UL: /* 0.1 */\n+\tcase (0UL << 32) | 2UL: /* 0.2 */\n+\t\tNT_LOG(DBG, NTHW,\n+\t\t       \"%s: MAC_PCS_XXV instance=%d: version=0x%08lX\\n\",\n+\t\t       p_adapter_id_str, p->mn_instance, n_module_version_packed64);\n+\t\tbreak;\n+\tdefault:\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: MAC_PCS_XXV instance=%d: version=0x%08lX: unsupported module version\\n\",\n+\t\t       p_adapter_id_str, p->mn_instance, n_module_version_packed64);\n+\t\treturn -1;\n+\t}\n+\n+\tassert(n_channels == 1 || n_channels == 2 || n_channels == 4);\n+\n+\t/* Register MAC_PCS_XXV_CORE_CONF_0 -- MAC_PCS_XXV_CORE_CONF_3 */\n+\tif (n_channels < 4) {\n+\t\t/* Initialize regs/fields for sub-module/channel 0 */\n+\t\trf = &p->regs[0];\n+\t\tr = get_register(module, MAC_PCS_XXV_CORE_CONF_0);\n+\n+\t\trf->mp_reg_core_conf = r;\n+\t\trf->mp_fld_core_conf_rx_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_0_RX_ENABLE);\n+\t\trf->mp_fld_core_conf_rx_force_resync =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_0_RX_FORCE_RESYNC);\n+\t\trf->mp_fld_core_conf_tx_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_ENABLE);\n+\t\trf->mp_fld_core_conf_tx_ins_fcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_INS_FCS);\n+\t\trf->mp_fld_core_conf_tx_ign_fcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_IGN_FCS);\n+\t\trf->mp_fld_core_conf_tx_send_lfi =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_LFI);\n+\t\trf->mp_fld_core_conf_tx_send_rfi =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_RFI);\n+\t\trf->mp_fld_core_conf_tx_send_idle =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_0_TX_SEND_IDLE);\n+\t\trf->mp_fld_core_conf_inline_mode =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_0_INLINE_MODE);\n+\t\trf->mp_fld_core_conf_line_loopback =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_0_LINE_LOOPBACK);\n+\t\trf->mp_fld_core_conf_ts_at_eop =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_0_TS_AT_EOP);\n+\t}\n+\n+\tif (n_channels >= 2) {\n+\t\t/* Initialize regs/fields for sub-module/channel 1 */\n+\t\trf = &p->regs[1];\n+\t\tr = get_register(module, MAC_PCS_XXV_CORE_CONF_1);\n+\n+\t\trf->mp_reg_core_conf = r;\n+\t\trf->mp_fld_core_conf_rx_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_1_RX_ENABLE);\n+\t\trf->mp_fld_core_conf_rx_force_resync =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_1_RX_FORCE_RESYNC);\n+\t\trf->mp_fld_core_conf_tx_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_ENABLE);\n+\t\trf->mp_fld_core_conf_tx_ins_fcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_INS_FCS);\n+\t\trf->mp_fld_core_conf_tx_ign_fcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_IGN_FCS);\n+\t\trf->mp_fld_core_conf_tx_send_lfi =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_LFI);\n+\t\trf->mp_fld_core_conf_tx_send_rfi =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_RFI);\n+\t\trf->mp_fld_core_conf_tx_send_idle =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_1_TX_SEND_IDLE);\n+\t\trf->mp_fld_core_conf_inline_mode =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_1_INLINE_MODE);\n+\t\trf->mp_fld_core_conf_line_loopback =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_1_LINE_LOOPBACK);\n+\t\trf->mp_fld_core_conf_ts_at_eop =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_1_TS_AT_EOP);\n+\t}\n+\n+\tif (n_channels == 4) {\n+\t\t/* Initialize regs/fields for sub-module/channel 2 */\n+\t\trf = &p->regs[2];\n+\t\tr = get_register(module, MAC_PCS_XXV_CORE_CONF_2);\n+\n+\t\trf->mp_reg_core_conf = r;\n+\t\trf->mp_fld_core_conf_rx_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_2_RX_ENABLE);\n+\t\trf->mp_fld_core_conf_rx_force_resync =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_2_RX_FORCE_RESYNC);\n+\t\trf->mp_fld_core_conf_tx_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_ENABLE);\n+\t\trf->mp_fld_core_conf_tx_ins_fcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_INS_FCS);\n+\t\trf->mp_fld_core_conf_tx_ign_fcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_IGN_FCS);\n+\t\trf->mp_fld_core_conf_tx_send_lfi =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_LFI);\n+\t\trf->mp_fld_core_conf_tx_send_rfi =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_RFI);\n+\t\trf->mp_fld_core_conf_tx_send_idle =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_2_TX_SEND_IDLE);\n+\t\trf->mp_fld_core_conf_inline_mode =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_2_INLINE_MODE);\n+\t\trf->mp_fld_core_conf_line_loopback =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_2_LINE_LOOPBACK);\n+\t\trf->mp_fld_core_conf_ts_at_eop =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_2_TS_AT_EOP);\n+\n+\t\t/* Initialize regs/fields for sub-module/channel 3 */\n+\t\trf = &p->regs[3];\n+\t\tr = get_register(module, MAC_PCS_XXV_CORE_CONF_3);\n+\n+\t\trf->mp_reg_core_conf = r;\n+\t\trf->mp_fld_core_conf_rx_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_3_RX_ENABLE);\n+\t\trf->mp_fld_core_conf_rx_force_resync =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_3_RX_FORCE_RESYNC);\n+\t\trf->mp_fld_core_conf_tx_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_ENABLE);\n+\t\trf->mp_fld_core_conf_tx_ins_fcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_INS_FCS);\n+\t\trf->mp_fld_core_conf_tx_ign_fcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_IGN_FCS);\n+\t\trf->mp_fld_core_conf_tx_send_lfi =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_LFI);\n+\t\trf->mp_fld_core_conf_tx_send_rfi =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_RFI);\n+\t\trf->mp_fld_core_conf_tx_send_idle =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_3_TX_SEND_IDLE);\n+\t\trf->mp_fld_core_conf_inline_mode =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_3_INLINE_MODE);\n+\t\trf->mp_fld_core_conf_line_loopback =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_3_LINE_LOOPBACK);\n+\t\trf->mp_fld_core_conf_ts_at_eop =\n+\t\t\tget_field(r, MAC_PCS_XXV_CORE_CONF_3_TS_AT_EOP);\n+\t}\n+\n+\t/*\n+\t * Registers MAC_PCS_XXV_ANEG_CONFIG_0 -- MAC_PCS_XXV_ANEG_CONFIG_3\n+\t * and       MAC_PCS_XXV_ANEG_ABILITY_0 -- MAC_PCS_XXV_ANEG_ABILITY_3\n+\t * and       MAC_PCS_XXV_LT_CONF_0 -- MAC_PCS_XXV_LT_CONF_3\n+\t */\n+\tif (!m_mac8x10_g && n_channels < 4) {\n+\t\t/* 2 x 10 25 G */\n+\t\t/* ANEG_CONFIG */\n+\t\trf = &p->regs[0];\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_0);\n+\t\trf->mp_reg_aneg_config = r;\n+\t\trf->mp_fld_aneg_config_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_ENABLE);\n+\t\trf->mp_fld_aneg_config_bypass =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_BYPASS);\n+\t\trf->mp_fld_aneg_config_restart =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_RESTART);\n+\t\trf->mp_fld_aneg_config_pseudo =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_PSEUDO);\n+\t\trf->mp_fld_aneg_config_nonce_seed =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_NONCE_SEED);\n+\t\trf->mp_fld_aneg_config_remote_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_REMOTE_FAULT);\n+\t\trf->mp_fld_aneg_config_pause =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_PAUSE);\n+\t\trf->mp_fld_aneg_config_asmdir =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_ASMDIR);\n+\t\trf->mp_fld_aneg_config_fec74_request10_g =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST_10G);\n+\t\trf->mp_fld_aneg_config_hide_fec74 =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_HIDE_FEC74);\n+\t\trf->mp_fld_aneg_config_fec74_request =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC74_REQUEST);\n+\t\trf->mp_fld_aneg_config_fec91_request =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_REQUEST);\n+\t\trf->mp_fld_aneg_config_fec91_ability =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_FEC91_ABILITY);\n+\t\trf->mp_fld_aneg_config_rs_fec_request =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_RS_FEC_REQUEST);\n+\t\trf->mp_fld_aneg_config_sw_fec_overwrite =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_SW_FEC_OVERWRITE);\n+\t\trf->mp_fld_aneg_config_sw_speed_overwrite =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_0_SW_SPEED_OVERWRITE);\n+\n+\t\t/* ANEG_ABILITY */\n+\t\tr = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_0);\n+\t\trf->mp_reg_aneg_ability = r;\n+\n+\t\trf->mp_fld_aneg_ability25_g_base_cr =\n+\t\t\tquery_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR);\n+\t\tif (!rf->mp_fld_aneg_ability25_g_base_cr) {\n+\t\t\trf->mp_fld_aneg_ability25_g_base_cr =\n+\t\t\t\tquery_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR);\n+\t\t}\n+\n+\t\trf->mp_fld_aneg_ability25_g_base_crs =\n+\t\t\tquery_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR_S);\n+\t\tif (!rf->mp_fld_aneg_ability25_g_base_crs) {\n+\t\t\trf->mp_fld_aneg_ability25_g_base_crs =\n+\t\t\t\tquery_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR_S);\n+\t\t}\n+\n+\t\trf->mp_fld_aneg_ability25_g_base_cr1 =\n+\t\t\tquery_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_BASE25G_CR1);\n+\t\tif (!rf->mp_fld_aneg_ability25_g_base_cr1) {\n+\t\t\trf->mp_fld_aneg_ability25_g_base_cr1 =\n+\t\t\t\tquery_field(r, MAC_PCS_XXV_ANEG_ABILITY_0_25GBASE_CR1);\n+\t\t}\n+\n+\t\t/* LT_CONF */\n+\t\tr = get_register(module, MAC_PCS_XXV_LT_CONF_0);\n+\t\trf->mp_reg_lt_conf = r;\n+\t\trf->mp_fld_lt_conf_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_LT_CONF_0_ENABLE);\n+\t\trf->mp_fld_lt_conf_restart =\n+\t\t\tget_field(r, MAC_PCS_XXV_LT_CONF_0_RESTART);\n+\t\trf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_0_SEED);\n+\t}\n+\n+\tif (!m_mac8x10_g && n_channels >= 2) {\n+\t\t/* 2 x 10 25 G */\n+\t\t/* ANEG_CONFIG */\n+\n+\t\t/* Initialize regs/fields for sub-module/channel 1 */\n+\t\trf = &p->regs[1];\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_1);\n+\t\trf->mp_reg_aneg_config = r;\n+\t\trf->mp_fld_aneg_config_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_ENABLE);\n+\t\trf->mp_fld_aneg_config_bypass =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_BYPASS);\n+\t\trf->mp_fld_aneg_config_restart =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_RESTART);\n+\t\trf->mp_fld_aneg_config_pseudo =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_PSEUDO);\n+\t\trf->mp_fld_aneg_config_nonce_seed =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_NONCE_SEED);\n+\t\trf->mp_fld_aneg_config_remote_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_REMOTE_FAULT);\n+\t\trf->mp_fld_aneg_config_pause =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_PAUSE);\n+\t\trf->mp_fld_aneg_config_asmdir =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_ASMDIR);\n+\t\trf->mp_fld_aneg_config_fec74_request10_g =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST_10G);\n+\t\trf->mp_fld_aneg_config_hide_fec74 =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_HIDE_FEC74);\n+\t\trf->mp_fld_aneg_config_fec74_request =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC74_REQUEST);\n+\t\trf->mp_fld_aneg_config_fec91_request =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_REQUEST);\n+\t\trf->mp_fld_aneg_config_fec91_ability =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_FEC91_ABILITY);\n+\t\trf->mp_fld_aneg_config_rs_fec_request =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_RS_FEC_REQUEST);\n+\t\trf->mp_fld_aneg_config_sw_fec_overwrite =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_SW_FEC_OVERWRITE);\n+\t\trf->mp_fld_aneg_config_sw_speed_overwrite =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_1_SW_SPEED_OVERWRITE);\n+\n+\t\t/* ANEG_ABILITY */\n+\t\tr = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_1);\n+\t\trf->mp_reg_aneg_ability = r;\n+\n+\t\trf->mp_fld_aneg_ability25_g_base_cr =\n+\t\t\tquery_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR);\n+\t\tif (!rf->mp_fld_aneg_ability25_g_base_cr) {\n+\t\t\trf->mp_fld_aneg_ability25_g_base_cr =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR);\n+\t\t}\n+\n+\t\trf->mp_fld_aneg_ability25_g_base_crs =\n+\t\t\tquery_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR_S);\n+\t\tif (!rf->mp_fld_aneg_ability25_g_base_crs) {\n+\t\t\trf->mp_fld_aneg_ability25_g_base_crs =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR_S);\n+\t\t}\n+\n+\t\trf->mp_fld_aneg_ability25_g_base_cr1 =\n+\t\t\tquery_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_BASE25G_CR1);\n+\t\tif (!rf->mp_fld_aneg_ability25_g_base_cr1) {\n+\t\t\trf->mp_fld_aneg_ability25_g_base_cr1 =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_ANEG_ABILITY_1_25GBASE_CR1);\n+\t\t}\n+\n+\t\t/* LT_CONF */\n+\t\tr = get_register(module, MAC_PCS_XXV_LT_CONF_1);\n+\t\trf->mp_reg_lt_conf = r;\n+\t\trf->mp_fld_lt_conf_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_LT_CONF_1_ENABLE);\n+\t\trf->mp_fld_lt_conf_restart =\n+\t\t\tget_field(r, MAC_PCS_XXV_LT_CONF_1_RESTART);\n+\t\trf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_1_SEED);\n+\t}\n+\n+\tif (!m_mac8x10_g && n_channels == 4) {\n+\t\t/* Initialize regs/fields for sub-module/channel 2 */\n+\t\trf = &p->regs[2];\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_2);\n+\t\trf->mp_reg_aneg_config = r;\n+\t\trf->mp_fld_aneg_config_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_ENABLE);\n+\t\trf->mp_fld_aneg_config_bypass =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_BYPASS);\n+\t\trf->mp_fld_aneg_config_restart =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_RESTART);\n+\t\trf->mp_fld_aneg_config_pseudo =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_PSEUDO);\n+\t\trf->mp_fld_aneg_config_nonce_seed =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_NONCE_SEED);\n+\t\trf->mp_fld_aneg_config_remote_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_REMOTE_FAULT);\n+\t\trf->mp_fld_aneg_config_pause =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_PAUSE);\n+\t\trf->mp_fld_aneg_config_asmdir =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_ASMDIR);\n+\t\trf->mp_fld_aneg_config_fec74_request10_g =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST_10G);\n+\t\trf->mp_fld_aneg_config_hide_fec74 =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_HIDE_FEC74);\n+\t\trf->mp_fld_aneg_config_fec74_request =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC74_REQUEST);\n+\t\trf->mp_fld_aneg_config_fec91_request =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_REQUEST);\n+\t\trf->mp_fld_aneg_config_fec91_ability =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_FEC91_ABILITY);\n+\t\trf->mp_fld_aneg_config_rs_fec_request =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_RS_FEC_REQUEST);\n+\t\trf->mp_fld_aneg_config_sw_fec_overwrite =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_SW_FEC_OVERWRITE);\n+\t\trf->mp_fld_aneg_config_sw_speed_overwrite =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_2_SW_SPEED_OVERWRITE);\n+\n+\t\t/* ANEG_ABILITY */\n+\t\tr = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_2);\n+\t\trf->mp_reg_aneg_ability = r;\n+\t\trf->mp_fld_aneg_ability25_g_base_cr =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR);\n+\t\trf->mp_fld_aneg_ability25_g_base_crs =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR_S);\n+\t\trf->mp_fld_aneg_ability25_g_base_cr1 =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_ABILITY_2_25GBASE_CR1);\n+\n+\t\t/* LT_CONF */\n+\t\tr = get_register(module, MAC_PCS_XXV_LT_CONF_2);\n+\t\trf->mp_reg_lt_conf = r;\n+\t\trf->mp_fld_lt_conf_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_LT_CONF_2_ENABLE);\n+\t\trf->mp_fld_lt_conf_restart =\n+\t\t\tget_field(r, MAC_PCS_XXV_LT_CONF_2_RESTART);\n+\t\trf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_2_SEED);\n+\n+\t\t/* Initialize regs/fields for sub-module/channel 3 */\n+\t\trf = &p->regs[3];\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_ANEG_CONFIG_3);\n+\t\trf->mp_reg_aneg_config = r;\n+\t\trf->mp_fld_aneg_config_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_ENABLE);\n+\t\trf->mp_fld_aneg_config_bypass =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_BYPASS);\n+\t\trf->mp_fld_aneg_config_restart =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_RESTART);\n+\t\trf->mp_fld_aneg_config_pseudo =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_PSEUDO);\n+\t\trf->mp_fld_aneg_config_nonce_seed =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_NONCE_SEED);\n+\t\trf->mp_fld_aneg_config_remote_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_REMOTE_FAULT);\n+\t\trf->mp_fld_aneg_config_pause =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_PAUSE);\n+\t\trf->mp_fld_aneg_config_asmdir =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_ASMDIR);\n+\t\trf->mp_fld_aneg_config_fec74_request10_g =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST_10G);\n+\t\trf->mp_fld_aneg_config_hide_fec74 =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_HIDE_FEC74);\n+\t\trf->mp_fld_aneg_config_fec74_request =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC74_REQUEST);\n+\t\trf->mp_fld_aneg_config_fec91_request =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_REQUEST);\n+\t\trf->mp_fld_aneg_config_fec91_ability =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_FEC91_ABILITY);\n+\t\trf->mp_fld_aneg_config_rs_fec_request =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_RS_FEC_REQUEST);\n+\t\trf->mp_fld_aneg_config_sw_fec_overwrite =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_SW_FEC_OVERWRITE);\n+\t\trf->mp_fld_aneg_config_sw_speed_overwrite =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_CONFIG_3_SW_SPEED_OVERWRITE);\n+\n+\t\t/* ANEG_ABILITY */\n+\t\tr = get_register(module, MAC_PCS_XXV_ANEG_ABILITY_3);\n+\t\trf->mp_reg_aneg_ability = r;\n+\t\trf->mp_fld_aneg_ability25_g_base_cr =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR);\n+\t\trf->mp_fld_aneg_ability25_g_base_crs =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR_S);\n+\t\trf->mp_fld_aneg_ability25_g_base_cr1 =\n+\t\t\tget_field(r, MAC_PCS_XXV_ANEG_ABILITY_3_25GBASE_CR1);\n+\n+\t\t/* LT_CONF */\n+\t\tr = get_register(module, MAC_PCS_XXV_LT_CONF_3);\n+\t\trf->mp_reg_lt_conf = r;\n+\t\trf->mp_fld_lt_conf_enable =\n+\t\t\tget_field(r, MAC_PCS_XXV_LT_CONF_3_ENABLE);\n+\t\trf->mp_fld_lt_conf_restart =\n+\t\t\tget_field(r, MAC_PCS_XXV_LT_CONF_3_RESTART);\n+\t\trf->mp_fld_lt_conf_seed = get_field(r, MAC_PCS_XXV_LT_CONF_3_SEED);\n+\t}\n+\n+\t/*\n+\t * Registers MAC_PCS_XXV_SUB_RST_0 -- MAC_PCS_XXV_SUB_RST_3\n+\t * and       MAC_PCS_XXV_SUB_RST_STATUS_0 -- MAC_PCS_XXV_SUB_RST_STATUS_3\n+\t */\n+\tif (n_channels < 4) {\n+\t\t/* Initialize regs/fields for sub-module/channel 0 */\n+\t\trf = &p->regs[0];\n+\t\tr = get_register(module, MAC_PCS_XXV_SUB_RST_0);\n+\n+\t\trf->mp_reg_sub_rst = r;\n+\t\trf->mp_fld_sub_rst_rx_mac_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_0_RX_MAC_PCS);\n+\t\trf->mp_fld_sub_rst_tx_mac_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_0_TX_MAC_PCS);\n+\t\trf->mp_fld_sub_rst_rx_gt_data =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_0_RX_GT_DATA);\n+\t\trf->mp_fld_sub_rst_tx_gt_data =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_0_TX_GT_DATA);\n+\t\trf->mp_fld_sub_rst_rx_buf =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_0_RX_BUF);\n+\t\trf->mp_fld_sub_rst_rx_pma =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_0_RX_PMA);\n+\t\trf->mp_fld_sub_rst_tx_pma =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_0_TX_PMA);\n+\t\trf->mp_fld_sub_rst_rx_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_0_RX_PCS);\n+\t\trf->mp_fld_sub_rst_tx_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_0_TX_PCS);\n+\t\trf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_0_AN_LT);\n+\t\trf->mp_fld_sub_rst_speed_ctrl =\n+\t\t\tquery_field(r, MAC_PCS_XXV_SUB_RST_0_SPEED_CTRL);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_0);\n+\t\trf->mp_reg_sub_rst_status = r;\n+\t\trf->mp_fld_sub_rst_status_user_rx_rst =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_USER_RX_RST);\n+\t\trf->mp_fld_sub_rst_status_user_tx_rst =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_USER_TX_RST);\n+\t\trf->mp_fld_sub_rst_status_qpll_lock =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_STATUS_0_QPLL_LOCK);\n+\t}\n+\n+\tif (n_channels >= 2) {\n+\t\t/* Initialize regs/fields for sub-module/channel 1 */\n+\t\trf = &p->regs[1];\n+\t\tr = get_register(module, MAC_PCS_XXV_SUB_RST_1);\n+\n+\t\trf->mp_reg_sub_rst = r;\n+\t\trf->mp_fld_sub_rst_rx_mac_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_1_RX_MAC_PCS);\n+\t\trf->mp_fld_sub_rst_tx_mac_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_1_TX_MAC_PCS);\n+\t\trf->mp_fld_sub_rst_rx_gt_data =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_1_RX_GT_DATA);\n+\t\trf->mp_fld_sub_rst_tx_gt_data =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_1_TX_GT_DATA);\n+\t\trf->mp_fld_sub_rst_rx_buf =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_1_RX_BUF);\n+\t\trf->mp_fld_sub_rst_rx_pma =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_1_RX_PMA);\n+\t\trf->mp_fld_sub_rst_tx_pma =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_1_TX_PMA);\n+\t\trf->mp_fld_sub_rst_rx_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_1_RX_PCS);\n+\t\trf->mp_fld_sub_rst_tx_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_1_TX_PCS);\n+\t\trf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_1_AN_LT);\n+\t\trf->mp_fld_sub_rst_speed_ctrl =\n+\t\t\tquery_field(r, MAC_PCS_XXV_SUB_RST_1_SPEED_CTRL);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_1);\n+\t\trf->mp_reg_sub_rst_status = r;\n+\t\trf->mp_fld_sub_rst_status_user_rx_rst =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_USER_RX_RST);\n+\t\trf->mp_fld_sub_rst_status_user_tx_rst =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_USER_TX_RST);\n+\t\trf->mp_fld_sub_rst_status_qpll_lock =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_STATUS_1_QPLL_LOCK);\n+\t}\n+\n+\tif (n_channels == 4) {\n+\t\t/* Initialize regs/fields for sub-module/channel 2 */\n+\t\trf = &p->regs[2];\n+\t\tr = get_register(module, MAC_PCS_XXV_SUB_RST_2);\n+\n+\t\trf->mp_reg_sub_rst = r;\n+\t\trf->mp_fld_sub_rst_rx_mac_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_2_RX_MAC_PCS);\n+\t\trf->mp_fld_sub_rst_tx_mac_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_2_TX_MAC_PCS);\n+\t\trf->mp_fld_sub_rst_rx_gt_data =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_2_RX_GT_DATA);\n+\t\trf->mp_fld_sub_rst_tx_gt_data =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_2_TX_GT_DATA);\n+\t\trf->mp_fld_sub_rst_rx_buf =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_2_RX_BUF);\n+\t\trf->mp_fld_sub_rst_rx_pma =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_2_RX_PMA);\n+\t\trf->mp_fld_sub_rst_tx_pma =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_2_TX_PMA);\n+\t\trf->mp_fld_sub_rst_rx_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_2_RX_PCS);\n+\t\trf->mp_fld_sub_rst_tx_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_2_TX_PCS);\n+\t\trf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_2_AN_LT);\n+\t\trf->mp_fld_sub_rst_speed_ctrl =\n+\t\t\tquery_field(r, MAC_PCS_XXV_SUB_RST_2_SPEED_CTRL);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_2);\n+\t\trf->mp_reg_sub_rst_status = r;\n+\t\trf->mp_fld_sub_rst_status_user_rx_rst =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_USER_RX_RST);\n+\t\trf->mp_fld_sub_rst_status_user_tx_rst =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_USER_TX_RST);\n+\t\trf->mp_fld_sub_rst_status_qpll_lock =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_STATUS_2_QPLL_LOCK);\n+\n+\t\t/* Initialize regs/fields for sub-module/channel 3 */\n+\t\trf = &p->regs[3];\n+\t\tr = get_register(module, MAC_PCS_XXV_SUB_RST_3);\n+\n+\t\trf->mp_reg_sub_rst = r;\n+\t\trf->mp_fld_sub_rst_rx_mac_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_3_RX_MAC_PCS);\n+\t\trf->mp_fld_sub_rst_tx_mac_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_3_TX_MAC_PCS);\n+\t\trf->mp_fld_sub_rst_rx_gt_data =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_3_RX_GT_DATA);\n+\t\trf->mp_fld_sub_rst_tx_gt_data =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_3_TX_GT_DATA);\n+\t\trf->mp_fld_sub_rst_rx_buf =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_3_RX_BUF);\n+\t\trf->mp_fld_sub_rst_rx_pma =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_3_RX_PMA);\n+\t\trf->mp_fld_sub_rst_tx_pma =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_3_TX_PMA);\n+\t\trf->mp_fld_sub_rst_rx_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_3_RX_PCS);\n+\t\trf->mp_fld_sub_rst_tx_pcs =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_3_TX_PCS);\n+\t\trf->mp_fld_sub_rst_an_lt = get_field(r, MAC_PCS_XXV_SUB_RST_3_AN_LT);\n+\t\trf->mp_fld_sub_rst_speed_ctrl =\n+\t\t\tquery_field(r, MAC_PCS_XXV_SUB_RST_3_SPEED_CTRL);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_SUB_RST_STATUS_3);\n+\t\trf->mp_reg_sub_rst_status = r;\n+\t\trf->mp_fld_sub_rst_status_user_rx_rst =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_USER_RX_RST);\n+\t\trf->mp_fld_sub_rst_status_user_tx_rst =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_USER_TX_RST);\n+\t\trf->mp_fld_sub_rst_status_qpll_lock =\n+\t\t\tget_field(r, MAC_PCS_XXV_SUB_RST_STATUS_3_QPLL_LOCK);\n+\t}\n+\n+\t/* Registers MAC_PCS_XXV_LINK_SUMMARY_0 -- MAC_PCS_XXV_LINK_SUMMARY_3 */\n+\tif (n_channels < 4) {\n+\t\t/* Initialize regs/fields for sub-module/channel 0 */\n+\t\trf = &p->regs[0];\n+\t\tr = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_0);\n+\n+\t\trf->mp_reg_link_summary = r;\n+\t\trf->mp_fld_link_summary_nt_phy_link_state =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_NT_PHY_LINK_STATE);\n+\t\trf->mp_fld_link_summary_ll_nt_phy_link_state =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_PHY_LINK_STATE);\n+\t\trf->mp_fld_link_summary_abs =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_ABS);\n+\t\trf->mp_fld_link_summary_lh_abs =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_ABS);\n+\t\trf->mp_fld_link_summary_link_down_cnt =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LINK_DOWN_CNT);\n+\t\tif (!m_mac8x10_g) {\n+\t\t\trf->mp_fld_link_summary_ll_rx_fec74_lock =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_FEC74_LOCK);\n+\t\t\trf->mp_fld_link_summary_lh_rx_rsfec_hi_ser =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_RSFEC_HI_SER);\n+\t\t\trf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_RSFEC_LANE_ALIGNMENT);\n+\t\t\trf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_TX_RSFEC_LANE_ALIGNMENT);\n+\t\t\trf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_PCS_VALID_CTRL_CODE);\n+\t\t}\n+\t\trf->mp_fld_link_summary_ll_rx_block_lock =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LL_RX_BLOCK_LOCK);\n+\t\trf->mp_fld_link_summary_lh_rx_high_bit_error_rate =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RX_HIGH_BIT_ERROR_RATE);\n+\t\t;\n+\t\trf->mp_fld_link_summary_lh_internal_local_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_INTERNAL_LOCAL_FAULT);\n+\t\trf->mp_fld_link_summary_lh_received_local_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_RECEIVED_LOCAL_FAULT);\n+\t\trf->mp_fld_link_summary_lh_local_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_LOCAL_FAULT);\n+\t\trf->mp_fld_link_summary_lh_remote_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_LH_REMOTE_FAULT);\n+\t\trf->mp_fld_link_summary_nim_interr =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_0_NIM_INTERR);\n+\t}\n+\n+\tif (n_channels >= 2) {\n+\t\t/* Initialize regs/fields for sub-module/channel 1 */\n+\t\trf = &p->regs[1];\n+\t\tr = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_1);\n+\n+\t\trf->mp_reg_link_summary = r;\n+\t\trf->mp_fld_link_summary_nt_phy_link_state =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_NT_PHY_LINK_STATE);\n+\t\trf->mp_fld_link_summary_ll_nt_phy_link_state =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_PHY_LINK_STATE);\n+\t\trf->mp_fld_link_summary_abs =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_ABS);\n+\t\trf->mp_fld_link_summary_lh_abs =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_ABS);\n+\t\trf->mp_fld_link_summary_link_down_cnt =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LINK_DOWN_CNT);\n+\t\tif (!m_mac8x10_g) {\n+\t\t\trf->mp_fld_link_summary_ll_rx_fec74_lock =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_FEC74_LOCK);\n+\t\t\trf->mp_fld_link_summary_lh_rx_rsfec_hi_ser =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_RSFEC_HI_SER);\n+\t\t\trf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_RSFEC_LANE_ALIGNMENT);\n+\t\t\trf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_TX_RSFEC_LANE_ALIGNMENT);\n+\t\t\trf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_PCS_VALID_CTRL_CODE);\n+\t\t}\n+\t\trf->mp_fld_link_summary_ll_rx_block_lock =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LL_RX_BLOCK_LOCK);\n+\t\trf->mp_fld_link_summary_lh_rx_high_bit_error_rate =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RX_HIGH_BIT_ERROR_RATE);\n+\t\t;\n+\t\trf->mp_fld_link_summary_lh_internal_local_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_INTERNAL_LOCAL_FAULT);\n+\t\trf->mp_fld_link_summary_lh_received_local_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_RECEIVED_LOCAL_FAULT);\n+\t\trf->mp_fld_link_summary_lh_local_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_LOCAL_FAULT);\n+\t\trf->mp_fld_link_summary_lh_remote_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_LH_REMOTE_FAULT);\n+\t\trf->mp_fld_link_summary_nim_interr =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_1_NIM_INTERR);\n+\t}\n+\n+\tif (n_channels == 4) {\n+\t\t/* Initialize regs/fields for sub-module/channel 2 */\n+\t\trf = &p->regs[2];\n+\t\tr = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_2);\n+\n+\t\trf->mp_reg_link_summary = r;\n+\t\trf->mp_fld_link_summary_nt_phy_link_state =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_NT_PHY_LINK_STATE);\n+\t\trf->mp_fld_link_summary_ll_nt_phy_link_state =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_PHY_LINK_STATE);\n+\t\trf->mp_fld_link_summary_abs =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_ABS);\n+\t\trf->mp_fld_link_summary_lh_abs =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_ABS);\n+\t\trf->mp_fld_link_summary_link_down_cnt =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LINK_DOWN_CNT);\n+\t\tif (!m_mac8x10_g) {\n+\t\t\trf->mp_fld_link_summary_ll_rx_fec74_lock =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_FEC74_LOCK);\n+\t\t\trf->mp_fld_link_summary_lh_rx_rsfec_hi_ser =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_RSFEC_HI_SER);\n+\t\t\trf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_RSFEC_LANE_ALIGNMENT);\n+\t\t\trf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_TX_RSFEC_LANE_ALIGNMENT);\n+\t\t\trf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_PCS_VALID_CTRL_CODE);\n+\t\t}\n+\t\trf->mp_fld_link_summary_ll_rx_block_lock =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LL_RX_BLOCK_LOCK);\n+\t\trf->mp_fld_link_summary_lh_rx_high_bit_error_rate =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RX_HIGH_BIT_ERROR_RATE);\n+\t\t;\n+\t\trf->mp_fld_link_summary_lh_internal_local_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_INTERNAL_LOCAL_FAULT);\n+\t\trf->mp_fld_link_summary_lh_received_local_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_RECEIVED_LOCAL_FAULT);\n+\t\trf->mp_fld_link_summary_lh_local_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_LOCAL_FAULT);\n+\t\trf->mp_fld_link_summary_lh_remote_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_LH_REMOTE_FAULT);\n+\t\trf->mp_fld_link_summary_nim_interr =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_2_NIM_INTERR);\n+\n+\t\t/* Initialize regs/fields for sub-module/channel 3 */\n+\t\trf = &p->regs[3];\n+\t\tr = get_register(module, MAC_PCS_XXV_LINK_SUMMARY_3);\n+\n+\t\trf->mp_reg_link_summary = r;\n+\t\trf->mp_fld_link_summary_nt_phy_link_state =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_NT_PHY_LINK_STATE);\n+\t\trf->mp_fld_link_summary_ll_nt_phy_link_state =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_PHY_LINK_STATE);\n+\t\trf->mp_fld_link_summary_abs =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_ABS);\n+\t\trf->mp_fld_link_summary_lh_abs =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_ABS);\n+\t\trf->mp_fld_link_summary_link_down_cnt =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LINK_DOWN_CNT);\n+\t\tif (!m_mac8x10_g) {\n+\t\t\trf->mp_fld_link_summary_ll_rx_fec74_lock =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_FEC74_LOCK);\n+\t\t\trf->mp_fld_link_summary_lh_rx_rsfec_hi_ser =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_RSFEC_HI_SER);\n+\t\t\trf->mp_fld_link_summary_ll_rx_rsfec_lane_alignment =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_RSFEC_LANE_ALIGNMENT);\n+\t\t\trf->mp_fld_link_summary_ll_tx_rsfec_lane_alignment =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_TX_RSFEC_LANE_ALIGNMENT);\n+\t\t\trf->mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_PCS_VALID_CTRL_CODE);\n+\t\t}\n+\t\trf->mp_fld_link_summary_ll_rx_block_lock =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LL_RX_BLOCK_LOCK);\n+\t\trf->mp_fld_link_summary_lh_rx_high_bit_error_rate =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RX_HIGH_BIT_ERROR_RATE);\n+\t\t;\n+\t\trf->mp_fld_link_summary_lh_internal_local_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_INTERNAL_LOCAL_FAULT);\n+\t\trf->mp_fld_link_summary_lh_received_local_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_RECEIVED_LOCAL_FAULT);\n+\t\trf->mp_fld_link_summary_lh_local_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_LOCAL_FAULT);\n+\t\trf->mp_fld_link_summary_lh_remote_fault =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_LH_REMOTE_FAULT);\n+\t\trf->mp_fld_link_summary_nim_interr =\n+\t\t\tget_field(r, MAC_PCS_XXV_LINK_SUMMARY_3_NIM_INTERR);\n+\t}\n+\n+\t/*\n+\t *  Registers MAC_PCS_XXV_GTY_LOOP_0 -- MAC_PCS_XXV_GTY_LOOP_3\n+\t * and       MAC_PCS_XXV_GTY_CTL_RX_0 -- MAC_PCS_XXV_GTY_CTL_RX_3\n+\t * and       MAC_PCS_XXV_GTY_CTL_TX_0 -- MAC_PCS_XXV_GTY_CTL_TX_3\n+\t * and       MAC_PCS_XXV_LINK_SPEED_0 -- MAC_PCS_XXV_LINK_SPEED_3\n+\t * and       MAC_PCS_XXV_RS_FEC_CONF_0 -- MAC_PCS_XXV_RS_FEC_CONF_0\n+\t */\n+\tif (n_channels < 4) {\n+\t\t/* Initialize regs/fields for sub-module/channel 0 */\n+\t\trf = &p->regs[0];\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_LOOP_0);\n+\t\trf->mp_reg_gty_loop = r;\n+\t\trf->mp_fld_gty_loop_gt_loop =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_LOOP_0_GT_LOOP);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_0);\n+\t\trf->mp_reg_gty_ctl_rx = r;\n+\t\trf->mp_fld_gty_ctl_rx_polarity =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_POLARITY);\n+\t\trf->mp_fld_gty_ctl_rx_lpm_en =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_LPM_EN);\n+\t\trf->mp_fld_gty_ctl_rx_equa_rst =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_RX_0_EQUA_RST);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_0);\n+\t\trf->mp_fld_gty_ctl_tx_polarity =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_TX_0_POLARITY);\n+\t\trf->mp_fld_gty_ctl_tx_inhibit =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_TX_0_INHIBIT);\n+\n+\t\tif (!m_mac8x10_g) {\n+\t\t\tr = get_register(module, MAC_PCS_XXV_LINK_SPEED_0);\n+\t\t\trf->mp_reg_link_speed =\n+\t\t\t\tget_register(module, MAC_PCS_XXV_LINK_SPEED_0);\n+\n+\t\t\trf->mp_fld_link_speed10_g =\n+\t\t\t\tquery_field(r, MAC_PCS_XXV_LINK_SPEED_0_SPEED);\n+\t\t\tif (!rf->mp_fld_link_speed10_g) {\n+\t\t\t\trf->mp_fld_link_speed10_g =\n+\t\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SPEED_0_10G);\n+\t\t\t}\n+\n+\t\t\trf->mp_fld_link_speed_toggle =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SPEED_0_TOGGLE);\n+\n+\t\t\tr = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_0);\n+\t\t\trf->mp_reg_rs_fec_conf = r;\n+\t\t\trf->mp_fld_rs_fec_conf_rs_fec_enable =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_RS_FEC_CONF_0_RS_FEC_ENABLE);\n+\n+\t\t\tr = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_0);\n+\t\t\trf->mp_reg_rs_fec_ccw = r;\n+\t\t\trf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_0_RS_FEC_CCW_CNT);\n+\n+\t\t\tr = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_0);\n+\t\t\trf->mp_reg_rs_fec_ucw = r;\n+\t\t\trf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_0_RS_FEC_UCW_CNT);\n+\t\t}\n+\t}\n+\n+\tif (n_channels >= 2) {\n+\t\t/* Initialize regs/fields for sub-module/channel 1 */\n+\t\trf = &p->regs[1];\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_LOOP_1);\n+\t\trf->mp_reg_gty_loop = r;\n+\t\trf->mp_fld_gty_loop_gt_loop =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_LOOP_1_GT_LOOP);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_1);\n+\t\trf->mp_reg_gty_ctl_rx = r;\n+\t\trf->mp_fld_gty_ctl_rx_polarity =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_POLARITY);\n+\t\trf->mp_fld_gty_ctl_rx_lpm_en =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_LPM_EN);\n+\t\trf->mp_fld_gty_ctl_rx_equa_rst =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_RX_1_EQUA_RST);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_1);\n+\t\trf->mp_fld_gty_ctl_tx_polarity =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_TX_1_POLARITY);\n+\t\trf->mp_fld_gty_ctl_tx_inhibit =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_TX_1_INHIBIT);\n+\n+\t\tif (!m_mac8x10_g) {\n+\t\t\tr = get_register(module, MAC_PCS_XXV_LINK_SPEED_1);\n+\t\t\trf->mp_reg_link_speed =\n+\t\t\t\tget_register(module, MAC_PCS_XXV_LINK_SPEED_1);\n+\n+\t\t\trf->mp_fld_link_speed10_g =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SPEED_1_SPEED);\n+\t\t\tif (!rf->mp_fld_link_speed10_g) {\n+\t\t\t\trf->mp_fld_link_speed10_g =\n+\t\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SPEED_1_10G);\n+\t\t\t}\n+\t\t\trf->mp_fld_link_speed_toggle =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SPEED_1_TOGGLE);\n+\n+\t\t\tr = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_1);\n+\t\t\trf->mp_reg_rs_fec_conf = r;\n+\t\t\trf->mp_fld_rs_fec_conf_rs_fec_enable =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_RS_FEC_CONF_1_RS_FEC_ENABLE);\n+\n+\t\t\tr = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_1);\n+\t\t\trf->mp_reg_rs_fec_ccw = r;\n+\t\t\trf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_1_RS_FEC_CCW_CNT);\n+\n+\t\t\tr = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_1);\n+\t\t\trf->mp_reg_rs_fec_ucw = r;\n+\t\t\trf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_1_RS_FEC_UCW_CNT);\n+\t\t}\n+\t}\n+\n+\tif (n_channels == 4) {\n+\t\t/* Initialize regs/fields for sub-module/channel 2 */\n+\t\trf = &p->regs[2];\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_LOOP_2);\n+\t\trf->mp_reg_gty_loop = r;\n+\t\trf->mp_fld_gty_loop_gt_loop =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_LOOP_2_GT_LOOP);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_2);\n+\t\trf->mp_reg_gty_ctl_rx = r;\n+\t\trf->mp_fld_gty_ctl_rx_polarity =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_POLARITY);\n+\t\trf->mp_fld_gty_ctl_rx_lpm_en =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_LPM_EN);\n+\t\trf->mp_fld_gty_ctl_rx_equa_rst =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_RX_2_EQUA_RST);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_2);\n+\t\trf->mp_fld_gty_ctl_tx_polarity =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_TX_2_POLARITY);\n+\t\trf->mp_fld_gty_ctl_tx_inhibit =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_TX_2_INHIBIT);\n+\n+\t\tif (!m_mac8x10_g) {\n+\t\t\tr = get_register(module, MAC_PCS_XXV_LINK_SPEED_2);\n+\t\t\trf->mp_reg_link_speed =\n+\t\t\t\tget_register(module, MAC_PCS_XXV_LINK_SPEED_2);\n+\n+\t\t\trf->mp_fld_link_speed10_g =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SPEED_2_SPEED);\n+\t\t\tif (!rf->mp_fld_link_speed10_g) {\n+\t\t\t\trf->mp_fld_link_speed10_g =\n+\t\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SPEED_2_10G);\n+\t\t\t}\n+\n+\t\t\trf->mp_fld_link_speed_toggle =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SPEED_2_TOGGLE);\n+\n+\t\t\tr = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_2);\n+\t\t\trf->mp_reg_rs_fec_conf = r;\n+\t\t\trf->mp_fld_rs_fec_conf_rs_fec_enable =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_RS_FEC_CONF_2_RS_FEC_ENABLE);\n+\n+\t\t\tr = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_2);\n+\t\t\trf->mp_reg_rs_fec_ccw = r;\n+\t\t\trf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_2_RS_FEC_CCW_CNT);\n+\n+\t\t\tr = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_2);\n+\t\t\trf->mp_reg_rs_fec_ucw = r;\n+\t\t\trf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_2_RS_FEC_UCW_CNT);\n+\t\t}\n+\n+\t\t/* Initialize regs/fields for sub-module/channel 3 */\n+\t\trf = &p->regs[3];\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_LOOP_3);\n+\t\trf->mp_reg_gty_loop = r;\n+\t\trf->mp_fld_gty_loop_gt_loop =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_LOOP_3_GT_LOOP);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_CTL_RX_3);\n+\t\trf->mp_reg_gty_ctl_rx = r;\n+\t\trf->mp_fld_gty_ctl_rx_polarity =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_POLARITY);\n+\t\trf->mp_fld_gty_ctl_rx_lpm_en =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_LPM_EN);\n+\t\trf->mp_fld_gty_ctl_rx_equa_rst =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_RX_3_EQUA_RST);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_CTL_TX_3);\n+\t\trf->mp_fld_gty_ctl_tx_polarity =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_TX_3_POLARITY);\n+\t\trf->mp_fld_gty_ctl_tx_inhibit =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_CTL_TX_3_INHIBIT);\n+\n+\t\tif (!m_mac8x10_g) {\n+\t\t\tr = get_register(module, MAC_PCS_XXV_LINK_SPEED_3);\n+\t\t\trf->mp_reg_link_speed =\n+\t\t\t\tget_register(module, MAC_PCS_XXV_LINK_SPEED_3);\n+\n+\t\t\trf->mp_fld_link_speed10_g =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SPEED_3_SPEED);\n+\t\t\tif (!rf->mp_fld_link_speed10_g) {\n+\t\t\t\trf->mp_fld_link_speed10_g =\n+\t\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SPEED_3_10G);\n+\t\t\t}\n+\t\t\trf->mp_fld_link_speed_toggle =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_LINK_SPEED_3_TOGGLE);\n+\n+\t\t\tr = get_register(module, MAC_PCS_XXV_RS_FEC_CONF_3);\n+\t\t\trf->mp_reg_rs_fec_conf = r;\n+\t\t\trf->mp_fld_rs_fec_conf_rs_fec_enable =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_RS_FEC_CONF_3_RS_FEC_ENABLE);\n+\n+\t\t\tr = get_register(module, MAC_PCS_XXV_RS_FEC_CCW_CNT_3);\n+\t\t\trf->mp_reg_rs_fec_ccw = r;\n+\t\t\trf->mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_RS_FEC_CCW_CNT_3_RS_FEC_CCW_CNT);\n+\n+\t\t\tr = get_register(module, MAC_PCS_XXV_RS_FEC_UCW_CNT_3);\n+\t\t\trf->mp_reg_rs_fec_ucw = r;\n+\t\t\trf->mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt =\n+\t\t\t\tget_field(r, MAC_PCS_XXV_RS_FEC_UCW_CNT_3_RS_FEC_UCW_CNT);\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Registers MAC_PCS_XXV_DEBOUNCE_CTRL_0 -- MAC_PCS_XXV_DEBOUNCE_CTRL_3\n+\t * and       MAC_PCS_XXV_TIMESTAMP_COMP_0 -- MAC_PCS_XXV_TIMESTAMP_COMP_3\n+\t * and       MAC_PCS_XXV_GTY_PRE_CURSOR_0 -- MAC_PCS_XXV_GTY_PRE_CURSOR_3\n+\t * and       MAC_PCS_XXV_GTY_DIFF_CTL_0 -- MAC_PCS_XXV_GTY_DIFF_CTL_0\n+\t * and       MAC_PCS_XXV_GTY_POST_CURSOR_0 -- MAC_PCS_XXV_GTY_POST_CURSOR_3\n+\t */\n+\tif (n_channels < 4) {\n+\t\t/* Initialize regs/fields for sub-module/channel 0 */\n+\t\trf = &p->regs[0];\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_0);\n+\n+\t\trf->mp_reg_debounce_ctrl = r;\n+\t\trf->mp_field_debounce_ctrl_nt_port_ctrl =\n+\t\t\tget_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_0_NT_PORT_CTRL);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_0);\n+\t\trf->mp_reg_timestamp_comp = r;\n+\t\trf->mp_field_timestamp_comp_rx_dly =\n+\t\t\tget_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_0_RX_DLY);\n+\t\trf->mp_field_timestamp_comp_tx_dly =\n+\t\t\tget_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_0_TX_DLY);\n+\n+\t\t/* GTY_PRE_CURSOR */\n+\t\tr = get_register(p->mp_mod_mac_pcs_xxv,\n+\t\t\t\t MAC_PCS_XXV_GTY_PRE_CURSOR_0);\n+\t\trf->mp_reg_gty_pre_cursor = r;\n+\t\trf->mp_field_gty_pre_cursor_tx_pre_csr =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_0_TX_PRE_CSR);\n+\n+\t\t/* GTY_DIFF_CTL */\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_0);\n+\t\trf->mp_reg_gty_diff_ctl = r;\n+\t\trf->mp_field_gty_gty_diff_ctl_tx_diff_ctl =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_0_TX_DIFF_CTL);\n+\n+\t\t/* GTY_POST_CURSOR */\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_0);\n+\t\trf->mp_reg_gty_post_cursor = r;\n+\t\trf->mp_field_gty_post_cursor_tx_post_csr =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_0_TX_POST_CSR);\n+\t}\n+\n+\tif (n_channels >= 2) {\n+\t\t/* Initialize regs/fields for sub-module/channel 1 */\n+\t\trf = &p->regs[1];\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_1);\n+\n+\t\trf->mp_reg_debounce_ctrl = r;\n+\t\trf->mp_field_debounce_ctrl_nt_port_ctrl =\n+\t\t\tget_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_1_NT_PORT_CTRL);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_1);\n+\t\trf->mp_reg_timestamp_comp = r;\n+\t\trf->mp_field_timestamp_comp_rx_dly =\n+\t\t\tget_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_1_RX_DLY);\n+\t\trf->mp_field_timestamp_comp_tx_dly =\n+\t\t\tget_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_1_TX_DLY);\n+\n+\t\t/* GTY_PRE_CURSOR */\n+\t\tr = get_register(p->mp_mod_mac_pcs_xxv,\n+\t\t\t\tMAC_PCS_XXV_GTY_PRE_CURSOR_1);\n+\t\trf->mp_reg_gty_pre_cursor = r;\n+\t\trf->mp_field_gty_pre_cursor_tx_pre_csr =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_1_TX_PRE_CSR);\n+\n+\t\t/* GTY_DIFF_CTL */\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_1);\n+\t\trf->mp_reg_gty_diff_ctl = r;\n+\t\trf->mp_field_gty_gty_diff_ctl_tx_diff_ctl =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_1_TX_DIFF_CTL);\n+\n+\t\t/* GTY_POST_CURSOR */\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_1);\n+\t\trf->mp_reg_gty_post_cursor = r;\n+\t\trf->mp_field_gty_post_cursor_tx_post_csr =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_1_TX_POST_CSR);\n+\t}\n+\n+\tif (n_channels == 4) {\n+\t\t/* Initialize regs/fields for sub-module/channel 2 */\n+\t\trf = &p->regs[2];\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_2);\n+\n+\t\trf->mp_reg_debounce_ctrl = r;\n+\t\trf->mp_field_debounce_ctrl_nt_port_ctrl =\n+\t\t\tget_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_2_NT_PORT_CTRL);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_2);\n+\t\trf->mp_reg_timestamp_comp = r;\n+\t\trf->mp_field_timestamp_comp_rx_dly =\n+\t\t\tget_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_2_RX_DLY);\n+\t\trf->mp_field_timestamp_comp_tx_dly =\n+\t\t\tget_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_2_TX_DLY);\n+\n+\t\t/* GTY_PRE_CURSOR */\n+\t\tr = get_register(p->mp_mod_mac_pcs_xxv,\n+\t\t\t\tMAC_PCS_XXV_GTY_PRE_CURSOR_2);\n+\t\trf->mp_reg_gty_pre_cursor = r;\n+\t\trf->mp_field_gty_pre_cursor_tx_pre_csr =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_2_TX_PRE_CSR);\n+\n+\t\t/* GTY_DIFF_CTL */\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_2);\n+\t\trf->mp_reg_gty_diff_ctl = r;\n+\t\trf->mp_field_gty_gty_diff_ctl_tx_diff_ctl =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_2_TX_DIFF_CTL);\n+\n+\t\t/* GTY_POST_CURSOR */\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_2);\n+\t\trf->mp_reg_gty_post_cursor = r;\n+\t\trf->mp_field_gty_post_cursor_tx_post_csr =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_2_TX_POST_CSR);\n+\n+\t\t/* Initialize regs/fields for sub-module/channel 3 */\n+\t\trf = &p->regs[3];\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_DEBOUNCE_CTRL_3);\n+\n+\t\trf->mp_reg_debounce_ctrl = r;\n+\t\trf->mp_field_debounce_ctrl_nt_port_ctrl =\n+\t\t\tget_field(r, MAC_PCS_XXV_DEBOUNCE_CTRL_3_NT_PORT_CTRL);\n+\n+\t\tr = get_register(module, MAC_PCS_XXV_TIMESTAMP_COMP_3);\n+\t\trf->mp_reg_timestamp_comp = r;\n+\t\trf->mp_field_timestamp_comp_rx_dly =\n+\t\t\tget_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_3_RX_DLY);\n+\t\trf->mp_field_timestamp_comp_tx_dly =\n+\t\t\tget_field(r, MAC_PCS_XXV_TIMESTAMP_COMP_3_TX_DLY);\n+\n+\t\t/* GTY_PRE_CURSOR */\n+\t\tr = get_register(p->mp_mod_mac_pcs_xxv,\n+\t\t\t\tMAC_PCS_XXV_GTY_PRE_CURSOR_3);\n+\t\trf->mp_reg_gty_pre_cursor = r;\n+\t\trf->mp_field_gty_pre_cursor_tx_pre_csr =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_PRE_CURSOR_3_TX_PRE_CSR);\n+\n+\t\t/* GTY_DIFF_CTL */\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_DIFF_CTL_3);\n+\t\trf->mp_reg_gty_diff_ctl = r;\n+\t\trf->mp_field_gty_gty_diff_ctl_tx_diff_ctl =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_DIFF_CTL_3_TX_DIFF_CTL);\n+\n+\t\t/* GTY_POST_CURSOR */\n+\t\tr = get_register(module, MAC_PCS_XXV_GTY_POST_CURSOR_3);\n+\t\trf->mp_reg_gty_post_cursor = r;\n+\t\trf->mp_field_gty_post_cursor_tx_post_csr =\n+\t\t\tget_field(r, MAC_PCS_XXV_GTY_POST_CURSOR_3_TX_POST_CSR);\n+\t}\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h\nnew file mode 100644\nindex 0000000000..5a38494f7e\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_mac_pcs_xxv.h\n@@ -0,0 +1,291 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef NTHW_MAC_PCS_XXV_H_\n+#define NTHW_MAC_PCS_XXV_H_\n+\n+#include <stdint.h>\n+#include <stdbool.h>\n+#include \"nthw_fpga_model.h\"\n+\n+enum nthw_mac_pcs_xxv_led_mode_e {\n+\tNTHW_MAC_PCS_XXV_LED_AUTO = 0x00,\n+\tNTHW_MAC_PCS_XXV_LED_ON = 0x01,\n+\tNTHW_MAC_PCS_XXV_LED_OFF = 0x02,\n+\tNTHW_MAC_PCS_XXV_LED_PORTID = 0x03,\n+};\n+\n+enum nthw_mac_pcs_xxv_dac_mode_e {\n+\tNTHW_MAC_PCS_XXV_DAC_OFF = 0x00,\n+\tNTHW_MAC_PCS_XXV_DAC_CA_25G_N = 0x01,\n+\tNTHW_MAC_PCS_XXV_DAC_CA_25G_S = 0x02,\n+\tNTHW_MAC_PCS_XXV_DAC_CA_25G_L = 0x03,\n+};\n+\n+struct nthw_mac_pcs_xxv {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_mac_pcs_xxv;\n+\tint mn_instance;\n+\n+\tuint8_t m_port_no;\n+\n+#define NTHW_MAC_PCS_XXV_NUM_ELEMS 4\n+\tstruct nthw_mac_pcs_xxv__registers_fields {\n+\t\t/* CORE_CONF */\n+\t\tnt_register_t *mp_reg_core_conf;\n+\t\tnt_field_t *mp_fld_core_conf_rx_enable;\n+\t\tnt_field_t *mp_fld_core_conf_rx_force_resync;\n+\t\tnt_field_t *mp_fld_core_conf_tx_enable;\n+\t\tnt_field_t *mp_fld_core_conf_tx_ins_fcs;\n+\t\tnt_field_t *mp_fld_core_conf_tx_ign_fcs;\n+\t\tnt_field_t *mp_fld_core_conf_tx_send_lfi;\n+\t\tnt_field_t *mp_fld_core_conf_tx_send_rfi;\n+\t\tnt_field_t *mp_fld_core_conf_tx_send_idle;\n+\t\tnt_field_t *mp_fld_core_conf_inline_mode;\n+\t\tnt_field_t *mp_fld_core_conf_line_loopback;\n+\t\tnt_field_t *mp_fld_core_conf_ts_at_eop;\n+\n+\t\t/* ANEG_CONFIG */\n+\t\tnt_register_t *mp_reg_aneg_config;\n+\t\tnt_field_t *mp_fld_aneg_config_enable;\n+\t\tnt_field_t *mp_fld_aneg_config_bypass;\n+\t\tnt_field_t *mp_fld_aneg_config_restart;\n+\t\tnt_field_t *mp_fld_aneg_config_pseudo;\n+\t\tnt_field_t *mp_fld_aneg_config_nonce_seed;\n+\t\tnt_field_t *mp_fld_aneg_config_remote_fault;\n+\t\tnt_field_t *mp_fld_aneg_config_pause;\n+\t\tnt_field_t *mp_fld_aneg_config_asmdir;\n+\t\tnt_field_t *mp_fld_aneg_config_fec74_request10_g;\n+\t\tnt_field_t *mp_fld_aneg_config_hide_fec74;\n+\t\tnt_field_t *mp_fld_aneg_config_fec74_request;\n+\t\tnt_field_t *mp_fld_aneg_config_fec91_request;\n+\t\tnt_field_t *mp_fld_aneg_config_fec91_ability;\n+\t\tnt_field_t *mp_fld_aneg_config_rs_fec_request;\n+\t\tnt_field_t *mp_fld_aneg_config_sw_fec_overwrite;\n+\t\tnt_field_t *mp_fld_aneg_config_sw_speed_overwrite;\n+\n+\t\t/* ANEG_ABILITY */\n+\t\tnt_register_t *mp_reg_aneg_ability;\n+\t\tnt_field_t *mp_fld_aneg_ability25_g_base_cr;\n+\t\tnt_field_t *mp_fld_aneg_ability25_g_base_crs;\n+\t\tnt_field_t *mp_fld_aneg_ability25_g_base_cr1;\n+\n+\t\t/* LT_CONF */\n+\t\tnt_register_t *mp_reg_lt_conf;\n+\t\tnt_field_t *mp_fld_lt_conf_enable;\n+\t\tnt_field_t *mp_fld_lt_conf_restart;\n+\t\tnt_field_t *mp_fld_lt_conf_seed;\n+\n+\t\t/* SUB_RST */\n+\t\tnt_register_t *mp_reg_sub_rst;\n+\t\tnt_field_t *mp_fld_sub_rst_rx_mac_pcs;\n+\t\tnt_field_t *mp_fld_sub_rst_tx_mac_pcs;\n+\t\tnt_field_t *mp_fld_sub_rst_rx_gt_data;\n+\t\tnt_field_t *mp_fld_sub_rst_tx_gt_data;\n+\t\tnt_field_t *mp_fld_sub_rst_rx_buf;\n+\t\tnt_field_t *mp_fld_sub_rst_rx_pma;\n+\t\tnt_field_t *mp_fld_sub_rst_tx_pma;\n+\t\tnt_field_t *mp_fld_sub_rst_rx_pcs;\n+\t\tnt_field_t *mp_fld_sub_rst_tx_pcs;\n+\t\tnt_field_t *mp_fld_sub_rst_an_lt;\n+\t\tnt_field_t *mp_fld_sub_rst_speed_ctrl;\n+\n+\t\t/* SUB_RST_STATUS */\n+\t\tnt_register_t *mp_reg_sub_rst_status;\n+\t\tnt_field_t *mp_fld_sub_rst_status_user_rx_rst;\n+\t\tnt_field_t *mp_fld_sub_rst_status_user_tx_rst;\n+\t\tnt_field_t *mp_fld_sub_rst_status_qpll_lock;\n+\n+\t\t/* LINK_SUMMARY */\n+\t\tnt_register_t *mp_reg_link_summary;\n+\t\tnt_field_t *mp_fld_link_summary_nt_phy_link_state;\n+\t\tnt_field_t *mp_fld_link_summary_ll_nt_phy_link_state;\n+\t\tnt_field_t *mp_fld_link_summary_abs;\n+\t\tnt_field_t *mp_fld_link_summary_lh_abs;\n+\t\tnt_field_t *mp_fld_link_summary_link_down_cnt;\n+\t\t/* Begin 2 x 10/25 Gbps only fields: */\n+\t\tnt_field_t *mp_fld_link_summary_ll_rx_fec74_lock;\n+\t\tnt_field_t *mp_fld_link_summary_lh_rx_rsfec_hi_ser;\n+\t\tnt_field_t *mp_fld_link_summary_ll_rx_rsfec_lane_alignment;\n+\t\tnt_field_t *mp_fld_link_summary_ll_tx_rsfec_lane_alignment;\n+\t\tnt_field_t *mp_fld_link_summary_lh_rx_pcs_valid_ctrl_code;\n+\t\t/* End 2 x 10/25 Gbps only fields. */\n+\t\tnt_field_t *mp_fld_link_summary_ll_rx_block_lock;\n+\t\tnt_field_t *mp_fld_link_summary_lh_rx_high_bit_error_rate;\n+\t\tnt_field_t *mp_fld_link_summary_lh_internal_local_fault;\n+\t\tnt_field_t *mp_fld_link_summary_lh_received_local_fault;\n+\t\tnt_field_t *mp_fld_link_summary_lh_local_fault;\n+\t\tnt_field_t *mp_fld_link_summary_lh_remote_fault;\n+\t\tnt_field_t *mp_fld_link_summary_lh_tx_local_fault;\n+\t\tnt_field_t *mp_fld_link_summary_nim_interr;\n+\n+\t\t/* GTY_LOOP */\n+\t\tnt_register_t *mp_reg_gty_loop;\n+\t\tnt_field_t *mp_fld_gty_loop_gt_loop;\n+\n+\t\t/* GTY_CTL_RX */\n+\t\tnt_register_t *mp_reg_gty_ctl_rx;\n+\t\tnt_field_t *mp_fld_gty_ctl_rx_polarity;\n+\t\tnt_field_t *mp_fld_gty_ctl_rx_lpm_en;\n+\t\tnt_field_t *mp_fld_gty_ctl_rx_equa_rst;\n+\n+\t\t/* GTY_CTL_TX */\n+\t\tnt_register_t *mp_reg_gty_ctl_tx;\n+\t\tnt_field_t *mp_fld_gty_ctl_tx_polarity;\n+\t\tnt_field_t *mp_fld_gty_ctl_tx_inhibit;\n+\n+\t\t/* LINK_SPEED */\n+\t\tnt_register_t *mp_reg_link_speed;\n+\t\tnt_field_t *mp_fld_link_speed10_g;\n+\t\tnt_field_t *mp_fld_link_speed_toggle;\n+\n+\t\t/* RS_FEC_CONF */\n+\t\tnt_register_t *mp_reg_rs_fec_conf;\n+\t\tnt_field_t *mp_fld_rs_fec_conf_rs_fec_enable;\n+\n+\t\t/* DEBOUNCE_CTRL */\n+\t\tnt_register_t *mp_reg_debounce_ctrl;\n+\t\tnt_field_t *mp_field_debounce_ctrl_nt_port_ctrl;\n+\n+\t\t/* FEC_CCW_CNT */\n+\t\tnt_register_t *mp_reg_rs_fec_ccw;\n+\t\tnt_field_t *mp_field_reg_rs_fec_ccw_reg_rs_fec_ccw_cnt;\n+\n+\t\t/* FEC_UCW_CNT */\n+\t\tnt_register_t *mp_reg_rs_fec_ucw;\n+\t\tnt_field_t *mp_field_reg_rs_fec_ucw_reg_rs_fec_ucw_cnt;\n+\n+\t\t/* TIMESTAMP_COMP */\n+\t\tnt_register_t *mp_reg_timestamp_comp;\n+\t\tnt_field_t *mp_field_timestamp_comp_rx_dly;\n+\t\tnt_field_t *mp_field_timestamp_comp_tx_dly;\n+\n+\t\t/* GTY_PRE_CURSOR */\n+\t\tnt_register_t *mp_reg_gty_pre_cursor;\n+\t\tnt_field_t *mp_field_gty_pre_cursor_tx_pre_csr;\n+\n+\t\t/* GTY_DIFF_CTL */\n+\t\tnt_register_t *mp_reg_gty_diff_ctl;\n+\t\tnt_field_t *mp_field_gty_gty_diff_ctl_tx_diff_ctl;\n+\n+\t\t/* GTY_POST_CURSOR */\n+\t\tnt_register_t *mp_reg_gty_post_cursor;\n+\t\tnt_field_t *mp_field_gty_post_cursor_tx_post_csr;\n+\t} regs[NTHW_MAC_PCS_XXV_NUM_ELEMS];\n+};\n+\n+typedef struct nthw_mac_pcs_xxv nthw_mac_pcs_xxv_t;\n+typedef struct nthw_mac_pcs_xxv nthw_mac_pcs_xxv;\n+\n+nthw_mac_pcs_xxv_t *nthw_mac_pcs_xxv_new(void);\n+void nthw_mac_pcs_xxv_delete(nthw_mac_pcs_xxv_t *p);\n+int nthw_mac_pcs_xxv_init(nthw_mac_pcs_xxv_t *p, nt_fpga_t *p_fpga, int n_instance,\n+\t\t       int n_channels);\n+\n+void nthw_mac_pcs_xxv_get_link_summary(nthw_mac_pcs_xxv_t *p,\n+\tuint32_t *p_abs, uint32_t *p_nt_phy_link_state,\n+\tuint32_t *p_lh_abs, uint32_t *p_ll_nt_phy_link_state, uint32_t *p_link_down_cnt,\n+\tuint32_t *p_nim_interr, uint32_t *p_lh_local_fault, uint32_t *p_lh_remote_fault,\n+\tuint32_t *p_lh_internal_local_fault, uint32_t *p_lh_received_local_fault,\n+\tuint8_t index);\n+\n+uint8_t nthw_mac_pcs_xxv_get_port_no(const nthw_mac_pcs_xxv_t *p, uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_port_no(nthw_mac_pcs_xxv_t *p, uint8_t port_no);\n+\n+void nthw_mac_pcs_xxv_set_tx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);\n+void nthw_mac_pcs_xxv_set_rx_enable(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);\n+void nthw_mac_pcs_xxv_rx_force_resync(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t uint8_t index);\n+\n+void nthw_mac_pcs_xxv_reset_rx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t uint8_t index);\n+void nthw_mac_pcs_xxv_reset_tx_gt_data(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t uint8_t index);\n+\n+void nthw_mac_pcs_xxv_reset_an_lt(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);\n+void nthw_mac_pcs_xxv_reset_speed_ctrl(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t  uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);\n+void nthw_mac_pcs_xxv_set_tx_send_lfi(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);\n+void nthw_mac_pcs_xxv_set_tx_send_lfi_tx_send_rfi(nthw_mac_pcs_xxv_t *p, bool enable_lfi,\n+\t\tbool enable_rfi, uint8_t index);\n+\n+bool nthw_mac_pcs_xxv_is_dfe_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index);\n+void nthw_mac_pcs_xxv_set_dfe(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_rx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t    uint8_t index);\n+void nthw_mac_pcs_xxv_set_tx_gty_polarity(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t    uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_tx_gty_inhibit(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t   uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_host_loopback(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t   uint8_t index);\n+void nthw_mac_pcs_xxv_set_line_loopback(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t   uint8_t index);\n+\n+bool nthw_mac_pcs_xxv_is_user_rx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index);\n+bool nthw_mac_pcs_xxv_is_user_tx_rst(nthw_mac_pcs_xxv_t *p, uint8_t index);\n+\n+bool nthw_mac_pcs_xxv_is_qpll_lock(nthw_mac_pcs_xxv_t *p, uint8_t index);\n+bool nthw_mac_pcs_xxv_is_sub_rst_ready(nthw_mac_pcs_xxv_t *p, uint8_t index);\n+bool nthw_mac_pcs_xxv_is_aneg_enabled(nthw_mac_pcs_xxv_t *p, uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_tx_send_idle(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t uint8_t index);\n+void nthw_mac_pcs_xxv_set_tx_ins_fcs(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);\n+\n+bool nthw_mac_pcs_xxv_get_link_speed10_g(nthw_mac_pcs_xxv_t *p, uint8_t index);\n+void nthw_mac_pcs_xxv_set_link_speed10_g(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t   uint8_t index);\n+void nthw_mac_pcs_xxv_set_link_speed_toggle(nthw_mac_pcs_xxv_t *p, uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_rs_fec_conf_rs_fec_enable(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\tuint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_led_mode(nthw_mac_pcs_xxv_t *p, uint8_t mode, uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_rx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t  uint8_t index);\n+void nthw_mac_pcs_xxv_set_tx_mac_pcs_rst(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t  uint8_t index);\n+\n+void nthw_mac_pcs_xxv_reset_fec_counters(nthw_mac_pcs_xxv_t *p, uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_gty_diff(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index);\n+void nthw_mac_pcs_xxv_set_gty_pre(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index);\n+void nthw_mac_pcs_xxv_set_gty_post(nthw_mac_pcs_xxv_t *p, uint8_t value, uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_ts_at_eop(nthw_mac_pcs_xxv_t *p, bool enable, uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_aneg_config_enable(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t       uint8_t index);\n+void nthw_mac_pcs_xxv_set_aneg_config_bypass(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t       uint8_t index);\n+void nthw_mac_pcs_xxv_set_lt_conf_enable(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\t\t\t   uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_dac_mode(nthw_mac_pcs_xxv_t *p, uint8_t dac_mode,\n+\t\t\t      uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_timestamp_comp_rx(nthw_mac_pcs_xxv_t *p, uint16_t rx_dly,\n+\t\t\t\t      uint8_t index);\n+void nthw_mac_pcs_xxv_set_timestamp_comp_tx(nthw_mac_pcs_xxv_t *p, uint16_t tx_dly,\n+\t\t\t\t      uint8_t index);\n+\n+void nthw_mac_pcs_xxv_set_aneg_config_fec91_request(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\tuint8_t index);\n+void nthw_mac_pcs_xxv_set_aneg_config_rs_fec_request(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\tuint8_t index);\n+void nthw_mac_pcs_xxv_set_aneg_config_fec74_request(nthw_mac_pcs_xxv_t *p, bool enable,\n+\t\tuint8_t index);\n+\n+bool nthw_mac_pcs_xxv_get_ll_rx_fec74_lock(nthw_mac_pcs_xxv_t *p, uint8_t index);\n+bool nthw_mac_pcs_xxv_get_ll_rx_rsfec_lane_alignment(nthw_mac_pcs_xxv_t *p, uint8_t index);\n+\n+#endif /* NTHW_MAC_PCS_XXV_H_ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c\nnew file mode 100644\nindex 0000000000..92089d2fa3\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.c\n@@ -0,0 +1,121 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_pci_rd_tg.h\"\n+\n+nthw_pci_rd_tg_t *nthw_pci_rd_tg_new(void)\n+{\n+\tnthw_pci_rd_tg_t *p = malloc(sizeof(nthw_pci_rd_tg_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_pci_rd_tg_t));\n+\treturn p;\n+}\n+\n+void nthw_pci_rd_tg_delete(nthw_pci_rd_tg_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_pci_rd_tg_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+int nthw_pci_rd_tg_init(nthw_pci_rd_tg_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_PCI_RD_TG, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: PCI_RD_TG %d: no such instance\\n\",\n+\t\t       p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_pci_rd_tg = mod;\n+\n+\tp->mn_param_pci_ta_tg_present =\n+\t\tfpga_get_product_param(p_fpga, NT_PCI_TA_TG_PRESENT, 1);\n+\n+\tp->mp_reg_pci_rd_tg_rd_data0 =\n+\t\tmodule_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDDATA0);\n+\tp->mp_fld_pci_rd_tg_phys_addr_low =\n+\t\tregister_get_field(p->mp_reg_pci_rd_tg_rd_data0,\n+\t\t\t\t   PCI_RD_TG_TG_RDDATA0_PHYS_ADDR_LOW);\n+\n+\tp->mp_reg_pci_rd_tg_rd_data1 =\n+\t\tmodule_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDDATA1);\n+\tp->mp_fld_pci_rd_tg_phys_addr_high =\n+\t\tregister_get_field(p->mp_reg_pci_rd_tg_rd_data1,\n+\t\t\t\t   PCI_RD_TG_TG_RDDATA1_PHYS_ADDR_HIGH);\n+\n+\tp->mp_reg_pci_rd_tg_rd_data2 =\n+\t\tmodule_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDDATA2);\n+\tp->mp_fld_pci_rd_tg_req_size =\n+\t\tregister_get_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_REQ_SIZE);\n+\tp->mp_fld_pci_rd_tg_wait =\n+\t\tregister_get_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_WAIT);\n+\tp->mp_fld_pci_rd_tg_wrap =\n+\t\tregister_get_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_WRAP);\n+\t/* optional VF host id */\n+\tp->mp_fld_pci_rd_tg_req_hid =\n+\t\tregister_query_field(p->mp_reg_pci_rd_tg_rd_data2, PCI_RD_TG_TG_RDDATA2_REQ_HID);\n+\n+\tp->mp_reg_pci_rd_tg_rd_addr =\n+\t\tmodule_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RDADDR);\n+\tp->mp_fld_pci_rd_tg_ram_addr =\n+\t\tregister_get_field(p->mp_reg_pci_rd_tg_rd_addr, PCI_RD_TG_TG_RDADDR_RAM_ADDR);\n+\n+\tp->mp_reg_pci_rd_tg_rd_run =\n+\t\tmodule_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_RD_RUN);\n+\tp->mp_fld_pci_rd_tg_run_iteration =\n+\t\tregister_get_field(p->mp_reg_pci_rd_tg_rd_run, PCI_RD_TG_TG_RD_RUN_RD_ITERATION);\n+\n+\tp->mp_reg_pci_rd_tg_rd_ctrl =\n+\t\tmodule_get_register(p->mp_mod_pci_rd_tg, PCI_RD_TG_TG_CTRL);\n+\tp->mp_fld_pci_rd_tg_ctrl_rdy =\n+\t\tregister_get_field(p->mp_reg_pci_rd_tg_rd_ctrl, PCI_RD_TG_TG_CTRL_TG_RD_RDY);\n+\n+\treturn 0;\n+}\n+\n+void nthw_pci_rd_tg_set_phys_addr(nthw_pci_rd_tg_t *p, uint64_t n_phys_addr)\n+{\n+\tfield_set_val_flush32(p->mp_fld_pci_rd_tg_phys_addr_low,\n+\t\t\t    (uint32_t)(n_phys_addr & ((1UL << 32) - 1)));\n+\tfield_set_val_flush32(p->mp_fld_pci_rd_tg_phys_addr_high,\n+\t\t\t    (uint32_t)((n_phys_addr >> 32) & ((1UL << 32) - 1)));\n+}\n+\n+void nthw_pci_rd_tg_set_ram_addr(nthw_pci_rd_tg_t *p, int n_ram_addr)\n+{\n+\tfield_set_val_flush32(p->mp_fld_pci_rd_tg_ram_addr, n_ram_addr);\n+}\n+\n+void nthw_pci_rd_tg_set_ram_data(nthw_pci_rd_tg_t *p, uint32_t req_size, bool wait,\n+\t\t\t    bool wrap)\n+{\n+\tfield_set_val32(p->mp_fld_pci_rd_tg_req_size, req_size);\n+\tfield_set_val32(p->mp_fld_pci_rd_tg_wait, wait);\n+\tfield_set_val32(p->mp_fld_pci_rd_tg_wrap, wrap);\n+\tfield_flush_register(p->mp_fld_pci_rd_tg_wrap);\n+}\n+\n+void nthw_pci_rd_tg_set_run(nthw_pci_rd_tg_t *p, int n_iterations)\n+{\n+\tfield_set_val_flush32(p->mp_fld_pci_rd_tg_run_iteration, n_iterations);\n+}\n+\n+uint32_t nthw_pci_rd_tg_get_ctrl_rdy(nthw_pci_rd_tg_t *p)\n+{\n+\treturn field_get_updated(p->mp_fld_pci_rd_tg_ctrl_rdy);\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h\nnew file mode 100644\nindex 0000000000..b1c912f0f3\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_pci_rd_tg.h\n@@ -0,0 +1,51 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_PCI_RD_TG_H__\n+#define __NTHW_PCI_RD_TG_H__\n+\n+struct nthw_pci_rd_tg {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_pci_rd_tg;\n+\tint mn_instance;\n+\n+\tint mn_param_pci_ta_tg_present;\n+\n+\tnt_register_t *mp_reg_pci_rd_tg_rd_data0;\n+\tnt_field_t *mp_fld_pci_rd_tg_phys_addr_low;\n+\n+\tnt_register_t *mp_reg_pci_rd_tg_rd_data1;\n+\tnt_field_t *mp_fld_pci_rd_tg_phys_addr_high;\n+\n+\tnt_register_t *mp_reg_pci_rd_tg_rd_data2;\n+\tnt_field_t *mp_fld_pci_rd_tg_req_size;\n+\tnt_field_t *mp_fld_pci_rd_tg_req_hid;\n+\tnt_field_t *mp_fld_pci_rd_tg_wait;\n+\tnt_field_t *mp_fld_pci_rd_tg_wrap;\n+\n+\tnt_register_t *mp_reg_pci_rd_tg_rd_addr;\n+\tnt_field_t *mp_fld_pci_rd_tg_ram_addr;\n+\n+\tnt_register_t *mp_reg_pci_rd_tg_rd_run;\n+\tnt_field_t *mp_fld_pci_rd_tg_run_iteration;\n+\n+\tnt_register_t *mp_reg_pci_rd_tg_rd_ctrl;\n+\tnt_field_t *mp_fld_pci_rd_tg_ctrl_rdy;\n+};\n+\n+typedef struct nthw_pci_rd_tg nthw_pci_rd_tg_t;\n+typedef struct nthw_pci_rd_tg nthw_pci_rd_tg;\n+\n+nthw_pci_rd_tg_t *nthw_pci_rd_tg_new(void);\n+void nthw_pci_rd_tg_delete(nthw_pci_rd_tg_t *p);\n+int nthw_pci_rd_tg_init(nthw_pci_rd_tg_t *p, nt_fpga_t *p_fpga, int n_instance);\n+\n+void nthw_pci_rd_tg_set_phys_addr(nthw_pci_rd_tg_t *p, uint64_t n_phys_addr);\n+void nthw_pci_rd_tg_set_ram_addr(nthw_pci_rd_tg_t *p, int n_ram_addr);\n+void nthw_pci_rd_tg_set_ram_data(nthw_pci_rd_tg_t *p, uint32_t req_size, bool wait,\n+\t\t\t    bool wrap);\n+void nthw_pci_rd_tg_set_run(nthw_pci_rd_tg_t *p, int n_iterations);\n+uint32_t nthw_pci_rd_tg_get_ctrl_rdy(nthw_pci_rd_tg_t *p);\n+\n+#endif /* __NTHW_PCI_RD_TG_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_pci_ta.c b/drivers/net/ntnic/nthw/core/nthw_pci_ta.c\nnew file mode 100644\nindex 0000000000..17e30a670d\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_pci_ta.c\n@@ -0,0 +1,99 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_pci_ta.h\"\n+\n+nthw_pci_ta_t *nthw_pci_ta_new(void)\n+{\n+\tnthw_pci_ta_t *p = malloc(sizeof(nthw_pci_ta_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_pci_ta_t));\n+\treturn p;\n+}\n+\n+void nthw_pci_ta_delete(nthw_pci_ta_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_pci_ta_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+int nthw_pci_ta_init(nthw_pci_ta_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_PCI_TA, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: PCI_TA %d: no such instance\\n\",\n+\t\t       p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_pci_ta = mod;\n+\n+\tp->mn_param_pci_ta_tg_present =\n+\t\tfpga_get_product_param(p_fpga, NT_PCI_TA_TG_PRESENT, 1);\n+\n+\tp->mp_reg_pci_ta_ctrl = module_get_register(p->mp_mod_pci_ta, PCI_TA_CONTROL);\n+\tp->mp_fld_pci_ta_ctrl_enable =\n+\t\tregister_get_field(p->mp_reg_pci_ta_ctrl, PCI_TA_CONTROL_ENABLE);\n+\n+\tp->mp_reg_pci_ta_packet_good =\n+\t\tmodule_get_register(p->mp_mod_pci_ta, PCI_TA_PACKET_GOOD);\n+\tp->mp_fld_pci_ta_packet_good_amount =\n+\t\tregister_get_field(p->mp_reg_pci_ta_packet_good, PCI_TA_PACKET_GOOD_AMOUNT);\n+\n+\tp->mp_reg_pci_ta_packet_bad =\n+\t\tmodule_get_register(p->mp_mod_pci_ta, PCI_TA_PACKET_BAD);\n+\tp->mp_fld_pci_ta_packet_bad_amount =\n+\t\tregister_get_field(p->mp_reg_pci_ta_packet_bad, PCI_TA_PACKET_BAD_AMOUNT);\n+\n+\tp->mp_reg_pci_ta_length_error =\n+\t\tmodule_get_register(p->mp_mod_pci_ta, PCI_TA_LENGTH_ERROR);\n+\tp->mp_fld_pci_ta_length_error_amount =\n+\t\tregister_get_field(p->mp_reg_pci_ta_length_error, PCI_TA_LENGTH_ERROR_AMOUNT);\n+\n+\tp->mp_reg_pci_ta_payload_error =\n+\t\tmodule_get_register(p->mp_mod_pci_ta, PCI_TA_PAYLOAD_ERROR);\n+\tp->mp_fld_pci_ta_payload_error_amount =\n+\t\tregister_get_field(p->mp_reg_pci_ta_payload_error, PCI_TA_PAYLOAD_ERROR_AMOUNT);\n+\n+\treturn 0;\n+}\n+\n+void nthw_pci_ta_set_control_enable(nthw_pci_ta_t *p, uint32_t val)\n+{\n+\tfield_set_val_flush32(p->mp_fld_pci_ta_ctrl_enable, val);\n+}\n+\n+void nthw_pci_ta_get_packet_good(nthw_pci_ta_t *p, uint32_t *val)\n+{\n+\t*val = field_get_updated(p->mp_fld_pci_ta_packet_good_amount);\n+}\n+\n+void nthw_pci_ta_get_packet_bad(nthw_pci_ta_t *p, uint32_t *val)\n+{\n+\t*val = field_get_updated(p->mp_fld_pci_ta_packet_bad_amount);\n+}\n+\n+void nthw_pci_ta_get_length_error(nthw_pci_ta_t *p, uint32_t *val)\n+{\n+\t*val = field_get_updated(p->mp_fld_pci_ta_length_error_amount);\n+}\n+\n+void nthw_pci_ta_get_payload_error(nthw_pci_ta_t *p, uint32_t *val)\n+{\n+\t*val = field_get_updated(p->mp_fld_pci_ta_payload_error_amount);\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_pci_ta.h b/drivers/net/ntnic/nthw/core/nthw_pci_ta.h\nnew file mode 100644\nindex 0000000000..7968cad9fa\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_pci_ta.h\n@@ -0,0 +1,40 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_PCI_TA_H__\n+#define __NTHW_PCI_TA_H__\n+\n+struct nthw_pci_ta {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_pci_ta;\n+\tint mn_instance;\n+\n+\tint mn_param_pci_ta_tg_present;\n+\n+\tnt_register_t *mp_reg_pci_ta_ctrl;\n+\tnt_field_t *mp_fld_pci_ta_ctrl_enable;\n+\tnt_register_t *mp_reg_pci_ta_packet_good;\n+\tnt_field_t *mp_fld_pci_ta_packet_good_amount;\n+\tnt_register_t *mp_reg_pci_ta_packet_bad;\n+\tnt_field_t *mp_fld_pci_ta_packet_bad_amount;\n+\tnt_register_t *mp_reg_pci_ta_length_error;\n+\tnt_field_t *mp_fld_pci_ta_length_error_amount;\n+\tnt_register_t *mp_reg_pci_ta_payload_error;\n+\tnt_field_t *mp_fld_pci_ta_payload_error_amount;\n+};\n+\n+typedef struct nthw_pci_ta nthw_pci_ta_t;\n+typedef struct nthw_pci_ta nthw_pci_ta;\n+\n+nthw_pci_ta_t *nthw_pci_ta_new(void);\n+void nthw_pci_ta_delete(nthw_pci_ta_t *p);\n+int nthw_pci_ta_init(nthw_pci_ta_t *p, nt_fpga_t *p_fpga, int n_instance);\n+\n+void nthw_pci_ta_set_control_enable(nthw_pci_ta_t *p, uint32_t val);\n+void nthw_pci_ta_get_packet_good(nthw_pci_ta_t *p, uint32_t *val);\n+void nthw_pci_ta_get_packet_bad(nthw_pci_ta_t *p, uint32_t *val);\n+void nthw_pci_ta_get_length_error(nthw_pci_ta_t *p, uint32_t *val);\n+void nthw_pci_ta_get_payload_error(nthw_pci_ta_t *p, uint32_t *val);\n+\n+#endif /* __NTHW_PCI_TA_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c\nnew file mode 100644\nindex 0000000000..f830a586b2\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.c\n@@ -0,0 +1,127 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_pci_wr_tg.h\"\n+\n+nthw_pci_wr_tg_t *nthw_pci_wr_tg_new(void)\n+{\n+\tnthw_pci_wr_tg_t *p = malloc(sizeof(nthw_pci_wr_tg_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_pci_wr_tg_t));\n+\treturn p;\n+}\n+\n+void nthw_pci_wr_tg_delete(nthw_pci_wr_tg_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_pci_wr_tg_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+int nthw_pci_wr_tg_init(nthw_pci_wr_tg_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_PCI_WR_TG, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: PCI_WR_TG %d: no such instance\\n\",\n+\t\t       p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_pci_wr_tg = mod;\n+\n+\tp->mn_param_pci_ta_tg_present =\n+\t\tfpga_get_product_param(p_fpga, NT_PCI_TA_TG_PRESENT, 1);\n+\n+\tp->mp_reg_pci_wr_tg_data0 =\n+\t\tmodule_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRDATA0);\n+\tp->mp_fld_pci_wr_tg_phys_addr_low =\n+\t\tregister_get_field(p->mp_reg_pci_wr_tg_data0, PCI_WR_TG_TG_WRDATA0_PHYS_ADDR_LOW);\n+\n+\tp->mp_reg_pci_wr_tg_data1 =\n+\t\tmodule_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRDATA1);\n+\tp->mp_fld_pci_wr_tg_phys_addr_high =\n+\t\tregister_get_field(p->mp_reg_pci_wr_tg_data1, PCI_WR_TG_TG_WRDATA1_PHYS_ADDR_HIGH);\n+\n+\tp->mp_reg_pci_wr_tg_data2 =\n+\t\tmodule_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRDATA2);\n+\tp->mp_fld_pci_wr_tg_req_size =\n+\t\tregister_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_REQ_SIZE);\n+\tp->mp_fld_pci_wr_tg_inc_mode =\n+\t\tregister_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_INC_MODE);\n+\tp->mp_fld_pci_wr_tg_wait =\n+\t\tregister_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_WAIT);\n+\tp->mp_fld_pci_wr_tg_wrap =\n+\t\tregister_get_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_WRAP);\n+\t/* optional VF host id */\n+\tp->mp_fld_pci_wr_tg_req_hid =\n+\t\tregister_query_field(p->mp_reg_pci_wr_tg_data2, PCI_WR_TG_TG_WRDATA2_REQ_HID);\n+\n+\tp->mp_reg_pci_wr_tg_addr =\n+\t\tmodule_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WRADDR);\n+\tp->mp_fld_pci_wr_tg_ram_addr =\n+\t\tregister_get_field(p->mp_reg_pci_wr_tg_addr, PCI_WR_TG_TG_WRADDR_RAM_ADDR);\n+\n+\tp->mp_reg_pci_wr_tg_run =\n+\t\tmodule_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_WR_RUN);\n+\tp->mp_fld_pci_wr_tg_run_iteration =\n+\t\tregister_get_field(p->mp_reg_pci_wr_tg_run, PCI_WR_TG_TG_WR_RUN_WR_ITERATION);\n+\n+\tp->mp_reg_pci_wr_tg_ctrl =\n+\t\tmodule_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_CTRL);\n+\tp->mp_fld_pci_wr_tg_ctrl_rdy =\n+\t\tregister_get_field(p->mp_reg_pci_wr_tg_ctrl, PCI_WR_TG_TG_CTRL_TG_WR_RDY);\n+\n+\tp->mp_reg_pci_wr_tg_seq =\n+\t\tmodule_get_register(p->mp_mod_pci_wr_tg, PCI_WR_TG_TG_SEQ);\n+\tp->mp_fld_pci_wr_tg_seq_sequence =\n+\t\tregister_get_field(p->mp_reg_pci_wr_tg_seq, PCI_WR_TG_TG_SEQ_SEQUENCE);\n+\n+\treturn 0;\n+}\n+\n+void nthw_pci_wr_tg_set_phys_addr(nthw_pci_wr_tg_t *p, uint64_t n_phys_addr)\n+{\n+\tfield_set_val_flush32(p->mp_fld_pci_wr_tg_phys_addr_low,\n+\t\t\t    (uint32_t)(n_phys_addr & ((1UL << 32) - 1)));\n+\tfield_set_val_flush32(p->mp_fld_pci_wr_tg_phys_addr_high,\n+\t\t\t    (uint32_t)((n_phys_addr >> 32) & ((1UL << 32) - 1)));\n+}\n+\n+void nthw_pci_wr_tg_set_ram_addr(nthw_pci_wr_tg_t *p, int n_ram_addr)\n+{\n+\tfield_set_val_flush32(p->mp_fld_pci_wr_tg_ram_addr, n_ram_addr);\n+}\n+\n+void nthw_pci_wr_tg_set_ram_data(nthw_pci_wr_tg_t *p, uint32_t req_size, bool wait,\n+\t\t\t    bool wrap, bool inc)\n+{\n+\tfield_set_val32(p->mp_fld_pci_wr_tg_req_size, req_size);\n+\tfield_set_val32(p->mp_fld_pci_wr_tg_wait, wait);\n+\tfield_set_val32(p->mp_fld_pci_wr_tg_wrap, wrap);\n+\tfield_set_val32(p->mp_fld_pci_wr_tg_inc_mode, inc);\n+\tfield_flush_register(p->mp_fld_pci_wr_tg_inc_mode);\n+}\n+\n+void nthw_pci_wr_tg_set_run(nthw_pci_wr_tg_t *p, int n_iterations)\n+{\n+\tfield_set_val_flush32(p->mp_fld_pci_wr_tg_run_iteration, n_iterations);\n+}\n+\n+uint32_t nthw_pci_wr_tg_get_ctrl_rdy(nthw_pci_wr_tg_t *p)\n+{\n+\treturn field_get_updated(p->mp_fld_pci_wr_tg_ctrl_rdy);\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h\nnew file mode 100644\nindex 0000000000..535b39526e\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_pci_wr_tg.h\n@@ -0,0 +1,55 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_PCI_WR_TG_H__\n+#define __NTHW_PCI_WR_TG_H__\n+\n+struct nthw_pci_wr_tg {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_pci_wr_tg;\n+\tint mn_instance;\n+\n+\tint mn_param_pci_ta_tg_present;\n+\n+\tnt_register_t *mp_reg_pci_wr_tg_data0;\n+\tnt_field_t *mp_fld_pci_wr_tg_phys_addr_low;\n+\n+\tnt_register_t *mp_reg_pci_wr_tg_data1;\n+\tnt_field_t *mp_fld_pci_wr_tg_phys_addr_high;\n+\n+\tnt_register_t *mp_reg_pci_wr_tg_data2;\n+\tnt_field_t *mp_fld_pci_wr_tg_req_size;\n+\tnt_field_t *mp_fld_pci_wr_tg_req_hid;\n+\tnt_field_t *mp_fld_pci_wr_tg_inc_mode;\n+\tnt_field_t *mp_fld_pci_wr_tg_wait;\n+\tnt_field_t *mp_fld_pci_wr_tg_wrap;\n+\n+\tnt_register_t *mp_reg_pci_wr_tg_addr;\n+\tnt_field_t *mp_fld_pci_wr_tg_ram_addr;\n+\n+\tnt_register_t *mp_reg_pci_wr_tg_run;\n+\tnt_field_t *mp_fld_pci_wr_tg_run_iteration;\n+\n+\tnt_register_t *mp_reg_pci_wr_tg_ctrl;\n+\tnt_field_t *mp_fld_pci_wr_tg_ctrl_rdy;\n+\n+\tnt_register_t *mp_reg_pci_wr_tg_seq;\n+\tnt_field_t *mp_fld_pci_wr_tg_seq_sequence;\n+};\n+\n+typedef struct nthw_pci_wr_tg nthw_pci_wr_tg_t;\n+typedef struct nthw_pci_wr_tg nthw_pci_wr_tg;\n+\n+nthw_pci_wr_tg_t *nthw_pci_wr_tg_new(void);\n+void nthw_pci_wr_tg_delete(nthw_pci_wr_tg_t *p);\n+int nthw_pci_wr_tg_init(nthw_pci_wr_tg_t *p, nt_fpga_t *p_fpga, int n_instance);\n+\n+void nthw_pci_wr_tg_set_phys_addr(nthw_pci_wr_tg_t *p, uint64_t n_phys_addr);\n+void nthw_pci_wr_tg_set_ram_addr(nthw_pci_wr_tg_t *p, int n_ram_addr);\n+void nthw_pci_wr_tg_set_ram_data(nthw_pci_wr_tg_t *p, uint32_t req_size, bool wait,\n+\t\t\t    bool wrap, bool inc);\n+void nthw_pci_wr_tg_set_run(nthw_pci_wr_tg_t *p, int n_iterations);\n+uint32_t nthw_pci_wr_tg_get_ctrl_rdy(nthw_pci_wr_tg_t *p);\n+\n+#endif /* __NTHW_PCI_WR_TG_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_pcie3.c b/drivers/net/ntnic/nthw/core/nthw_pcie3.c\nnew file mode 100644\nindex 0000000000..07ad784695\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_pcie3.c\n@@ -0,0 +1,274 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_pcie3.h\"\n+\n+#define NTHW_TG_REF_FREQ (250000000ULL)\n+\n+nthw_pcie3_t *nthw_pcie3_new(void)\n+{\n+\tnthw_pcie3_t *p = malloc(sizeof(nthw_pcie3_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_pcie3_t));\n+\treturn p;\n+}\n+\n+void nthw_pcie3_delete(nthw_pcie3_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_pcie3_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+int nthw_pcie3_init(nthw_pcie3_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_PCIE3, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn (mod == NULL ? -1 : 0);\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: PCIE3 %d: no such instance\\n\",\n+\t\t       p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_pcie3 = mod;\n+\n+\t/* PCIe3 */\n+\tp->mp_reg_stat_ctrl = module_get_register(p->mp_mod_pcie3, PCIE3_STAT_CTRL);\n+\tp->mp_fld_stat_ctrl_ena =\n+\t\tregister_get_field(p->mp_reg_stat_ctrl, PCIE3_STAT_CTRL_STAT_ENA);\n+\tp->mp_fld_stat_ctrl_req =\n+\t\tregister_get_field(p->mp_reg_stat_ctrl, PCIE3_STAT_CTRL_STAT_REQ);\n+\n+\tp->mp_reg_stat_rx = module_get_register(p->mp_mod_pcie3, PCIE3_STAT_RX);\n+\tp->mp_fld_stat_rx_counter =\n+\t\tregister_get_field(p->mp_reg_stat_rx, PCIE3_STAT_RX_COUNTER);\n+\n+\tp->mp_reg_stat_tx = module_get_register(p->mp_mod_pcie3, PCIE3_STAT_TX);\n+\tp->mp_fld_stat_tx_counter =\n+\t\tregister_get_field(p->mp_reg_stat_tx, PCIE3_STAT_TX_COUNTER);\n+\n+\tp->mp_reg_stat_ref_clk =\n+\t\tmodule_get_register(p->mp_mod_pcie3, PCIE3_STAT_REFCLK);\n+\tp->mp_fld_stat_ref_clk_ref_clk =\n+\t\tregister_get_field(p->mp_reg_stat_ref_clk, PCIE3_STAT_REFCLK_REFCLK250);\n+\n+\tp->mp_reg_stat_rq_rdy =\n+\t\tmodule_get_register(p->mp_mod_pcie3, PCIE3_STAT_RQ_RDY);\n+\tp->mp_fld_stat_rq_rdy_counter =\n+\t\tregister_get_field(p->mp_reg_stat_rq_rdy, PCIE3_STAT_RQ_RDY_COUNTER);\n+\n+\tp->mp_reg_stat_rq_vld =\n+\t\tmodule_get_register(p->mp_mod_pcie3, PCIE3_STAT_RQ_VLD);\n+\tp->mp_fld_stat_rq_vld_counter =\n+\t\tregister_get_field(p->mp_reg_stat_rq_vld, PCIE3_STAT_RQ_VLD_COUNTER);\n+\n+\tp->mp_reg_status0 = module_get_register(p->mp_mod_pcie3, PCIE3_STATUS0);\n+\tp->mp_fld_status0_tags_in_use =\n+\t\tregister_get_field(p->mp_reg_status0, PCIE3_STATUS0_TAGS_IN_USE);\n+\n+\tp->mp_reg_rp_to_ep_err =\n+\t\tmodule_get_register(p->mp_mod_pcie3, PCIE3_RP_TO_EP_ERR);\n+\tp->mp_fld_rp_to_ep_err_cor =\n+\t\tregister_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_COR);\n+\tp->mp_fld_rp_to_ep_err_non_fatal =\n+\t\tregister_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_NONFATAL);\n+\tp->mp_fld_rp_to_ep_err_fatal =\n+\t\tregister_get_field(p->mp_reg_rp_to_ep_err, PCIE3_RP_TO_EP_ERR_ERR_FATAL);\n+\n+\tp->mp_reg_ep_to_rp_err =\n+\t\tmodule_get_register(p->mp_mod_pcie3, PCIE3_EP_TO_RP_ERR);\n+\tp->mp_fld_ep_to_rp_err_cor = register_get_field(p->mp_reg_ep_to_rp_err,\n+\t\t\t       PCIE3_EP_TO_RP_ERR_ERR_COR);\n+\tp->mp_fld_ep_to_rp_err_non_fatal =\n+\t\tregister_get_field(p->mp_reg_ep_to_rp_err, PCIE3_EP_TO_RP_ERR_ERR_NONFATAL);\n+\tp->mp_fld_ep_to_rp_err_fatal =\n+\t\tregister_get_field(p->mp_reg_ep_to_rp_err, PCIE3_EP_TO_RP_ERR_ERR_FATAL);\n+\n+\tp->mp_reg_sample_time =\n+\t\tmodule_get_register(p->mp_mod_pcie3, PCIE3_SAMPLE_TIME);\n+\tp->mp_fld_sample_time =\n+\t\tregister_get_field(p->mp_reg_sample_time, PCIE3_SAMPLE_TIME_SAMPLE_TIME);\n+\n+\tp->mp_reg_pci_end_point =\n+\t\tmodule_get_register(p->mp_mod_pcie3, PCIE3_PCI_ENDPOINT);\n+\tp->mp_fld_pci_end_point_if_id =\n+\t\tregister_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_IF_ID);\n+\tp->mp_fld_pci_end_point_send_msg =\n+\t\tregister_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_SEND_MSG);\n+\tp->mp_fld_pci_end_point_get_msg =\n+\t\tregister_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_GET_MSG);\n+\tp->mp_fld_pci_end_point_dmae_p0_allow_mask =\n+\t\tregister_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_DMA_EP0_ALLOW_MASK);\n+\tp->mp_fld_pci_end_point_dmae_p1_allow_mask =\n+\t\tregister_get_field(p->mp_reg_pci_end_point, PCIE3_PCI_ENDPOINT_DMA_EP1_ALLOW_MASK);\n+\tif (p->mp_reg_pci_end_point)\n+\t\tregister_update(p->mp_reg_pci_end_point);\n+\n+\tp->mp_reg_pci_test0 = module_get_register(p->mp_mod_pcie3, PCIE3_PCI_TEST0);\n+\tp->mp_fld_pci_test0 =\n+\t\tregister_get_field(p->mp_reg_pci_test0, PCIE3_PCI_TEST0_DATA);\n+\tif (p->mp_reg_pci_test0)\n+\t\tregister_update(p->mp_reg_pci_test0);\n+\n+\tp->mp_reg_pci_test1 = module_get_register(p->mp_mod_pcie3, PCIE3_PCI_TEST1);\n+\tp->mp_fld_pci_test1 =\n+\t\tregister_get_field(p->mp_reg_pci_test1, PCIE3_PCI_TEST1_DATA);\n+\tif (p->mp_reg_pci_test1)\n+\t\tregister_update(p->mp_reg_pci_test1);\n+\n+\tp->mp_reg_pci_e3_mark_adr_lsb =\n+\t\tmodule_get_register(p->mp_mod_pcie3, PCIE3_MARKADR_LSB);\n+\tp->mp_fld_pci_e3_mark_adr_lsb_adr =\n+\t\tregister_get_field(p->mp_reg_pci_e3_mark_adr_lsb, PCIE3_MARKADR_LSB_ADR);\n+\tif (p->mp_reg_pci_e3_mark_adr_lsb)\n+\t\tregister_update(p->mp_reg_pci_e3_mark_adr_lsb);\n+\n+\tp->mp_reg_pci_e3_mark_adr_msb =\n+\t\tmodule_get_register(p->mp_mod_pcie3, PCIE3_MARKADR_MSB);\n+\tp->mp_fld_pci_e3_mark_adr_msb_adr =\n+\t\tregister_get_field(p->mp_reg_pci_e3_mark_adr_msb, PCIE3_MARKADR_MSB_ADR);\n+\tif (p->mp_reg_pci_e3_mark_adr_msb)\n+\t\tregister_update(p->mp_reg_pci_e3_mark_adr_msb);\n+\n+\t/* Initial setup - disable markerscheme and bifurcation */\n+\tif (p->mp_fld_pci_end_point_dmae_p0_allow_mask)\n+\t\tfield_clr_flush(p->mp_fld_pci_end_point_dmae_p0_allow_mask);\n+\n+\tif (p->mp_fld_pci_end_point_dmae_p1_allow_mask)\n+\t\tfield_clr_flush(p->mp_fld_pci_end_point_dmae_p1_allow_mask);\n+\n+\tif (p->mp_fld_pci_e3_mark_adr_lsb_adr)\n+\t\tfield_set_val_flush32(p->mp_fld_pci_e3_mark_adr_lsb_adr, 0UL);\n+\n+\tif (p->mp_fld_pci_e3_mark_adr_msb_adr)\n+\t\tfield_set_val_flush32(p->mp_fld_pci_e3_mark_adr_msb_adr, 0UL);\n+\n+\tif (p->mp_fld_pci_end_point_dmae_p0_allow_mask)\n+\t\tfield_set_flush(p->mp_fld_pci_end_point_dmae_p0_allow_mask);\n+\n+\tif (p->mp_fld_pci_end_point_dmae_p1_allow_mask)\n+\t\tfield_clr_flush(p->mp_fld_pci_end_point_dmae_p1_allow_mask);\n+\treturn 0;\n+};\n+\n+int nthw_pcie3_trigger_sample_time(nthw_pcie3_t *p)\n+{\n+\tfield_set_val_flush32(p->mp_fld_sample_time, 0xfee1dead);\n+\n+\treturn 0;\n+}\n+\n+int nthw_pcie3_stat_req_enable(nthw_pcie3_t *p)\n+{\n+\tfield_set_all(p->mp_fld_stat_ctrl_ena);\n+\tfield_set_all(p->mp_fld_stat_ctrl_req);\n+\tfield_flush_register(p->mp_fld_stat_ctrl_req);\n+\treturn 0;\n+}\n+\n+int nthw_pcie3_stat_req_disable(nthw_pcie3_t *p)\n+{\n+\tfield_clr_all(p->mp_fld_stat_ctrl_ena);\n+\tfield_set_all(p->mp_fld_stat_ctrl_req);\n+\tfield_flush_register(p->mp_fld_stat_ctrl_req);\n+\treturn 0;\n+}\n+\n+int nthw_pcie3_get_stat(nthw_pcie3_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt,\n+\t\t\tuint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size,\n+\t\t\tuint32_t *p_tg_ref_freq, uint32_t *p_tag_use_cnt,\n+\t\t\tuint32_t *p_rq_rdy_cnt, uint32_t *p_rq_vld_cnt)\n+{\n+\t*p_rx_cnt = field_get_updated(p->mp_fld_stat_rx_counter);\n+\t*p_tx_cnt = field_get_updated(p->mp_fld_stat_tx_counter);\n+\n+\t*p_ref_clk_cnt = field_get_updated(p->mp_fld_stat_ref_clk_ref_clk);\n+\n+\t*p_tg_unit_size = NTHW_TG_CNT_SIZE;\n+\t*p_tg_ref_freq = NTHW_TG_REF_FREQ;\n+\n+\t*p_tag_use_cnt = field_get_updated(p->mp_fld_status0_tags_in_use);\n+\n+\t*p_rq_rdy_cnt = field_get_updated(p->mp_fld_stat_rq_rdy_counter);\n+\t*p_rq_vld_cnt = field_get_updated(p->mp_fld_stat_rq_vld_counter);\n+\n+\treturn 0;\n+}\n+\n+int nthw_pcie3_get_stat_rate(nthw_pcie3_t *p, uint64_t *p_pci_rx_rate,\n+\t\t\t  uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt,\n+\t\t\t  uint64_t *p_tag_use_cnt, uint64_t *p_pci_nt_bus_util,\n+\t\t\t  uint64_t *p_pci_xil_bus_util)\n+{\n+\tuint32_t rx_cnt, tx_cnt, ref_clk_cnt;\n+\tuint32_t tg_unit_size, tg_ref_freq;\n+\tuint32_t tag_use_cnt, rq_rdy_cnt, rq_vld_cnt;\n+\n+\tnthw_pcie3_get_stat(p, &rx_cnt, &tx_cnt, &ref_clk_cnt, &tg_unit_size,\n+\t\t\t  &tg_ref_freq, &tag_use_cnt, &rq_rdy_cnt, &rq_vld_cnt);\n+\n+\tif (ref_clk_cnt) {\n+\t\tuint64_t nt_bus_util, xil_bus_util;\n+\t\tuint64_t rx_rate, tx_rate;\n+\n+\t\trx_rate = ((uint64_t)rx_cnt * tg_unit_size * tg_ref_freq) /\n+\t\t\t (uint64_t)ref_clk_cnt;\n+\t\t*p_pci_rx_rate = rx_rate;\n+\n+\t\ttx_rate = ((uint64_t)tx_cnt * tg_unit_size * tg_ref_freq) /\n+\t\t\t (uint64_t)ref_clk_cnt;\n+\t\t*p_pci_tx_rate = tx_rate;\n+\n+\t\t*p_ref_clk_cnt = ref_clk_cnt;\n+\n+\t\t*p_tag_use_cnt = tag_use_cnt;\n+\n+\t\tnt_bus_util =\n+\t\t\t((uint64_t)rq_vld_cnt * 1000000ULL) / (uint64_t)ref_clk_cnt;\n+\t\t*p_pci_nt_bus_util = nt_bus_util;\n+\t\txil_bus_util =\n+\t\t\t((uint64_t)rq_rdy_cnt * 1000000ULL) / (uint64_t)ref_clk_cnt;\n+\t\t*p_pci_xil_bus_util = xil_bus_util;\n+\t} else {\n+\t\t*p_ref_clk_cnt = 0;\n+\t\t*p_pci_nt_bus_util = 0;\n+\t\t*p_pci_xil_bus_util = 0;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int nthw_pcie3_end_point_counters_sample_pre(nthw_pcie3_t *p,\n+\t\t\t\t\tstruct nthw_hif_end_point_counters *epc)\n+{\n+\tNT_LOG(DBG, NTHW, \"%s:%u: empty function\\n\", __func__, __LINE__);\n+\n+\t(void)p;\n+\t(void)epc;\n+\n+\treturn 0;\n+}\n+\n+int nthw_pcie3_end_point_counters_sample_post(nthw_pcie3_t *p,\n+\t\tstruct nthw_hif_end_point_counters *epc)\n+{\n+\tNT_LOG(DBG, NTHW, \"%s:%u:\\n\", __func__, __LINE__);\n+\tassert(epc);\n+\tnthw_pcie3_get_stat_rate(p, &epc->cur_tx, &epc->cur_rx, &epc->n_ref_clk_cnt,\n+\t\t\t      &epc->n_tags_in_use, &epc->cur_pci_nt_util,\n+\t\t\t      &epc->cur_pci_xil_util);\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_pcie3.h b/drivers/net/ntnic/nthw/core/nthw_pcie3.h\nnew file mode 100644\nindex 0000000000..beb79a9577\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_pcie3.h\n@@ -0,0 +1,100 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_PCIE3_H__\n+#define __NTHW_PCIE3_H__\n+\n+struct nthw_pcie3 {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_pcie3;\n+\tint mn_instance;\n+\n+\tnt_register_t *mp_reg_stat_ctrl;\n+\tnt_field_t *mp_fld_stat_ctrl_req;\n+\tnt_field_t *mp_fld_stat_ctrl_ena;\n+\n+\tnt_register_t *mp_reg_stat_rx;\n+\tnt_field_t *mp_fld_stat_rx_counter;\n+\n+\tnt_register_t *mp_reg_stat_tx;\n+\tnt_field_t *mp_fld_stat_tx_counter;\n+\n+\tnt_register_t *mp_reg_stat_rq_rdy;\n+\tnt_field_t *mp_fld_stat_rq_rdy_counter;\n+\n+\tnt_register_t *mp_reg_stat_rq_vld;\n+\tnt_field_t *mp_fld_stat_rq_vld_counter;\n+\n+\tnt_register_t *mp_reg_status0;\n+\tnt_field_t *mp_fld_status0_tags_in_use;\n+\n+\tnt_register_t *mp_reg_stat_ref_clk;\n+\tnt_field_t *mp_fld_stat_ref_clk_ref_clk;\n+\n+\tnt_register_t *mp_reg_rp_to_ep_err;\n+\tnt_field_t *mp_fld_rp_to_ep_err_cor;\n+\tnt_field_t *mp_fld_rp_to_ep_err_non_fatal;\n+\tnt_field_t *mp_fld_rp_to_ep_err_fatal;\n+\n+\tnt_register_t *mp_reg_ep_to_rp_err;\n+\tnt_field_t *mp_fld_ep_to_rp_err_cor;\n+\tnt_field_t *mp_fld_ep_to_rp_err_non_fatal;\n+\tnt_field_t *mp_fld_ep_to_rp_err_fatal;\n+\n+\tnt_register_t *mp_reg_sample_time;\n+\tnt_field_t *mp_fld_sample_time;\n+\n+\tnt_register_t *mp_reg_pci_end_point;\n+\tnt_field_t *mp_fld_pci_end_point_if_id;\n+\tnt_field_t *mp_fld_pci_end_point_send_msg;\n+\tnt_field_t *mp_fld_pci_end_point_get_msg;\n+\tnt_field_t *mp_fld_pci_end_point_dmae_p0_allow_mask;\n+\tnt_field_t *mp_fld_pci_end_point_dmae_p1_allow_mask;\n+\n+\tnt_register_t *mp_reg_pci_e3_mark_adr_lsb;\n+\tnt_field_t *mp_fld_pci_e3_mark_adr_lsb_adr;\n+\n+\tnt_register_t *mp_reg_pci_e3_mark_adr_msb;\n+\tnt_field_t *mp_fld_pci_e3_mark_adr_msb_adr;\n+\n+\tnt_register_t *mp_reg_pci_test0;\n+\tnt_field_t *mp_fld_pci_test0;\n+\n+\tnt_register_t *mp_reg_pci_test1;\n+\tnt_field_t *mp_fld_pci_test1;\n+\n+\tnt_register_t *mp_reg_pci_test2;\n+\tnt_field_t *mp_fld_pci_test2;\n+\n+\tnt_register_t *mp_reg_pci_test3;\n+\tnt_field_t *mp_fld_pci_test3;\n+};\n+\n+typedef struct nthw_pcie3 nthw_pcie3_t;\n+typedef struct nthw_pcie3 nthw_pcie3;\n+\n+nthw_pcie3_t *nthw_pcie3_new(void);\n+void nthw_pcie3_delete(nthw_pcie3_t *p);\n+int nthw_pcie3_init(nthw_pcie3_t *p, nt_fpga_t *p_fpga, int n_instance);\n+\n+int nthw_pcie3_trigger_sample_time(nthw_pcie3_t *p);\n+\n+int nthw_pcie3_stat_req_enable(nthw_pcie3_t *p);\n+int nthw_pcie3_stat_req_disable(nthw_pcie3_t *p);\n+\n+int nthw_pcie3_get_stat(nthw_pcie3_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt,\n+\t\t      uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size,\n+\t\t      uint32_t *p_tg_ref_freq, uint32_t *p_tag_use_cnt,\n+\t\t      uint32_t *p_rq_rdy_cnt, uint32_t *p_rq_vld_cnt);\n+int nthw_pcie3_get_stat_rate(nthw_pcie3_t *p, uint64_t *p_pci_rx_rate,\n+\t\t\t  uint64_t *p_pci_tx_rate, uint64_t *p_ref_clk_cnt,\n+\t\t\t  uint64_t *p_tag_use_cnt, uint64_t *p_pci_nt_bus_util,\n+\t\t\t  uint64_t *p_pci_xil_bus_util);\n+\n+int nthw_pcie3_end_point_counters_sample_pre(nthw_pcie3_t *p,\n+\t\t\t\t\tstruct nthw_hif_end_point_counters *epc);\n+int nthw_pcie3_end_point_counters_sample_post(nthw_pcie3_t *p,\n+\t\tstruct nthw_hif_end_point_counters *epc);\n+\n+#endif /* __NTHW_PCIE3_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_sdc.c b/drivers/net/ntnic/nthw/core/nthw_sdc.c\nnew file mode 100644\nindex 0000000000..0547b92c47\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_sdc.c\n@@ -0,0 +1,177 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_sdc.h\"\n+\n+nthw_sdc_t *nthw_sdc_new(void)\n+{\n+\tnthw_sdc_t *p = malloc(sizeof(nthw_sdc_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_sdc_t));\n+\treturn p;\n+}\n+\n+void nthw_sdc_delete(nthw_sdc_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_sdc_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+int nthw_sdc_init(nthw_sdc_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tconst char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_SDC, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: SDC %d: no such instance\\n\",\n+\t\t       p_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_sdc = mod;\n+\n+\t{\n+\t\tnt_register_t *p_reg;\n+\n+\t\tp_reg = module_get_register(p->mp_mod_sdc, SDC_CTRL);\n+\t\tp->mp_fld_ctrl_init = register_get_field(p_reg, SDC_CTRL_INIT);\n+\t\tp->mp_fld_ctrl_run_test =\n+\t\t\tregister_get_field(p_reg, SDC_CTRL_RUN_TEST);\n+\t\tp->mp_fld_ctrl_stop_client =\n+\t\t\tregister_get_field(p_reg, SDC_CTRL_STOP_CLIENT);\n+\t\tp->mp_fld_ctrl_test_enable =\n+\t\t\tregister_get_field(p_reg, SDC_CTRL_TEST_EN);\n+\n+\t\tp_reg = module_get_register(p->mp_mod_sdc, SDC_STAT);\n+\t\tp->mp_fld_stat_calib = register_get_field(p_reg, SDC_STAT_CALIB);\n+\t\tp->mp_fld_stat_cell_cnt_stopped =\n+\t\t\tregister_get_field(p_reg, SDC_STAT_CELL_CNT_STOPPED);\n+\t\tp->mp_fld_stat_err_found =\n+\t\t\tregister_get_field(p_reg, SDC_STAT_ERR_FOUND);\n+\t\tp->mp_fld_stat_init_done =\n+\t\t\tregister_get_field(p_reg, SDC_STAT_INIT_DONE);\n+\t\tp->mp_fld_stat_mmcm_lock =\n+\t\t\tregister_get_field(p_reg, SDC_STAT_MMCM_LOCK);\n+\t\tp->mp_fld_stat_pll_lock =\n+\t\t\tregister_get_field(p_reg, SDC_STAT_PLL_LOCK);\n+\t\tp->mp_fld_stat_resetting =\n+\t\t\tregister_get_field(p_reg, SDC_STAT_RESETTING);\n+\n+\t\tp_reg = module_get_register(p->mp_mod_sdc, SDC_CELL_CNT);\n+\t\tp->mp_fld_cell_cnt =\n+\t\t\tregister_get_field(p_reg, SDC_CELL_CNT_CELL_CNT);\n+\n+\t\tp_reg = module_get_register(p->mp_mod_sdc, SDC_CELL_CNT_PERIOD);\n+\t\tp->mp_fld_cell_cnt_period =\n+\t\t\tregister_get_field(p_reg, SDC_CELL_CNT_PERIOD_CELL_CNT_PERIOD);\n+\n+\t\tp_reg = module_get_register(p->mp_mod_sdc, SDC_FILL_LVL);\n+\t\tp->mp_fld_fill_level =\n+\t\t\tregister_get_field(p_reg, SDC_FILL_LVL_FILL_LVL);\n+\n+\t\tp_reg = module_get_register(p->mp_mod_sdc, SDC_MAX_FILL_LVL);\n+\t\tp->mp_fld_max_fill_level =\n+\t\t\tregister_get_field(p_reg, SDC_MAX_FILL_LVL_MAX_FILL_LVL);\n+\t}\n+\treturn 0;\n+}\n+\n+int nthw_sdc_get_states(nthw_sdc_t *p, uint64_t *pn_result_mask)\n+{\n+\tint n_err_cnt = 0;\n+\tuint64_t n_mask = 0;\n+\tuint32_t val;\n+\tuint32_t val_mask;\n+\tint n_val_width;\n+\n+\tif (!p || !pn_result_mask)\n+\t\treturn -1;\n+\n+\tval = field_get_updated(p->mp_fld_stat_calib);\n+\tn_val_width = field_get_bit_width(p->mp_fld_stat_calib);\n+\tval_mask = ((1 << n_val_width) - 1);\n+\tn_mask = (n_mask << n_val_width) | (val & val_mask);\n+\tif (val != val_mask)\n+\t\tn_err_cnt++;\n+\n+\tval = field_get_updated(p->mp_fld_stat_init_done);\n+\tn_val_width = field_get_bit_width(p->mp_fld_stat_init_done);\n+\tval_mask = ((1 << n_val_width) - 1);\n+\tn_mask = (n_mask << n_val_width) | (val & val_mask);\n+\tif (val != val_mask)\n+\t\tn_err_cnt++;\n+\n+\tval = field_get_updated(p->mp_fld_stat_mmcm_lock);\n+\tn_val_width = field_get_bit_width(p->mp_fld_stat_mmcm_lock);\n+\tval_mask = ((1 << n_val_width) - 1);\n+\tn_mask = (n_mask << n_val_width) | (val & val_mask);\n+\tif (val != val_mask)\n+\t\tn_err_cnt++;\n+\n+\tval = field_get_updated(p->mp_fld_stat_pll_lock);\n+\tn_val_width = field_get_bit_width(p->mp_fld_stat_pll_lock);\n+\tval_mask = ((1 << n_val_width) - 1);\n+\tn_mask = (n_mask << n_val_width) | (val & val_mask);\n+\tif (val != val_mask)\n+\t\tn_err_cnt++;\n+\n+\tval = field_get_updated(p->mp_fld_stat_resetting);\n+\tn_val_width = field_get_bit_width(p->mp_fld_stat_resetting);\n+\tval_mask = ((1 << n_val_width) - 1);\n+\tn_mask = (n_mask << n_val_width) | (val & val_mask);\n+\tif (val != 0)\n+\t\tn_err_cnt++;\n+\n+\tif (pn_result_mask)\n+\t\t*pn_result_mask = n_mask;\n+\n+\treturn n_err_cnt; /* 0 = all ok */\n+}\n+\n+int nthw_sdc_wait_states(nthw_sdc_t *p, const int n_poll_iterations,\n+\t\t       const int n_poll_interval)\n+{\n+\tint res;\n+\tint n_err_cnt = 0;\n+\n+\tres = field_wait_set_all32(p->mp_fld_stat_calib, n_poll_iterations,\n+\t\t\t\t n_poll_interval);\n+\tif (res)\n+\t\tn_err_cnt++;\n+\n+\tres = field_wait_set_all32(p->mp_fld_stat_init_done, n_poll_iterations,\n+\t\t\t\t n_poll_interval);\n+\tif (res)\n+\t\tn_err_cnt++;\n+\n+\tres = field_wait_set_all32(p->mp_fld_stat_mmcm_lock, n_poll_iterations,\n+\t\t\t\t n_poll_interval);\n+\tif (res)\n+\t\tn_err_cnt++;\n+\n+\tres = field_wait_set_all32(p->mp_fld_stat_pll_lock, n_poll_iterations,\n+\t\t\t\t n_poll_interval);\n+\tif (res)\n+\t\tn_err_cnt++;\n+\n+\tres = field_wait_clr_all32(p->mp_fld_stat_resetting, n_poll_iterations,\n+\t\t\t\t n_poll_interval);\n+\tif (res)\n+\t\tn_err_cnt++;\n+\n+\treturn n_err_cnt; /* 0 = all ok */\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_sdc.h b/drivers/net/ntnic/nthw/core/nthw_sdc.h\nnew file mode 100644\nindex 0000000000..e6c08ffbc3\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_sdc.h\n@@ -0,0 +1,43 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_SDC_H__\n+#define __NTHW_SDC_H__\n+\n+struct nthw_sdc {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_sdc;\n+\tint mn_instance;\n+\n+\tnt_field_t *mp_fld_ctrl_init;\n+\tnt_field_t *mp_fld_ctrl_run_test;\n+\tnt_field_t *mp_fld_ctrl_stop_client;\n+\tnt_field_t *mp_fld_ctrl_test_enable;\n+\n+\tnt_field_t *mp_fld_stat_calib;\n+\tnt_field_t *mp_fld_stat_cell_cnt_stopped;\n+\tnt_field_t *mp_fld_stat_err_found;\n+\tnt_field_t *mp_fld_stat_init_done;\n+\tnt_field_t *mp_fld_stat_mmcm_lock;\n+\tnt_field_t *mp_fld_stat_pll_lock;\n+\tnt_field_t *mp_fld_stat_resetting;\n+\n+\tnt_field_t *mp_fld_cell_cnt;\n+\tnt_field_t *mp_fld_cell_cnt_period;\n+\tnt_field_t *mp_fld_fill_level;\n+\tnt_field_t *mp_fld_max_fill_level;\n+};\n+\n+typedef struct nthw_sdc nthw_sdc_t;\n+typedef struct nthw_sdc nthw_sdc;\n+\n+nthw_sdc_t *nthw_sdc_new(void);\n+int nthw_sdc_init(nthw_sdc_t *p, nt_fpga_t *p_fpga, int n_instance);\n+void nthw_sdc_delete(nthw_sdc_t *p);\n+\n+int nthw_sdc_wait_states(nthw_sdc_t *p, const int n_poll_iterations,\n+\t\t       const int n_poll_interval);\n+int nthw_sdc_get_states(nthw_sdc_t *p, uint64_t *pn_result_mask);\n+\n+#endif /* __NTHW_SDC_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_si5340.c b/drivers/net/ntnic/nthw/core/nthw_si5340.c\nnew file mode 100644\nindex 0000000000..3337f1f9e3\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_si5340.c\n@@ -0,0 +1,206 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ *\n+ * This file implements Si5340 clock synthesizer support.\n+ * The implementation is generic and must be tailored to a specific use by the\n+ * correct initialization data.\n+ */\n+\n+#include \"nt_util.h\"\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_si5340.h\"\n+\n+#define SI5340_WAIT_US(x) NT_OS_WAIT_USEC(x)\n+\n+#define SI5340_LOG_DEBUG(...) NT_LOG(DBG, NTHW, __VA_ARGS__)\n+#define SI5340_LOG_INFO(...) NT_LOG(INF, NTHW, __VA_ARGS__)\n+#define SI5340_LOG_WARN(...) NT_LOG(WRN, NTHW, __VA_ARGS__)\n+#define SI5340_LOG_ERROR(...) NT_LOG(ERR, NTHW, __VA_ARGS__)\n+\n+#define SI5340_PAGE_REG_ADDR (0x01)\n+\n+nthw_si5340_t *nthw_si5340_new(void)\n+{\n+\tnthw_si5340_t *p = malloc(sizeof(nthw_si5340_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_si5340_t));\n+\treturn p;\n+}\n+\n+int nthw_si5340_init(nthw_si5340_t *p, nthw_iic_t *p_nthw_iic, uint8_t n_iic_addr)\n+{\n+\tuint8_t data;\n+\n+\tp->mp_nthw_iic = p_nthw_iic;\n+\tp->mn_iic_addr = n_iic_addr;\n+\tp->mn_clk_cfg = -1;\n+\n+\tp->m_si5340_page = 0;\n+\tdata = p->m_si5340_page;\n+\tnthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, SI5340_PAGE_REG_ADDR, 1,\n+\t\t\t  &data);\n+\n+\treturn 0;\n+}\n+\n+void nthw_si5340_delete(nthw_si5340_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_si5340_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+/*\n+ * Read access (via I2C) to the clock synthesizer IC. The IC is located at I2C\n+ * 7bit address 0x74\n+ */\n+static uint8_t nthw_si5340_read(nthw_si5340_t *p, uint16_t reg_addr)\n+{\n+\tconst uint8_t offset_adr = (uint8_t)(reg_addr & 0xff);\n+\tuint8_t page = (uint8_t)((reg_addr >> 8) & 0xff);\n+\tuint8_t data;\n+\n+\t/* check if we are on the right page */\n+\tif (page != p->m_si5340_page) {\n+\t\tnthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr,\n+\t\t\t\t  SI5340_PAGE_REG_ADDR, 1, &page);\n+\t\tp->m_si5340_page = page;\n+\t}\n+\tnthw_iic_read_data(p->mp_nthw_iic, p->mn_iic_addr, offset_adr, 1, &data);\n+\treturn data;\n+}\n+\n+/*\n+ * Write access (via I2C) to the clock synthesizer IC. The IC is located at I2C\n+ * 7 bit address 0x74\n+ */\n+static int nthw_si5340_write(nthw_si5340_t *p, uint16_t reg_addr, uint8_t data)\n+{\n+\tconst uint8_t offset_adr = (uint8_t)(reg_addr & 0xff);\n+\tuint8_t page = (uint8_t)((reg_addr >> 8) & 0xff);\n+\n+\t/* check if we are on the right page */\n+\tif (page != p->m_si5340_page) {\n+\t\tnthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr,\n+\t\t\t\t  SI5340_PAGE_REG_ADDR, 1, &page);\n+\t\tp->m_si5340_page = page;\n+\t}\n+\tnthw_iic_write_data(p->mp_nthw_iic, p->mn_iic_addr, offset_adr, 1, &data);\n+\n+\treturn 0;\n+}\n+\n+static int nthw_si5340_cfg(nthw_si5340_t *p, const void *p_data, int data_cnt,\n+\t\t\t  clk_profile_data_fmt_t data_format)\n+{\n+\tconst char *const p_adapter_id_str =\n+\t\tp->mp_nthw_iic->mp_fpga->p_fpga_info->mp_adapter_id_str;\n+\tint i;\n+\tuint16_t addr;\n+\tuint8_t value;\n+\tuint8_t ctrl_value;\n+\n+\tNT_LOG(DBG, NTHW, \"%s: %s: data_cnt = %d, dataFormat = %d\\n\",\n+\t       p_adapter_id_str, __func__, data_cnt, data_format);\n+\n+\tfor (i = 0; i < data_cnt; i++) {\n+\t\tif (data_format == CLK_PROFILE_DATA_FMT_1) {\n+\t\t\taddr = ((const clk_profile_data_fmt1_t *)p_data)->reg_addr;\n+\t\t\tvalue = ((const clk_profile_data_fmt1_t *)p_data)->reg_val;\n+\t\t\tp_data = ((const clk_profile_data_fmt1_t *)p_data) + 1;\n+\t\t} else if (data_format == CLK_PROFILE_DATA_FMT_2) {\n+\t\t\taddr = (uint16_t)(((const clk_profile_data_fmt2_t *)p_data)\n+\t\t\t\t\t  ->reg_addr);\n+\t\t\tvalue = ((const clk_profile_data_fmt2_t *)p_data)->reg_val;\n+\t\t\tp_data = ((const clk_profile_data_fmt2_t *)p_data) + 1;\n+\t\t} else {\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: Unhandled Si5340 data format (%d)\\n\",\n+\t\t\t       p_adapter_id_str, data_format);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tif (addr == 0x0006) {\n+\t\t\t/* Wait 300ms before continuing. See NT200E3-2-PTP_U23_Si5340_adr0_v2.h */\n+\t\t\tNT_OS_WAIT_USEC(300000);\n+\t\t}\n+\n+\t\tnthw_si5340_write(p, addr, value);\n+\n+\t\tif (addr == 0x001C) {\n+\t\t\t/* skip readback for \"soft reset\" register */\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tctrl_value = nthw_si5340_read(p, addr);\n+\n+\t\tif (ctrl_value != value) {\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: Si5340 configuration readback check failed. (Addr = 0x%04X, Write = 0x%02X, Read = 0x%02X)\\n\",\n+\t\t\t       p_adapter_id_str, addr, value, ctrl_value);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+int nthw_si5340_config(nthw_si5340_t *p, const void *p_data, int data_cnt,\n+\t\t      clk_profile_data_fmt_t data_format)\n+{\n+\tconst char *const p_adapter_id_str =\n+\t\tp->mp_nthw_iic->mp_fpga->p_fpga_info->mp_adapter_id_str;\n+\tint i;\n+\tbool success = false;\n+\tuint8_t status, sticky;\n+\tuint8_t design_id[9];\n+\n+\t(void)nthw_si5340_cfg(p, p_data, data_cnt, data_format);\n+\n+\t/* Check if DPLL is locked and SYS is calibrated */\n+\tfor (i = 0; i < 5; i++) {\n+\t\tstatus = nthw_si5340_read(p, 0x0c);\n+\t\tsticky = nthw_si5340_read(p, 0x11);\n+\t\tnthw_si5340_write(p, 0x11, 0x00);\n+\n+\t\tif (((status & 0x09) == 0x00) && ((sticky & 0x09) == 0x00)) {\n+\t\t\tsuccess = true;\n+\t\t\tbreak;\n+\t\t}\n+\t\tNT_OS_WAIT_USEC(1000000); /* 1 sec */\n+\t}\n+\n+\tif (!success) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: Si5340 configuration failed. (Status = 0x%02X, Sticky = 0x%02X)\\n\",\n+\t\t       p_adapter_id_str, status, sticky);\n+\t\treturn -1;\n+\t}\n+\n+\tfor (i = 0; i < (int)sizeof(design_id) - 1; i++)\n+\t\tdesign_id[i] = nthw_si5340_read(p, (uint16_t)(0x26B + i));\n+\tdesign_id[sizeof(design_id) - 1] = 0;\n+\n+\t(void)design_id; /* Only used in debug mode */\n+\tNT_LOG(DBG, NTHW, \"%s: Si5340.DesignId = %s\\n\", p_adapter_id_str,\n+\t       design_id);\n+\n+\treturn 0;\n+}\n+\n+int nthw_si5340_config_fmt1(nthw_si5340_t *p, const clk_profile_data_fmt1_t *p_data,\n+\t\t\t  const int data_cnt)\n+{\n+\treturn nthw_si5340_config(p, p_data, data_cnt, CLK_PROFILE_DATA_FMT_1);\n+}\n+\n+int nthw_si5340_config_fmt2(nthw_si5340_t *p, const clk_profile_data_fmt2_t *p_data,\n+\t\t\t  const int data_cnt)\n+{\n+\treturn nthw_si5340_config(p, p_data, data_cnt, CLK_PROFILE_DATA_FMT_2);\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_si5340.h b/drivers/net/ntnic/nthw/core/nthw_si5340.h\nnew file mode 100644\nindex 0000000000..f588b5b825\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_si5340.h\n@@ -0,0 +1,34 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_SI5340_H__\n+#define __NTHW_SI5340_H__\n+\n+#include \"nthw_clock_profiles.h\"\n+\n+#define SI5340_SUCCESS (0)\n+#define SI5340_FAILED (999)\n+#define SI5340_TIMEOUT (666)\n+\n+struct nthw_si5340 {\n+\tuint8_t mn_iic_addr;\n+\tnthw_iic_t *mp_nthw_iic;\n+\tint mn_clk_cfg;\n+\tuint8_t m_si5340_page;\n+};\n+\n+typedef struct nthw_si5340 nthw_si5340_t;\n+\n+nthw_si5340_t *nthw_si5340_new(void);\n+int nthw_si5340_init(nthw_si5340_t *p, nthw_iic_t *p_nthw_iic, uint8_t n_iic_addr);\n+void nthw_si5340_delete(nthw_si5340_t *p);\n+\n+int nthw_si5340_config(nthw_si5340_t *p, const void *p_data, int data_cnt,\n+\t\t      clk_profile_data_fmt_t data_format);\n+int nthw_si5340_config_fmt1(nthw_si5340_t *p, const clk_profile_data_fmt1_t *p_data,\n+\t\t\t  const int data_cnt);\n+int nthw_si5340_config_fmt2(nthw_si5340_t *p, const clk_profile_data_fmt2_t *p_data,\n+\t\t\t  const int data_cnt);\n+\n+#endif /* __NTHW_SI5338_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_spi_v3.c b/drivers/net/ntnic/nthw/core/nthw_spi_v3.c\nnew file mode 100644\nindex 0000000000..454c9b73b8\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_spi_v3.c\n@@ -0,0 +1,380 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_fpga.h\"\n+\n+#include \"nthw_spi_v3.h\"\n+\n+#include <arpa/inet.h>\n+\n+#undef SPI_V3_DEBUG_PRINT\n+\n+nthw_spi_v3_t *nthw_spi_v3_new(void)\n+{\n+\tnthw_spi_v3_t *p = malloc(sizeof(nthw_spi_v3_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_spi_v3_t));\n+\treturn p;\n+}\n+\n+void nthw_spi_v3_delete(nthw_spi_v3_t *p)\n+{\n+\tif (p) {\n+\t\tif (p->mp_spim_mod) {\n+\t\t\tnthw_spim_delete(p->mp_spim_mod);\n+\t\t\tp->mp_spim_mod = NULL;\n+\t\t}\n+\n+\t\tif (p->mp_spis_mod) {\n+\t\t\tnthw_spis_delete(p->mp_spis_mod);\n+\t\t\tp->mp_spis_mod = NULL;\n+\t\t}\n+\n+\t\tmemset(p, 0, sizeof(nthw_spi_v3_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+int nthw_spi_v3_set_timeout(nthw_spi_v3_t *p, int time_out)\n+{\n+\tp->m_time_out = time_out;\n+\treturn 0;\n+}\n+\n+int nthw_spi_v3_get_version(nthw_spi_v3_t *p)\n+{\n+\t(void)p;\n+\treturn 3;\n+}\n+\n+/*\n+ * Wait until Tx data have been sent after they have been placed in the Tx FIFO.\n+ */\n+static int wait_for_tx_data_sent(nthw_spim_t *p_spim_mod, uint64_t time_out)\n+{\n+\tint result;\n+\tbool empty;\n+\tuint64_t start_time;\n+\tuint64_t cur_time;\n+\n+\tstart_time = NT_OS_GET_TIME_MONOTONIC_COUNTER();\n+\n+\twhile (true) {\n+\t\tNT_OS_WAIT_USEC(1000); /* Every 1ms */\n+\n+\t\tresult = nthw_spim_get_tx_fifo_empty(p_spim_mod, &empty);\n+\t\tif (result != 0) {\n+\t\t\tNT_LOG(WRN, NTHW,\n+\t\t\t       \"nthw_spim_get_tx_fifo_empty failed\\n\");\n+\t\t\treturn result;\n+\t\t}\n+\n+\t\tif (empty)\n+\t\t\tbreak;\n+\n+\t\tcur_time = NT_OS_GET_TIME_MONOTONIC_COUNTER();\n+\t\tif ((cur_time - start_time) > time_out) {\n+\t\t\tNT_LOG(WRN, NTHW, \"%s: Timed out\\n\", __func__);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Wait until Rx data have been received.\n+ */\n+static int wait_for_rx_data_ready(nthw_spis_t *p_spis_mod, uint64_t time_out)\n+{\n+\tint result;\n+\tbool empty;\n+\tuint64_t start_time;\n+\tuint64_t cur_time;\n+\n+\tstart_time = NT_OS_GET_TIME_MONOTONIC_COUNTER();\n+\n+\t/* Wait for data to become ready in the Rx FIFO */\n+\twhile (true) {\n+\t\tNT_OS_WAIT_USEC(10000); /* Every 10ms */\n+\n+\t\tresult = nthw_spis_get_rx_fifo_empty(p_spis_mod, &empty);\n+\t\tif (result != 0) {\n+\t\t\tNT_LOG(WRN, NTHW, \"nthw_spis_get_rx_empty failed\\n\");\n+\t\t\treturn result;\n+\t\t}\n+\n+\t\tif (!empty)\n+\t\t\tbreak;\n+\n+\t\tcur_time = NT_OS_GET_TIME_MONOTONIC_COUNTER();\n+\t\tif ((cur_time - start_time) > time_out) {\n+\t\t\tNT_LOG(WRN, NTHW, \"%s: Timed out\\n\", __func__);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+#ifdef SPI_V3_DEBUG_PRINT\n+static void dump_hex(uint8_t *p_data, uint16_t count)\n+{\n+\tint i;\n+\tint j = 0;\n+\tchar tmp_str[128];\n+\n+\tfor (i = 0; i < count; i++) {\n+\t\tsprintf(&tmp_str[j * 3], \"%02X \", *(p_data++));\n+\t\tj++;\n+\n+\t\tif (j == 16 || (i == count - 1)) {\n+\t\t\ttmp_str[j * 3 - 1] = '\\0';\n+\t\t\tNT_LOG(DBG, NTHW, \"    %s\\n\", tmp_str);\n+\t\t\tj = 0;\n+\t\t}\n+\t}\n+}\n+#endif\n+\n+int nthw_spi_v3_init(nthw_spi_v3_t *p, nt_fpga_t *p_fpga, int n_instance_no)\n+{\n+\tconst char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;\n+\tuint32_t result;\n+\n+\tp->mn_instance_no = n_instance_no;\n+\n+\tnthw_spi_v3_set_timeout(p, 1);\n+\n+\t/* Initialize SPIM module */\n+\tp->mp_spim_mod = nthw_spim_new();\n+\n+\tresult = nthw_spim_init(p->mp_spim_mod, p_fpga, n_instance_no);\n+\tif (result != 0) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: nthw_spis_init failed: %d\\n\",\n+\t\t       p_adapter_id_str, result);\n+\t}\n+\n+\t/* Initialize SPIS module */\n+\tp->mp_spis_mod = nthw_spis_new();\n+\n+\tresult = nthw_spis_init(p->mp_spis_mod, p_fpga, n_instance_no);\n+\tif (result != 0) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: nthw_spim_init failed: %d\\n\",\n+\t\t       p_adapter_id_str, result);\n+\t}\n+\n+\t/* Reset SPIM and SPIS modules */\n+\tresult = nthw_spim_reset(p->mp_spim_mod);\n+\tif (result != 0) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: nthw_spim_reset failed: %d\\n\",\n+\t\t       p_adapter_id_str, result);\n+\t}\n+\n+\tresult = nthw_spis_reset(p->mp_spis_mod);\n+\tif (result != 0) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: nthw_spis_reset failed: %d\\n\",\n+\t\t       p_adapter_id_str, result);\n+\t}\n+\n+\treturn result;\n+}\n+\n+/*\n+ * Send Tx data using the SPIM module and receive any data using the SPIS module.\n+ * The data are sent and received being wrapped into a SPI v3 container.\n+ */\n+int nthw_spi_v3_transfer(nthw_spi_v3_t *p, uint16_t opcode,\n+\t\t\t struct tx_rx_buf *tx_buf, struct tx_rx_buf *rx_buf)\n+{\n+\tconst uint16_t max_payload_rx_size = rx_buf->size;\n+\tint result = 0;\n+\n+#pragma pack(push, 1)\n+\tunion {\n+\t\tuint32_t raw;\n+\n+\t\tstruct {\n+\t\t\tuint16_t opcode;\n+\t\t\tuint16_t size;\n+\t\t};\n+\t} spi_tx_hdr;\n+\n+\tunion {\n+\t\tuint32_t raw;\n+\n+\t\tstruct {\n+\t\t\tuint16_t error_code;\n+\t\t\tuint16_t size;\n+\t\t};\n+\t} spi_rx_hdr;\n+#pragma pack(pop)\n+\n+#ifdef SPI_V3_DEBUG_PRINT\n+\tNT_LOG(DBG, NTHW, \"%s:  Started\\n\", __func__);\n+#endif\n+\n+\t/* Disable transmission from Tx FIFO */\n+\tresult = nthw_spim_enable(p->mp_spim_mod, false);\n+\tif (result != 0) {\n+\t\tNT_LOG(WRN, NTHW, \"nthw_spim_enable failed\\n\");\n+\t\treturn result;\n+\t}\n+\n+\t/* Enable SPIS module */\n+\tresult = nthw_spis_enable(p->mp_spis_mod, true);\n+\tif (result != 0) {\n+\t\tNT_LOG(WRN, NTHW, \"nthw_spis_enable failed\\n\");\n+\t\treturn result;\n+\t}\n+\n+\t/* Put data into Tx FIFO */\n+\tspi_tx_hdr.opcode = opcode;\n+\tspi_tx_hdr.size = tx_buf->size;\n+\n+#ifdef SPI_V3_DEBUG_PRINT\n+\tNT_LOG(DBG, NTHW, \"opcode=0x%04X tx_bufsize=0x%04X rx_bufsize=0x%04X\\n\",\n+\t       opcode, tx_buf->size, rx_buf->size);\n+\n+#endif /* SPI_V3_DEBUG_PRINT */\n+\n+\tresult = nthw_spim_write_tx_fifo(p->mp_spim_mod, htonl(spi_tx_hdr.raw));\n+\tif (result != 0) {\n+\t\tNT_LOG(WRN, NTHW, \"nthw_spim_write_tx_fifo failed\\n\");\n+\t\treturn result;\n+\t}\n+\n+\t{\n+\t\tuint8_t *tx_data = (uint8_t *)tx_buf->p_buf;\n+\t\tuint16_t tx_size = tx_buf->size;\n+\t\tuint16_t count;\n+\t\tuint32_t value;\n+\n+\t\twhile (tx_size > 0) {\n+\t\t\tif (tx_size > 4) {\n+\t\t\t\tcount = 4;\n+\t\t\t} else {\n+\t\t\t\tcount = tx_size;\n+\t\t\t\tvalue = 0;\n+\t\t\t}\n+\n+\t\t\tmemcpy(&value, tx_data, count);\n+\n+\t\t\tresult = nthw_spim_write_tx_fifo(p->mp_spim_mod,\n+\t\t\t\t\t\t\thtonl(value));\n+\t\t\tif (result != 0) {\n+\t\t\t\tNT_LOG(WRN, NTHW,\n+\t\t\t\t       \"nthw_spim_write_tx_fifo failed\\n\");\n+\t\t\t\treturn result;\n+\t\t\t}\n+\n+\t\t\ttx_size = (uint16_t)(tx_size - count);\n+\t\t\ttx_data += count;\n+\t\t}\n+\t}\n+\n+\t/* Enable Tx FIFO */\n+\tresult = nthw_spim_enable(p->mp_spim_mod, true);\n+\tif (result != 0) {\n+\t\tNT_LOG(WRN, NTHW, \"nthw_spim_enable failed\\n\");\n+\t\treturn result;\n+\t}\n+\n+\tresult = wait_for_tx_data_sent(p->mp_spim_mod, p->m_time_out);\n+\tif (result != 0)\n+\t\treturn result;\n+\n+#ifdef SPI_V3_DEBUG_PRINT\n+\tNT_LOG(DBG, NTHW, \"%s: SPI header and payload data have been sent\\n\",\n+\t       __func__);\n+#endif\n+\n+\t{\n+\t\t/*\n+\t\t * Start receiving data\n+\t\t * The first data to read is the header\n+\t\t */\n+\t\tuint16_t rx_size = sizeof(spi_rx_hdr.raw);\n+\t\tuint8_t *rx_data = (uint8_t *)rx_buf->p_buf;\n+\t\tbool rx_hdr_read = false;\n+\n+\t\trx_buf->size = 0;\n+\n+\t\twhile (true) {\n+\t\t\tuint16_t count;\n+\t\t\tuint32_t value;\n+\n+\t\t\tif (!rx_hdr_read) { /* Read the header */\n+\t\t\t\tresult = wait_for_rx_data_ready(p->mp_spis_mod,\n+\t\t\t\t\t\t\t\tp->m_time_out);\n+\t\t\t\tif (result != 0)\n+\t\t\t\t\treturn result;\n+\n+\t\t\t\tresult = nthw_spis_read_rx_fifo(p->mp_spis_mod,\n+\t\t\t\t\t\t\t\t&spi_rx_hdr.raw);\n+\t\t\t\tif (result != 0) {\n+\t\t\t\t\tNT_LOG(WRN, NTHW,\n+\t\t\t\t\t       \"nthw_spis_read_rx_fifo failed\\n\");\n+\t\t\t\t\treturn result;\n+\t\t\t\t}\n+\n+\t\t\t\tspi_rx_hdr.raw = ntohl(spi_rx_hdr.raw);\n+\t\t\t\trx_size = spi_rx_hdr.size;\n+\t\t\t\trx_hdr_read = true; /* Next time read payload */\n+\n+#ifdef SPI_V3_DEBUG_PRINT\n+\t\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t\t       \"  spi_rx_hdr.error_code = 0x%04X, spi_rx_hdr.size = 0x%04X\\n\",\n+\t\t\t\t       spi_rx_hdr.error_code, spi_rx_hdr.size);\n+#endif\n+\n+\t\t\t\tif (spi_rx_hdr.error_code != 0) {\n+\t\t\t\t\tresult = -1; /* NT_ERROR_AVR_OPCODE_RETURNED_ERROR; */\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\n+\t\t\t\tif (rx_size > max_payload_rx_size) {\n+\t\t\t\t\tresult = 1; /* NT_ERROR_AVR_RX_BUFFER_TOO_SMALL; */\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t} else { /* Read the payload */\n+\t\t\t\tcount = (uint16_t)(rx_size < 4U ? rx_size : 4U);\n+\n+\t\t\t\tif (count == 0)\n+\t\t\t\t\tbreak;\n+\n+\t\t\t\tresult = wait_for_rx_data_ready(p->mp_spis_mod,\n+\t\t\t\t\t\t\t    p->m_time_out);\n+\t\t\t\tif (result != 0)\n+\t\t\t\t\treturn result;\n+\n+\t\t\t\tresult = nthw_spis_read_rx_fifo(p->mp_spis_mod,\n+\t\t\t\t\t\t\t       &value);\n+\t\t\t\tif (result != 0) {\n+\t\t\t\t\tNT_LOG(WRN, NTHW,\n+\t\t\t\t\t       \"nthw_spis_read_rx_fifo failed\\n\");\n+\t\t\t\t\treturn result;\n+\t\t\t\t}\n+\n+\t\t\t\tvalue = ntohl(value); /* Convert to host endian */\n+\t\t\t\tmemcpy(rx_data, &value, count);\n+\t\t\t\trx_buf->size = (uint16_t)(rx_buf->size + count);\n+\t\t\t\trx_size = (uint16_t)(rx_size - count);\n+\t\t\t\trx_data += count;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+#ifdef SPI_V3_DEBUG_PRINT\n+\tNT_LOG(DBG, NTHW, \"  RxData: %d\\n\", rx_buf->size);\n+\tdump_hex(rx_buf->p_buf, rx_buf->size);\n+\tNT_LOG(DBG, NTHW, \"%s:  Ended: %d\\n\", __func__, result);\n+#endif\n+\n+\treturn result;\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_spi_v3.h b/drivers/net/ntnic/nthw/core/nthw_spi_v3.h\nnew file mode 100644\nindex 0000000000..c54379a273\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_spi_v3.h\n@@ -0,0 +1,106 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NT4GA_SPI_V3__\n+#define __NT4GA_SPI_V3__\n+\n+/* Must include v1.x series. The first v1.0a only had 248 bytes of storage. v2.0x have 255 */\n+#define MAX_AVR_CONTAINER_SIZE (248)\n+\n+enum avr_opcodes {\n+\tAVR_OP_NOP = 0, /* v2 NOP command */\n+\t/* version handlers */\n+\tAVR_OP_VERSION = 1,\n+\tAVR_OP_SPI_VERSION = 2, /* v2.0+ command Get protocol version */\n+\tAVR_OP_SYSINFO = 3,\n+\t/* Ping handlers */\n+\tAVR_OP_PING = 4,\n+\tAVR_OP_PING_DELAY = 5,\n+\t/* i2c handlers */\n+\tAVR_OP_I2C_READ = 9,\n+\tAVR_OP_I2C_WRITE = 10,\n+\tAVR_OP_I2C_RANDOM_READ = 11,\n+\t/* VPD handlers */\n+\tAVR_OP_VPD_READ = 19,\n+\tAVR_OP_VPD_WRITE = 20,\n+\t/* SENSOR handlers */\n+\tAVR_OP_SENSOR_FETCH = 28,\n+\t/* The following command are only relevant to V3 */\n+\tAVR_OP_SENSOR_MON_CONTROL = 42,\n+\tAVR_OP_SENSOR_MON_SETUP = 43,\n+\t/* special version handler */\n+\tAVR_OP_SYSINFO_2 = 62,\n+};\n+\n+#define GEN2_AVR_IDENT_SIZE (20)\n+#define GEN2_AVR_VERSION_SIZE (50)\n+\n+#define GEN2_PN_SIZE (13)\n+#define GEN2_PBA_SIZE (16)\n+#define GEN2_SN_SIZE (10)\n+#define GEN2_BNAME_SIZE (14)\n+#define GEN2_PLATFORM_SIZE (72)\n+#define GEN2_VPD_SIZE_TOTAL                                                  \\\n+\t(1 + GEN2_PN_SIZE + GEN2_PBA_SIZE + GEN2_SN_SIZE + GEN2_BNAME_SIZE + \\\n+\t GEN2_PLATFORM_SIZE + 2)\n+\n+typedef struct vpd_eeprom_s {\n+\tuint8_t psu_hw_version; /* Hw revision - MUST NEVER ne overwritten. */\n+\t/* Vital Product Data: P/N   (13bytes ascii 0-9) */\n+\tuint8_t vpd_pn[GEN2_PN_SIZE];\n+\t/* Vital Product Data: PBA   (16bytes ascii 0-9) */\n+\tuint8_t vpd_pba[GEN2_PBA_SIZE];\n+\t/* Vital Product Data: S/N   (10bytes ascii 0-9) */\n+\tuint8_t vpd_sn[GEN2_SN_SIZE];\n+\t/* Vital Product Data: Board Name (10bytes ascii) (e.g. \"ntmainb1e2\" or \"ntfront20b1\") */\n+\tuint8_t vpd_board_name[GEN2_BNAME_SIZE];\n+\t/*\n+\t * Vital Product Data: Other (72bytes of MAC addresses or other stuff.. (gives up to 12 mac\n+\t * addresses)\n+\t */\n+\tuint8_t vpd_platform_section[GEN2_PLATFORM_SIZE];\n+\t/* CRC16 checksum of all of above. This field is not included in the checksum */\n+\tuint16_t crc16;\n+} vpd_eeprom_t;\n+\n+typedef struct {\n+\tuint8_t psu_hw_revision;\n+\tchar board_type[GEN2_BNAME_SIZE + 1];\n+\tchar product_id[GEN2_PN_SIZE + 1];\n+\tchar pba_id[GEN2_PBA_SIZE + 1];\n+\tchar serial_number[GEN2_SN_SIZE + 1];\n+\tuint8_t product_family;\n+\tuint32_t feature_mask;\n+\tuint32_t invfeature_mask;\n+\tuint8_t no_of_macs;\n+\tuint8_t mac_address[6];\n+\tuint16_t custom_id;\n+\tuint8_t user_id[8];\n+} board_info_t;\n+\n+struct tx_rx_buf {\n+\tuint16_t size;\n+\tvoid *p_buf;\n+};\n+\n+struct nthw__spi__v3 {\n+\tint m_time_out;\n+\tint mn_instance_no;\n+\tnthw_spim_t *mp_spim_mod;\n+\tnthw_spis_t *mp_spis_mod;\n+};\n+\n+typedef struct nthw__spi__v3 nthw_spi_v3_t;\n+typedef struct nthw__spi__v3 nthw_spi_v3;\n+\n+nthw_spi_v3_t *nthw_spi_v3_new(void);\n+int nthw_spi_v3_init(nthw_spi_v3_t *p, nt_fpga_t *p_fpga, int n_instance_no);\n+void nthw_spi_v3_delete(nthw_spi_v3_t *p);\n+\n+int nthw_spi_v3_set_timeout(nthw_spi_v3_t *p, int time_out);\n+int nthw_spi_v3_get_version(nthw_spi_v3_t *p);\n+int nthw_spi_v3_transfer(nthw_spi_v3_t *p, uint16_t opcode,\n+\t\t\t struct tx_rx_buf *tx_buf, struct tx_rx_buf *rx_buf);\n+\n+#endif /* __NT4GA_SPI_V3__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_spim.c b/drivers/net/ntnic/nthw/core/nthw_spim.c\nnew file mode 100644\nindex 0000000000..ece7db26e1\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_spim.c\n@@ -0,0 +1,117 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_spim.h\"\n+\n+nthw_spim_t *nthw_spim_new(void)\n+{\n+\tnthw_spim_t *p = malloc(sizeof(nthw_spim_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_spim_t));\n+\treturn p;\n+}\n+\n+int nthw_spim_init(nthw_spim_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tconst char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_SPIM, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: SPIM %d: no such instance\\n\",\n+\t\t       p_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_spim = mod;\n+\n+\t/* SPIM is a primary communication channel - turn off debug by default */\n+\tmodule_set_debug_mode(p->mp_mod_spim, 0x00);\n+\n+\tp->mp_reg_srr = module_get_register(p->mp_mod_spim, SPIM_SRR);\n+\tp->mp_fld_srr_rst = register_get_field(p->mp_reg_srr, SPIM_SRR_RST);\n+\n+\tp->mp_reg_cr = module_get_register(p->mp_mod_spim, SPIM_CR);\n+\tp->mp_fld_cr_loop = register_get_field(p->mp_reg_cr, SPIM_CR_LOOP);\n+\tp->mp_fld_cr_en = register_get_field(p->mp_reg_cr, SPIM_CR_EN);\n+\tp->mp_fld_cr_txrst = register_get_field(p->mp_reg_cr, SPIM_CR_TXRST);\n+\tp->mp_fld_cr_rxrst = register_get_field(p->mp_reg_cr, SPIM_CR_RXRST);\n+\n+\tp->mp_reg_sr = module_get_register(p->mp_mod_spim, SPIM_SR);\n+\tp->mp_fld_sr_done = register_get_field(p->mp_reg_sr, SPIM_SR_DONE);\n+\tp->mp_fld_sr_txempty = register_get_field(p->mp_reg_sr, SPIM_SR_TXEMPTY);\n+\tp->mp_fld_sr_rxempty = register_get_field(p->mp_reg_sr, SPIM_SR_RXEMPTY);\n+\tp->mp_fld_sr_txfull = register_get_field(p->mp_reg_sr, SPIM_SR_TXFULL);\n+\tp->mp_fld_sr_rxfull = register_get_field(p->mp_reg_sr, SPIM_SR_RXFULL);\n+\tp->mp_fld_sr_txlvl = register_get_field(p->mp_reg_sr, SPIM_SR_TXLVL);\n+\tp->mp_fld_sr_rxlvl = register_get_field(p->mp_reg_sr, SPIM_SR_RXLVL);\n+\n+\tp->mp_reg_dtr = module_get_register(p->mp_mod_spim, SPIM_DTR);\n+\tp->mp_fld_dtr_dtr = register_get_field(p->mp_reg_dtr, SPIM_DTR_DTR);\n+\n+\tp->mp_reg_drr = module_get_register(p->mp_mod_spim, SPIM_DRR);\n+\tp->mp_fld_drr_drr = register_get_field(p->mp_reg_drr, SPIM_DRR_DRR);\n+\n+\tp->mp_reg_cfg = module_get_register(p->mp_mod_spim, SPIM_CFG);\n+\tp->mp_fld_cfg_pre = register_get_field(p->mp_reg_cfg, SPIM_CFG_PRE);\n+\n+\treturn 0;\n+}\n+\n+void nthw_spim_delete(nthw_spim_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_spim_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+uint32_t nthw_spim_reset(nthw_spim_t *p)\n+{\n+\tregister_update(p->mp_reg_srr);\n+\tfield_set_val32(p->mp_fld_srr_rst,\n+\t\t       0x0A); /* 0x0A hardcoded value - see doc */\n+\tregister_flush(p->mp_reg_srr, 1);\n+\n+\treturn 0;\n+}\n+\n+uint32_t nthw_spim_enable(nthw_spim_t *p, bool b_enable)\n+{\n+\tfield_update_register(p->mp_fld_cr_en);\n+\n+\tif (b_enable)\n+\t\tfield_set_all(p->mp_fld_cr_en);\n+\n+\telse\n+\t\tfield_clr_all(p->mp_fld_cr_en);\n+\tfield_flush_register(p->mp_fld_cr_en);\n+\n+\treturn 0;\n+}\n+\n+uint32_t nthw_spim_write_tx_fifo(nthw_spim_t *p, uint32_t n_data)\n+{\n+\tfield_set_val_flush32(p->mp_fld_dtr_dtr, n_data);\n+\treturn 0;\n+}\n+\n+uint32_t nthw_spim_get_tx_fifo_empty(nthw_spim_t *p, bool *pb_empty)\n+{\n+\tassert(pb_empty);\n+\n+\t*pb_empty = field_get_updated(p->mp_fld_sr_txempty) ? true : false;\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_spim.h b/drivers/net/ntnic/nthw/core/nthw_spim.h\nnew file mode 100644\nindex 0000000000..713751e563\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_spim.h\n@@ -0,0 +1,52 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_SPIM_H__\n+#define __NTHW_SPIM_H__\n+\n+struct nthw_spim {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_spim;\n+\tint mn_instance;\n+\n+\tnt_register_t *mp_reg_srr;\n+\tnt_field_t *mp_fld_srr_rst;\n+\n+\tnt_register_t *mp_reg_cr;\n+\tnt_field_t *mp_fld_cr_loop;\n+\tnt_field_t *mp_fld_cr_en;\n+\tnt_field_t *mp_fld_cr_txrst;\n+\tnt_field_t *mp_fld_cr_rxrst;\n+\n+\tnt_register_t *mp_reg_sr;\n+\tnt_field_t *mp_fld_sr_done;\n+\tnt_field_t *mp_fld_sr_txempty;\n+\tnt_field_t *mp_fld_sr_rxempty;\n+\tnt_field_t *mp_fld_sr_txfull;\n+\tnt_field_t *mp_fld_sr_rxfull;\n+\tnt_field_t *mp_fld_sr_txlvl;\n+\tnt_field_t *mp_fld_sr_rxlvl;\n+\n+\tnt_register_t *mp_reg_dtr;\n+\tnt_field_t *mp_fld_dtr_dtr;\n+\n+\tnt_register_t *mp_reg_drr;\n+\tnt_field_t *mp_fld_drr_drr;\n+\tnt_register_t *mp_reg_cfg;\n+\tnt_field_t *mp_fld_cfg_pre;\n+};\n+\n+typedef struct nthw_spim nthw_spim_t;\n+typedef struct nthw_spim nthw_spim;\n+\n+nthw_spim_t *nthw_spim_new(void);\n+int nthw_spim_init(nthw_spim_t *p, nt_fpga_t *p_fpga, int n_instance);\n+void nthw_spim_delete(nthw_spim_t *p);\n+\n+uint32_t nthw_spim_reset(nthw_spim_t *p);\n+uint32_t nthw_spim_enable(nthw_spim_t *p, bool b_enable);\n+uint32_t nthw_spim_get_tx_fifo_empty(nthw_spim_t *p, bool *pb_empty);\n+uint32_t nthw_spim_write_tx_fifo(nthw_spim_t *p, uint32_t n_data);\n+\n+#endif /* __NTHW_SPIM_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_spis.c b/drivers/net/ntnic/nthw/core/nthw_spis.c\nnew file mode 100644\nindex 0000000000..8799584194\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_spis.c\n@@ -0,0 +1,147 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_spis.h\"\n+\n+nthw_spis_t *nthw_spis_new(void)\n+{\n+\tnthw_spis_t *p = malloc(sizeof(nthw_spis_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_spis_t));\n+\treturn p;\n+}\n+\n+int nthw_spis_init(nthw_spis_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tconst char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_SPIS, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: SPIS %d: no such instance\\n\",\n+\t\t       p_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_spis = mod;\n+\n+\t/* SPIS is a primary communication channel - turn off debug by default */\n+\tmodule_set_debug_mode(p->mp_mod_spis, 0x00);\n+\n+\tp->mp_reg_srr = module_get_register(p->mp_mod_spis, SPIS_SRR);\n+\tp->mp_fld_srr_rst = register_get_field(p->mp_reg_srr, SPIS_SRR_RST);\n+\n+\tp->mp_reg_cr = module_get_register(p->mp_mod_spis, SPIS_CR);\n+\tp->mp_fld_cr_loop = register_get_field(p->mp_reg_cr, SPIS_CR_LOOP);\n+\tp->mp_fld_cr_en = register_get_field(p->mp_reg_cr, SPIS_CR_EN);\n+\tp->mp_fld_cr_txrst = register_get_field(p->mp_reg_cr, SPIS_CR_TXRST);\n+\tp->mp_fld_cr_rxrst = register_get_field(p->mp_reg_cr, SPIS_CR_RXRST);\n+\tp->mp_fld_cr_debug = register_get_field(p->mp_reg_cr, SPIS_CR_DEBUG);\n+\n+\tp->mp_reg_sr = module_get_register(p->mp_mod_spis, SPIS_SR);\n+\tp->mp_fld_sr_done = register_get_field(p->mp_reg_sr, SPIS_SR_DONE);\n+\tp->mp_fld_sr_txempty = register_get_field(p->mp_reg_sr, SPIS_SR_TXEMPTY);\n+\tp->mp_fld_sr_rxempty = register_get_field(p->mp_reg_sr, SPIS_SR_RXEMPTY);\n+\tp->mp_fld_sr_txfull = register_get_field(p->mp_reg_sr, SPIS_SR_TXFULL);\n+\tp->mp_fld_sr_rxfull = register_get_field(p->mp_reg_sr, SPIS_SR_RXFULL);\n+\tp->mp_fld_sr_txlvl = register_get_field(p->mp_reg_sr, SPIS_SR_TXLVL);\n+\tp->mp_fld_sr_rxlvl = register_get_field(p->mp_reg_sr, SPIS_SR_RXLVL);\n+\tp->mp_fld_sr_frame_err =\n+\t\tregister_get_field(p->mp_reg_sr, SPIS_SR_FRAME_ERR);\n+\tp->mp_fld_sr_read_err = register_get_field(p->mp_reg_sr, SPIS_SR_READ_ERR);\n+\tp->mp_fld_sr_write_err =\n+\t\tregister_get_field(p->mp_reg_sr, SPIS_SR_WRITE_ERR);\n+\n+\tp->mp_reg_dtr = module_get_register(p->mp_mod_spis, SPIS_DTR);\n+\tp->mp_fld_dtr_dtr = register_get_field(p->mp_reg_dtr, SPIS_DTR_DTR);\n+\n+\tp->mp_reg_drr = module_get_register(p->mp_mod_spis, SPIS_DRR);\n+\tp->mp_fld_drr_drr = register_get_field(p->mp_reg_drr, SPIS_DRR_DRR);\n+\n+\tp->mp_reg_ram_ctrl = module_get_register(p->mp_mod_spis, SPIS_RAM_CTRL);\n+\tp->mp_fld_ram_ctrl_adr =\n+\t\tregister_get_field(p->mp_reg_ram_ctrl, SPIS_RAM_CTRL_ADR);\n+\tp->mp_fld_ram_ctrl_cnt =\n+\t\tregister_get_field(p->mp_reg_ram_ctrl, SPIS_RAM_CTRL_CNT);\n+\n+\tp->mp_reg_ram_data = module_get_register(p->mp_mod_spis, SPIS_RAM_DATA);\n+\tp->mp_fld_ram_data_data =\n+\t\tregister_get_field(p->mp_reg_ram_data, SPIS_RAM_DATA_DATA);\n+\n+\treturn 0;\n+}\n+\n+void nthw_spis_delete(nthw_spis_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_spis_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+uint32_t nthw_spis_reset(nthw_spis_t *p)\n+{\n+\tregister_update(p->mp_reg_srr);\n+\tfield_set_val32(p->mp_fld_srr_rst,\n+\t\t       0x0A); /* 0x0A hardcoded value - see doc */\n+\tregister_flush(p->mp_reg_srr, 1);\n+\n+\treturn 0;\n+}\n+\n+uint32_t nthw_spis_enable(nthw_spis_t *p, bool b_enable)\n+{\n+\tfield_update_register(p->mp_fld_cr_en);\n+\n+\tif (b_enable)\n+\t\tfield_set_all(p->mp_fld_cr_en);\n+\n+\telse\n+\t\tfield_clr_all(p->mp_fld_cr_en);\n+\tfield_flush_register(p->mp_fld_cr_en);\n+\n+\treturn 0;\n+}\n+\n+uint32_t nthw_spis_get_rx_fifo_empty(nthw_spis_t *p, bool *pb_empty)\n+{\n+\tassert(pb_empty);\n+\n+\t*pb_empty = field_get_updated(p->mp_fld_sr_rxempty) ? true : false;\n+\n+\treturn 0;\n+}\n+\n+uint32_t nthw_spis_read_rx_fifo(nthw_spis_t *p, uint32_t *p_data)\n+{\n+\tassert(p_data);\n+\n+\t*p_data = field_get_updated(p->mp_fld_drr_drr);\n+\n+\treturn 0;\n+}\n+\n+uint32_t nthw_spis_read_sensor(nthw_spis_t *p, uint8_t n_result_idx,\n+\t\t\t      uint32_t *p_sensor_result)\n+{\n+\tassert(p_sensor_result);\n+\n+\tfield_set_val32(p->mp_fld_ram_ctrl_adr, n_result_idx);\n+\tfield_set_val32(p->mp_fld_ram_ctrl_cnt, 1);\n+\tregister_flush(p->mp_reg_ram_ctrl, 1);\n+\n+\t*p_sensor_result = field_get_updated(p->mp_fld_ram_data_data);\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_spis.h b/drivers/net/ntnic/nthw/core/nthw_spis.h\nnew file mode 100644\nindex 0000000000..2ebe840c9e\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_spis.h\n@@ -0,0 +1,63 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_SPIS_H__\n+#define __NTHW_SPIS_H__\n+\n+struct nthw_spis {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_spis;\n+\tint mn_instance;\n+\n+\tnt_register_t *mp_reg_srr;\n+\tnt_field_t *mp_fld_srr_rst;\n+\n+\tnt_register_t *mp_reg_cr;\n+\tnt_field_t *mp_fld_cr_loop;\n+\tnt_field_t *mp_fld_cr_en;\n+\tnt_field_t *mp_fld_cr_txrst;\n+\tnt_field_t *mp_fld_cr_rxrst;\n+\tnt_field_t *mp_fld_cr_debug;\n+\n+\tnt_register_t *mp_reg_sr;\n+\tnt_field_t *mp_fld_sr_done;\n+\tnt_field_t *mp_fld_sr_txempty;\n+\tnt_field_t *mp_fld_sr_rxempty;\n+\tnt_field_t *mp_fld_sr_txfull;\n+\tnt_field_t *mp_fld_sr_rxfull;\n+\tnt_field_t *mp_fld_sr_txlvl;\n+\tnt_field_t *mp_fld_sr_rxlvl;\n+\tnt_field_t *mp_fld_sr_frame_err;\n+\tnt_field_t *mp_fld_sr_read_err;\n+\tnt_field_t *mp_fld_sr_write_err;\n+\n+\tnt_register_t *mp_reg_dtr;\n+\tnt_field_t *mp_fld_dtr_dtr;\n+\n+\tnt_register_t *mp_reg_drr;\n+\tnt_field_t *mp_fld_drr_drr;\n+\n+\tnt_register_t *mp_reg_ram_ctrl;\n+\tnt_field_t *mp_fld_ram_ctrl_adr;\n+\tnt_field_t *mp_fld_ram_ctrl_cnt;\n+\n+\tnt_register_t *mp_reg_ram_data;\n+\tnt_field_t *mp_fld_ram_data_data;\n+};\n+\n+typedef struct nthw_spis nthw_spis_t;\n+typedef struct nthw_spis nthw_spis;\n+\n+nthw_spis_t *nthw_spis_new(void);\n+int nthw_spis_init(nthw_spis_t *p, nt_fpga_t *p_fpga, int n_instance);\n+void nthw_spis_delete(nthw_spis_t *p);\n+\n+uint32_t nthw_spis_reset(nthw_spis_t *p);\n+uint32_t nthw_spis_enable(nthw_spis_t *p, bool b_enable);\n+uint32_t nthw_spis_get_rx_fifo_empty(nthw_spis_t *p, bool *pb_empty);\n+uint32_t nthw_spis_read_rx_fifo(nthw_spis_t *p, uint32_t *p_data);\n+uint32_t nthw_spis_read_sensor(nthw_spis_t *p, uint8_t n_result_idx,\n+\t\t\t      uint32_t *p_sensor_result);\n+\n+#endif /* __NTHW_SPIS_H__ */\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_tsm.c b/drivers/net/ntnic/nthw/core/nthw_tsm.c\nnew file mode 100644\nindex 0000000000..8ea4a4c440\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_tsm.c\n@@ -0,0 +1,179 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_tsm.h\"\n+\n+nthw_tsm_t *nthw_tsm_new(void)\n+{\n+\tnthw_tsm_t *p = malloc(sizeof(nthw_tsm_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_tsm_t));\n+\treturn p;\n+}\n+\n+void nthw_tsm_delete(nthw_tsm_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_tsm_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+int nthw_tsm_init(nthw_tsm_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tconst char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_TSM, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: TSM %d: no such instance\\n\",\n+\t\t       p_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_tsm = mod;\n+\n+\t{\n+\t\tnt_register_t *p_reg;\n+\n+\t\tp_reg = module_get_register(p->mp_mod_tsm, TSM_CONFIG);\n+\t\tp->mp_fld_config_ts_format =\n+\t\t\tregister_get_field(p_reg, TSM_CONFIG_TS_FORMAT);\n+\n+\t\tp_reg = module_get_register(p->mp_mod_tsm, TSM_TIMER_CTRL);\n+\t\tp->mp_fld_timer_ctrl_timer_en_t0 =\n+\t\t\tregister_get_field(p_reg, TSM_TIMER_CTRL_TIMER_EN_T0);\n+\t\tp->mp_fld_timer_ctrl_timer_en_t1 =\n+\t\t\tregister_get_field(p_reg, TSM_TIMER_CTRL_TIMER_EN_T1);\n+\n+\t\tp_reg = module_get_register(p->mp_mod_tsm, TSM_TIMER_T0);\n+\t\tp->mp_fld_timer_timer_t0_max_count =\n+\t\t\tregister_get_field(p_reg, TSM_TIMER_T0_MAX_COUNT);\n+\n+\t\tp_reg = module_get_register(p->mp_mod_tsm, TSM_TIMER_T1);\n+\t\tp->mp_fld_timer_timer_t1_max_count =\n+\t\t\tregister_get_field(p_reg, TSM_TIMER_T1_MAX_COUNT);\n+\n+\t\tp_reg = module_get_register(p->mp_mod_tsm, TSM_TIME_LO);\n+\t\tp->mp_reg_time_lo = module_get_register(p->mp_mod_tsm, TSM_TIME_LO);\n+\t\tp->mp_fld_time_lo = register_get_field(p_reg, TSM_TIME_LO_NS);\n+\n+\t\tp_reg = module_get_register(p->mp_mod_tsm, TSM_TIME_HI);\n+\t\tp->mp_reg_time_hi = module_get_register(p->mp_mod_tsm, TSM_TIME_HI);\n+\t\tp->mp_fld_time_hi = register_get_field(p_reg, TSM_TIME_HI_SEC);\n+\n+\t\tp_reg = module_get_register(p->mp_mod_tsm, TSM_TS_LO);\n+\t\tp->mp_reg_ts_lo = module_get_register(p->mp_mod_tsm, TSM_TS_LO);\n+\t\tp->mp_fld_ts_lo = register_get_field(p_reg, TSM_TS_LO_TIME);\n+\n+\t\tp_reg = module_get_register(p->mp_mod_tsm, TSM_TS_HI);\n+\t\tp->mp_reg_ts_hi = module_get_register(p->mp_mod_tsm, TSM_TS_HI);\n+\t\tp->mp_fld_ts_hi = register_get_field(p_reg, TSM_TS_HI_TIME);\n+\t}\n+\treturn 0;\n+}\n+\n+int nthw_tsm_get_ts(nthw_tsm_t *p, uint64_t *p_ts)\n+{\n+\tuint32_t n_ts_lo, n_ts_hi;\n+\tuint64_t val;\n+\n+\tif (!p_ts)\n+\t\treturn -1;\n+\n+\tn_ts_lo = field_get_updated(p->mp_fld_ts_lo);\n+\tn_ts_hi = field_get_updated(p->mp_fld_ts_hi);\n+\n+\tval = ((((uint64_t)n_ts_hi) << 32UL) | n_ts_lo);\n+\n+\tif (p_ts)\n+\t\t*p_ts = val;\n+\n+\treturn 0;\n+}\n+\n+int nthw_tsm_get_time(nthw_tsm_t *p, uint64_t *p_time)\n+{\n+\tuint32_t n_time_lo, n_time_hi;\n+\tuint64_t val;\n+\n+\tif (!p_time)\n+\t\treturn -1;\n+\n+\tn_time_lo = field_get_updated(p->mp_fld_time_lo);\n+\tn_time_hi = field_get_updated(p->mp_fld_time_hi);\n+\n+\tval = ((((uint64_t)n_time_hi) << 32UL) | n_time_lo);\n+\n+\tif (p_time)\n+\t\t*p_time = val;\n+\n+\treturn 0;\n+}\n+\n+int nthw_tsm_set_time(nthw_tsm_t *p, uint64_t n_time)\n+{\n+\tfield_set_val_flush32(p->mp_fld_time_lo, (n_time & 0xFFFFFFFF));\n+\tfield_set_val_flush32(p->mp_fld_time_hi,\n+\t\t\t    (uint32_t)((n_time >> 32) & 0xFFFFFFFF));\n+\treturn 0;\n+}\n+\n+int nthw_tsm_set_timer_t0_enable(nthw_tsm_t *p, bool b_enable)\n+{\n+\tfield_update_register(p->mp_fld_timer_ctrl_timer_en_t0);\n+\tif (b_enable)\n+\t\tfield_set_flush(p->mp_fld_timer_ctrl_timer_en_t0);\n+\n+\telse\n+\t\tfield_clr_flush(p->mp_fld_timer_ctrl_timer_en_t0);\n+\treturn 0;\n+}\n+\n+int nthw_tsm_set_timer_t0_max_count(nthw_tsm_t *p, uint32_t n_timer_val)\n+{\n+\t/* Timer T0 - stat toggle timer */\n+\tfield_update_register(p->mp_fld_timer_timer_t0_max_count);\n+\tfield_set_val_flush32(p->mp_fld_timer_timer_t0_max_count,\n+\t\t\t    n_timer_val); /* ns (50*1000*1000) */\n+\treturn 0;\n+}\n+\n+int nthw_tsm_set_timer_t1_enable(nthw_tsm_t *p, bool b_enable)\n+{\n+\tfield_update_register(p->mp_fld_timer_ctrl_timer_en_t1);\n+\tif (b_enable)\n+\t\tfield_set_flush(p->mp_fld_timer_ctrl_timer_en_t1);\n+\n+\telse\n+\t\tfield_clr_flush(p->mp_fld_timer_ctrl_timer_en_t1);\n+\treturn 0;\n+}\n+\n+int nthw_tsm_set_timer_t1_max_count(nthw_tsm_t *p, uint32_t n_timer_val)\n+{\n+\t/* Timer T1 - keep alive timer */\n+\tfield_update_register(p->mp_fld_timer_timer_t1_max_count);\n+\tfield_set_val_flush32(p->mp_fld_timer_timer_t1_max_count,\n+\t\t\t    n_timer_val); /* ns (100*1000*1000) */\n+\treturn 0;\n+}\n+\n+int nthw_tsm_set_config_ts_format(nthw_tsm_t *p, uint32_t n_val)\n+{\n+\tfield_update_register(p->mp_fld_config_ts_format);\n+\t/* 0x1: Native - 10ns units, start date: 1970-01-01. */\n+\tfield_set_val_flush32(p->mp_fld_config_ts_format, n_val);\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/core/nthw_tsm.h b/drivers/net/ntnic/nthw/core/nthw_tsm.h\nnew file mode 100644\nindex 0000000000..590e04c312\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/core/nthw_tsm.h\n@@ -0,0 +1,53 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_TSM_H__\n+#define __NTHW_TSM_H__\n+\n+struct nthw_tsm {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_tsm;\n+\tint mn_instance;\n+\n+\tnt_field_t *mp_fld_config_ts_format;\n+\n+\tnt_field_t *mp_fld_timer_ctrl_timer_en_t0;\n+\tnt_field_t *mp_fld_timer_ctrl_timer_en_t1;\n+\n+\tnt_field_t *mp_fld_timer_timer_t0_max_count;\n+\n+\tnt_field_t *mp_fld_timer_timer_t1_max_count;\n+\n+\tnt_register_t *mp_reg_ts_lo;\n+\tnt_field_t *mp_fld_ts_lo;\n+\n+\tnt_register_t *mp_reg_ts_hi;\n+\tnt_field_t *mp_fld_ts_hi;\n+\n+\tnt_register_t *mp_reg_time_lo;\n+\tnt_field_t *mp_fld_time_lo;\n+\n+\tnt_register_t *mp_reg_time_hi;\n+\tnt_field_t *mp_fld_time_hi;\n+};\n+\n+typedef struct nthw_tsm nthw_tsm_t;\n+typedef struct nthw_tsm nthw_tsm;\n+\n+nthw_tsm_t *nthw_tsm_new(void);\n+void nthw_tsm_delete(nthw_tsm_t *p);\n+int nthw_tsm_init(nthw_tsm_t *p, nt_fpga_t *p_fpga, int n_instance);\n+\n+int nthw_tsm_get_ts(nthw_tsm_t *p, uint64_t *p_ts);\n+int nthw_tsm_get_time(nthw_tsm_t *p, uint64_t *p_time);\n+int nthw_tsm_set_time(nthw_tsm_t *p, uint64_t n_time);\n+\n+int nthw_tsm_set_timer_t0_enable(nthw_tsm_t *p, bool b_enable);\n+int nthw_tsm_set_timer_t0_max_count(nthw_tsm_t *p, uint32_t n_timer_val);\n+int nthw_tsm_set_timer_t1_enable(nthw_tsm_t *p, bool b_enable);\n+int nthw_tsm_set_timer_t1_max_count(nthw_tsm_t *p, uint32_t n_timer_val);\n+\n+int nthw_tsm_set_config_ts_format(nthw_tsm_t *p, uint32_t n_val);\n+\n+#endif /* __NTHW_TSM_H__ */\ndiff --git a/drivers/net/ntnic/nthw/nthw_dbs.c b/drivers/net/ntnic/nthw/nthw_dbs.c\nnew file mode 100644\nindex 0000000000..9fc853da73\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_dbs.c\n@@ -0,0 +1,1301 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <errno.h>\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_dbs.h\"\n+\n+#undef DBS_PRINT_REGS\n+\n+static void set_shadow_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable,\n+\t\t\t\tuint32_t ir, uint32_t bs);\n+static void flush_tx_qos_data(nthw_dbs_t *p, uint32_t index);\n+static void set_shadow_tx_qp_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint32_t virtual_port);\n+static void flush_tx_qp_data(nthw_dbs_t *p, uint32_t index);\n+static void set_shadow_tx_dr_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint64_t guest_physical_address, uint32_t host_id,\n+\t\t\t       uint32_t queue_size, uint32_t port,\n+\t\t\t       uint32_t header, uint32_t packed);\n+static void flush_tx_dr_data(nthw_dbs_t *p, uint32_t index);\n+static void set_shadow_rx_dr_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint64_t guest_physical_address, uint32_t host_id,\n+\t\t\t       uint32_t queue_size, uint32_t header,\n+\t\t\t       uint32_t packed);\n+static void flush_rx_dr_data(nthw_dbs_t *p, uint32_t index);\n+static void set_shadow_tx_uw_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint64_t guest_physical_address, uint32_t host_id,\n+\t\t\t       uint32_t queue_size, uint32_t packed,\n+\t\t\t       uint32_t int_enable, uint32_t vec, uint32_t istk,\n+\t\t\t       uint32_t in_order);\n+static void flush_tx_uw_data(nthw_dbs_t *p, uint32_t index);\n+static void set_shadow_rx_uw_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint64_t guest_physical_address, uint32_t host_id,\n+\t\t\t       uint32_t queue_size, uint32_t packed,\n+\t\t\t       uint32_t int_enable, uint32_t vec,\n+\t\t\t       uint32_t istk);\n+static void flush_rx_uw_data(nthw_dbs_t *p, uint32_t index);\n+static void set_shadow_rx_am_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint64_t guest_physical_address, uint32_t enable,\n+\t\t\t       uint32_t host_id, uint32_t packed,\n+\t\t\t       uint32_t int_enable);\n+static void flush_rx_am_data(nthw_dbs_t *p, uint32_t index);\n+static void set_shadow_tx_am_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint64_t guest_physical_address, uint32_t enable,\n+\t\t\t       uint32_t host_id, uint32_t packed,\n+\t\t\t       uint32_t int_enable);\n+static void flush_tx_am_data(nthw_dbs_t *p, uint32_t index);\n+\n+nthw_dbs_t *nthw_dbs_new(void)\n+{\n+\tnthw_dbs_t *p = malloc(sizeof(nthw_dbs_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_dbs_t));\n+\treturn p;\n+}\n+\n+void nthw_dbs_delete(nthw_dbs_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_dbs_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+int dbs_init(nthw_dbs_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_DBS, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: DBS %d: no such instance\\n\",\n+\t\t       p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_dbs = mod;\n+\n+\tp->mn_param_dbs_present = fpga_get_product_param(p_fpga, NT_DBS_PRESENT, 0);\n+\tif (p->mn_param_dbs_present == 0) {\n+\t\tNT_LOG(WRN, NTHW,\n+\t\t       \"%s: DBS %d: logical error: module found but not flagged at present\\n\",\n+\t\t       p->mp_fpga->p_fpga_info->mp_adapter_id_str, p->mn_instance);\n+\t}\n+\n+\tp->mp_reg_rx_control = module_get_register(p->mp_mod_dbs, DBS_RX_CONTROL);\n+\tp->mp_fld_rx_control_last_queue =\n+\t\tregister_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_LQ);\n+\tp->mp_fld_rx_control_avail_monitor_enable =\n+\t\tregister_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_AME);\n+\tp->mp_fld_rx_control_avail_monitor_scan_speed =\n+\t\tregister_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_AMS);\n+\tp->mp_fld_rx_control_used_write_enable =\n+\t\tregister_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_UWE);\n+\tp->mp_fld_rx_control_used_writer_update_speed =\n+\t\tregister_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_UWS);\n+\tp->mp_fld_rx_control_rx_queues_enable =\n+\t\tregister_get_field(p->mp_reg_rx_control, DBS_RX_CONTROL_QE);\n+\n+\tp->mp_reg_tx_control = module_get_register(p->mp_mod_dbs, DBS_TX_CONTROL);\n+\tp->mp_fld_tx_control_last_queue =\n+\t\tregister_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_LQ);\n+\tp->mp_fld_tx_control_avail_monitor_enable =\n+\t\tregister_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_AME);\n+\tp->mp_fld_tx_control_avail_monitor_scan_speed =\n+\t\tregister_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_AMS);\n+\tp->mp_fld_tx_control_used_write_enable =\n+\t\tregister_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_UWE);\n+\tp->mp_fld_tx_control_used_writer_update_speed =\n+\t\tregister_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_UWS);\n+\tp->mp_fld_tx_control_tx_queues_enable =\n+\t\tregister_get_field(p->mp_reg_tx_control, DBS_TX_CONTROL_QE);\n+\n+\tp->mp_reg_rx_init = module_get_register(p->mp_mod_dbs, DBS_RX_INIT);\n+\tp->mp_fld_rx_init_init =\n+\t\tregister_get_field(p->mp_reg_rx_init, DBS_RX_INIT_INIT);\n+\tp->mp_fld_rx_init_queue =\n+\t\tregister_get_field(p->mp_reg_rx_init, DBS_RX_INIT_QUEUE);\n+\tp->mp_fld_rx_init_busy =\n+\t\tregister_get_field(p->mp_reg_rx_init, DBS_RX_INIT_BUSY);\n+\n+\tp->mp_reg_rx_init_val = module_query_register(p->mp_mod_dbs, DBS_RX_INIT_VAL);\n+\tif (p->mp_reg_rx_init_val) {\n+\t\tp->mp_fld_rx_init_val_idx = register_query_field(p->mp_reg_rx_init_val,\n+\t\t\t\t       DBS_RX_INIT_VAL_IDX);\n+\t\tp->mp_fld_rx_init_val_ptr = register_query_field(p->mp_reg_rx_init_val,\n+\t\t\t\t       DBS_RX_INIT_VAL_PTR);\n+\t}\n+\n+\tp->mp_reg_rx_ptr = module_query_register(p->mp_mod_dbs, DBS_RX_PTR);\n+\tif (p->mp_reg_rx_ptr) {\n+\t\tp->mp_fld_rx_ptr_ptr =\n+\t\t\tregister_query_field(p->mp_reg_rx_ptr, DBS_RX_PTR_PTR);\n+\t\tp->mp_fld_rx_ptr_queue =\n+\t\t\tregister_query_field(p->mp_reg_rx_ptr, DBS_RX_PTR_QUEUE);\n+\t\tp->mp_fld_rx_ptr_valid =\n+\t\t\tregister_query_field(p->mp_reg_rx_ptr, DBS_RX_PTR_VALID);\n+\t}\n+\n+\tp->mp_reg_tx_init = module_get_register(p->mp_mod_dbs, DBS_TX_INIT);\n+\tp->mp_fld_tx_init_init =\n+\t\tregister_get_field(p->mp_reg_tx_init, DBS_TX_INIT_INIT);\n+\tp->mp_fld_tx_init_queue =\n+\t\tregister_get_field(p->mp_reg_tx_init, DBS_TX_INIT_QUEUE);\n+\tp->mp_fld_tx_init_busy =\n+\t\tregister_get_field(p->mp_reg_tx_init, DBS_TX_INIT_BUSY);\n+\n+\tp->mp_reg_tx_init_val = module_query_register(p->mp_mod_dbs, DBS_TX_INIT_VAL);\n+\tif (p->mp_reg_tx_init_val) {\n+\t\tp->mp_fld_tx_init_val_idx = register_query_field(p->mp_reg_tx_init_val,\n+\t\t\t\t       DBS_TX_INIT_VAL_IDX);\n+\t\tp->mp_fld_tx_init_val_ptr = register_query_field(p->mp_reg_tx_init_val,\n+\t\t\t\t       DBS_TX_INIT_VAL_PTR);\n+\t}\n+\n+\tp->mp_reg_tx_ptr = module_query_register(p->mp_mod_dbs, DBS_TX_PTR);\n+\tif (p->mp_reg_tx_ptr) {\n+\t\tp->mp_fld_tx_ptr_ptr =\n+\t\t\tregister_query_field(p->mp_reg_tx_ptr, DBS_TX_PTR_PTR);\n+\t\tp->mp_fld_tx_ptr_queue =\n+\t\t\tregister_query_field(p->mp_reg_tx_ptr, DBS_TX_PTR_QUEUE);\n+\t\tp->mp_fld_tx_ptr_valid =\n+\t\t\tregister_query_field(p->mp_reg_tx_ptr, DBS_TX_PTR_VALID);\n+\t}\n+\n+\tp->mp_reg_rx_idle = module_query_register(p->mp_mod_dbs, DBS_RX_IDLE);\n+\tif (p->mp_reg_rx_idle) {\n+\t\tp->mp_fld_rx_idle_idle =\n+\t\t\tregister_query_field(p->mp_reg_rx_idle, DBS_RX_IDLE_IDLE);\n+\t\tp->mp_fld_rx_idle_queue =\n+\t\t\tregister_query_field(p->mp_reg_rx_idle, DBS_RX_IDLE_QUEUE);\n+\t\tp->mp_fld_rx_idle_busy =\n+\t\t\tregister_query_field(p->mp_reg_rx_idle, DBS_RX_IDLE_BUSY);\n+\t}\n+\n+\tp->mp_reg_tx_idle = module_query_register(p->mp_mod_dbs, DBS_TX_IDLE);\n+\tif (p->mp_reg_tx_idle) {\n+\t\tp->mp_fld_tx_idle_idle =\n+\t\t\tregister_query_field(p->mp_reg_tx_idle, DBS_TX_IDLE_IDLE);\n+\t\tp->mp_fld_tx_idle_queue =\n+\t\t\tregister_query_field(p->mp_reg_tx_idle, DBS_TX_IDLE_QUEUE);\n+\t\tp->mp_fld_tx_idle_busy =\n+\t\t\tregister_query_field(p->mp_reg_tx_idle, DBS_TX_IDLE_BUSY);\n+\t}\n+\n+\tp->mp_reg_rx_avail_monitor_control =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_RX_AM_CTRL);\n+\tp->mp_fld_rx_avail_monitor_control_adr =\n+\t\tregister_get_field(p->mp_reg_rx_avail_monitor_control, DBS_RX_AM_CTRL_ADR);\n+\tp->mp_fld_rx_avail_monitor_control_cnt =\n+\t\tregister_get_field(p->mp_reg_rx_avail_monitor_control, DBS_RX_AM_CTRL_CNT);\n+\n+\tp->mp_reg_rx_avail_monitor_data =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_RX_AM_DATA);\n+\tp->mp_fld_rx_avail_monitor_data_guest_physical_address =\n+\t\tregister_get_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_GPA);\n+\tp->mp_fld_rx_avail_monitor_data_enable =\n+\t\tregister_get_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_ENABLE);\n+\tp->mp_fld_rx_avail_monitor_data_host_id =\n+\t\tregister_get_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_HID);\n+\tp->mp_fld_rx_avail_monitor_data_packed =\n+\t\tregister_query_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_PCKED);\n+\tp->mp_fld_rx_avail_monitor_data_int =\n+\t\tregister_query_field(p->mp_reg_rx_avail_monitor_data, DBS_RX_AM_DATA_INT);\n+\n+\tp->mp_reg_tx_avail_monitor_control =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_TX_AM_CTRL);\n+\tp->mp_fld_tx_avail_monitor_control_adr =\n+\t\tregister_get_field(p->mp_reg_tx_avail_monitor_control, DBS_TX_AM_CTRL_ADR);\n+\tp->mp_fld_tx_avail_monitor_control_cnt =\n+\t\tregister_get_field(p->mp_reg_tx_avail_monitor_control, DBS_TX_AM_CTRL_CNT);\n+\n+\tp->mp_reg_tx_avail_monitor_data =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_TX_AM_DATA);\n+\tp->mp_fld_tx_avail_monitor_data_guest_physical_address =\n+\t\tregister_get_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_GPA);\n+\tp->mp_fld_tx_avail_monitor_data_enable =\n+\t\tregister_get_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_ENABLE);\n+\tp->mp_fld_tx_avail_monitor_data_host_id =\n+\t\tregister_get_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_HID);\n+\tp->mp_fld_tx_avail_monitor_data_packed =\n+\t\tregister_query_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_PCKED);\n+\tp->mp_fld_tx_avail_monitor_data_int =\n+\t\tregister_query_field(p->mp_reg_tx_avail_monitor_data, DBS_TX_AM_DATA_INT);\n+\n+\tp->mp_reg_rx_used_writer_control =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_RX_UW_CTRL);\n+\tp->mp_fld_rx_used_writer_control_adr =\n+\t\tregister_get_field(p->mp_reg_rx_used_writer_control, DBS_RX_UW_CTRL_ADR);\n+\tp->mp_fld_rx_used_writer_control_cnt =\n+\t\tregister_get_field(p->mp_reg_rx_used_writer_control, DBS_RX_UW_CTRL_CNT);\n+\n+\tp->mp_reg_rx_used_writer_data =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_RX_UW_DATA);\n+\tp->mp_fld_rx_used_writer_data_guest_physical_address =\n+\t\tregister_get_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_GPA);\n+\tp->mp_fld_rx_used_writer_data_host_id =\n+\t\tregister_get_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_HID);\n+\tp->mp_fld_rx_used_writer_data_queue_size =\n+\t\tregister_get_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_QS);\n+\tp->mp_fld_rx_used_writer_data_packed =\n+\t\tregister_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_PCKED);\n+\tp->mp_fld_rx_used_writer_data_int =\n+\t\tregister_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_INT);\n+\tp->mp_fld_rx_used_writer_data_vec =\n+\t\tregister_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_VEC);\n+\tp->mp_fld_rx_used_writer_data_istk =\n+\t\tregister_query_field(p->mp_reg_rx_used_writer_data, DBS_RX_UW_DATA_ISTK);\n+\n+\tp->mp_reg_tx_used_writer_control =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_TX_UW_CTRL);\n+\tp->mp_fld_tx_used_writer_control_adr =\n+\t\tregister_get_field(p->mp_reg_tx_used_writer_control, DBS_TX_UW_CTRL_ADR);\n+\tp->mp_fld_tx_used_writer_control_cnt =\n+\t\tregister_get_field(p->mp_reg_tx_used_writer_control, DBS_TX_UW_CTRL_CNT);\n+\n+\tp->mp_reg_tx_used_writer_data =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_TX_UW_DATA);\n+\tp->mp_fld_tx_used_writer_data_guest_physical_address =\n+\t\tregister_get_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_GPA);\n+\tp->mp_fld_tx_used_writer_data_host_id =\n+\t\tregister_get_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_HID);\n+\tp->mp_fld_tx_used_writer_data_queue_size =\n+\t\tregister_get_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_QS);\n+\tp->mp_fld_tx_used_writer_data_packed =\n+\t\tregister_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_PCKED);\n+\tp->mp_fld_tx_used_writer_data_int =\n+\t\tregister_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_INT);\n+\tp->mp_fld_tx_used_writer_data_vec =\n+\t\tregister_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_VEC);\n+\tp->mp_fld_tx_used_writer_data_istk =\n+\t\tregister_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_ISTK);\n+\tp->mp_fld_tx_used_writer_data_in_order =\n+\t\tregister_query_field(p->mp_reg_tx_used_writer_data, DBS_TX_UW_DATA_INO);\n+\n+\tp->mp_reg_rx_descriptor_reader_control =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_RX_DR_CTRL);\n+\tp->mp_fld_rx_descriptor_reader_control_adr =\n+\t\tregister_get_field(p->mp_reg_rx_descriptor_reader_control, DBS_RX_DR_CTRL_ADR);\n+\tp->mp_fld_rx_descriptor_reader_control_cnt =\n+\t\tregister_get_field(p->mp_reg_rx_descriptor_reader_control, DBS_RX_DR_CTRL_CNT);\n+\n+\tp->mp_reg_rx_descriptor_reader_data =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_RX_DR_DATA);\n+\tp->mp_fld_rx_descriptor_reader_data_guest_physical_address =\n+\t\tregister_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_GPA);\n+\tp->mp_fld_rx_descriptor_reader_data_host_id =\n+\t\tregister_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_HID);\n+\tp->mp_fld_rx_descriptor_reader_data_queue_size =\n+\t\tregister_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_QS);\n+\tp->mp_fld_rx_descriptor_reader_data_header =\n+\t\tregister_get_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_HDR);\n+\tp->mp_fld_rx_descriptor_reader_data_packed =\n+\t\tregister_query_field(p->mp_reg_rx_descriptor_reader_data, DBS_RX_DR_DATA_PCKED);\n+\n+\tp->mp_reg_tx_descriptor_reader_control =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_TX_DR_CTRL);\n+\tp->mp_fld_tx_descriptor_reader_control_adr =\n+\t\tregister_get_field(p->mp_reg_tx_descriptor_reader_control, DBS_TX_DR_CTRL_ADR);\n+\tp->mp_fld_tx_descriptor_reader_control_cnt =\n+\t\tregister_get_field(p->mp_reg_tx_descriptor_reader_control, DBS_TX_DR_CTRL_CNT);\n+\n+\tp->mp_reg_tx_descriptor_reader_data =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_TX_DR_DATA);\n+\tp->mp_fld_tx_descriptor_reader_data_guest_physical_address =\n+\t\tregister_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_GPA);\n+\tp->mp_fld_tx_descriptor_reader_data_host_id =\n+\t\tregister_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_HID);\n+\tp->mp_fld_tx_descriptor_reader_data_queue_size =\n+\t\tregister_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_QS);\n+\tp->mp_fld_tx_descriptor_reader_data_header =\n+\t\tregister_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_HDR);\n+\tp->mp_fld_tx_descriptor_reader_data_port =\n+\t\tregister_get_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_PORT);\n+\tp->mp_fld_tx_descriptor_reader_data_packed =\n+\t\tregister_query_field(p->mp_reg_tx_descriptor_reader_data, DBS_TX_DR_DATA_PCKED);\n+\n+\tp->mp_reg_tx_queue_property_control =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_TX_QP_CTRL);\n+\tp->mp_fld_tx_queue_property_control_adr =\n+\t\tregister_get_field(p->mp_reg_tx_queue_property_control, DBS_TX_QP_CTRL_ADR);\n+\tp->mp_fld_tx_queue_property_control_cnt =\n+\t\tregister_get_field(p->mp_reg_tx_queue_property_control, DBS_TX_QP_CTRL_CNT);\n+\n+\tp->mp_reg_tx_queue_property_data =\n+\t\tmodule_get_register(p->mp_mod_dbs, DBS_TX_QP_DATA);\n+\tp->mp_fld_tx_queue_property_data_v_port =\n+\t\tregister_get_field(p->mp_reg_tx_queue_property_data, DBS_TX_QP_DATA_VPORT);\n+\n+\t/* HW QoS Tx rate limiting policing RFC2697/RFC4111 */\n+\tp->mp_reg_tx_queue_qos_control =\n+\t\tmodule_query_register(p->mp_mod_dbs, DBS_TX_QOS_CTRL);\n+\tp->mp_reg_tx_queue_qos_data =\n+\t\tmodule_query_register(p->mp_mod_dbs, DBS_TX_QOS_DATA);\n+\tif (p->mp_reg_tx_queue_qos_control) {\n+\t\tp->mp_reg_tx_queue_qos_control_adr =\n+\t\t\tregister_query_field(p->mp_reg_tx_queue_qos_control, DBS_TX_QOS_CTRL_ADR);\n+\t\tp->mp_reg_tx_queue_qos_control_cnt =\n+\t\t\tregister_query_field(p->mp_reg_tx_queue_qos_control, DBS_TX_QOS_CTRL_CNT);\n+\n+\t\tif (p->mp_reg_tx_queue_qos_data) {\n+\t\t\tp->mp_reg_tx_queue_qos_data_en =\n+\t\t\t\tregister_query_field(p->mp_reg_tx_queue_qos_data,\n+\t\t\t\t\t\t     DBS_TX_QOS_DATA_EN);\n+\t\t\tp->mp_reg_tx_queue_qos_data_ir =\n+\t\t\t\tregister_query_field(p->mp_reg_tx_queue_qos_data,\n+\t\t\t\t\t\t     DBS_TX_QOS_DATA_IR);\n+\t\t\tp->mp_reg_tx_queue_qos_data_bs =\n+\t\t\t\tregister_query_field(p->mp_reg_tx_queue_qos_data,\n+\t\t\t\t\t\t     DBS_TX_QOS_DATA_BS);\n+\t\t}\n+\t}\n+\n+\tp->mp_reg_tx_queue_qos_rate =\n+\t\tmodule_query_register(p->mp_mod_dbs, DBS_TX_QOS_RATE);\n+\tif (p->mp_reg_tx_queue_qos_rate) {\n+\t\tp->mp_reg_tx_queue_qos_rate_mul =\n+\t\t\tregister_query_field(p->mp_reg_tx_queue_qos_rate, DBS_TX_QOS_RATE_MUL);\n+\t\tp->mp_reg_tx_queue_qos_rate_div =\n+\t\t\tregister_query_field(p->mp_reg_tx_queue_qos_rate, DBS_TX_QOS_RATE_DIV);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int dbs_reset_rx_control(nthw_dbs_t *p)\n+{\n+\tfield_set_val32(p->mp_fld_rx_control_last_queue, 0);\n+\tfield_set_val32(p->mp_fld_rx_control_avail_monitor_enable, 0);\n+\tfield_set_val32(p->mp_fld_rx_control_avail_monitor_scan_speed, 8);\n+\tfield_set_val32(p->mp_fld_rx_control_used_write_enable, 0);\n+\tfield_set_val32(p->mp_fld_rx_control_used_writer_update_speed, 5);\n+\tfield_set_val32(p->mp_fld_rx_control_rx_queues_enable, 0);\n+\tregister_flush(p->mp_reg_rx_control, 1);\n+\treturn 0;\n+}\n+\n+int dbs_reset_tx_control(nthw_dbs_t *p)\n+{\n+\tfield_set_val32(p->mp_fld_tx_control_last_queue, 0);\n+\tfield_set_val32(p->mp_fld_tx_control_avail_monitor_enable, 0);\n+\tfield_set_val32(p->mp_fld_tx_control_avail_monitor_scan_speed, 5);\n+\tfield_set_val32(p->mp_fld_tx_control_used_write_enable, 0);\n+\tfield_set_val32(p->mp_fld_tx_control_used_writer_update_speed, 8);\n+\tfield_set_val32(p->mp_fld_tx_control_tx_queues_enable, 0);\n+\tregister_flush(p->mp_reg_tx_control, 1);\n+\treturn 0;\n+}\n+\n+void dbs_reset(nthw_dbs_t *p)\n+{\n+\tuint32_t i;\n+\n+\tNT_LOG(DBG, NTHW, \"NthwDbs::%s: resetting DBS\", __func__);\n+\n+\tdbs_reset_rx_control(p);\n+\tdbs_reset_tx_control(p);\n+\n+\t/* Reset RX memory banks and shado */\n+\tfor (i = 0; i < NT_DBS_RX_QUEUES_MAX; ++i) {\n+\t\tset_shadow_rx_am_data(p, i, 0, 0, 0, 0, 0);\n+\t\tflush_rx_am_data(p, i);\n+\n+\t\tset_shadow_rx_uw_data(p, i, 0, 0, 0, 0, 0, 0, 0);\n+\t\tflush_rx_uw_data(p, i);\n+\n+\t\tset_shadow_rx_dr_data(p, i, 0, 0, 0, 0, 0);\n+\t\tflush_rx_dr_data(p, i);\n+\t}\n+\n+\t/* Reset TX memory banks and shado */\n+\tfor (i = 0; i < NT_DBS_TX_QUEUES_MAX; ++i) {\n+\t\tset_shadow_tx_am_data(p, i, 0, 0, 0, 0, 0);\n+\t\tflush_tx_am_data(p, i);\n+\n+\t\tset_shadow_tx_uw_data(p, i, 0, 0, 0, 0, 0, 0, 0, 0);\n+\t\tflush_tx_uw_data(p, i);\n+\n+\t\tset_shadow_tx_dr_data(p, i, 0, 0, 0, 0, 0, 0);\n+\t\tflush_tx_dr_data(p, i);\n+\n+\t\tset_shadow_tx_qp_data(p, i, 0);\n+\t\tflush_tx_qp_data(p, i);\n+\n+\t\tset_shadow_tx_qos_data(p, i, 0, 0, 0);\n+\t\tflush_tx_qos_data(p, i);\n+\t}\n+}\n+\n+int set_rx_control(nthw_dbs_t *p, uint32_t last_queue,\n+\t\t   uint32_t avail_monitor_enable, uint32_t avail_monitor_speed,\n+\t\t   uint32_t used_write_enable, uint32_t used_write_speed,\n+\t\t   uint32_t rx_queue_enable)\n+{\n+#ifdef DBS_PRINT_REGS\n+\tprintf(\"last_queue %u\\n\", last_queue);\n+\tprintf(\"avail_monitor_enable %u\\n\", avail_monitor_enable);\n+\tprintf(\"avail_monitor_speed %u\\n\", avail_monitor_speed);\n+\tprintf(\"used_write_enable %u\\n\", used_write_enable);\n+\tprintf(\"used_write_speed %u\\n\", used_write_speed);\n+\tprintf(\"rx_queue_enable %u\\n\", rx_queue_enable);\n+#endif\n+\n+\tfield_set_val32(p->mp_fld_rx_control_last_queue, last_queue);\n+\tfield_set_val32(p->mp_fld_rx_control_avail_monitor_enable, avail_monitor_enable);\n+\tfield_set_val32(p->mp_fld_rx_control_avail_monitor_scan_speed,\n+\t\t       avail_monitor_speed);\n+\tfield_set_val32(p->mp_fld_rx_control_used_write_enable, used_write_enable);\n+\tfield_set_val32(p->mp_fld_rx_control_used_writer_update_speed, used_write_speed);\n+\tfield_set_val32(p->mp_fld_rx_control_rx_queues_enable, rx_queue_enable);\n+\tregister_flush(p->mp_reg_rx_control, 1);\n+\treturn 0;\n+}\n+\n+int nthw_dbs_get_rx_control(nthw_dbs_t *p, uint32_t *last_queue,\n+\t\t\t uint32_t *avail_monitor_enable,\n+\t\t\t uint32_t *avail_monitor_speed, uint32_t *used_write_enable,\n+\t\t\t uint32_t *used_write_speed, uint32_t *rx_queue_enable)\n+{\n+\t*last_queue = field_get_val32(p->mp_fld_rx_control_last_queue);\n+\t*avail_monitor_enable =\n+\t\tfield_get_val32(p->mp_fld_rx_control_avail_monitor_enable);\n+\t*avail_monitor_speed =\n+\t\tfield_get_val32(p->mp_fld_rx_control_avail_monitor_scan_speed);\n+\t*used_write_enable = field_get_val32(p->mp_fld_rx_control_used_write_enable);\n+\t*used_write_speed =\n+\t\tfield_get_val32(p->mp_fld_rx_control_used_writer_update_speed);\n+\t*rx_queue_enable = field_get_val32(p->mp_fld_rx_control_rx_queues_enable);\n+\treturn 0;\n+}\n+\n+int set_tx_control(nthw_dbs_t *p, uint32_t last_queue,\n+\t\t   uint32_t avail_monitor_enable, uint32_t avail_monitor_speed,\n+\t\t   uint32_t used_write_enable, uint32_t used_write_speed,\n+\t\t   uint32_t tx_queue_enable)\n+{\n+#ifdef DBS_PRINT_REGS\n+\tprintf(\"last_queue %u\\n\", last_queue);\n+\tprintf(\"avail_monitor_enable %u\\n\", avail_monitor_enable);\n+\tprintf(\"avail_monitor_speed %u\\n\", avail_monitor_speed);\n+\tprintf(\"used_write_enable %u\\n\", used_write_enable);\n+\tprintf(\"used_write_speed %u\\n\", used_write_speed);\n+#endif\n+\n+\tfield_set_val32(p->mp_fld_tx_control_last_queue, last_queue);\n+\tfield_set_val32(p->mp_fld_tx_control_avail_monitor_enable, avail_monitor_enable);\n+\tfield_set_val32(p->mp_fld_tx_control_avail_monitor_scan_speed,\n+\t\t       avail_monitor_speed);\n+\tfield_set_val32(p->mp_fld_tx_control_used_write_enable, used_write_enable);\n+\tfield_set_val32(p->mp_fld_tx_control_used_writer_update_speed, used_write_speed);\n+\tfield_set_val32(p->mp_fld_tx_control_tx_queues_enable, tx_queue_enable);\n+\tregister_flush(p->mp_reg_tx_control, 1);\n+\treturn 0;\n+}\n+\n+int nthw_dbs_get_tx_control(nthw_dbs_t *p, uint32_t *last_queue,\n+\t\t\t uint32_t *avail_monitor_enable,\n+\t\t\t uint32_t *avail_monitor_speed, uint32_t *used_write_enable,\n+\t\t\t uint32_t *used_write_speed, uint32_t *tx_queue_enable)\n+{\n+\t*last_queue = field_get_val32(p->mp_fld_tx_control_last_queue);\n+\t*avail_monitor_enable =\n+\t\tfield_get_val32(p->mp_fld_tx_control_avail_monitor_enable);\n+\t*avail_monitor_speed =\n+\t\tfield_get_val32(p->mp_fld_tx_control_avail_monitor_scan_speed);\n+\t*used_write_enable = field_get_val32(p->mp_fld_tx_control_used_write_enable);\n+\t*used_write_speed =\n+\t\tfield_get_val32(p->mp_fld_tx_control_used_writer_update_speed);\n+\t*tx_queue_enable = field_get_val32(p->mp_fld_tx_control_tx_queues_enable);\n+\treturn 0;\n+}\n+\n+int set_rx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr,\n+\t\tuint32_t init, uint32_t queue)\n+{\n+\tif (p->mp_reg_rx_init_val) {\n+\t\tfield_set_val32(p->mp_fld_rx_init_val_idx, start_idx);\n+\t\tfield_set_val32(p->mp_fld_rx_init_val_ptr, start_ptr);\n+\t\tregister_flush(p->mp_reg_rx_init_val, 1);\n+\t}\n+\tfield_set_val32(p->mp_fld_rx_init_init, init);\n+\tfield_set_val32(p->mp_fld_rx_init_queue, queue);\n+\tregister_flush(p->mp_reg_rx_init, 1);\n+\treturn 0;\n+}\n+\n+int get_rx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy)\n+{\n+\t*init = field_get_val32(p->mp_fld_rx_init_init);\n+\t*queue = field_get_val32(p->mp_fld_rx_init_queue);\n+\t*busy = field_get_val32(p->mp_fld_rx_init_busy);\n+\treturn 0;\n+}\n+\n+int set_tx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr,\n+\t\tuint32_t init, uint32_t queue)\n+{\n+\tif (p->mp_reg_tx_init_val) {\n+\t\tfield_set_val32(p->mp_fld_tx_init_val_idx, start_idx);\n+\t\tfield_set_val32(p->mp_fld_tx_init_val_ptr, start_ptr);\n+\t\tregister_flush(p->mp_reg_tx_init_val, 1);\n+\t}\n+\tfield_set_val32(p->mp_fld_tx_init_init, init);\n+\tfield_set_val32(p->mp_fld_tx_init_queue, queue);\n+\tregister_flush(p->mp_reg_tx_init, 1);\n+\treturn 0;\n+}\n+\n+int get_tx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy)\n+{\n+\t*init = field_get_val32(p->mp_fld_tx_init_init);\n+\t*queue = field_get_val32(p->mp_fld_tx_init_queue);\n+\t*busy = field_get_val32(p->mp_fld_tx_init_busy);\n+\treturn 0;\n+}\n+\n+int set_rx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue)\n+\n+{\n+\tif (!p->mp_reg_rx_idle)\n+\t\treturn -ENOTSUP;\n+\n+\tfield_set_val32(p->mp_fld_rx_idle_idle, idle);\n+\tfield_set_val32(p->mp_fld_rx_idle_queue, queue);\n+\tregister_flush(p->mp_reg_rx_idle, 1);\n+\treturn 0;\n+}\n+\n+int get_rx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy)\n+{\n+\tif (!p->mp_reg_rx_idle)\n+\t\treturn -ENOTSUP;\n+\n+\t*idle = field_get_updated(p->mp_fld_rx_idle_idle);\n+\t*queue = 0;\n+\t*busy = field_get_updated(p->mp_fld_rx_idle_busy);\n+\treturn 0;\n+}\n+\n+int set_tx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue)\n+\n+{\n+\tif (!p->mp_reg_tx_idle)\n+\t\treturn -ENOTSUP;\n+\n+\tfield_set_val32(p->mp_fld_tx_idle_idle, idle);\n+\tfield_set_val32(p->mp_fld_tx_idle_queue, queue);\n+\tregister_flush(p->mp_reg_tx_idle, 1);\n+\treturn 0;\n+}\n+\n+int get_tx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy)\n+{\n+\tif (!p->mp_reg_tx_idle)\n+\t\treturn -ENOTSUP;\n+\n+\t*idle = field_get_updated(p->mp_fld_tx_idle_idle);\n+\t*queue = 0;\n+\t*busy = field_get_updated(p->mp_fld_tx_idle_busy);\n+\treturn 0;\n+}\n+\n+int set_rx_ptr_queue(nthw_dbs_t *p, uint32_t queue)\n+{\n+\tif (!p->mp_reg_rx_ptr)\n+\t\treturn -ENOTSUP;\n+\n+\tfield_set_val32(p->mp_fld_rx_ptr_queue, queue);\n+\tregister_flush(p->mp_reg_rx_ptr, 1);\n+\treturn 0;\n+}\n+\n+int get_rx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid)\n+{\n+\tif (!p->mp_reg_rx_ptr)\n+\t\treturn -ENOTSUP;\n+\n+\t*ptr = field_get_updated(p->mp_fld_rx_ptr_ptr);\n+\t*queue = 0;\n+\t*valid = field_get_updated(p->mp_fld_rx_ptr_valid);\n+\treturn 0;\n+}\n+\n+int set_tx_ptr_queue(nthw_dbs_t *p, uint32_t queue)\n+{\n+\tif (!p->mp_reg_tx_ptr)\n+\t\treturn -ENOTSUP;\n+\n+\tfield_set_val32(p->mp_fld_tx_ptr_queue, queue);\n+\tregister_flush(p->mp_reg_tx_ptr, 1);\n+\treturn 0;\n+}\n+\n+int get_tx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid)\n+{\n+\tif (!p->mp_reg_tx_ptr)\n+\t\treturn -ENOTSUP;\n+\n+\t*ptr = field_get_updated(p->mp_fld_tx_ptr_ptr);\n+\t*queue = 0;\n+\t*valid = field_get_updated(p->mp_fld_tx_ptr_valid);\n+\treturn 0;\n+}\n+\n+static void set_rx_am_data_index(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val32(p->mp_fld_rx_avail_monitor_control_adr, index);\n+\tfield_set_val32(p->mp_fld_rx_avail_monitor_control_cnt, 1);\n+\tregister_flush(p->mp_reg_rx_avail_monitor_control, 1);\n+}\n+\n+static void\n+set_shadow_rx_am_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t       uint64_t guest_physical_address)\n+{\n+\tp->m_rx_am_shadow[index].guest_physical_address = guest_physical_address;\n+}\n+\n+static void nthw_dbs_set_shadow_rx_am_data_enable(nthw_dbs_t *p, uint32_t index,\n+\t\tuint32_t enable)\n+{\n+\tp->m_rx_am_shadow[index].enable = enable;\n+}\n+\n+static void set_shadow_rx_am_data_host_id(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t     uint32_t host_id)\n+{\n+\tp->m_rx_am_shadow[index].host_id = host_id;\n+}\n+\n+static void set_shadow_rx_am_data_packed(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t     uint32_t packed)\n+{\n+\tp->m_rx_am_shadow[index].packed = packed;\n+}\n+\n+static void set_shadow_rx_am_data_int_enable(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t\tuint32_t int_enable)\n+{\n+\tp->m_rx_am_shadow[index].int_enable = int_enable;\n+}\n+\n+static void set_shadow_rx_am_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint64_t guest_physical_address, uint32_t enable,\n+\t\t\t       uint32_t host_id, uint32_t packed,\n+\t\t\t       uint32_t int_enable)\n+{\n+\tset_shadow_rx_am_data_guest_physical_address(p, index, guest_physical_address);\n+\tnthw_dbs_set_shadow_rx_am_data_enable(p, index, enable);\n+\tset_shadow_rx_am_data_host_id(p, index, host_id);\n+\tset_shadow_rx_am_data_packed(p, index, packed);\n+\tset_shadow_rx_am_data_int_enable(p, index, int_enable);\n+}\n+\n+static void flush_rx_am_data(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val(p->mp_fld_rx_avail_monitor_data_guest_physical_address,\n+\t\t     (uint32_t *)&p->m_rx_am_shadow[index].guest_physical_address,\n+\t\t     2);\n+\tfield_set_val32(p->mp_fld_rx_avail_monitor_data_enable,\n+\t\t       p->m_rx_am_shadow[index].enable);\n+\tfield_set_val32(p->mp_fld_rx_avail_monitor_data_host_id,\n+\t\t       p->m_rx_am_shadow[index].host_id);\n+\tif (p->mp_fld_rx_avail_monitor_data_packed) {\n+\t\tfield_set_val32(p->mp_fld_rx_avail_monitor_data_packed,\n+\t\t\t       p->m_rx_am_shadow[index].packed);\n+\t}\n+\tif (p->mp_fld_rx_avail_monitor_data_int) {\n+\t\tfield_set_val32(p->mp_fld_rx_avail_monitor_data_int,\n+\t\t\t       p->m_rx_am_shadow[index].int_enable);\n+\t}\n+\n+\tset_rx_am_data_index(p, index);\n+\tregister_flush(p->mp_reg_rx_avail_monitor_data, 1);\n+}\n+\n+int set_rx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,\n+\t\t   uint32_t enable, uint32_t host_id, uint32_t packed,\n+\t\t   uint32_t int_enable)\n+{\n+\tif (!p->mp_reg_rx_avail_monitor_data)\n+\t\treturn -ENOTSUP;\n+\n+\tset_shadow_rx_am_data(p, index, guest_physical_address, enable, host_id,\n+\t\t\t   packed, int_enable);\n+\tflush_rx_am_data(p, index);\n+\treturn 0;\n+}\n+\n+static void set_tx_am_data_index(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val32(p->mp_fld_tx_avail_monitor_control_adr, index);\n+\tfield_set_val32(p->mp_fld_tx_avail_monitor_control_cnt, 1);\n+\tregister_flush(p->mp_reg_tx_avail_monitor_control, 1);\n+}\n+\n+static void set_shadow_tx_am_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint64_t guest_physical_address, uint32_t enable,\n+\t\t\t       uint32_t host_id, uint32_t packed,\n+\t\t\t       uint32_t int_enable)\n+{\n+\tp->m_tx_am_shadow[index].guest_physical_address = guest_physical_address;\n+\tp->m_tx_am_shadow[index].enable = enable;\n+\tp->m_tx_am_shadow[index].host_id = host_id;\n+\tp->m_tx_am_shadow[index].packed = packed;\n+\tp->m_tx_am_shadow[index].int_enable = int_enable;\n+}\n+\n+static void flush_tx_am_data(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val(p->mp_fld_tx_avail_monitor_data_guest_physical_address,\n+\t\t     (uint32_t *)&p->m_tx_am_shadow[index].guest_physical_address,\n+\t\t     2);\n+\tfield_set_val32(p->mp_fld_tx_avail_monitor_data_enable,\n+\t\t       p->m_tx_am_shadow[index].enable);\n+\tfield_set_val32(p->mp_fld_tx_avail_monitor_data_host_id,\n+\t\t       p->m_tx_am_shadow[index].host_id);\n+\tif (p->mp_fld_tx_avail_monitor_data_packed) {\n+\t\tfield_set_val32(p->mp_fld_tx_avail_monitor_data_packed,\n+\t\t\t       p->m_tx_am_shadow[index].packed);\n+\t}\n+\tif (p->mp_fld_tx_avail_monitor_data_int) {\n+\t\tfield_set_val32(p->mp_fld_tx_avail_monitor_data_int,\n+\t\t\t       p->m_tx_am_shadow[index].int_enable);\n+\t}\n+\n+\tset_tx_am_data_index(p, index);\n+\tregister_flush(p->mp_reg_tx_avail_monitor_data, 1);\n+}\n+\n+int set_tx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,\n+\t\t   uint32_t enable, uint32_t host_id, uint32_t packed,\n+\t\t   uint32_t int_enable)\n+{\n+\tif (!p->mp_reg_tx_avail_monitor_data)\n+\t\treturn -ENOTSUP;\n+\n+\tset_shadow_tx_am_data(p, index, guest_physical_address, enable, host_id,\n+\t\t\t   packed, int_enable);\n+\tflush_tx_am_data(p, index);\n+\treturn 0;\n+}\n+\n+static void set_rx_uw_data_index(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val32(p->mp_fld_rx_used_writer_control_adr, index);\n+\tfield_set_val32(p->mp_fld_rx_used_writer_control_cnt, 1);\n+\tregister_flush(p->mp_reg_rx_used_writer_control, 1);\n+}\n+\n+static void\n+set_shadow_rx_uw_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t       uint64_t guest_physical_address)\n+{\n+\tp->m_rx_uw_shadow[index].guest_physical_address = guest_physical_address;\n+}\n+\n+static void set_shadow_rx_uw_data_host_id(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t     uint32_t host_id)\n+{\n+\tp->m_rx_uw_shadow[index].host_id = host_id;\n+}\n+\n+static void set_shadow_rx_uw_data_queue_size(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t\tuint32_t queue_size)\n+{\n+\tp->m_rx_uw_shadow[index].queue_size = queue_size;\n+}\n+\n+static void set_shadow_rx_uw_data_packed(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t     uint32_t packed)\n+{\n+\tp->m_rx_uw_shadow[index].packed = packed;\n+}\n+\n+static void set_shadow_rx_uw_data_int_enable(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t\tuint32_t int_enable)\n+{\n+\tp->m_rx_uw_shadow[index].int_enable = int_enable;\n+}\n+\n+static void set_shadow_rx_uw_data_vec(nthw_dbs_t *p, uint32_t index, uint32_t vec)\n+{\n+\tp->m_rx_uw_shadow[index].vec = vec;\n+}\n+\n+static void set_shadow_rx_uw_data_istk(nthw_dbs_t *p, uint32_t index, uint32_t istk)\n+{\n+\tp->m_rx_uw_shadow[index].istk = istk;\n+}\n+\n+static void set_shadow_rx_uw_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint64_t guest_physical_address, uint32_t host_id,\n+\t\t\t       uint32_t queue_size, uint32_t packed,\n+\t\t\t       uint32_t int_enable, uint32_t vec, uint32_t istk)\n+{\n+\tset_shadow_rx_uw_data_guest_physical_address(p, index, guest_physical_address);\n+\tset_shadow_rx_uw_data_host_id(p, index, host_id);\n+\tset_shadow_rx_uw_data_queue_size(p, index, queue_size);\n+\tset_shadow_rx_uw_data_packed(p, index, packed);\n+\tset_shadow_rx_uw_data_int_enable(p, index, int_enable);\n+\tset_shadow_rx_uw_data_vec(p, index, vec);\n+\tset_shadow_rx_uw_data_istk(p, index, istk);\n+}\n+\n+static void flush_rx_uw_data(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val(p->mp_fld_rx_used_writer_data_guest_physical_address,\n+\t\t     (uint32_t *)&p->m_rx_uw_shadow[index].guest_physical_address,\n+\t\t     2);\n+\tfield_set_val32(p->mp_fld_rx_used_writer_data_host_id,\n+\t\t       p->m_rx_uw_shadow[index].host_id);\n+\tif (module_is_version_newer(p->mp_mod_dbs, 0, 8)) {\n+\t\tfield_set_val32(p->mp_fld_rx_used_writer_data_queue_size,\n+\t\t\t       (1U << p->m_rx_uw_shadow[index].queue_size) - 1U);\n+\t} else {\n+\t\tfield_set_val32(p->mp_fld_rx_used_writer_data_queue_size,\n+\t\t\t       p->m_rx_uw_shadow[index].queue_size);\n+\t}\n+\tif (p->mp_fld_rx_used_writer_data_packed) {\n+\t\tfield_set_val32(p->mp_fld_rx_used_writer_data_packed,\n+\t\t\t       p->m_rx_uw_shadow[index].packed);\n+\t}\n+\tif (p->mp_fld_rx_used_writer_data_int) {\n+\t\tfield_set_val32(p->mp_fld_rx_used_writer_data_int,\n+\t\t\t       p->m_rx_uw_shadow[index].int_enable);\n+\t\tfield_set_val32(p->mp_fld_rx_used_writer_data_vec,\n+\t\t\t       p->m_rx_uw_shadow[index].vec);\n+\t\tfield_set_val32(p->mp_fld_rx_used_writer_data_istk,\n+\t\t\t       p->m_rx_uw_shadow[index].istk);\n+\t}\n+\n+\tset_rx_uw_data_index(p, index);\n+\tregister_flush(p->mp_reg_rx_used_writer_data, 1);\n+}\n+\n+int set_rx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,\n+\t\t   uint32_t host_id, uint32_t queue_size, uint32_t packed,\n+\t\t   uint32_t int_enable, uint32_t vec, uint32_t istk)\n+{\n+\tif (!p->mp_reg_rx_used_writer_data)\n+\t\treturn -ENOTSUP;\n+\n+\tset_shadow_rx_uw_data(p, index, guest_physical_address, host_id, queue_size,\n+\t\t\t   packed, int_enable, vec, istk);\n+\tflush_rx_uw_data(p, index);\n+\treturn 0;\n+}\n+\n+static void set_tx_uw_data_index(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val32(p->mp_fld_tx_used_writer_control_adr, index);\n+\tfield_set_val32(p->mp_fld_tx_used_writer_control_cnt, 1);\n+\tregister_flush(p->mp_reg_tx_used_writer_control, 1);\n+}\n+\n+static void\n+set_shadow_tx_uw_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t       uint64_t guest_physical_address)\n+{\n+\tp->m_tx_uw_shadow[index].guest_physical_address = guest_physical_address;\n+}\n+\n+static void set_shadow_tx_uw_data_host_id(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t     uint32_t host_id)\n+{\n+\tp->m_tx_uw_shadow[index].host_id = host_id;\n+}\n+\n+static void set_shadow_tx_uw_data_queue_size(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t\tuint32_t queue_size)\n+{\n+\tp->m_tx_uw_shadow[index].queue_size = queue_size;\n+}\n+\n+static void set_shadow_tx_uw_data_packed(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t     uint32_t packed)\n+{\n+\tp->m_tx_uw_shadow[index].packed = packed;\n+}\n+\n+static void set_shadow_tx_uw_data_int_enable(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t\tuint32_t int_enable)\n+{\n+\tp->m_tx_uw_shadow[index].int_enable = int_enable;\n+}\n+\n+static void set_shadow_tx_uw_data_vec(nthw_dbs_t *p, uint32_t index, uint32_t vec)\n+{\n+\tp->m_tx_uw_shadow[index].vec = vec;\n+}\n+\n+static void set_shadow_tx_uw_data_istk(nthw_dbs_t *p, uint32_t index, uint32_t istk)\n+{\n+\tp->m_tx_uw_shadow[index].istk = istk;\n+}\n+\n+static void set_shadow_tx_uw_data_in_order(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t      uint32_t in_order)\n+{\n+\tp->m_tx_uw_shadow[index].in_order = in_order;\n+}\n+\n+static void set_shadow_tx_uw_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint64_t guest_physical_address, uint32_t host_id,\n+\t\t\t       uint32_t queue_size, uint32_t packed,\n+\t\t\t       uint32_t int_enable, uint32_t vec, uint32_t istk,\n+\t\t\t       uint32_t in_order)\n+{\n+\tset_shadow_tx_uw_data_guest_physical_address(p, index, guest_physical_address);\n+\tset_shadow_tx_uw_data_host_id(p, index, host_id);\n+\tset_shadow_tx_uw_data_queue_size(p, index, queue_size);\n+\tset_shadow_tx_uw_data_packed(p, index, packed);\n+\tset_shadow_tx_uw_data_int_enable(p, index, int_enable);\n+\tset_shadow_tx_uw_data_vec(p, index, vec);\n+\tset_shadow_tx_uw_data_istk(p, index, istk);\n+\tset_shadow_tx_uw_data_in_order(p, index, in_order);\n+}\n+\n+static void flush_tx_uw_data(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val(p->mp_fld_tx_used_writer_data_guest_physical_address,\n+\t\t     (uint32_t *)&p->m_tx_uw_shadow[index].guest_physical_address,\n+\t\t     2);\n+\tfield_set_val32(p->mp_fld_tx_used_writer_data_host_id,\n+\t\t       p->m_tx_uw_shadow[index].host_id);\n+\tif (module_is_version_newer(p->mp_mod_dbs, 0, 8)) {\n+\t\tfield_set_val32(p->mp_fld_tx_used_writer_data_queue_size,\n+\t\t\t       (1U << p->m_tx_uw_shadow[index].queue_size) - 1U);\n+\t} else {\n+\t\tfield_set_val32(p->mp_fld_tx_used_writer_data_queue_size,\n+\t\t\t       p->m_tx_uw_shadow[index].queue_size);\n+\t}\n+\tif (p->mp_fld_tx_used_writer_data_packed) {\n+\t\tfield_set_val32(p->mp_fld_tx_used_writer_data_packed,\n+\t\t\t       p->m_tx_uw_shadow[index].packed);\n+\t}\n+\tif (p->mp_fld_tx_used_writer_data_int) {\n+\t\tfield_set_val32(p->mp_fld_tx_used_writer_data_int,\n+\t\t\t       p->m_tx_uw_shadow[index].int_enable);\n+\t\tfield_set_val32(p->mp_fld_tx_used_writer_data_vec,\n+\t\t\t       p->m_tx_uw_shadow[index].vec);\n+\t\tfield_set_val32(p->mp_fld_tx_used_writer_data_istk,\n+\t\t\t       p->m_tx_uw_shadow[index].istk);\n+\t}\n+\tif (p->mp_fld_tx_used_writer_data_in_order) {\n+\t\tfield_set_val32(p->mp_fld_tx_used_writer_data_in_order,\n+\t\t\t       p->m_tx_uw_shadow[index].in_order);\n+\t}\n+\n+\tset_tx_uw_data_index(p, index);\n+\tregister_flush(p->mp_reg_tx_used_writer_data, 1);\n+}\n+\n+int set_tx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,\n+\t\t   uint32_t host_id, uint32_t queue_size, uint32_t packed,\n+\t\t   uint32_t int_enable, uint32_t vec, uint32_t istk,\n+\t\t   uint32_t in_order)\n+{\n+\tif (!p->mp_reg_tx_used_writer_data)\n+\t\treturn -ENOTSUP;\n+\n+\tset_shadow_tx_uw_data(p, index, guest_physical_address, host_id, queue_size,\n+\t\t\t   packed, int_enable, vec, istk, in_order);\n+\tflush_tx_uw_data(p, index);\n+\treturn 0;\n+}\n+\n+static void set_rx_dr_data_index(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val32(p->mp_fld_rx_descriptor_reader_control_adr, index);\n+\tfield_set_val32(p->mp_fld_rx_descriptor_reader_control_cnt, 1);\n+\tregister_flush(p->mp_reg_rx_descriptor_reader_control, 1);\n+}\n+\n+static void\n+set_shadow_rx_dr_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t       uint64_t guest_physical_address)\n+{\n+\tp->m_rx_dr_shadow[index].guest_physical_address = guest_physical_address;\n+}\n+\n+static void set_shadow_rx_dr_data_host_id(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t     uint32_t host_id)\n+{\n+\tp->m_rx_dr_shadow[index].host_id = host_id;\n+}\n+\n+static void set_shadow_rx_dr_data_queue_size(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t\tuint32_t queue_size)\n+{\n+\tp->m_rx_dr_shadow[index].queue_size = queue_size;\n+}\n+\n+static void set_shadow_rx_dr_data_header(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t     uint32_t header)\n+{\n+\tp->m_rx_dr_shadow[index].header = header;\n+}\n+\n+static void set_shadow_rx_dr_data_packed(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t     uint32_t packed)\n+{\n+\tp->m_rx_dr_shadow[index].packed = packed;\n+}\n+\n+static void set_shadow_rx_dr_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint64_t guest_physical_address, uint32_t host_id,\n+\t\t\t       uint32_t queue_size, uint32_t header,\n+\t\t\t       uint32_t packed)\n+{\n+\tset_shadow_rx_dr_data_guest_physical_address(p, index, guest_physical_address);\n+\tset_shadow_rx_dr_data_host_id(p, index, host_id);\n+\tset_shadow_rx_dr_data_queue_size(p, index, queue_size);\n+\tset_shadow_rx_dr_data_header(p, index, header);\n+\tset_shadow_rx_dr_data_packed(p, index, packed);\n+}\n+\n+static void flush_rx_dr_data(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val(p->mp_fld_rx_descriptor_reader_data_guest_physical_address,\n+\t\t     (uint32_t *)&p->m_rx_dr_shadow[index].guest_physical_address,\n+\t\t     2);\n+\tfield_set_val32(p->mp_fld_rx_descriptor_reader_data_host_id,\n+\t\t       p->m_rx_dr_shadow[index].host_id);\n+\tif (module_is_version_newer(p->mp_mod_dbs, 0, 8)) {\n+\t\tfield_set_val32(p->mp_fld_rx_descriptor_reader_data_queue_size,\n+\t\t\t       (1U << p->m_rx_dr_shadow[index].queue_size) - 1U);\n+\t} else {\n+\t\tfield_set_val32(p->mp_fld_rx_descriptor_reader_data_queue_size,\n+\t\t\t       p->m_rx_dr_shadow[index].queue_size);\n+\t}\n+\tfield_set_val32(p->mp_fld_rx_descriptor_reader_data_header,\n+\t\t       p->m_rx_dr_shadow[index].header);\n+\tif (p->mp_fld_rx_descriptor_reader_data_packed) {\n+\t\tfield_set_val32(p->mp_fld_rx_descriptor_reader_data_packed,\n+\t\t\t       p->m_rx_dr_shadow[index].packed);\n+\t}\n+\n+\tset_rx_dr_data_index(p, index);\n+\tregister_flush(p->mp_reg_rx_descriptor_reader_data, 1);\n+}\n+\n+int set_rx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,\n+\t\t   uint32_t host_id, uint32_t queue_size, uint32_t header,\n+\t\t   uint32_t packed)\n+{\n+\tif (!p->mp_reg_rx_descriptor_reader_data)\n+\t\treturn -ENOTSUP;\n+\n+\tset_shadow_rx_dr_data(p, index, guest_physical_address, host_id, queue_size,\n+\t\t\t   header, packed);\n+\tflush_rx_dr_data(p, index);\n+\treturn 0;\n+}\n+\n+static void set_tx_dr_data_index(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val32(p->mp_fld_tx_descriptor_reader_control_adr, index);\n+\tfield_set_val32(p->mp_fld_tx_descriptor_reader_control_cnt, 1);\n+\tregister_flush(p->mp_reg_tx_descriptor_reader_control, 1);\n+}\n+\n+static void\n+set_shadow_tx_dr_data_guest_physical_address(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t       uint64_t guest_physical_address)\n+{\n+\tp->m_tx_dr_shadow[index].guest_physical_address = guest_physical_address;\n+}\n+\n+static void set_shadow_tx_dr_data_host_id(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t     uint32_t host_id)\n+{\n+\tp->m_tx_dr_shadow[index].host_id = host_id;\n+}\n+\n+static void set_shadow_tx_dr_data_queue_size(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t\tuint32_t queue_size)\n+{\n+\tp->m_tx_dr_shadow[index].queue_size = queue_size;\n+}\n+\n+static void set_shadow_tx_dr_data_header(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t     uint32_t header)\n+{\n+\tp->m_tx_dr_shadow[index].header = header;\n+}\n+\n+static void set_shadow_tx_dr_data_port(nthw_dbs_t *p, uint32_t index, uint32_t port)\n+{\n+\tp->m_tx_dr_shadow[index].port = port;\n+}\n+\n+static void set_shadow_tx_dr_data_packed(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t     uint32_t packed)\n+{\n+\tp->m_tx_dr_shadow[index].packed = packed;\n+}\n+\n+static void set_shadow_tx_dr_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint64_t guest_physical_address, uint32_t host_id,\n+\t\t\t       uint32_t queue_size, uint32_t port,\n+\t\t\t       uint32_t header, uint32_t packed)\n+{\n+\tset_shadow_tx_dr_data_guest_physical_address(p, index, guest_physical_address);\n+\tset_shadow_tx_dr_data_host_id(p, index, host_id);\n+\tset_shadow_tx_dr_data_queue_size(p, index, queue_size);\n+\tset_shadow_tx_dr_data_header(p, index, header);\n+\tset_shadow_tx_dr_data_port(p, index, port);\n+\tset_shadow_tx_dr_data_packed(p, index, packed);\n+}\n+\n+static void flush_tx_dr_data(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val(p->mp_fld_tx_descriptor_reader_data_guest_physical_address,\n+\t\t     (uint32_t *)&p->m_tx_dr_shadow[index].guest_physical_address,\n+\t\t     2);\n+\tfield_set_val32(p->mp_fld_tx_descriptor_reader_data_host_id,\n+\t\t       p->m_tx_dr_shadow[index].host_id);\n+\tif (module_is_version_newer(p->mp_mod_dbs, 0, 8)) {\n+\t\tfield_set_val32(p->mp_fld_tx_descriptor_reader_data_queue_size,\n+\t\t\t       (1U << p->m_tx_dr_shadow[index].queue_size) - 1U);\n+\t} else {\n+\t\tfield_set_val32(p->mp_fld_tx_descriptor_reader_data_queue_size,\n+\t\t\t       p->m_tx_dr_shadow[index].queue_size);\n+\t}\n+\tfield_set_val32(p->mp_fld_tx_descriptor_reader_data_header,\n+\t\t       p->m_tx_dr_shadow[index].header);\n+\tfield_set_val32(p->mp_fld_tx_descriptor_reader_data_port,\n+\t\t       p->m_tx_dr_shadow[index].port);\n+\tif (p->mp_fld_tx_descriptor_reader_data_packed) {\n+\t\tfield_set_val32(p->mp_fld_tx_descriptor_reader_data_packed,\n+\t\t\t       p->m_tx_dr_shadow[index].packed);\n+\t}\n+\n+\tset_tx_dr_data_index(p, index);\n+\tregister_flush(p->mp_reg_tx_descriptor_reader_data, 1);\n+}\n+\n+int set_tx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,\n+\t\t   uint32_t host_id, uint32_t queue_size, uint32_t port,\n+\t\t   uint32_t header, uint32_t packed)\n+{\n+\tif (!p->mp_reg_tx_descriptor_reader_data)\n+\t\treturn -ENOTSUP;\n+\n+\tset_shadow_tx_dr_data(p, index, guest_physical_address, host_id, queue_size,\n+\t\t\t   port, header, packed);\n+\tflush_tx_dr_data(p, index);\n+\treturn 0;\n+}\n+\n+static void set_tx_qp_data_index(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val32(p->mp_fld_tx_queue_property_control_adr, index);\n+\tfield_set_val32(p->mp_fld_tx_queue_property_control_cnt, 1);\n+\tregister_flush(p->mp_reg_tx_queue_property_control, 1);\n+}\n+\n+static void set_shadow_tx_qp_data_virtual_port(nthw_dbs_t *p, uint32_t index,\n+\t\tuint32_t virtual_port)\n+{\n+\tp->m_tx_qp_shadow[index].virtual_port = virtual_port;\n+}\n+\n+static void set_shadow_tx_qp_data(nthw_dbs_t *p, uint32_t index,\n+\t\t\t       uint32_t virtual_port)\n+{\n+\tset_shadow_tx_qp_data_virtual_port(p, index, virtual_port);\n+}\n+\n+static void flush_tx_qp_data(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val32(p->mp_fld_tx_queue_property_data_v_port,\n+\t\t       p->m_tx_qp_shadow[index].virtual_port);\n+\n+\tset_tx_qp_data_index(p, index);\n+\tregister_flush(p->mp_reg_tx_queue_property_data, 1);\n+}\n+\n+int nthw_dbs_set_tx_qp_data(nthw_dbs_t *p, uint32_t index, uint32_t virtual_port)\n+{\n+\tif (!p->mp_reg_tx_queue_property_data)\n+\t\treturn -ENOTSUP;\n+\n+\tset_shadow_tx_qp_data(p, index, virtual_port);\n+\tflush_tx_qp_data(p, index);\n+\treturn 0;\n+}\n+\n+static void set_tx_qos_data_index(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val32(p->mp_reg_tx_queue_qos_control_adr, index);\n+\tfield_set_val32(p->mp_reg_tx_queue_qos_control_cnt, 1);\n+\tregister_flush(p->mp_reg_tx_queue_qos_control, 1);\n+}\n+\n+static void set_shadow_tx_qos_data_enable(nthw_dbs_t *p, uint32_t index,\n+\t\t\t\t      uint32_t enable)\n+{\n+\tp->m_tx_qos_shadow[index].enable = enable;\n+}\n+\n+static void set_shadow_tx_qos_data_ir(nthw_dbs_t *p, uint32_t index, uint32_t ir)\n+{\n+\tp->m_tx_qos_shadow[index].ir = ir;\n+}\n+\n+static void set_shadow_tx_qos_data_bs(nthw_dbs_t *p, uint32_t index, uint32_t bs)\n+{\n+\tp->m_tx_qos_shadow[index].bs = bs;\n+}\n+\n+static void set_shadow_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable,\n+\t\t\t\tuint32_t ir, uint32_t bs)\n+{\n+\tset_shadow_tx_qos_data_enable(p, index, enable);\n+\tset_shadow_tx_qos_data_ir(p, index, ir);\n+\tset_shadow_tx_qos_data_bs(p, index, bs);\n+}\n+\n+static void flush_tx_qos_data(nthw_dbs_t *p, uint32_t index)\n+{\n+\tfield_set_val32(p->mp_reg_tx_queue_qos_data_en, p->m_tx_qos_shadow[index].enable);\n+\tfield_set_val32(p->mp_reg_tx_queue_qos_data_ir, p->m_tx_qos_shadow[index].ir);\n+\tfield_set_val32(p->mp_reg_tx_queue_qos_data_bs, p->m_tx_qos_shadow[index].bs);\n+\n+\tset_tx_qos_data_index(p, index);\n+\tregister_flush(p->mp_reg_tx_queue_qos_data, 1);\n+}\n+\n+int set_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable, uint32_t ir,\n+\t\t    uint32_t bs)\n+{\n+\tif (!p->mp_reg_tx_queue_qos_data)\n+\t\treturn -ENOTSUP;\n+\n+\tset_shadow_tx_qos_data(p, index, enable, ir, bs);\n+\tflush_tx_qos_data(p, index);\n+\treturn 0;\n+}\n+\n+int set_tx_qos_rate(nthw_dbs_t *p, uint32_t mul, uint32_t div)\n+{\n+\tif (!p->mp_reg_tx_queue_qos_rate)\n+\t\treturn -ENOTSUP;\n+\n+\tfield_set_val32(p->mp_reg_tx_queue_qos_rate_mul, mul);\n+\tfield_set_val32(p->mp_reg_tx_queue_qos_rate_div, div);\n+\tregister_flush(p->mp_reg_tx_queue_qos_rate, 1);\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/nthw_dbs.h b/drivers/net/ntnic/nthw/nthw_dbs.h\nnew file mode 100644\nindex 0000000000..d5891d7538\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_dbs.h\n@@ -0,0 +1,313 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef NTHW_DBS_HPP_\n+#define NTHW_DBS_HPP_\n+\n+#define NT_DBS_RX_QUEUES_MAX (128)\n+#define NT_DBS_TX_QUEUES_MAX (128)\n+\n+/*\n+ * Struct for implementation of memory bank shadows\n+ */\n+\n+/* DBS_RX_AM_DATA */\n+struct nthw_dbs_rx_am_data_s {\n+\tuint64_t guest_physical_address;\n+\tuint32_t enable;\n+\tuint32_t host_id;\n+\tuint32_t packed;\n+\tuint32_t int_enable;\n+};\n+\n+/* DBS_TX_AM_DATA */\n+struct nthw_dbs_tx_am_data_s {\n+\tuint64_t guest_physical_address;\n+\tuint32_t enable;\n+\tuint32_t host_id;\n+\tuint32_t packed;\n+\tuint32_t int_enable;\n+};\n+\n+/* DBS_RX_UW_DATA */\n+struct nthw_dbs_rx_uw_data_s {\n+\tuint64_t guest_physical_address;\n+\tuint32_t host_id;\n+\tuint32_t queue_size;\n+\tuint32_t packed;\n+\tuint32_t int_enable;\n+\tuint32_t vec;\n+\tuint32_t istk;\n+};\n+\n+/* DBS_TX_UW_DATA */\n+struct nthw_dbs_tx_uw_data_s {\n+\tuint64_t guest_physical_address;\n+\tuint32_t host_id;\n+\tuint32_t queue_size;\n+\tuint32_t packed;\n+\tuint32_t int_enable;\n+\tuint32_t vec;\n+\tuint32_t istk;\n+\tuint32_t in_order;\n+};\n+\n+/* DBS_RX_DR_DATA */\n+struct nthw_dbs_rx_dr_data_s {\n+\tuint64_t guest_physical_address;\n+\tuint32_t host_id;\n+\tuint32_t queue_size;\n+\tuint32_t header;\n+\tuint32_t packed;\n+};\n+\n+/* DBS_TX_DR_DATA */\n+struct nthw_dbs_tx_dr_data_s {\n+\tuint64_t guest_physical_address;\n+\tuint32_t host_id;\n+\tuint32_t queue_size;\n+\tuint32_t header;\n+\tuint32_t port;\n+\tuint32_t packed;\n+};\n+\n+/* DBS_TX_QP_DATA */\n+struct nthw_dbs_tx_qp_data_s {\n+\tuint32_t virtual_port;\n+};\n+\n+struct nthw_dbs_tx_qos_data_s {\n+\tuint32_t enable;\n+\tuint32_t ir;\n+\tuint32_t bs;\n+};\n+\n+struct nthw_dbs_s {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_dbs;\n+\tint mn_instance;\n+\n+\tint mn_param_dbs_present;\n+\n+\tnt_register_t *mp_reg_rx_control;\n+\tnt_field_t *mp_fld_rx_control_last_queue;\n+\tnt_field_t *mp_fld_rx_control_avail_monitor_enable;\n+\tnt_field_t *mp_fld_rx_control_avail_monitor_scan_speed;\n+\tnt_field_t *mp_fld_rx_control_used_write_enable;\n+\tnt_field_t *mp_fld_rx_control_used_writer_update_speed;\n+\tnt_field_t *mp_fld_rx_control_rx_queues_enable;\n+\n+\tnt_register_t *mp_reg_tx_control;\n+\tnt_field_t *mp_fld_tx_control_last_queue;\n+\tnt_field_t *mp_fld_tx_control_avail_monitor_enable;\n+\tnt_field_t *mp_fld_tx_control_avail_monitor_scan_speed;\n+\tnt_field_t *mp_fld_tx_control_used_write_enable;\n+\tnt_field_t *mp_fld_tx_control_used_writer_update_speed;\n+\tnt_field_t *mp_fld_tx_control_tx_queues_enable;\n+\n+\tnt_register_t *mp_reg_rx_init;\n+\tnt_field_t *mp_fld_rx_init_init;\n+\tnt_field_t *mp_fld_rx_init_queue;\n+\tnt_field_t *mp_fld_rx_init_busy;\n+\n+\tnt_register_t *mp_reg_rx_init_val;\n+\tnt_field_t *mp_fld_rx_init_val_idx;\n+\tnt_field_t *mp_fld_rx_init_val_ptr;\n+\n+\tnt_register_t *mp_reg_rx_ptr;\n+\tnt_field_t *mp_fld_rx_ptr_ptr;\n+\tnt_field_t *mp_fld_rx_ptr_queue;\n+\tnt_field_t *mp_fld_rx_ptr_valid;\n+\n+\tnt_register_t *mp_reg_tx_init;\n+\tnt_field_t *mp_fld_tx_init_init;\n+\tnt_field_t *mp_fld_tx_init_queue;\n+\tnt_field_t *mp_fld_tx_init_busy;\n+\n+\tnt_register_t *mp_reg_tx_init_val;\n+\tnt_field_t *mp_fld_tx_init_val_idx;\n+\tnt_field_t *mp_fld_tx_init_val_ptr;\n+\n+\tnt_register_t *mp_reg_tx_ptr;\n+\tnt_field_t *mp_fld_tx_ptr_ptr;\n+\tnt_field_t *mp_fld_tx_ptr_queue;\n+\tnt_field_t *mp_fld_tx_ptr_valid;\n+\n+\tnt_register_t *mp_reg_rx_idle;\n+\tnt_field_t *mp_fld_rx_idle_idle;\n+\tnt_field_t *mp_fld_rx_idle_queue;\n+\tnt_field_t *mp_fld_rx_idle_busy;\n+\n+\tnt_register_t *mp_reg_tx_idle;\n+\tnt_field_t *mp_fld_tx_idle_idle;\n+\tnt_field_t *mp_fld_tx_idle_queue;\n+\tnt_field_t *mp_fld_tx_idle_busy;\n+\n+\tnt_register_t *mp_reg_rx_avail_monitor_control;\n+\tnt_field_t *mp_fld_rx_avail_monitor_control_adr;\n+\tnt_field_t *mp_fld_rx_avail_monitor_control_cnt;\n+\n+\tnt_register_t *mp_reg_rx_avail_monitor_data;\n+\tnt_field_t *mp_fld_rx_avail_monitor_data_guest_physical_address;\n+\tnt_field_t *mp_fld_rx_avail_monitor_data_enable;\n+\tnt_field_t *mp_fld_rx_avail_monitor_data_host_id;\n+\tnt_field_t *mp_fld_rx_avail_monitor_data_packed;\n+\tnt_field_t *mp_fld_rx_avail_monitor_data_int;\n+\n+\tnt_register_t *mp_reg_tx_avail_monitor_control;\n+\tnt_field_t *mp_fld_tx_avail_monitor_control_adr;\n+\tnt_field_t *mp_fld_tx_avail_monitor_control_cnt;\n+\n+\tnt_register_t *mp_reg_tx_avail_monitor_data;\n+\tnt_field_t *mp_fld_tx_avail_monitor_data_guest_physical_address;\n+\tnt_field_t *mp_fld_tx_avail_monitor_data_enable;\n+\tnt_field_t *mp_fld_tx_avail_monitor_data_host_id;\n+\tnt_field_t *mp_fld_tx_avail_monitor_data_packed;\n+\tnt_field_t *mp_fld_tx_avail_monitor_data_int;\n+\n+\tnt_register_t *mp_reg_rx_used_writer_control;\n+\tnt_field_t *mp_fld_rx_used_writer_control_adr;\n+\tnt_field_t *mp_fld_rx_used_writer_control_cnt;\n+\n+\tnt_register_t *mp_reg_rx_used_writer_data;\n+\tnt_field_t *mp_fld_rx_used_writer_data_guest_physical_address;\n+\tnt_field_t *mp_fld_rx_used_writer_data_host_id;\n+\tnt_field_t *mp_fld_rx_used_writer_data_queue_size;\n+\tnt_field_t *mp_fld_rx_used_writer_data_packed;\n+\tnt_field_t *mp_fld_rx_used_writer_data_int;\n+\tnt_field_t *mp_fld_rx_used_writer_data_vec;\n+\tnt_field_t *mp_fld_rx_used_writer_data_istk;\n+\n+\tnt_register_t *mp_reg_tx_used_writer_control;\n+\tnt_field_t *mp_fld_tx_used_writer_control_adr;\n+\tnt_field_t *mp_fld_tx_used_writer_control_cnt;\n+\n+\tnt_register_t *mp_reg_tx_used_writer_data;\n+\tnt_field_t *mp_fld_tx_used_writer_data_guest_physical_address;\n+\tnt_field_t *mp_fld_tx_used_writer_data_host_id;\n+\tnt_field_t *mp_fld_tx_used_writer_data_queue_size;\n+\tnt_field_t *mp_fld_tx_used_writer_data_packed;\n+\tnt_field_t *mp_fld_tx_used_writer_data_int;\n+\tnt_field_t *mp_fld_tx_used_writer_data_vec;\n+\tnt_field_t *mp_fld_tx_used_writer_data_istk;\n+\tnt_field_t *mp_fld_tx_used_writer_data_in_order;\n+\n+\tnt_register_t *mp_reg_rx_descriptor_reader_control;\n+\tnt_field_t *mp_fld_rx_descriptor_reader_control_adr;\n+\tnt_field_t *mp_fld_rx_descriptor_reader_control_cnt;\n+\n+\tnt_register_t *mp_reg_rx_descriptor_reader_data;\n+\tnt_field_t *mp_fld_rx_descriptor_reader_data_guest_physical_address;\n+\tnt_field_t *mp_fld_rx_descriptor_reader_data_host_id;\n+\tnt_field_t *mp_fld_rx_descriptor_reader_data_queue_size;\n+\tnt_field_t *mp_fld_rx_descriptor_reader_data_header;\n+\tnt_field_t *mp_fld_rx_descriptor_reader_data_packed;\n+\n+\tnt_register_t *mp_reg_tx_descriptor_reader_control;\n+\tnt_field_t *mp_fld_tx_descriptor_reader_control_adr;\n+\tnt_field_t *mp_fld_tx_descriptor_reader_control_cnt;\n+\n+\tnt_register_t *mp_reg_tx_descriptor_reader_data;\n+\tnt_field_t *mp_fld_tx_descriptor_reader_data_guest_physical_address;\n+\tnt_field_t *mp_fld_tx_descriptor_reader_data_host_id;\n+\tnt_field_t *mp_fld_tx_descriptor_reader_data_queue_size;\n+\tnt_field_t *mp_fld_tx_descriptor_reader_data_port;\n+\tnt_field_t *mp_fld_tx_descriptor_reader_data_header;\n+\tnt_field_t *mp_fld_tx_descriptor_reader_data_packed;\n+\n+\tnt_register_t *mp_reg_tx_queue_property_control;\n+\tnt_field_t *mp_fld_tx_queue_property_control_adr;\n+\tnt_field_t *mp_fld_tx_queue_property_control_cnt;\n+\n+\tnt_register_t *mp_reg_tx_queue_property_data;\n+\tnt_field_t *mp_fld_tx_queue_property_data_v_port;\n+\n+\tnt_register_t *mp_reg_tx_queue_qos_control;\n+\tnt_field_t *mp_reg_tx_queue_qos_control_adr;\n+\tnt_field_t *mp_reg_tx_queue_qos_control_cnt;\n+\n+\tnt_register_t *mp_reg_tx_queue_qos_data;\n+\tnt_field_t *mp_reg_tx_queue_qos_data_en;\n+\tnt_field_t *mp_reg_tx_queue_qos_data_ir;\n+\tnt_field_t *mp_reg_tx_queue_qos_data_bs;\n+\n+\tnt_register_t *mp_reg_tx_queue_qos_rate;\n+\tnt_field_t *mp_reg_tx_queue_qos_rate_mul;\n+\tnt_field_t *mp_reg_tx_queue_qos_rate_div;\n+\n+\tstruct nthw_dbs_rx_am_data_s m_rx_am_shadow[NT_DBS_RX_QUEUES_MAX];\n+\tstruct nthw_dbs_rx_uw_data_s m_rx_uw_shadow[NT_DBS_RX_QUEUES_MAX];\n+\tstruct nthw_dbs_rx_dr_data_s m_rx_dr_shadow[NT_DBS_RX_QUEUES_MAX];\n+\n+\tstruct nthw_dbs_tx_am_data_s m_tx_am_shadow[NT_DBS_TX_QUEUES_MAX];\n+\tstruct nthw_dbs_tx_uw_data_s m_tx_uw_shadow[NT_DBS_TX_QUEUES_MAX];\n+\tstruct nthw_dbs_tx_dr_data_s m_tx_dr_shadow[NT_DBS_TX_QUEUES_MAX];\n+\tstruct nthw_dbs_tx_qp_data_s m_tx_qp_shadow[NT_DBS_TX_QUEUES_MAX];\n+\tstruct nthw_dbs_tx_qos_data_s m_tx_qos_shadow[NT_DBS_TX_QUEUES_MAX];\n+};\n+\n+typedef struct nthw_dbs_s nthw_dbs_t;\n+\n+nthw_dbs_t *nthw_dbs_new(void);\n+void nthw_dbs_delete(nthw_dbs_t *p);\n+int dbs_init(nthw_dbs_t *p, nt_fpga_t *p_fpga, int n_instance);\n+void dbs_reset(nthw_dbs_t *p);\n+\n+int dbs_reset_rx_control(nthw_dbs_t *p);\n+int dbs_reset_tx_control(nthw_dbs_t *p);\n+int set_rx_control(nthw_dbs_t *p, uint32_t last_queue,\n+\t\t   uint32_t avail_monitor_enable, uint32_t avail_monitor_speed,\n+\t\t   uint32_t used_write_enable, uint32_t used_write_speed,\n+\t\t   uint32_t rx_queue_enable);\n+int nthw_dbs_get_rx_control(nthw_dbs_t *p, uint32_t *last_queue,\n+\t\t\t uint32_t *avail_monitor_enable,\n+\t\t\t uint32_t *avail_monitor_speed, uint32_t *used_write_enable,\n+\t\t\t uint32_t *used_write_speed, uint32_t *rx_queue_enable);\n+int set_tx_control(nthw_dbs_t *p, uint32_t last_queue,\n+\t\t   uint32_t avail_monitor_enable, uint32_t avail_monitor_speed,\n+\t\t   uint32_t used_write_enable, uint32_t used_write_speed,\n+\t\t   uint32_t tx_queue_enable);\n+int nthw_dbs_get_tx_control(nthw_dbs_t *p, uint32_t *last_queue,\n+\t\t\t uint32_t *avail_monitor_enable,\n+\t\t\t uint32_t *avail_monitor_speed, uint32_t *used_write_enable,\n+\t\t\t uint32_t *used_write_speed, uint32_t *tx_queue_enable);\n+int set_rx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr,\n+\t\tuint32_t init, uint32_t queue);\n+int get_rx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy);\n+int set_tx_init(nthw_dbs_t *p, uint32_t start_idx, uint32_t start_ptr,\n+\t\tuint32_t init, uint32_t queue);\n+int get_tx_init(nthw_dbs_t *p, uint32_t *init, uint32_t *queue, uint32_t *busy);\n+int set_rx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue);\n+int get_rx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy);\n+int set_tx_idle(nthw_dbs_t *p, uint32_t idle, uint32_t queue);\n+int get_tx_idle(nthw_dbs_t *p, uint32_t *idle, uint32_t *queue, uint32_t *busy);\n+int set_rx_ptr_queue(nthw_dbs_t *p, uint32_t queue);\n+int get_rx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid);\n+int set_tx_ptr_queue(nthw_dbs_t *p, uint32_t queue);\n+int get_tx_ptr(nthw_dbs_t *p, uint32_t *ptr, uint32_t *queue, uint32_t *valid);\n+int set_rx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,\n+\t\t   uint32_t enable, uint32_t host_id, uint32_t packed,\n+\t\t   uint32_t int_enable);\n+int set_tx_am_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,\n+\t\t   uint32_t enable, uint32_t host_id, uint32_t packed,\n+\t\t   uint32_t int_enable);\n+int set_rx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,\n+\t\t   uint32_t host_id, uint32_t queue_size, uint32_t packed,\n+\t\t   uint32_t int_enable, uint32_t vec, uint32_t istk);\n+int set_tx_uw_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,\n+\t\t   uint32_t host_id, uint32_t queue_size, uint32_t packed,\n+\t\t   uint32_t int_enable, uint32_t vec, uint32_t istk,\n+\t\t   uint32_t in_order);\n+int set_rx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,\n+\t\t   uint32_t host_id, uint32_t queue_size, uint32_t header,\n+\t\t   uint32_t packed);\n+int set_tx_dr_data(nthw_dbs_t *p, uint32_t index, uint64_t guest_physical_address,\n+\t\t   uint32_t host_id, uint32_t queue_size, uint32_t port,\n+\t\t   uint32_t header, uint32_t packed);\n+int nthw_dbs_set_tx_qp_data(nthw_dbs_t *p, uint32_t index, uint32_t virtual_port);\n+int set_tx_qos_data(nthw_dbs_t *p, uint32_t index, uint32_t enable, uint32_t ir,\n+\t\t    uint32_t bs);\n+int set_tx_qos_rate(nthw_dbs_t *p, uint32_t mul, uint32_t div);\n+\n+#endif /* NTHW_DBS_H_ */\ndiff --git a/drivers/net/ntnic/nthw/nthw_drv.h b/drivers/net/ntnic/nthw/nthw_drv.h\nnew file mode 100644\nindex 0000000000..7fdd9bf0e2\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_drv.h\n@@ -0,0 +1,82 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_DRV_H__\n+#define __NTHW_DRV_H__\n+\n+#include \"nthw_profile.h\"\n+\n+typedef enum nt_meta_port_type_e {\n+\tPORT_TYPE_PHYSICAL,\n+\tPORT_TYPE_VIRTUAL,\n+\tPORT_TYPE_OVERRIDE,\n+} nt_meta_port_type_t;\n+\n+#include \"nthw_helper.h\"\n+#include \"nthw_platform_drv.h\"\n+#include \"nthw_fpga_model.h\"\n+#include \"nthw_stat.h\"\n+#include \"nthw_dbs.h\"\n+#include \"nthw_epp.h\"\n+#include \"nthw_core.h\"\n+\n+typedef struct nthwhw_info_s {\n+\t/* From FW */\n+\tint hw_id;\n+\tint hw_id_emulated;\n+\tchar hw_plat_id_str[32];\n+\n+\tstruct vpd_info_s {\n+\t\tint mn_mac_addr_count;\n+\t\tuint64_t mn_mac_addr_value;\n+\t\tuint8_t ma_mac_addr_octets[6];\n+\t} vpd_info;\n+} nthw_hw_info_t;\n+\n+typedef struct fpga_info_s {\n+\tuint64_t n_fpga_ident;\n+\n+\tint n_fpga_type_id;\n+\tint n_fpga_prod_id;\n+\tint n_fpga_ver_id;\n+\tint n_fpga_rev_id;\n+\n+\tint n_fpga_build_time;\n+\n+\tint n_fpga_debug_mode;\n+\n+\tint n_nims;\n+\tint n_phy_ports;\n+\tint n_phy_quads;\n+\tint n_rx_ports;\n+\tint n_tx_ports;\n+\n+\tenum fpga_info_profile profile;\n+\n+\tstruct nt_fpga_s *mp_fpga;\n+\n+\tstruct nthw_rac *mp_nthw_rac;\n+\tstruct nthw_hif *mp_nthw_hif;\n+\tstruct nthw_pcie3 *mp_nthw_pcie3;\n+\tstruct nthw_tsm *mp_nthw_tsm;\n+\n+\tnthw_dbs_t *mp_nthw_dbs;\n+\tnthw_epp_t *mp_nthw_epp;\n+\n+\tuint8_t *bar0_addr; /* Needed for register read/write */\n+\tsize_t bar0_size;\n+\n+\tint adapter_no; /* Needed for nthw_rac DMA array indexing */\n+\tuint32_t pciident; /* Needed for nthw_rac DMA memzone_reserve */\n+\tint numa_node; /* Needed for nthw_rac DMA memzone_reserve */\n+\n+\tchar *mp_adapter_id_str; /* Pointer to string literal used in nthw log messages */\n+\n+\tstruct nthwhw_info_s nthw_hw_info;\n+\n+\tnthw_adapter_id_t n_nthw_adapter_id;\n+\n+} fpga_info_t;\n+\n+#endif /* __NTHW_DRV_H__ */\ndiff --git a/drivers/net/ntnic/nthw/nthw_epp.c b/drivers/net/ntnic/nthw/nthw_epp.c\nnew file mode 100644\nindex 0000000000..fbe3993b25\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_epp.c\n@@ -0,0 +1,335 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_epp.h\"\n+\n+#include <errno.h> /* ENOTSUP */\n+\n+nthw_epp_t *nthw_epp_new(void)\n+{\n+\tnthw_epp_t *p = malloc(sizeof(nthw_epp_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_epp_t));\n+\treturn p;\n+}\n+\n+void nthw_epp_delete(nthw_epp_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_epp_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+int nthw_epp_present(nt_fpga_t *p_fpga, int n_instance)\n+{\n+\treturn nthw_epp_init(NULL, p_fpga, n_instance) == 0;\n+}\n+\n+int nthw_epp_init(nthw_epp_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_EPP, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: EPP %d: no such instance\\n\",\n+\t\t       p_fpga->p_fpga_info->mp_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_epp = mod;\n+\n+\tp->mn_epp_categories = fpga_get_product_param(p_fpga, NT_EPP_CATEGORIES, 0);\n+\n+\tp->mp_reg_reciepe_memory_control =\n+\t\tmodule_get_register(p->mp_mod_epp, EPP_RCP_CTRL);\n+\tp->mp_fld_reciepe_memory_control_adr =\n+\t\tregister_get_field(p->mp_reg_reciepe_memory_control, EPP_RCP_CTRL_ADR);\n+\tp->mp_fld_reciepe_memory_control_cnt =\n+\t\tregister_get_field(p->mp_reg_reciepe_memory_control, EPP_RCP_CTRL_CNT);\n+\n+\tp->mp_reg_reciepe_memory_data =\n+\t\tmodule_get_register(p->mp_mod_epp, EPP_RCP_DATA);\n+\tp->mp_fld_reciepe_memory_data_tx_mtu_epp_enable =\n+\t\tregister_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_TX_MTU_EPP_EN);\n+\tp->mp_fld_reciepe_memory_data_queue_mtu_epp_enable =\n+\t\tregister_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_QUEUE_MTU_EPP_EN);\n+\tp->mp_fld_reciepe_memory_data_size_adjust_tx_port =\n+\t\tregister_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_SIZE_ADJUST_TXP);\n+\tp->mp_fld_reciepe_memory_data_size_adjust_virtual_port =\n+\t\tregister_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_SIZE_ADJUST_VPORT);\n+\tp->mp_fld_reciepe_memory_data_fixed18b_l2_mtu =\n+\t\tregister_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_FIXED_18B_L2_MTU);\n+\tp->mp_fld_reciepe_memory_data_txp_qos_epp_enable =\n+\t\tregister_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_TX_QOS_EPP_EN);\n+\tp->mp_fld_reciepe_memory_data_queue_qos_epp_enable =\n+\t\tregister_get_field(p->mp_reg_reciepe_memory_data, EPP_RCP_DATA_QUEUE_QOS_EPP_EN);\n+\n+\tp->mp_reg_txp_port_mtu_control =\n+\t\tmodule_get_register(p->mp_mod_epp, EPP_TXP_MTU_CTRL);\n+\tp->mp_fld_txp_port_mtu_control_adr =\n+\t\tregister_get_field(p->mp_reg_txp_port_mtu_control, EPP_TXP_MTU_CTRL_ADR);\n+\tp->mp_fld_txp_port_mtu_control_cnt =\n+\t\tregister_get_field(p->mp_reg_txp_port_mtu_control, EPP_TXP_MTU_CTRL_CNT);\n+\n+\tp->mp_reg_txp_port_mtu_data =\n+\t\tmodule_get_register(p->mp_mod_epp, EPP_TXP_MTU_DATA);\n+\tp->mp_fld_txp_port_mtu_data_max_mtu =\n+\t\tregister_get_field(p->mp_reg_txp_port_mtu_data, EPP_TXP_MTU_DATA_MAX_MTU);\n+\n+\tp->mp_reg_queue_mtu_control =\n+\t\tmodule_get_register(p->mp_mod_epp, EPP_QUEUE_MTU_CTRL);\n+\tp->mp_fld_queue_mtu_control_adr =\n+\t\tregister_get_field(p->mp_reg_queue_mtu_control, EPP_QUEUE_MTU_CTRL_ADR);\n+\tp->mp_fld_queue_mtu_control_cnt =\n+\t\tregister_get_field(p->mp_reg_queue_mtu_control, EPP_QUEUE_MTU_CTRL_CNT);\n+\n+\tp->mp_reg_queue_mtu_data =\n+\t\tmodule_get_register(p->mp_mod_epp, EPP_QUEUE_MTU_DATA);\n+\tp->mp_fld_queue_mtu_data_max_mtu =\n+\t\tregister_get_field(p->mp_reg_queue_mtu_data, EPP_QUEUE_MTU_DATA_MAX_MTU);\n+\n+\tp->mp_reg_txp_qos_control =\n+\t\tmodule_get_register(p->mp_mod_epp, EPP_TXP_QOS_CTRL);\n+\tp->mp_fld_txp_qos_control_adr =\n+\t\tregister_get_field(p->mp_reg_txp_qos_control, EPP_TXP_QOS_CTRL_ADR);\n+\tp->mp_fld_txp_qos_control_cnt =\n+\t\tregister_get_field(p->mp_reg_txp_qos_control, EPP_TXP_QOS_CTRL_CNT);\n+\n+\tp->mp_reg_txp_qos_data = module_get_register(p->mp_mod_epp, EPP_TXP_QOS_DATA);\n+\tp->mp_fld_txp_qos_data_enable =\n+\t\tregister_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_EN);\n+\tp->mp_fld_txp_qos_data_information_rate =\n+\t\tregister_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_IR);\n+\tp->mp_fld_txp_qos_data_information_rate_fractional =\n+\t\tregister_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_IR_FRACTION);\n+\tp->mp_fld_txp_qos_data_burst_size =\n+\t\tregister_get_field(p->mp_reg_txp_qos_data, EPP_TXP_QOS_DATA_BS);\n+\n+\tp->mp_reg_vport_qos_control =\n+\t\tmodule_get_register(p->mp_mod_epp, EPP_VPORT_QOS_CTRL);\n+\tp->mp_fld_vport_qos_control_adr =\n+\t\tregister_get_field(p->mp_reg_vport_qos_control, EPP_VPORT_QOS_CTRL_ADR);\n+\tp->mp_fld_vport_qos_control_cnt =\n+\t\tregister_get_field(p->mp_reg_vport_qos_control, EPP_VPORT_QOS_CTRL_CNT);\n+\n+\tp->mp_reg_vport_qos_data =\n+\t\tmodule_get_register(p->mp_mod_epp, EPP_VPORT_QOS_DATA);\n+\tp->mp_fld_vport_qos_data_enable =\n+\t\tregister_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_EN);\n+\tp->mp_fld_vport_qos_data_information_rate =\n+\t\tregister_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_IR);\n+\tp->mp_fld_vport_qos_data_information_rate_fractional =\n+\t\tregister_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_IR_FRACTION);\n+\tp->mp_fld_vport_qos_data_burst_size =\n+\t\tregister_get_field(p->mp_reg_vport_qos_data, EPP_VPORT_QOS_DATA_BS);\n+\n+\tp->mp_reg_queue_vport_control =\n+\t\tmodule_get_register(p->mp_mod_epp, EPP_QUEUE_VPORT_CTRL);\n+\tp->mp_fld_queue_vport_control_adr =\n+\t\tregister_get_field(p->mp_reg_queue_vport_control, EPP_QUEUE_VPORT_CTRL_ADR);\n+\tp->mp_fld_queue_vport_control_cnt =\n+\t\tregister_get_field(p->mp_reg_queue_vport_control, EPP_QUEUE_VPORT_CTRL_CNT);\n+\n+\tp->mp_reg_queue_vport_data =\n+\t\tmodule_get_register(p->mp_mod_epp, EPP_QUEUE_VPORT_DATA);\n+\tp->mp_fld_queue_vport_data_vport =\n+\t\tregister_get_field(p->mp_reg_queue_vport_data, EPP_QUEUE_VPORT_DATA_VPORT);\n+\n+\treturn 0;\n+}\n+\n+int nthw_epp_setup(nthw_epp_t *p)\n+{\n+\tif (p == NULL)\n+\t\treturn 0;\n+\n+\t/* Set recieps for 2 first records */\n+\tfield_set_val32(p->mp_fld_reciepe_memory_control_cnt, 1);\n+\n+\t/* Zero all categories */\n+\tfor (int i = 0; i < p->mn_epp_categories; ++i) {\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_control_adr, i);\n+\t\tregister_flush(p->mp_reg_reciepe_memory_control, 1);\n+\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_tx_mtu_epp_enable, 0);\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_queue_mtu_epp_enable, 0);\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_tx_port, 0);\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_virtual_port,\n+\t\t\t       0);\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_fixed18b_l2_mtu, 0);\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_txp_qos_epp_enable, 0);\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_queue_qos_epp_enable, 0);\n+\t\tregister_flush(p->mp_reg_reciepe_memory_data, 1);\n+\t}\n+\n+\tfor (int i = 0; i < NRECIPE; ++i) {\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_control_adr, i);\n+\t\tregister_flush(p->mp_reg_reciepe_memory_control, 1);\n+\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_tx_mtu_epp_enable, 1);\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_queue_mtu_epp_enable, 1);\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_tx_port,\n+\t\t\t       rcp_data_size_adjust_txp[i]);\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_size_adjust_virtual_port,\n+\t\t\t       rcp_data_size_adjust_vport[i]);\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_fixed18b_l2_mtu, 1);\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_txp_qos_epp_enable, 1);\n+\t\tfield_set_val32(p->mp_fld_reciepe_memory_data_queue_qos_epp_enable, 1);\n+\t\tregister_flush(p->mp_reg_reciepe_memory_data, 1);\n+\t}\n+\t/* phy mtu setup */\n+\tfield_set_val32(p->mp_fld_txp_port_mtu_control_cnt, 1);\n+\tfor (int i = 0; i < 2; ++i) {\n+\t\tfield_set_val32(p->mp_fld_txp_port_mtu_control_adr, i);\n+\t\tregister_flush(p->mp_reg_txp_port_mtu_control, 1);\n+\n+\t\tfield_set_val32(p->mp_fld_txp_port_mtu_data_max_mtu, MTUINITVAL);\n+\t\tregister_flush(p->mp_reg_txp_port_mtu_data, 1);\n+\t}\n+\t/* phy QoS setup */\n+\tfield_set_val32(p->mp_fld_txp_qos_control_cnt, 1);\n+\tfor (int i = 0; i < 2; ++i) {\n+\t\tfield_set_val32(p->mp_fld_txp_qos_control_adr, i);\n+\t\tregister_flush(p->mp_reg_txp_qos_control, 1);\n+\n+\t\tfield_set_val32(p->mp_fld_txp_qos_data_enable, 0);\n+\t\tregister_flush(p->mp_reg_txp_qos_data, 1);\n+\t}\n+\n+\t/* virt mtu setup */\n+\tfield_set_val32(p->mp_fld_queue_mtu_control_cnt, 1);\n+\tfor (int i = 0; i < 128; ++i) {\n+\t\tfield_set_val32(p->mp_fld_queue_mtu_control_adr, i);\n+\t\tregister_flush(p->mp_reg_queue_mtu_control, 1);\n+\n+\t\tfield_set_val32(p->mp_fld_queue_mtu_data_max_mtu, MTUINITVAL);\n+\t\tregister_flush(p->mp_reg_queue_mtu_data, 1);\n+\t}\n+\n+\t/* virt QoS setup */\n+\tfield_set_val32(p->mp_fld_vport_qos_control_cnt, 1);\n+\tfor (int i = 0; i < 128; ++i) {\n+\t\tfield_set_val32(p->mp_fld_vport_qos_control_adr, i);\n+\t\tregister_flush(p->mp_reg_vport_qos_control, 1);\n+\n+\t\tfield_set_val32(p->mp_fld_vport_qos_data_enable, 0);\n+\t\tregister_flush(p->mp_reg_vport_qos_data, 1);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Set the MTU registers in context with the current setMTU request.\n+ */\n+int nthw_epp_set_mtu(nthw_epp_t *p, uint32_t port, uint32_t max_mtu,\n+\t\t   nt_meta_port_type_t port_type)\n+{\n+\tif (p == NULL)\n+\t\treturn 0;\n+\n+\tif (port_type == PORT_TYPE_PHYSICAL) {\n+\t\t/* Set the TXP Mtu control register */\n+\t\tfield_set_val32(p->mp_fld_txp_port_mtu_control_adr, port);\n+\t\tfield_set_val32(p->mp_fld_txp_port_mtu_control_cnt, 1);\n+\t\tregister_flush(p->mp_reg_txp_port_mtu_control, 1);\n+\n+\t\t/* Set the TXP Mtu control register */\n+\t\tfield_set_val32(p->mp_fld_txp_port_mtu_data_max_mtu, max_mtu);\n+\t\tregister_flush(p->mp_reg_txp_port_mtu_data, 1);\n+\t} else if (port_type == PORT_TYPE_VIRTUAL) {\n+\t\t/* Set the TXP Mtu control register */\n+\t\tfield_set_val32(p->mp_fld_queue_mtu_control_adr, port);\n+\t\tfield_set_val32(p->mp_fld_queue_mtu_control_cnt, 1);\n+\t\tregister_flush(p->mp_reg_queue_mtu_control, 1);\n+\n+\t\t/* Set the TXP Mtu control register */\n+\t\tfield_set_val32(p->mp_fld_queue_mtu_data_max_mtu, max_mtu);\n+\t\tregister_flush(p->mp_reg_queue_mtu_data, 1);\n+\t} else {\n+\t\tNT_LOG(DBG, NTHW, \"NthwEpp::%s - port_type unsupported\",\n+\t\t       __func__);\n+\t\tregister_reset(p->mp_reg_queue_mtu_control);\n+\t\tregister_flush(p->mp_reg_queue_mtu_control, 1);\n+\t\tregister_reset(p->mp_reg_queue_mtu_data);\n+\t\tregister_flush(p->mp_reg_queue_mtu_data, 1);\n+\t\tregister_reset(p->mp_reg_txp_port_mtu_control);\n+\t\tregister_flush(p->mp_reg_txp_port_mtu_control, 1);\n+\t\tregister_reset(p->mp_reg_txp_port_mtu_data);\n+\t\tregister_flush(p->mp_reg_txp_port_mtu_data, 1);\n+\n+\t\treturn -ENOTSUP;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int nthw_epp_set_txp_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate,\n+\t\t      uint32_t information_rate_fractional, uint32_t burst_size)\n+{\n+\tif (p == NULL)\n+\t\treturn 0;\n+\n+\tfield_set_val32(p->mp_fld_txp_qos_control_adr, port);\n+\tfield_set_val32(p->mp_fld_txp_qos_control_cnt, 1);\n+\tregister_flush(p->mp_reg_txp_qos_control, 1);\n+\n+\tuint32_t enable = ((information_rate | information_rate_fractional |\n+\t\t\t    burst_size) != 0);\n+\tfield_set_val32(p->mp_fld_txp_qos_data_enable, enable);\n+\tfield_set_val32(p->mp_fld_txp_qos_data_information_rate, information_rate);\n+\tfield_set_val32(p->mp_fld_txp_qos_data_information_rate_fractional,\n+\t\t       information_rate_fractional);\n+\tfield_set_val32(p->mp_fld_txp_qos_data_burst_size, burst_size);\n+\tregister_flush(p->mp_reg_txp_qos_data, 1);\n+\n+\treturn 0;\n+}\n+\n+int nthw_epp_set_vport_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate,\n+\t\t\tuint32_t information_rate_fractional, uint32_t burst_size)\n+{\n+\tif (p == NULL)\n+\t\treturn 0;\n+\n+\tfield_set_val32(p->mp_fld_vport_qos_control_adr, port);\n+\tfield_set_val32(p->mp_fld_vport_qos_control_cnt, 1);\n+\tregister_flush(p->mp_reg_vport_qos_control, 1);\n+\n+\tuint32_t enable = ((information_rate | information_rate_fractional |\n+\t\t\t    burst_size) != 0);\n+\tfield_set_val32(p->mp_fld_vport_qos_data_enable, enable);\n+\tfield_set_val32(p->mp_fld_vport_qos_data_information_rate, information_rate);\n+\tfield_set_val32(p->mp_fld_vport_qos_data_information_rate_fractional,\n+\t\t       information_rate_fractional);\n+\tfield_set_val32(p->mp_fld_vport_qos_data_burst_size, burst_size);\n+\tregister_flush(p->mp_reg_vport_qos_data, 1);\n+\n+\treturn 0;\n+}\n+\n+int nthw_epp_set_queue_to_vport(nthw_epp_t *p, uint32_t qid, uint32_t vport)\n+{\n+\tif (p == NULL)\n+\t\treturn 0;\n+\n+\tfield_set_val32(p->mp_fld_queue_vport_control_adr, qid);\n+\tfield_set_val32(p->mp_fld_queue_vport_control_cnt, 1);\n+\tregister_flush(p->mp_reg_queue_vport_control, 1);\n+\n+\tfield_set_val32(p->mp_fld_queue_vport_data_vport, vport);\n+\tregister_flush(p->mp_reg_queue_vport_data, 1);\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/nthw_epp.h b/drivers/net/ntnic/nthw/nthw_epp.h\nnew file mode 100644\nindex 0000000000..b404c9b61a\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_epp.h\n@@ -0,0 +1,99 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef NTHW_EPP_HPP_\n+#define NTHW_EPP_HPP_\n+\n+/* VXLAN adds extra 50 bytes */\n+#define VXLANDATASIZEADJUST 50\n+#define VXLANDATASIZEADJUSTIPV6 70\n+#define MTUINITVAL 1500\n+#define NRECIPE 3\n+\n+/* List of size adjust values to put in the recipe memory data register at startup */\n+static const int rcp_data_size_adjust_txp[NRECIPE] = { 0, VXLANDATASIZEADJUST,\n+\t\t\t\t\t\t   VXLANDATASIZEADJUSTIPV6\n+\t\t\t\t\t\t };\n+static const int rcp_data_size_adjust_vport[NRECIPE] = { 0, VXLANDATASIZEADJUST,\n+\t\t\t\t\t\t     VXLANDATASIZEADJUSTIPV6\n+\t\t\t\t\t\t   };\n+\n+struct nthw_epp_s {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_epp;\n+\tint mn_instance;\n+\tint mn_epp_categories;\n+\n+\tnt_register_t *mp_reg_reciepe_memory_control;\n+\tnt_field_t *mp_fld_reciepe_memory_control_adr;\n+\tnt_field_t *mp_fld_reciepe_memory_control_cnt;\n+\n+\tnt_register_t *mp_reg_reciepe_memory_data;\n+\tnt_field_t *mp_fld_reciepe_memory_data_tx_mtu_epp_enable;\n+\tnt_field_t *mp_fld_reciepe_memory_data_queue_mtu_epp_enable;\n+\tnt_field_t *mp_fld_reciepe_memory_data_size_adjust_tx_port;\n+\tnt_field_t *mp_fld_reciepe_memory_data_size_adjust_virtual_port;\n+\tnt_field_t *mp_fld_reciepe_memory_data_fixed18b_l2_mtu;\n+\tnt_field_t *mp_fld_reciepe_memory_data_txp_qos_epp_enable;\n+\tnt_field_t *mp_fld_reciepe_memory_data_queue_qos_epp_enable;\n+\n+\tnt_register_t *mp_reg_txp_port_mtu_control;\n+\tnt_field_t *mp_fld_txp_port_mtu_control_adr;\n+\tnt_field_t *mp_fld_txp_port_mtu_control_cnt;\n+\n+\tnt_register_t *mp_reg_txp_port_mtu_data;\n+\tnt_field_t *mp_fld_txp_port_mtu_data_max_mtu;\n+\n+\tnt_register_t *mp_reg_queue_mtu_control;\n+\tnt_field_t *mp_fld_queue_mtu_control_adr;\n+\tnt_field_t *mp_fld_queue_mtu_control_cnt;\n+\n+\tnt_register_t *mp_reg_queue_mtu_data;\n+\tnt_field_t *mp_fld_queue_mtu_data_max_mtu;\n+\n+\tnt_register_t *mp_reg_txp_qos_control;\n+\tnt_field_t *mp_fld_txp_qos_control_adr;\n+\tnt_field_t *mp_fld_txp_qos_control_cnt;\n+\n+\tnt_register_t *mp_reg_txp_qos_data;\n+\tnt_field_t *mp_fld_txp_qos_data_enable;\n+\tnt_field_t *mp_fld_txp_qos_data_information_rate;\n+\tnt_field_t *mp_fld_txp_qos_data_information_rate_fractional;\n+\tnt_field_t *mp_fld_txp_qos_data_burst_size;\n+\n+\tnt_register_t *mp_reg_vport_qos_control;\n+\tnt_field_t *mp_fld_vport_qos_control_adr;\n+\tnt_field_t *mp_fld_vport_qos_control_cnt;\n+\n+\tnt_register_t *mp_reg_vport_qos_data;\n+\tnt_field_t *mp_fld_vport_qos_data_enable;\n+\tnt_field_t *mp_fld_vport_qos_data_information_rate;\n+\tnt_field_t *mp_fld_vport_qos_data_information_rate_fractional;\n+\tnt_field_t *mp_fld_vport_qos_data_burst_size;\n+\n+\tnt_register_t *mp_reg_queue_vport_control;\n+\tnt_field_t *mp_fld_queue_vport_control_adr;\n+\tnt_field_t *mp_fld_queue_vport_control_cnt;\n+\n+\tnt_register_t *mp_reg_queue_vport_data;\n+\tnt_field_t *mp_fld_queue_vport_data_vport;\n+};\n+\n+typedef struct nthw_epp_s nthw_epp_t;\n+\n+nthw_epp_t *nthw_epp_new(void);\n+void nthw_epp_delete(nthw_epp_t *p);\n+\n+int nthw_epp_present(nt_fpga_t *p_fpga, int n_instance);\n+int nthw_epp_init(nthw_epp_t *p, nt_fpga_t *p_fpga, int n_instance);\n+int nthw_epp_setup(nthw_epp_t *p);\n+int nthw_epp_set_mtu(nthw_epp_t *p, uint32_t port, uint32_t max_mtu,\n+\t\t   nt_meta_port_type_t port_type);\n+int nthw_epp_set_txp_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate,\n+\t\t      uint32_t information_rate_fractional, uint32_t burst_size);\n+int nthw_epp_set_vport_qos(nthw_epp_t *p, uint32_t port, uint32_t information_rate,\n+\t\t\tuint32_t information_rate_fractional, uint32_t burst_size);\n+int nthw_epp_set_queue_to_vport(nthw_epp_t *p, uint32_t qid, uint32_t vport);\n+\n+#endif /* NTHW_EPP_HPP_ */\ndiff --git a/drivers/net/ntnic/nthw/nthw_fpga_model.c b/drivers/net/ntnic/nthw/nthw_fpga_model.c\nnew file mode 100644\nindex 0000000000..fca13e0f31\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_fpga_model.c\n@@ -0,0 +1,1677 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <time.h> /* ctime */\n+\n+#include \"nthw_drv.h\" /* fpga_info_s */\n+#include \"nthw_register.h\"\n+#include \"nthw_fpga_model.h\"\n+#include \"nthw_rac.h\"\n+#include \"ntlog.h\"\n+\n+#include \"nthw_fpga_instances.h\"\n+#include \"nthw_fpga_modules_defs.h\"\n+\n+/* Generated code */\n+nt_fpga_prod_init_t *nthw_fpga_instances[] = { &nthw_fpga_9563_055_024_0000,\n+\t\t\t\t\t       NULL\n+\t\t\t\t\t     };\n+\n+static const struct {\n+\tconst int a;\n+\tconst char *b;\n+} sa_nthw_fpga_mod_map[] = {\n+\t{ MOD_CAT, \"CAT\" },\n+\t{ MOD_CB, \"CB\" },\n+\t{ MOD_CCIP, \"CCIP\" },\n+\t{ MOD_CFP4_CTRL_GBOX, \"CFP4_CTRL_GBOX\" },\n+\t{ MOD_COR, \"COR\" },\n+\t{ MOD_CPY, \"CPY\" },\n+\t{ MOD_CSU, \"CSU\" },\n+\t{ MOD_DBS, \"DBS\" },\n+\t{ MOD_DDP, \"DDP\" },\n+\t{ MOD_EPP, \"EPP\" },\n+\t{ MOD_EQM, \"EQM\" },\n+\t{ MOD_FHM, \"FHM\" },\n+\t{ MOD_FLM, \"FLM\" },\n+\t{ MOD_GFG, \"GFG\" },\n+\t{ MOD_GMF, \"GMF\" },\n+\t{ MOD_GPIO_PHY, \"GPIO_PHY\" },\n+\t{ MOD_GPIO_PHY_PORTS, \"GPIO_PHY_PORTS\" },\n+\t{ MOD_GPIO_SFPP, \"GPIO_SFPP\" },\n+\t{ MOD_HFU, \"HFU\" },\n+\t{ MOD_HIF, \"HIF\" },\n+\t{ MOD_HSH, \"HSH\" },\n+\t{ MOD_HST, \"HST\" },\n+\t{ MOD_ICORE_10G, \"ICORE_10G\" },\n+\t{ MOD_IFR, \"IFR\" },\n+\t{ MOD_IIC, \"IIC\" },\n+\t{ MOD_INS, \"INS\" },\n+\t{ MOD_IOA, \"IOA\" },\n+\t{ MOD_IPF, \"IPF\" },\n+\t{ MOD_KM, \"KM\" },\n+\t{ MOD_LAO, \"LAO\" },\n+\t{ MOD_MAC, \"MAC\" },\n+\t{ MOD_MAC10, \"MAC10\" },\n+\t{ MOD_MAC100, \"MAC100\" },\n+\t{ MOD_MAC10G, \"MAC10G\" },\n+\t{ MOD_MAC1G, \"MAC1G\" },\n+\t{ MOD_MAC_PCS, \"MAC_PCS\" },\n+\t{ MOD_MAC_PCS_XXV, \"MAC_PCS_XXV\" },\n+\t{ MOD_MAC_RX, \"MAC_RX\" },\n+\t{ MOD_MAC_TFG, \"MAC_TFG\" },\n+\t{ MOD_MAC_TX, \"MAC_TX\" },\n+\t{ MOD_MCU, \"MCU\" },\n+\t{ MOD_MDG, \"MDG\" },\n+\t{ MOD_MSK, \"MSK\" },\n+\t{ MOD_NIF, \"NIF\" },\n+\t{ MOD_PCIE3, \"PCIE3\" },\n+\t{ MOD_PCI_RD_TG, \"PCI_RD_TG\" },\n+\t{ MOD_PCI_TA, \"PCI_TA\" },\n+\t{ MOD_PCI_WR_TG, \"PCI_WR_TG\" },\n+\t{ MOD_PCM_NT100A01_01, \"PCM_NT100A01_01\" },\n+\t{ MOD_PCM_NT50B01_01, \"PCM_NT50B01_01\" },\n+\t{ MOD_PCS, \"PCS\" },\n+\t{ MOD_PCS100, \"PCS100\" },\n+\t{ MOD_PDB, \"PDB\" },\n+\t{ MOD_PDI, \"PDI\" },\n+\t{ MOD_PHY10G, \"PHY10G\" },\n+\t{ MOD_PHY3S10G, \"PHY3S10G\" },\n+\t{ MOD_PM, \"PM\" },\n+\t{ MOD_PRM_NT100A01_01, \"PRM_NT100A01_01\" },\n+\t{ MOD_PRM_NT50B01_01, \"PRM_NT50B01_01\" },\n+\t{ MOD_PTP1588, \"PTP1588\" },\n+\t{ MOD_QM, \"QM\" },\n+\t{ MOD_QSL, \"QSL\" },\n+\t{ MOD_QSPI, \"QSPI\" },\n+\t{ MOD_R2DRP, \"R2DRP\" },\n+\t{ MOD_RAC, \"RAC\" },\n+\t{ MOD_RBH, \"RBH\" },\n+\t{ MOD_RFD, \"RFD\" },\n+\t{ MOD_RMC, \"RMC\" },\n+\t{ MOD_RNTC, \"RNTC\" },\n+\t{ MOD_ROA, \"ROA\" },\n+\t{ MOD_RPL, \"RPL\" },\n+\t{ MOD_RPP_LR, \"RPP_LR\" },\n+\t{ MOD_RST7000, \"RST7000\" },\n+\t{ MOD_RST7001, \"RST7001\" },\n+\t{ MOD_RST9500, \"RST9500\" },\n+\t{ MOD_RST9501, \"RST9501\" },\n+\t{ MOD_RST9502, \"RST9502\" },\n+\t{ MOD_RST9503, \"RST9503\" },\n+\t{ MOD_RST9504, \"RST9504\" },\n+\t{ MOD_RST9505, \"RST9505\" },\n+\t{ MOD_RST9506, \"RST9506\" },\n+\t{ MOD_RST9507, \"RST9507\" },\n+\t{ MOD_RST9508, \"RST9508\" },\n+\t{ MOD_RST9509, \"RST9509\" },\n+\t{ MOD_RST9510, \"RST9510\" },\n+\t{ MOD_RST9512, \"RST9512\" },\n+\t{ MOD_RST9513, \"RST9513\" },\n+\t{ MOD_RST9515, \"RST9515\" },\n+\t{ MOD_RST9516, \"RST9516\" },\n+\t{ MOD_RST9517, \"RST9517\" },\n+\t{ MOD_RST9519, \"RST9519\" },\n+\t{ MOD_RST9520, \"RST9520\" },\n+\t{ MOD_RST9521, \"RST9521\" },\n+\t{ MOD_RST9522, \"RST9522\" },\n+\t{ MOD_RST9523, \"RST9523\" },\n+\t{ MOD_RST9524, \"RST9524\" },\n+\t{ MOD_RST9525, \"RST9525\" },\n+\t{ MOD_RST9526, \"RST9526\" },\n+\t{ MOD_RST9527, \"RST9527\" },\n+\t{ MOD_RST9528, \"RST9528\" },\n+\t{ MOD_RST9529, \"RST9529\" },\n+\t{ MOD_RST9530, \"RST9530\" },\n+\t{ MOD_RST9531, \"RST9531\" },\n+\t{ MOD_RST9532, \"RST9532\" },\n+\t{ MOD_RST9533, \"RST9533\" },\n+\t{ MOD_RST9534, \"RST9534\" },\n+\t{ MOD_RST9535, \"RST9535\" },\n+\t{ MOD_RST9536, \"RST9536\" },\n+\t{ MOD_RST9537, \"RST9537\" },\n+\t{ MOD_RST9538, \"RST9538\" },\n+\t{ MOD_RST9539, \"RST9539\" },\n+\t{ MOD_RST9540, \"RST9540\" },\n+\t{ MOD_RST9541, \"RST9541\" },\n+\t{ MOD_RST9542, \"RST9542\" },\n+\t{ MOD_RST9543, \"RST9543\" },\n+\t{ MOD_RST9544, \"RST9544\" },\n+\t{ MOD_RST9545, \"RST9545\" },\n+\t{ MOD_RST9546, \"RST9546\" },\n+\t{ MOD_RST9547, \"RST9547\" },\n+\t{ MOD_RST9548, \"RST9548\" },\n+\t{ MOD_RST9549, \"RST9549\" },\n+\t{ MOD_RST9553, \"RST9553\" },\n+\t{ MOD_RST9555, \"RST9555\" },\n+\t{ MOD_RST9559, \"RST9559\" },\n+\t{ MOD_RST9563, \"RST9563\" },\n+\t{ MOD_RTD, \"RTD\" },\n+\t{ MOD_RTD_HMP, \"RTD_HMP\" },\n+\t{ MOD_RTX, \"RTX\" },\n+\t{ MOD_SDC, \"SDC\" },\n+\t{ MOD_SLC, \"SLC\" },\n+\t{ MOD_SLC_LR, \"SLC_LR\" },\n+\t{ MOD_SMM, \"SMM\" },\n+\t{ MOD_SMM_RX, \"SMM_RX\" },\n+\t{ MOD_SMM_TX, \"SMM_TX\" },\n+\t{ MOD_SPIM, \"SPIM\" },\n+\t{ MOD_SPIS, \"SPIS\" },\n+\t{ MOD_STA, \"STA\" },\n+\t{ MOD_TBH, \"TBH\" },\n+\t{ MOD_TEMPMON, \"TEMPMON\" },\n+\t{ MOD_TINT, \"TINT\" },\n+\t{ MOD_TMC, \"TMC\" },\n+\t{ MOD_TSM, \"TSM\" },\n+\t{ MOD_TX_CPY, \"TX_CPY\" },\n+\t{ MOD_TX_CSI, \"TX_CSI\" },\n+\t{ MOD_TX_CSO, \"TX_CSO\" },\n+\t{ MOD_TX_INS, \"TX_INS\" },\n+\t{ MOD_TX_RPL, \"TX_RPL\" },\n+\t{ 0L, NULL },\n+};\n+\n+/* NOTE: this needs to be (manually) synced with enum */\n+static const char *const a_bus_type[] = {\n+\t\"ERR\", /* BUS_TYPE_UNKNOWN, */\n+\t\"BAR\", /* BUS_TYPE_BAR, */\n+\t\"PCI\", /* BUS_TYPE_PCI, */\n+\t\"CCIP\", /* BUS_TYPE_CCIP, */\n+\t\"RAB0\", /* BUS_TYPE_RAB0, */\n+\t\"RAB1\", /* BUS_TYPE_RAB1, */\n+\t\"RAB2\", /* BUS_TYPE_RAB2, */\n+\t\"NMB\", /* BUS_TYPE_NMB, */\n+\t\"NDM\", /* BUS_TYPE_NDM, */\n+};\n+\n+static const char *get_bus_name(int n_bus_type_id)\n+{\n+\tif (n_bus_type_id >= 1 && n_bus_type_id <= (int)ARRAY_SIZE(a_bus_type))\n+\t\treturn a_bus_type[n_bus_type_id];\n+\n+\telse\n+\t\treturn \"ERR\";\n+}\n+\n+/*\n+ * Module name lookup by id from array\n+ * Uses naive linear search as performance is not an issue here...\n+ */\n+static const char *nthw_fpga_mod_id_to_str(uint64_t n_fpga_mod_id)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i <= (int)ARRAY_SIZE(sa_nthw_fpga_mod_map); i++) {\n+\t\tif ((uint64_t)sa_nthw_fpga_mod_map[i].a == n_fpga_mod_id)\n+\t\t\tbreak;\n+\t}\n+\treturn (sa_nthw_fpga_mod_map[i].b ? sa_nthw_fpga_mod_map[i].b :\n+\t\t\"unknown\");\n+}\n+\n+/*\n+ * Force C linkage for xxx_addr_bases and xxx_module_versions\n+ */\n+static int read_data(struct fpga_info_s *p_fpga_info, int n_bus_type_id, uint32_t addr,\n+\t\t    uint32_t len, uint32_t *p_data)\n+{\n+\tint rc = -1;\n+\n+\tassert(p_fpga_info);\n+\tassert(p_data);\n+\n+\tswitch (n_bus_type_id) {\n+\tcase BUS_TYPE_BAR:\n+\tcase BUS_TYPE_PCI:\n+\t\tassert(len == 1);\n+\t\tnthw_rac_reg_read32(p_fpga_info, addr, p_data);\n+\t\trc = 0;\n+\t\tbreak;\n+\tcase BUS_TYPE_RAB0:\n+\t\tassert(p_fpga_info->mp_nthw_rac);\n+\t\trc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, addr, 0, len,\n+\t\t\t\t\tp_data);\n+\t\tbreak;\n+\tcase BUS_TYPE_RAB1:\n+\t\tassert(p_fpga_info->mp_nthw_rac);\n+\t\trc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, addr, 1, len,\n+\t\t\t\t\tp_data);\n+\t\tbreak;\n+\tcase BUS_TYPE_RAB2:\n+\t\tassert(p_fpga_info->mp_nthw_rac);\n+\t\trc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, addr, 2, len,\n+\t\t\t\t\tp_data);\n+\t\tbreak;\n+\tdefault:\n+\t\tassert(false);\n+\t\treturn -1;\n+\t}\n+\n+\treturn rc;\n+}\n+\n+static int read_data_tsc(struct fpga_info_s *p_fpga_info, int n_bus_type_id,\n+\t\t       uint32_t addr, uint32_t len, uint32_t *p_data,\n+\t\t       uint64_t *p_tsc1, uint64_t *p_tsc2)\n+{\n+\tint rc = -1;\n+\n+\t(void)p_tsc1;\n+\t(void)p_tsc2;\n+\n+\trc = read_data(p_fpga_info, n_bus_type_id, addr, len, p_data);\n+\n+\treturn rc;\n+}\n+\n+static int write_data(struct fpga_info_s *p_fpga_info, int n_bus_type_id,\n+\t\t     uint32_t addr, uint32_t len, const uint32_t *p_data)\n+{\n+\tint rc = -1;\n+\n+\tassert(p_fpga_info);\n+\tassert(p_data);\n+\n+\tswitch (n_bus_type_id) {\n+\tcase BUS_TYPE_BAR:\n+\tcase BUS_TYPE_PCI:\n+\t\tassert(len == 1);\n+\t\tnthw_rac_reg_write32(p_fpga_info, addr, *p_data);\n+\t\trc = 0;\n+\t\tbreak;\n+\tcase BUS_TYPE_RAB0:\n+\t\tassert(p_fpga_info->mp_nthw_rac);\n+\t\trc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, addr, 0, len,\n+\t\t\t\t\t p_data);\n+\t\tbreak;\n+\tcase BUS_TYPE_RAB1:\n+\t\tassert(p_fpga_info->mp_nthw_rac);\n+\t\trc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, addr, 1, len,\n+\t\t\t\t\t p_data);\n+\t\tbreak;\n+\tcase BUS_TYPE_RAB2:\n+\t\tassert(p_fpga_info->mp_nthw_rac);\n+\t\trc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, addr, 2, len,\n+\t\t\t\t\t p_data);\n+\t\tbreak;\n+\tdefault:\n+\t\tassert(false);\n+\t\treturn -1;\n+\t}\n+\n+\treturn rc;\n+}\n+\n+/*\n+ * FpgaMgr\n+ */\n+nt_fpga_mgr_t *fpga_mgr_new(void)\n+{\n+\tnt_fpga_mgr_t *p = malloc(sizeof(nt_fpga_mgr_t));\n+\treturn p;\n+}\n+\n+void fpga_mgr_delete(nt_fpga_mgr_t *p)\n+{\n+\tmemset(p, 0, sizeof(nt_fpga_mgr_t));\n+\tfree(p);\n+}\n+\n+void fpga_mgr_init(nt_fpga_mgr_t *p)\n+{\n+\tsize_t i;\n+\n+\t/* Count fpga instance in array */\n+\tp->mpa_fpga_prod_init = nthw_fpga_instances;\n+\tfor (i = 0; i < ARRAY_SIZE(nthw_fpga_instances); i++) {\n+\t\tif (p->mpa_fpga_prod_init[i] == NULL)\n+\t\t\tbreak;\n+\t}\n+\tp->mn_fpgas = (int)i;\n+}\n+\n+nt_fpga_t *fpga_mgr_query_fpga(nt_fpga_mgr_t *p, uint64_t n_fpga_id,\n+\t\t\t     struct fpga_info_s *p_fpga_info)\n+{\n+\tint i;\n+\n+\tconst int n_fpga_prod = FPGAID_TO_PRODUCTCODE(n_fpga_id);\n+\tconst int n_fpga_ver = FPGAID_TO_VERSIONCODE(n_fpga_id);\n+\tconst int n_fpga_rev = FPGAID_TO_REVISIONCODE(n_fpga_id);\n+\n+\tfor (i = 0; i < p->mn_fpgas; i++) {\n+\t\tnt_fpga_prod_init_t *p_init = p->mpa_fpga_prod_init[i];\n+\n+\t\tif (p_init->fpga_product_id == n_fpga_prod &&\n+\t\t\t\tp_init->fpga_version == n_fpga_ver &&\n+\t\t\t\tp_init->fpga_revision == n_fpga_rev) {\n+\t\t\t{\n+\t\t\t\tnt_fpga_t *p_fpga = fpga_new();\n+\n+\t\t\t\tfpga_init(p_fpga, p_init, p_fpga_info);\n+\t\t\t\treturn p_fpga;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tNT_LOG(ERR, NTHW,\n+\t       \"FPGA Id 0x%\" PRIX64 \": %04d: %d.%d: no match found\\n\", n_fpga_id,\n+\t       n_fpga_prod, n_fpga_ver, n_fpga_rev);\n+\n+\treturn NULL;\n+}\n+\n+void fpga_mgr_show(nt_fpga_mgr_t *p, FILE *fh_out, int detail_level)\n+{\n+\tint i;\n+\n+\tfprintf(fh_out, \"\\n\"); /* start of records */\n+\tfor (i = 0; i < p->mn_fpgas; i++) {\n+\t\tnt_fpga_prod_init_t *p_init = p->mpa_fpga_prod_init[i];\n+\n+\t\tif (detail_level == 0) {\n+\t\t\tfprintf(fh_out, \"%04d-%02d-%02d\\n\",\n+\t\t\t\tp_init->fpga_product_id, p_init->fpga_version,\n+\t\t\t\tp_init->fpga_revision);\n+\t\t} else {\n+\t\t\ttime_t fpga_build_time = p_init->fpga_build_time;\n+\n+\t\t\tfprintf(fh_out, \"%04d-%02d-%02d: 0x%08lX: %s\\n\",\n+\t\t\t\tp_init->fpga_product_id, p_init->fpga_version,\n+\t\t\t\tp_init->fpga_revision, fpga_build_time,\n+\t\t\t\t(fpga_build_time ? ctime(&fpga_build_time) :\n+\t\t\t\t \"NA\\n\"));\n+\t\t}\n+\t}\n+\tfprintf(fh_out, \"\\n\"); /* end of records */\n+\tfflush(fh_out);\n+}\n+\n+void fpga_mgr_log_dump(nt_fpga_mgr_t *p)\n+{\n+\tint i;\n+\n+\tNT_LOG(DBG, NTHW, \"%s: fpgas=%d\\n\", __func__, p->mn_fpgas);\n+\tfor (i = 0; i < p->mn_fpgas; i++) {\n+\t\tnt_fpga_prod_init_t *p_init _unused = p->mpa_fpga_prod_init[i];\n+\t\tNT_LOG(DBG, NTHW, \"%s: fpga=%d/%d: %04d-%02d-%02d\\n\", __func__,\n+\t\t       i, p->mn_fpgas, p_init->fpga_product_id, p_init->fpga_version,\n+\t\t       p_init->fpga_revision);\n+\t}\n+}\n+\n+/*\n+ * Fpga\n+ */\n+nt_fpga_t *fpga_new(void)\n+{\n+\tnt_fpga_t *p = malloc(sizeof(nt_fpga_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nt_fpga_t));\n+\treturn p;\n+}\n+\n+void fpga_delete(nt_fpga_t *p)\n+{\n+\tmemset(p, 0, sizeof(nt_fpga_t));\n+\tfree(p);\n+}\n+\n+void fpga_delete_all(nt_fpga_t *p)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < p->mn_modules; i++) {\n+\t\tnt_module_t *p_mod = p->mpa_modules[i];\n+\n+\t\tif (p_mod)\n+\t\t\tmodule_delete(p_mod);\n+\t}\n+\n+\tfpga_delete(p);\n+}\n+\n+void fpga_init(nt_fpga_t *p, nt_fpga_prod_init_t *fpga_prod_init,\n+\t       struct fpga_info_s *p_fpga_info)\n+{\n+\tint i;\n+\n+\tp->p_fpga_info = p_fpga_info;\n+\tp->mp_init = fpga_prod_init;\n+\n+\tp->m_item_id = fpga_prod_init->fpga_item_id;\n+\tp->m_product_id = fpga_prod_init->fpga_product_id;\n+\tp->m_fpga_version = fpga_prod_init->fpga_version;\n+\tp->m_fpga_revision = fpga_prod_init->fpga_revision;\n+\tp->m_fpga_patch_no = fpga_prod_init->fpga_patch_no;\n+\tp->m_fpga_build_no = fpga_prod_init->fpga_build_no;\n+\tp->m_fpga_build_time = fpga_prod_init->fpga_build_time;\n+\n+\tp->mn_params = fpga_prod_init->nb_prod_params;\n+\n+\tif (p->mn_params) {\n+\t\tp->mpa_params = malloc(p->mn_params * sizeof(nt_param_t *));\n+\t\tif (p->mpa_params) {\n+\t\t\tmemset(p->mpa_params, 0,\n+\t\t\t       (p->mn_params * sizeof(nt_param_t *)));\n+\t\t\tfor (i = 0; i < p->mn_params; i++) {\n+\t\t\t\tnt_param_t *p_param = param_new();\n+\n+\t\t\t\tparam_init(p_param, p,\n+\t\t\t\t\t   &fpga_prod_init->product_params[i]);\n+\t\t\t\tp->mpa_params[i] = p_param;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tp->mn_modules = fpga_prod_init->nb_modules;\n+\n+\tif (p->mn_modules) {\n+\t\tp->mpa_modules =\n+\t\t\tmalloc(fpga_prod_init->nb_modules * sizeof(nt_module_t *));\n+\t\tif (p->mpa_modules) {\n+\t\t\tmemset(p->mpa_modules, 0,\n+\t\t\t       (p->mn_modules * sizeof(nt_module_t *)));\n+\t\t\tfor (i = 0; i < p->mn_modules; i++) {\n+\t\t\t\tnt_module_t *p_mod = module_new();\n+\n+\t\t\t\tmodule_init(p_mod, p, &fpga_prod_init->modules[i]);\n+\t\t\t\tp->mpa_modules[i] = p_mod;\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+void fpga_set_debug_mode(nt_fpga_t *p, int n_debug_mode)\n+{\n+\tint i;\n+\n+\tp->m_debug_mode = n_debug_mode;\n+\n+\tfor (i = 0; i < p->mn_modules; i++) {\n+\t\tnt_module_t *p_mod = p->mpa_modules[i];\n+\n+\t\tif (p_mod)\n+\t\t\tmodule_set_debug_mode(p_mod, n_debug_mode);\n+\t}\n+}\n+\n+nt_module_t *fpga_query_module(const nt_fpga_t *p, int id, int instance)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < p->mn_modules; i++) {\n+\t\tnt_module_t *p_mod = p->mpa_modules[i];\n+\n+\t\tif (p_mod->m_mod_id == id && p_mod->m_instance == instance)\n+\t\t\treturn p_mod;\n+\t}\n+\treturn NULL;\n+}\n+\n+bool fpga_query(nt_fpga_t *p, int id, int instance)\n+{\n+\treturn (fpga_query_module(p, id, instance) != NULL);\n+}\n+\n+nt_fpga_module_init_t *fpga_lookup_init(nt_fpga_t *p, int id, int instance)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < p->mp_init->nb_modules; i++) {\n+\t\tnt_fpga_module_init_t *p_mod_init = &p->mp_init->modules[i];\n+\n+\t\tif (p_mod_init->id == id && p_mod_init->instance == instance)\n+\t\t\treturn p_mod_init;\n+\t}\n+\treturn NULL;\n+}\n+\n+int fpga_get_product_param(const nt_fpga_t *p, const int n_param_id,\n+\t\t\t const int n_default_value)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < p->mn_params; i++) {\n+\t\tnt_param_t *p_param = p->mpa_params[i];\n+\n+\t\tif (p_param->param_id == n_param_id)\n+\t\t\treturn p_param->param_value;\n+\t}\n+\n+\treturn n_default_value;\n+}\n+\n+int fpga_get_product_id(const nt_fpga_t *p)\n+{\n+\treturn p->m_product_id;\n+}\n+\n+int fpga_get_fpga_version(const nt_fpga_t *p)\n+{\n+\treturn p->m_fpga_version;\n+}\n+\n+int fpga_get_fpga_revision(const nt_fpga_t *p)\n+{\n+\treturn p->m_fpga_revision;\n+}\n+\n+void fpga_log_info(const nt_fpga_t *p _unused)\n+{\n+\tNT_LOG(INF, NTHW, \"FPGA: %d-%d-%d-%d-%d-%d (%08X)\\n\", p->m_item_id,\n+\t       p->m_product_id, p->m_fpga_version, p->m_fpga_revision,\n+\t       p->m_fpga_patch_no, p->m_fpga_build_no, p->m_fpga_build_time);\n+}\n+\n+void fpga_dump(const nt_fpga_t *p)\n+{\n+\tNT_LOG(DBG, NTHW, \"%s: id=%d ver=%d.%d params=%d modules=%d\\n\",\n+\t       __func__, p->m_product_id, p->m_fpga_version, p->m_fpga_revision,\n+\t       p->mn_params, p->mn_modules);\n+\tfpga_dump_params(p);\n+\tfpga_dump_modules(p);\n+}\n+\n+void fpga_dump_params(const nt_fpga_t *p)\n+{\n+\tint i;\n+\n+\tNT_LOG(DBG, NTHW, \"%s: params=%d\\n\", __func__, p->mn_params);\n+\n+\tfor (i = 0; i < p->mn_params; i++) {\n+\t\tnt_param_t *p_par = p->mpa_params[i];\n+\n+\t\tparam_dump(p_par);\n+\t}\n+}\n+\n+void fpga_dump_modules(const nt_fpga_t *p)\n+{\n+\tint i;\n+\n+\tNT_LOG(DBG, NTHW, \"%s: modules=%d\\n\", __func__, p->mn_modules);\n+\n+\tfor (i = 0; i < p->mn_modules; i++) {\n+\t\tnt_module_t *p_mod = p->mpa_modules[i];\n+\n+\t\tmodule_dump(p_mod);\n+\t}\n+}\n+\n+/*\n+ * Param\n+ */\n+nt_param_t *param_new(void)\n+{\n+\tnt_param_t *p = malloc(sizeof(nt_param_t));\n+\treturn p;\n+}\n+\n+void param_delete(nt_param_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nt_param_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+void param_init(nt_param_t *p, nt_fpga_t *p_fpga, nt_fpga_prod_param_t *p_init)\n+{\n+\tp->mp_owner = p_fpga;\n+\tp->mp_init = p_init;\n+\n+\tp->param_id = p_init->param_id;\n+\tp->param_value = p_init->param_value;\n+}\n+\n+void param_dump(const nt_param_t *p _unused)\n+{\n+\tNT_LOG(DBG, NTHW, \"%s: id=%d value=%d\\n\", __func__, p->param_id,\n+\t       p->param_value);\n+}\n+\n+/*\n+ * Module\n+ */\n+nt_module_t *module_new(void)\n+{\n+\tnt_module_t *p = malloc(sizeof(nt_module_t));\n+\treturn p;\n+}\n+\n+void module_delete(nt_module_t *p)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < p->mn_registers; i++) {\n+\t\tnt_register_t *p_reg = p->mpa_registers[i];\n+\n+\t\tif (p_reg)\n+\t\t\tregister_delete(p_reg);\n+\t}\n+\tmemset(p, 0, sizeof(nt_module_t));\n+\tfree(p);\n+}\n+\n+void module_init(nt_module_t *p, nt_fpga_t *p_fpga, nt_fpga_module_init_t *p_init)\n+{\n+\tint i;\n+\n+\tp->mp_owner = p_fpga;\n+\tp->mp_init = p_init;\n+\n+\tp->m_mod_id = p_init->id;\n+\tp->m_instance = p_init->instance;\n+\n+\t/* Copy debug mode from owner */\n+\tif (p->mp_owner)\n+\t\tp->m_debug_mode = p->mp_owner->m_debug_mode;\n+\n+\telse\n+\t\tp->m_debug_mode = 0;\n+\n+\tp->m_mod_def_id = p_init->def_id;\n+\tp->m_major_version = p_init->major_version;\n+\tp->m_minor_version = p_init->minor_version;\n+\tp->m_bus = p_init->bus_id;\n+\tp->m_addr_base = p_init->addr_base;\n+\n+\tp->mn_registers = p_init->nb_registers;\n+\tif (p->mn_registers) {\n+\t\tp->mpa_registers =\n+\t\t\tmalloc(p->mn_registers * sizeof(nt_register_t *));\n+\t\tif (p->mpa_registers) {\n+\t\t\tmemset(p->mpa_registers, 0,\n+\t\t\t       (p->mn_registers * sizeof(nt_register_t *)));\n+\t\t\tfor (i = 0; i < p->mn_registers; i++) {\n+\t\t\t\tnt_register_t *p_reg = register_new();\n+\n+\t\t\t\tregister_init(p_reg, p, &p_init->registers[i]);\n+\t\t\t\tp->mpa_registers[i] = p_reg;\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+void module_init2(nt_module_t *p, nt_fpga_t *p_fpga, int mod_id, int instance,\n+\t\t  int debug_mode)\n+{\n+\tnt_fpga_module_init_t *p_init = NULL;\n+\n+\tp_init = fpga_lookup_init(p_fpga, mod_id, instance);\n+\tmodule_init(p, p_fpga, p_init);\n+\n+\t/* set debug mode after regulat init... */\n+\tp->m_debug_mode = debug_mode;\n+}\n+\n+void module_dump(const nt_module_t *p)\n+{\n+\tNT_LOG(DBG, NTHW,\n+\t       \"%s: id=%d inst=%d def=%d ver=%d.%d busid=%d base=0x%X regs=%d\\n\",\n+\t       __func__, p->m_mod_id, p->m_instance, p->m_mod_def_id,\n+\t       p->m_major_version, p->m_minor_version, p->m_bus, p->m_addr_base,\n+\t       p->mn_registers);\n+\tmodule_dump_registers(p);\n+}\n+\n+void module_dump_registers(const nt_module_t *p)\n+{\n+\tint i;\n+\n+\tNT_LOG(DBG, NTHW, \"%s: regs=%d\\n\", __func__, p->mn_registers);\n+\n+\tfor (i = 0; i < p->mn_registers; i++) {\n+\t\tnt_register_t *p_reg = p->mpa_registers[i];\n+\n+\t\tregister_dump(p_reg);\n+\t}\n+}\n+\n+int module_get_major_version(const nt_module_t *p)\n+{\n+\treturn p->m_major_version;\n+}\n+\n+int module_get_minor_version(const nt_module_t *p)\n+{\n+\treturn p->m_minor_version;\n+}\n+\n+uint64_t module_get_version_packed64(const nt_module_t *p)\n+{\n+\treturn (((uint64_t)p->m_major_version & 0xFFFFFFFF) << 32) |\n+\t       (p->m_minor_version & 0xFFFFFFFF);\n+}\n+\n+bool module_is_version_newer(const nt_module_t *p, int major_version,\n+\t\t\t   int minor_version)\n+{\n+\tif (major_version == p->m_major_version)\n+\t\treturn p->m_minor_version >= minor_version;\n+\treturn p->m_major_version >= major_version;\n+}\n+\n+static nt_register_t *module_lookup_register(nt_module_t *p, uint32_t id)\n+{\n+\tint i;\n+\tnt_register_t *p_register = NULL;\n+\n+\tfor (i = 0; i < p->mn_registers; i++) {\n+\t\tif (p->mpa_registers[i]->m_id == id) {\n+\t\t\tp_register = p->mpa_registers[i];\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\treturn p_register;\n+}\n+\n+nt_register_t *module_get_register(nt_module_t *p, uint32_t id)\n+{\n+\tnt_register_t *p_register;\n+\n+\tif (p == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"Illegal module context for register %d\\n\",\n+\t\t       id);\n+\t\treturn NULL;\n+\t}\n+\n+\tp_register = module_lookup_register(p, id);\n+\tif (!p_register) {\n+\t\tNT_LOG(ERR, NTHW, \"Register %d not found in module: %s (%d)\\n\",\n+\t\t       id, nthw_fpga_mod_id_to_str(p->m_mod_id), p->m_mod_id);\n+\t}\n+\treturn p_register;\n+}\n+\n+nt_register_t *module_query_register(nt_module_t *p, uint32_t id)\n+{\n+\treturn module_lookup_register(p, id);\n+}\n+\n+int module_get_debug_mode(const nt_module_t *p)\n+{\n+\treturn p->m_debug_mode;\n+}\n+\n+void module_set_debug_mode(nt_module_t *p, unsigned int n_debug_mode)\n+{\n+\tint i;\n+\tnt_register_t *p_register = NULL;\n+\n+\tp->m_debug_mode = n_debug_mode;\n+\n+\tfor (i = 0; i < p->mn_registers; i++) {\n+\t\tp_register = p->mpa_registers[i];\n+\t\tif (p_register)\n+\t\t\tregister_set_debug_mode(p_register, n_debug_mode);\n+\t}\n+}\n+\n+int module_get_bus(const nt_module_t *p)\n+{\n+\treturn p->m_bus;\n+}\n+\n+uint32_t module_get_addr_base(const nt_module_t *p)\n+{\n+\treturn p->m_addr_base;\n+}\n+\n+void module_unsuppported(const nt_module_t *p)\n+{\n+\tNT_LOG(ERR, NTHW, \"Module %d not supported\", p->mp_init->id);\n+}\n+\n+/*\n+ * Register\n+ */\n+nt_register_t *register_new(void)\n+{\n+\tnt_register_t *p = malloc(sizeof(nt_register_t));\n+\treturn p;\n+}\n+\n+void register_delete(nt_register_t *p)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < p->mn_fields; i++) {\n+\t\tnt_field_t *p_field = p->mpa_fields[i];\n+\n+\t\tif (p_field)\n+\t\t\tfield_delete(p_field);\n+\t}\n+\n+\tif (p->mp_shadow)\n+\t\tfree(p->mp_shadow);\n+\n+\tif (p->mp_dirty)\n+\t\tfree(p->mp_dirty);\n+\n+\tmemset(p, 0, sizeof(nt_register_t));\n+\tfree(p);\n+}\n+\n+void register_init(nt_register_t *p, nt_module_t *p_module,\n+\t\t   nt_fpga_register_init_t *p_init)\n+{\n+\tint i;\n+\n+\tp->mp_owner = p_module;\n+\n+\tp->m_id = p_init->id;\n+\tp->mn_bit_width = p_init->bw;\n+\tp->mn_addr_rel = p_init->addr_rel;\n+\tp->m_addr = p_module->m_addr_base + p_init->addr_rel;\n+\tp->m_type = p_init->type;\n+\tp->m_len =\n+\t\t((p_init->bw != (uint16_t)-1) ?\n+\t\t ((p_init->bw + 31) >> 5) :\n+\t\t 1); /* Old P200 registers have no bw at register level - default to BW=-1 */\n+\tp->m_debug_mode = p_module->m_debug_mode;\n+\n+\tp->mn_fields = p_init->nb_fields;\n+\tif (p->mn_fields) {\n+\t\tp->mpa_fields = malloc(p->mn_fields * sizeof(nt_field_t *));\n+\n+\t\tif (p->mpa_fields) {\n+\t\t\tmemset(p->mpa_fields, 0,\n+\t\t\t       (p->mn_fields * sizeof(nt_field_t *)));\n+\t\t\tfor (i = 0; i < p->mn_fields; i++) {\n+\t\t\t\tnt_field_t *p_field = field_new();\n+\n+\t\t\t\tfield_init(p_field, p, &p_init->fields[i]);\n+\t\t\t\tp->mpa_fields[i] = p_field;\n+\t\t\t}\n+\n+\t\t\tp->mp_shadow = malloc(p->m_len * sizeof(uint32_t));\n+\t\t\tif (p->mp_shadow) {\n+\t\t\t\tmemset(p->mp_shadow, 0x00,\n+\t\t\t\t       (p->m_len * sizeof(uint32_t)));\n+\t\t\t}\n+\n+\t\t\tp->mp_dirty = malloc(p->m_len * sizeof(bool));\n+\t\t\tif (p->mp_dirty) {\n+\t\t\t\tmemset(p->mp_dirty, 0x00,\n+\t\t\t\t       (p->m_len * sizeof(bool)));\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+void register_dump(const nt_register_t *p)\n+{\n+\tNT_LOG(DBG, NTHW,\n+\t       \"%s(id=%d type=%d addr=0x%08X addrrel=0x%08X len=%d bw=%d\\n\",\n+\t       __func__, p->m_id, p->m_type, p->m_addr, p->mn_addr_rel, p->m_len,\n+\t       p->mn_bit_width);\n+\tregister_dump_fields(p);\n+}\n+\n+void register_dump_fields(const nt_register_t *p)\n+{\n+\tint i;\n+\n+\tNT_LOG(DBG, NTHW, \"%s(addr=0x%08X fields=%d\\n\", __func__, p->m_addr,\n+\t       p->mn_fields);\n+\tfor (i = 0; i < p->mn_fields; i++)\n+\t\tfield_dump(p->mpa_fields[i]);\n+\tNT_LOG(DBG, NTHW, \"\\n\");\n+}\n+\n+uint32_t register_get_address(const nt_register_t *p)\n+{\n+\treturn p->m_addr;\n+}\n+\n+void register_reset(const nt_register_t *p)\n+{\n+\tint i;\n+\tnt_field_t *p_field = NULL;\n+\n+\tfor (i = 0; i < p->mn_fields; i++) {\n+\t\tp_field = p->mpa_fields[i];\n+\t\tif (p_field)\n+\t\t\tfield_reset(p_field);\n+\t}\n+}\n+\n+static nt_field_t *register_lookup_field(const nt_register_t *p, uint32_t id)\n+{\n+\tint i;\n+\tnt_field_t *p_field = NULL;\n+\n+\tif (!p)\n+\t\treturn NULL;\n+\n+\tfor (i = 0; i < p->mn_fields; i++) {\n+\t\tif (p->mpa_fields[i]->m_id == id) {\n+\t\t\tp_field = p->mpa_fields[i];\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\treturn p_field;\n+}\n+\n+nt_field_t *register_get_field(const nt_register_t *p, uint32_t id)\n+{\n+\tnt_field_t *p_field;\n+\n+\tif (p == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"Illegal register context for field %d\\n\",\n+\t\t       id);\n+\t\treturn NULL;\n+\t}\n+\n+\tp_field = register_lookup_field(p, id);\n+\tif (!p_field) {\n+\t\tNT_LOG(ERR, NTHW, \"Field %d not found in module: %s (%d)\\n\", id,\n+\t\t       nthw_fpga_mod_id_to_str(p->mp_owner->m_mod_id),\n+\t\t       p->mp_owner->m_mod_id);\n+\t}\n+\treturn p_field;\n+}\n+\n+nt_field_t *register_query_field(const nt_register_t *p, uint32_t id)\n+{\n+\treturn register_lookup_field(p, id);\n+}\n+\n+int register_get_bit_width(const nt_register_t *p)\n+{\n+\treturn p->mn_bit_width;\n+}\n+\n+uint32_t register_get_addr_rel(const nt_register_t *p)\n+{\n+\treturn p->mn_addr_rel;\n+}\n+\n+int register_get_debug_mode(const nt_module_t *p)\n+{\n+\treturn p->m_debug_mode;\n+}\n+\n+/*\n+ * NOTE: do not set debug on fields - as register operation dumps typically are enough\n+ */\n+void register_set_debug_mode(nt_register_t *p, unsigned int n_debug_mode)\n+{\n+\tint i;\n+\tnt_field_t *p_field = NULL;\n+\n+\tp->m_debug_mode = n_debug_mode;\n+\n+\tfor (i = 0; i < p->mn_fields; i++) {\n+\t\tp_field = p->mpa_fields[i];\n+\t\tif (p_field)\n+\t\t\tfield_set_debug_mode(p_field, n_debug_mode);\n+\t}\n+}\n+\n+static int register_read_data(const nt_register_t *p)\n+{\n+\tint rc = -1;\n+\n+\tconst int n_bus_type_id = module_get_bus(p->mp_owner);\n+\tconst uint32_t addr = p->m_addr;\n+\tconst uint32_t len = p->m_len;\n+\tuint32_t *const p_data = p->mp_shadow;\n+\n+\tstruct fpga_info_s *p_fpga_info = NULL;\n+\n+\tif (p && p->mp_owner && p->mp_owner->mp_owner)\n+\t\tp_fpga_info = p->mp_owner->mp_owner->p_fpga_info;\n+\tassert(p_fpga_info);\n+\tassert(p_data);\n+\n+\trc = read_data(p_fpga_info, n_bus_type_id, addr, len, p_data);\n+\treturn rc;\n+}\n+\n+static int register_read_data_tsc(const nt_register_t *p, uint64_t *p_tsc1,\n+\t\t\t\tuint64_t *p_tsc2)\n+{\n+\tint rc = -1;\n+\n+\tconst int n_bus_type_id = module_get_bus(p->mp_owner);\n+\tconst uint32_t addr = p->m_addr;\n+\tconst uint32_t len = p->m_len;\n+\tuint32_t *const p_data = p->mp_shadow;\n+\n+\tstruct fpga_info_s *p_fpga_info = NULL;\n+\n+\tif (p && p->mp_owner && p->mp_owner->mp_owner)\n+\t\tp_fpga_info = p->mp_owner->mp_owner->p_fpga_info;\n+\n+\trc = read_data_tsc(p_fpga_info, n_bus_type_id, addr, len, p_data, p_tsc1, p_tsc2);\n+\n+\treturn rc;\n+}\n+\n+static int register_write_data(const nt_register_t *p, uint32_t cnt)\n+{\n+\tint rc = -1;\n+\n+\tconst int n_bus_type_id = module_get_bus(p->mp_owner);\n+\tconst uint32_t addr = p->m_addr;\n+\tconst uint32_t len = p->m_len;\n+\tuint32_t *const p_data = p->mp_shadow;\n+\n+\tstruct fpga_info_s *p_fpga_info = NULL;\n+\n+\tif (p && p->mp_owner && p->mp_owner->mp_owner)\n+\t\tp_fpga_info = p->mp_owner->mp_owner->p_fpga_info;\n+\tassert(p_fpga_info);\n+\tassert(p_data);\n+\n+\trc = write_data(p_fpga_info, n_bus_type_id, addr, (len * cnt), p_data);\n+\n+\treturn rc;\n+}\n+\n+void register_get_val(const nt_register_t *p, uint32_t *p_data, uint32_t len)\n+{\n+\tuint32_t i;\n+\n+\tif (len == (uint32_t)-1 || len > p->m_len)\n+\t\tlen = p->m_len;\n+\n+\tassert(len <= p->m_len);\n+\tassert(p_data);\n+\n+\tfor (i = 0; i < len; i++)\n+\t\tp_data[i] = p->mp_shadow[i];\n+}\n+\n+uint32_t register_get_val32(const nt_register_t *p)\n+{\n+\tuint32_t val = 0;\n+\n+\tregister_get_val(p, &val, 1);\n+\treturn val;\n+}\n+\n+void register_update(const nt_register_t *p)\n+{\n+\tif (p && p->m_type != REGISTER_TYPE_WO) {\n+\t\tconst char *const p_dev_name _unused = \"NA\";\n+\t\tconst int n_bus_type_id = module_get_bus(p->mp_owner);\n+\n+\t\tconst char *const p_bus_name _unused = get_bus_name(n_bus_type_id);\n+\t\tconst uint32_t addr _unused = p->m_addr;\n+\t\tconst uint32_t len = p->m_len;\n+\t\tuint32_t *const p_data = p->mp_shadow;\n+\n+\t\tregister_read_data(p);\n+\t\tif (p->m_debug_mode & ON_READ) {\n+\t\t\tuint32_t i = len;\n+\n+\t\t\tuint32_t *ptr _unused = p_data;\n+\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t       \"Register::read(Dev: %s, Bus: %s, Addr: 0x%08X, _cnt: %d, Data:\",\n+\t\t\t       p_dev_name, p_bus_name, addr, len);\n+\t\t\twhile (i--)\n+\t\t\t\tNT_LOG(DBG, NTHW, \" 0x%08X \", *ptr++);\n+\t\t\tNT_LOG(DBG, NTHW, \")\\n\");\n+\t\t}\n+\t}\n+}\n+\n+uint32_t register_get_val_updated32(const nt_register_t *p)\n+{\n+\tuint32_t val = 0;\n+\n+\tregister_update(p);\n+\tregister_get_val(p, &val, 1);\n+\treturn val;\n+}\n+\n+void register_make_dirty(nt_register_t *p)\n+{\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < p->m_len; i++)\n+\t\tp->mp_dirty[i] = true;\n+}\n+\n+void register_set_val(nt_register_t *p, const uint32_t *p_data, uint32_t len)\n+{\n+\tassert(len <= p->m_len);\n+\tassert(p_data);\n+\n+\tif (len == (uint32_t)-1 || len > p->m_len)\n+\t\tlen = p->m_len;\n+\n+\tif (p->mp_shadow != p_data)\n+\t\tmemcpy(p->mp_shadow, p_data, (len * sizeof(uint32_t)));\n+}\n+\n+void register_set_val_flush(nt_register_t *p, const uint32_t *p_data, uint32_t len)\n+{\n+\tregister_set_val(p, p_data, len);\n+\tregister_flush(p, 1);\n+}\n+\n+void register_flush(const nt_register_t *p, uint32_t cnt)\n+{\n+\tint rc;\n+\n+\tif (p->m_type != REGISTER_TYPE_RO) {\n+\t\tconst char *const p_dev_name = \"NA\";\n+\t\tconst int n_bus_type_id = module_get_bus(p->mp_owner);\n+\t\tconst char *p_bus_name = get_bus_name(n_bus_type_id);\n+\t\tconst uint32_t addr = p->m_addr;\n+\t\tconst uint32_t len = p->m_len;\n+\t\tuint32_t *const p_data = p->mp_shadow;\n+\t\tuint32_t i;\n+\n+\t\tassert(len * cnt <= 256);\n+\n+\t\tif (p->m_debug_mode & ON_WRITE) {\n+\t\t\tuint32_t i = len * cnt;\n+\t\t\tuint32_t *ptr = p_data;\n+\t\t\tchar *tmp_string =\n+\t\t\t\tntlog_helper_str_alloc(\"Register::write\");\n+\t\t\tntlog_helper_str_add(tmp_string,\n+\t\t\t\t\t     \"(Dev: %s, Bus: %s, Addr: 0x%08X, _cnt: %d, Data:\",\n+\t\t\t\t\t     p_dev_name, p_bus_name, addr, i);\n+\t\t\twhile (i--) {\n+\t\t\t\tntlog_helper_str_add(tmp_string, \" 0x%08X\",\n+\t\t\t\t\t\t     *ptr++);\n+\t\t\t}\n+\t\t\tntlog_helper_str_add(tmp_string, \")\\n\");\n+\t\t\tNT_LOG(DBG, NTHW, \"%s\", tmp_string);\n+\t\t\tntlog_helper_str_free(tmp_string);\n+\t\t}\n+\n+\t\trc = register_write_data(p, cnt);\n+\n+\t\tif (rc)\n+\t\t\tNT_LOG(ERR, NTHW, \"Register write error %d\\n\", rc);\n+\n+\t\tfor (i = 0; i < cnt; i++)\n+\t\t\tp->mp_dirty[i] = false;\n+\t}\n+}\n+\n+void register_do_read_trig_ts(const nt_register_t *p, uint64_t *tsc1,\n+\t\t\t   uint64_t *tsc2)\n+{\n+\tregister_read_data_tsc(p, tsc1, tsc2);\n+}\n+\n+void register_clr(nt_register_t *p)\n+{\n+\tmemset(p->mp_shadow, 0, p->m_len * sizeof(uint32_t));\n+\tregister_make_dirty(p);\n+}\n+\n+void register_set(nt_register_t *p)\n+{\n+\tmemset(p->mp_shadow, 0xff, p->m_len * sizeof(uint32_t));\n+\tregister_make_dirty(p);\n+}\n+\n+/*\n+ * Field\n+ */\n+nt_field_t *field_new(void)\n+{\n+\tnt_field_t *p = malloc(sizeof(nt_field_t));\n+\treturn p;\n+}\n+\n+void field_delete(nt_field_t *p)\n+{\n+\tmemset(p, 0, sizeof(nt_field_t));\n+\tfree(p);\n+}\n+\n+void field_init(nt_field_t *p, nt_register_t *p_reg,\n+\t\tconst nt_fpga_field_init_t *p_init)\n+{\n+\tp->mp_owner = p_reg;\n+\n+\tp->m_debug_mode = p_reg->m_debug_mode;\n+\n+\tp->m_id = p_init->id;\n+\tp->mn_bit_width = p_init->bw;\n+\tp->mn_bit_pos_low = p_init->low;\n+\tp->m_reset_val = (uint32_t)p_init->reset_val;\n+\tp->m_first_word = p_init->low / 32;\n+\tp->m_first_bit = p_init->low % 32;\n+\tp->m_front_mask = 0;\n+\tp->m_body_length = 0;\n+\tp->mn_words = (p_init->bw + 0x1f) / 0x20;\n+\tp->m_tail_mask = 0;\n+\n+\t{\n+\t\tint bits_remaining = p_init->bw;\n+\t\tint front_mask_length = 32 - p->m_first_bit;\n+\n+\t\tif (front_mask_length > bits_remaining)\n+\t\t\tfront_mask_length = bits_remaining;\n+\t\tbits_remaining -= front_mask_length;\n+\n+\t\tp->m_front_mask = (uint32_t)(((1ULL << front_mask_length) - 1)\n+\t\t\t\t\t   << p->m_first_bit);\n+\n+\t\tp->m_body_length = bits_remaining / 32;\n+\t\tbits_remaining -= p->m_body_length * 32;\n+\t\tp->m_tail_mask = (1 << bits_remaining) - 1;\n+\n+\t\tif (p->m_debug_mode >= 0x100) {\n+\t\t\tNT_LOG(DBG, NTHW,\n+\t\t\t       \"%s: fldid=%08d: [%08d:%08d] %08d/%08d: (%08d,%08d) (0x%08X,%08d,0x%08X)\\n\",\n+\t\t\t       __func__, p_init->id, p_init->low,\n+\t\t\t       (p_init->low + p_init->bw), p_init->bw,\n+\t\t\t       ((p_init->bw + 31) / 32), p->m_first_word,\n+\t\t\t       p->m_first_bit, p->m_front_mask, p->m_body_length,\n+\t\t\t       p->m_tail_mask);\n+\t\t}\n+\t}\n+}\n+\n+int field_get_debug_mode(const nt_module_t *p)\n+{\n+\treturn p->m_debug_mode;\n+}\n+\n+void field_set_debug_mode(nt_field_t *p, unsigned int n_debug_mode)\n+{\n+\tp->m_debug_mode = n_debug_mode;\n+}\n+\n+int field_get_bit_width(const nt_field_t *p)\n+{\n+\treturn p->mn_bit_width;\n+}\n+\n+int field_get_bit_pos_low(const nt_field_t *p)\n+{\n+\treturn p->mn_bit_pos_low;\n+}\n+\n+int field_get_bit_pos_high(const nt_field_t *p)\n+{\n+\treturn p->mn_bit_pos_low + p->mn_bit_width - 1;\n+}\n+\n+uint32_t field_get_mask(const nt_field_t *p)\n+{\n+\treturn p->m_front_mask;\n+}\n+\n+void field_reset(const nt_field_t *p)\n+{\n+\tfield_set_val32(p, (uint32_t)p->m_reset_val);\n+}\n+\n+uint32_t field_get_val_mask(const nt_field_t *p)\n+{\n+\treturn (p->m_front_mask >> p->mn_bit_pos_low);\n+}\n+\n+uint32_t field_get_reset_val(const nt_field_t *p)\n+{\n+\treturn (uint32_t)p->m_reset_val;\n+}\n+\n+void field_get_val(const nt_field_t *p, uint32_t *p_data, uint32_t len)\n+{\n+\tuint32_t i;\n+\tuint32_t data_index = 0;\n+\tuint32_t shadow_index = p->m_first_word;\n+\n+\tunion {\n+\t\tuint32_t w32[2];\n+\t\tuint64_t w64;\n+\t} buf;\n+\n+\t(void)len;\n+\tassert(len == p->mn_words);\n+\n+\t/* handle front */\n+\tbuf.w32[0] = p->mp_owner->mp_shadow[shadow_index++] & p->m_front_mask;\n+\n+\t/* handle body */\n+\tfor (i = 0; i < p->m_body_length; i++) {\n+\t\tbuf.w32[1] = p->mp_owner->mp_shadow[shadow_index++];\n+\t\tbuf.w64 = buf.w64 >> (p->m_first_bit);\n+\t\tassert(data_index < len);\n+\t\tp_data[data_index++] = buf.w32[0];\n+\t\tbuf.w64 = buf.w64 >> (32 - p->m_first_bit);\n+\t}\n+\n+\t/* handle tail */\n+\tif (p->m_tail_mask)\n+\t\tbuf.w32[1] = p->mp_owner->mp_shadow[shadow_index++] & p->m_tail_mask;\n+\n+\telse\n+\t\tbuf.w32[1] = 0;\n+\tbuf.w64 = buf.w64 >> (p->m_first_bit);\n+\tp_data[data_index++] = buf.w32[0];\n+\tif (data_index < p->mn_words)\n+\t\tp_data[data_index++] = buf.w32[1];\n+}\n+\n+void field_set_val(const nt_field_t *p, const uint32_t *p_data, uint32_t len)\n+{\n+\tuint32_t i;\n+\tuint32_t data_index = 0;\n+\tuint32_t shadow_index = p->m_first_word;\n+\n+\tunion {\n+\t\tuint32_t w32[2];\n+\t\tuint64_t w64;\n+\t} buf;\n+\n+\t(void)len;\n+\tassert(len == p->mn_words);\n+\n+\t/* handle front */\n+\tbuf.w32[0] = 0;\n+\tbuf.w32[1] = p_data[data_index++];\n+\tbuf.w64 = buf.w64 >> (32 - p->m_first_bit);\n+\tp->mp_owner->mp_shadow[shadow_index] =\n+\t\t(p->mp_owner->mp_shadow[shadow_index] & ~p->m_front_mask) |\n+\t\t(buf.w32[0] & p->m_front_mask);\n+\tshadow_index++;\n+\n+\t/* handle body */\n+\tfor (i = 0; i < p->m_body_length; i++) {\n+\t\tbuf.w64 = buf.w64 >> (p->m_first_bit);\n+\t\tassert(data_index < len);\n+\t\tbuf.w32[1] = p_data[data_index++];\n+\t\tbuf.w64 = buf.w64 >> (32 - p->m_first_bit);\n+\t\tp->mp_owner->mp_shadow[shadow_index++] = buf.w32[0];\n+\t}\n+\n+\t/* handle tail */\n+\tif (p->m_tail_mask) {\n+\t\tbuf.w64 = buf.w64 >> (p->m_first_bit);\n+\t\tif (data_index < len)\n+\t\t\tbuf.w32[1] = p_data[data_index];\n+\t\tbuf.w64 = buf.w64 >> (32 - p->m_first_bit);\n+\t\tp->mp_owner->mp_shadow[shadow_index] =\n+\t\t\t(p->mp_owner->mp_shadow[shadow_index] & ~p->m_tail_mask) |\n+\t\t\t(buf.w32[0] & p->m_tail_mask);\n+\t}\n+\n+\tregister_make_dirty(p->mp_owner);\n+}\n+\n+void field_set_val_flush(const nt_field_t *p, const uint32_t *p_data, uint32_t len)\n+{\n+\tfield_set_val(p, p_data, len);\n+\tfield_flush_register(p);\n+}\n+\n+uint32_t field_get_val32(const nt_field_t *p)\n+{\n+\tuint32_t val;\n+\n+\tfield_get_val(p, &val, 1);\n+\treturn val;\n+}\n+\n+uint32_t field_get_updated(const nt_field_t *p)\n+{\n+\tuint32_t val;\n+\n+\tregister_update(p->mp_owner);\n+\tfield_get_val(p, &val, 1);\n+\n+\treturn val;\n+}\n+\n+void field_read_trig_with_tsc(const nt_field_t *p, uint64_t *tsc1, uint64_t *tsc2)\n+{\n+\tregister_do_read_trig_ts(p->mp_owner, tsc1, tsc2);\n+}\n+\n+void field_update_register(const nt_field_t *p)\n+{\n+\tregister_update(p->mp_owner);\n+}\n+\n+void field_flush_register(const nt_field_t *p)\n+{\n+\tregister_flush(p->mp_owner, 1);\n+}\n+\n+void field_set_val32(const nt_field_t *p, uint32_t val)\n+{\n+\tfield_set_val(p, &val, 1);\n+}\n+\n+void field_set_val_flush32(const nt_field_t *p, uint32_t val)\n+{\n+\tfield_set_val(p, &val, 1);\n+\tregister_flush(p->mp_owner, 1);\n+}\n+\n+void field_clr_all(const nt_field_t *p)\n+{\n+\tassert(p->m_body_length == 0);\n+\tfield_set_val32(p, 0);\n+}\n+\n+void field_clr_flush(const nt_field_t *p)\n+{\n+\tfield_clr_all(p);\n+\tregister_flush(p->mp_owner, 1);\n+}\n+\n+void field_set_all(const nt_field_t *p)\n+{\n+\tassert(p->m_body_length == 0);\n+\tfield_set_val32(p, ~0);\n+}\n+\n+void field_set_flush(const nt_field_t *p)\n+{\n+\tfield_set_all(p);\n+\tregister_flush(p->mp_owner, 1);\n+}\n+\n+enum field_match {\n+\tFIELD_MATCH_CLR_ALL,\n+\tFIELD_MATCH_SET_ALL,\n+\tFIELD_MATCH_CLR_ANY,\n+\tFIELD_MATCH_SET_ANY,\n+};\n+\n+static int field_wait_cond32(const nt_field_t *p, enum field_match e_match,\n+\t\t\t    int n_poll_iterations, int n_poll_interval)\n+{\n+\tconst uint32_t n_mask = (1 << p->mn_bit_width) - 1;\n+\n+\tif (n_poll_iterations == -1)\n+\t\tn_poll_iterations = 10000;\n+\tif (n_poll_interval == -1)\n+\t\tn_poll_interval = 100; /* usec */\n+\n+\tif (p->m_debug_mode) {\n+\t\tconst char *const p_cond_name _unused =\n+\t\t\t((e_match == FIELD_MATCH_SET_ALL) ?\n+\t\t\t \"SetAll\" :\n+\t\t\t ((e_match == FIELD_MATCH_CLR_ALL) ?\n+\t\t\t  \"ClrAll\" :\n+\t\t\t  ((e_match == FIELD_MATCH_CLR_ANY) ?\n+\t\t\t   \"ClrAny\" :\n+\t\t\t   \"SetAny\")));\n+\t\tconst char *const p_dev_name _unused = \"NA\";\n+\t\tconst char *const p_bus_name _unused =\n+\t\t\tget_bus_name(module_get_bus(p->mp_owner->mp_owner));\n+\t\tuint32_t n_reg_addr _unused = register_get_address(p->mp_owner);\n+\n+\t\tuint32_t n_reg_mask _unused =\n+\t\t\t(((1 << p->mn_bit_width) - 1) << p->mn_bit_pos_low);\n+\n+\t\tNT_LOG(DBG, NTHW,\n+\t\t       \"Register::Field::wait%s32(Dev: %s, Bus: %s, Addr: 0x%08X, Mask: 0x%08X, Iterations: %d, Interval: %d)\\n\",\n+\t\t       p_cond_name, p_dev_name, p_bus_name, n_reg_addr, n_reg_mask,\n+\t\t       n_poll_iterations, n_poll_interval);\n+\t}\n+\n+\twhile (true) {\n+\t\tuint32_t val = field_get_updated(p);\n+\n+\t\tif (e_match == FIELD_MATCH_SET_ANY && val != 0) {\n+\t\t\treturn 0;\n+\t\t} else if (e_match == FIELD_MATCH_SET_ALL && val == n_mask) {\n+\t\t\treturn 0;\n+\t\t} else if (e_match == FIELD_MATCH_CLR_ALL && val == 0) {\n+\t\t\treturn 0;\n+\t\t} else if (e_match == FIELD_MATCH_CLR_ANY) {\n+\t\t\tuint32_t mask = field_get_mask(p);\n+\n+\t\t\tif (val != mask)\n+\t\t\t\treturn 0;\n+\t\t}\n+\n+\t\tn_poll_iterations--;\n+\t\tif (n_poll_iterations <= 0)\n+\t\t\treturn -1;\n+\t\tNT_OS_WAIT_USEC(n_poll_interval);\n+\t}\n+\treturn 0;\n+}\n+\n+int field_wait_set_all32(const nt_field_t *p, int n_poll_iterations,\n+\t\t       int n_poll_interval)\n+{\n+\treturn field_wait_cond32(p, FIELD_MATCH_SET_ALL, n_poll_iterations,\n+\t\t\t\tn_poll_interval);\n+}\n+\n+int field_wait_clr_all32(const nt_field_t *p, int n_poll_iterations,\n+\t\t       int n_poll_interval)\n+{\n+\treturn field_wait_cond32(p, FIELD_MATCH_CLR_ALL, n_poll_iterations,\n+\t\t\t\tn_poll_interval);\n+}\n+\n+int field_wait_set_any32(const nt_field_t *p, int n_poll_iterations,\n+\t\t       int n_poll_interval)\n+{\n+\treturn field_wait_cond32(p, FIELD_MATCH_SET_ANY, n_poll_iterations,\n+\t\t\t\tn_poll_interval);\n+}\n+\n+int field_wait_clr_any32(const nt_field_t *p, int n_poll_iterations,\n+\t\t       int n_poll_interval)\n+{\n+\treturn field_wait_cond32(p, FIELD_MATCH_CLR_ANY, n_poll_iterations,\n+\t\t\t\tn_poll_interval);\n+}\n+\n+int field_wait_val_mask32(const nt_field_t *p, uint32_t n_wait_cond_value,\n+\t\t\tuint32_t n_wait_cond_mask, int n_poll_iterations,\n+\t\t\tint n_poll_interval)\n+{\n+\tif (n_poll_iterations == -1)\n+\t\tn_poll_iterations = 10000;\n+\tif (n_poll_interval == -1)\n+\t\tn_poll_interval = 100;\n+\n+\twhile (true) {\n+\t\tuint32_t val = field_get_updated(p);\n+\n+\t\tif (val == (n_wait_cond_value & n_wait_cond_mask))\n+\t\t\tbreak;\n+\t\tn_poll_iterations--;\n+\t\tif (n_poll_iterations <= 0)\n+\t\t\treturn -1;\n+\t\tNT_OS_WAIT_USEC(n_poll_interval);\n+\t}\n+\treturn 0;\n+}\n+\n+void field_dump(const nt_field_t *p _unused)\n+{\n+\tNT_LOG(DBG, NTHW, \"%s: %02d: %02d %02d %02d: %02d: %X\\n\", __func__,\n+\t       p->m_id, p->mn_bit_pos_low, (p->mn_bit_pos_low + p->mn_bit_width),\n+\t       p->mn_bit_width, p->mn_words, p->m_reset_val);\n+}\n+\n+void field_dump_val(const nt_field_t *p)\n+{\n+\tint i;\n+\tuint32_t buf[32];\n+\n+\tfield_get_val(p, buf, p->mn_words);\n+\tNT_LOG(DBG, NTHW, \" @%d:\", p->m_first_bit + p->m_first_word * 32);\n+\tNT_LOG(DBG, NTHW, \"%X\", buf[p->mn_words - 1]);\n+\tfor (i = p->mn_words - 1; i > 0; i--)\n+\t\tNT_LOG(DBG, NTHW, \"%08X\", buf[i - 1]);\n+\tNT_LOG(DBG, NTHW, \"\\n\");\n+}\n+\n+void field_dump_init(const nt_fpga_field_init_t *p _unused)\n+{\n+\tNT_LOG(DBG, NTHW, \"%s: %02d: %02d %02d %02d: 0x%\" PRIX64 \"\\n\", __func__,\n+\t       p->id, p->low, p->low + p->bw, p->bw, p->reset_val);\n+}\n+\n+/*\n+ * nthw fpga model helpers\n+ */\n+\n+nt_fpga_t *nthw_get_fpga(struct fpga_info_s *p_fpga_info, uint64_t n_fpga_ident)\n+{\n+\tnt_fpga_mgr_t *p_fpga_mgr = NULL;\n+\tnt_fpga_t *p_fpga = NULL;\n+\tint n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id, n_fpga_rev_id;\n+\tchar s_fpga_prod_ver_rev_str[32];\n+\n+\tp_fpga_mgr = fpga_mgr_new();\n+\tfpga_mgr_init(p_fpga_mgr);\n+\tp_fpga = fpga_mgr_query_fpga(p_fpga_mgr, n_fpga_ident, p_fpga_info);\n+\n+\tn_fpga_type_id = FPGAID_TO_PRODUCTTYPE(n_fpga_ident);\n+\tn_fpga_prod_id = FPGAID_TO_PRODUCTCODE(n_fpga_ident);\n+\tn_fpga_ver_id = FPGAID_TO_VERSIONCODE(n_fpga_ident);\n+\tn_fpga_rev_id = FPGAID_TO_REVISIONCODE(n_fpga_ident);\n+\n+\tsnprintf(s_fpga_prod_ver_rev_str, sizeof(s_fpga_prod_ver_rev_str),\n+\t\t \"%04d-%04d-%02d-%02d\", n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id,\n+\t\t n_fpga_rev_id);\n+\n+\tif (p_fpga == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: no match for FPGA: %s\\n\", __func__,\n+\t\t       s_fpga_prod_ver_rev_str);\n+\t\t/* do not return here... */\n+\t}\n+\n+\tif (p_fpga_mgr) {\n+\t\tfpga_mgr_delete(p_fpga_mgr);\n+\t\tp_fpga_mgr = NULL;\n+\t}\n+\n+\treturn p_fpga;\n+}\n+\n+nt_module_t *nthw_get_module(nt_fpga_t *p_fpga, int n_mod, int n_instance)\n+{\n+\tnt_module_t *p_mod = fpga_query_module(p_fpga, n_mod, n_instance);\n+\treturn p_mod;\n+}\n+\n+nt_register_t *nthw_get_register(nt_module_t *p_mod, int n_reg)\n+{\n+\tnt_register_t *p_reg = module_get_register(p_mod, n_reg);\n+\treturn p_reg;\n+}\n+\n+nt_field_t *nthw_get_field(nt_register_t *p_reg, int n_fld)\n+{\n+\tnt_field_t *p_fld = register_get_field(p_reg, n_fld);\n+\treturn p_fld;\n+}\ndiff --git a/drivers/net/ntnic/nthw/nthw_fpga_model.h b/drivers/net/ntnic/nthw/nthw_fpga_model.h\nnew file mode 100644\nindex 0000000000..b00b7b6cfa\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_fpga_model.h\n@@ -0,0 +1,308 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_FPGA_MODEL_H__\n+#define __NTHW_FPGA_MODEL_H__\n+\n+#include <stdbool.h>\n+#include <stdio.h>\n+#include \"fpga_model.h\"\n+\n+#ifndef FPGAID_TO_PRODUCTCODE\n+#define FPGAID_TO_PRODUCTTYPE(fpga_id) ((uint16_t)((fpga_id) >> 32) & 0xFF)\n+#define FPGAID_TO_PRODUCTCODE(fpga_id) ((uint16_t)((fpga_id) >> 16) & 0xFFFF)\n+#define FPGAID_TO_VERSIONCODE(fpga_id) ((uint16_t)((fpga_id) >> 8 & 0xFF))\n+#define FPGAID_TO_REVISIONCODE(fpga_id) ((uint16_t)((fpga_id) >> 0 & 0xFF))\n+#endif\n+\n+#define VERSION_PACKED64(_major_, _minor_) \\\n+\t((((uint64_t)(_major_) & 0xFFFFFFFF) << 32) | ((_minor_) & 0xFFFFFFFF))\n+\n+enum debug_mode { NO_DEBUG, ON_READ, ON_WRITE };\n+\n+enum nthw_bus_type {\n+\tNTHW_BUS_UNKNOWN,\n+\tNTHW_BUS_BAR,\n+\tNTHW_BUS_PCI,\n+\tNTHW_BUS_NMB,\n+\tNTHW_BUS_NDM,\n+\tNTHW_BUS_RAB0,\n+\tNTHW_BUS_RAB1,\n+\tNTHW_BUS_RAB2\n+};\n+\n+struct nt_fpga_s;\n+\n+struct nt_param_s;\n+\n+struct nt_module_s;\n+\n+struct nt_register_s;\n+\n+struct nt_field_s;\n+\n+struct nt_fpga_mgr_s {\n+\tint mn_fpgas;\n+\tstruct nt_fpga_prod_init **mpa_fpga_prod_init;\n+};\n+\n+typedef struct nt_fpga_mgr_s nt_fpga_mgr_t;\n+\n+struct nt_fpga_s {\n+\tstruct fpga_info_s *p_fpga_info;\n+\n+\tint m_item_id;\n+\tint m_product_id;\n+\tint m_fpga_version;\n+\tint m_fpga_revision;\n+\tint m_fpga_patch_no;\n+\tint m_fpga_build_no;\n+\tuint32_t m_fpga_build_time;\n+\n+\tint mn_params;\n+\tstruct nt_param_s **mpa_params;\n+\n+\tint mn_modules;\n+\tstruct nt_module_s **mpa_modules;\n+\n+\tnt_fpga_prod_init_t *mp_init;\n+\n+\tint m_debug_mode;\n+};\n+\n+typedef struct nt_fpga_s nt_fpga_t;\n+\n+struct nt_param_s {\n+\tnt_fpga_t *mp_owner;\n+\n+\tint param_id;\n+\tint param_value;\n+\n+\tnt_fpga_prod_param_t *mp_init;\n+};\n+\n+typedef struct nt_param_s nt_param_t;\n+\n+struct nt_module_s {\n+\tnt_fpga_t *mp_owner;\n+\n+\tint m_mod_id;\n+\n+\tint m_instance;\n+\n+\tint m_mod_def_id;\n+\tint m_major_version;\n+\tint m_minor_version;\n+\n+\tint m_bus;\n+\tuint32_t m_addr_base;\n+\n+\tint m_debug_mode;\n+\n+\tint mn_registers;\n+\tstruct nt_register_s **mpa_registers;\n+\n+\tnt_fpga_module_init_t *mp_init;\n+};\n+\n+typedef struct nt_module_s nt_module_t;\n+\n+struct nt_register_s {\n+\tnt_module_t *mp_owner;\n+\n+\tuint32_t m_id;\n+\n+\tuint32_t mn_bit_width;\n+\tuint32_t mn_addr_rel;\n+\tuint32_t m_addr;\n+\tuint32_t m_type;\n+\tuint32_t m_len;\n+\n+\tint m_debug_mode;\n+\n+\tint mn_fields;\n+\tstruct nt_field_s **mpa_fields;\n+\n+\tuint32_t *mp_shadow;\n+\tbool *mp_dirty;\n+\n+\tnt_fpga_register_init_t *mp_init;\n+};\n+\n+typedef struct nt_register_s nt_register_t;\n+\n+struct nt_field_s {\n+\tnt_register_t *mp_owner;\n+\n+\tuint32_t m_id;\n+\n+\tuint32_t mn_bit_width;\n+\tuint32_t mn_bit_pos_low;\n+\tuint32_t m_reset_val;\n+\tuint32_t m_first_word;\n+\tuint32_t m_first_bit;\n+\tuint32_t m_front_mask;\n+\tuint32_t m_body_length;\n+\tuint32_t mn_words;\n+\tuint32_t m_tail_mask;\n+\n+\tint m_debug_mode;\n+\n+\tnt_fpga_field_init_t *mp_init;\n+};\n+\n+typedef struct nt_field_s nt_field_t;\n+\n+nt_fpga_mgr_t *fpga_mgr_new(void);\n+void fpga_mgr_init(nt_fpga_mgr_t *p);\n+void fpga_mgr_delete(nt_fpga_mgr_t *p);\n+nt_fpga_t *fpga_mgr_query_fpga(nt_fpga_mgr_t *p, uint64_t n_fpga_id,\n+\t\t\t     struct fpga_info_s *p_fpga_info);\n+\n+void fpga_mgr_log_dump(nt_fpga_mgr_t *p);\n+void fpga_mgr_show(nt_fpga_mgr_t *p, FILE *out, int detail_level);\n+\n+nt_fpga_t *fpga_new(void);\n+void fpga_delete(nt_fpga_t *p);\n+void fpga_delete_all(nt_fpga_t *p);\n+void fpga_init(nt_fpga_t *p, nt_fpga_prod_init_t *fpga_prod_init,\n+\t       struct fpga_info_s *p_fpga_info);\n+\n+int fpga_get_product_param(const nt_fpga_t *p, const int n_param_id,\n+\t\t\t const int default_value);\n+int fpga_get_product_id(const nt_fpga_t *p);\n+int fpga_get_fpga_version(const nt_fpga_t *p);\n+int fpga_get_fpga_revision(const nt_fpga_t *p);\n+nt_module_t *fpga_query_module(const nt_fpga_t *p, int id, int instance);\n+nt_fpga_module_init_t *fpga_lookup_init(nt_fpga_t *p, int id, int instance);\n+bool fpga_query(nt_fpga_t *p, int id, int instance);\n+void fpga_set_debug_mode(nt_fpga_t *p, int n_debug_mode);\n+\n+void fpga_log_info(const nt_fpga_t *p);\n+void fpga_dump(const nt_fpga_t *p);\n+void fpga_dump_params(const nt_fpga_t *p);\n+void fpga_dump_modules(const nt_fpga_t *p);\n+\n+nt_param_t *param_new(void);\n+void param_delete(nt_param_t *p);\n+void param_init(nt_param_t *p, nt_fpga_t *p_fpga, nt_fpga_prod_param_t *p_init);\n+\n+void param_dump(const nt_param_t *p);\n+\n+nt_module_t *module_new(void);\n+void module_delete(nt_module_t *p);\n+void module_init(nt_module_t *p, nt_fpga_t *p_fpga,\n+\t\t nt_fpga_module_init_t *p_init);\n+void module_init2(nt_module_t *p, nt_fpga_t *p_fpga, int mod_id, int instance,\n+\t\t  int debug_mode);\n+\n+int module_get_major_version(const nt_module_t *p);\n+int module_get_minor_version(const nt_module_t *p);\n+uint64_t module_get_version_packed64(const nt_module_t *p);\n+bool module_is_version_newer(const nt_module_t *p, int major_version,\n+\t\t\t   int minor_version);\n+\n+int module_get_bus(const nt_module_t *p);\n+nt_register_t *module_get_register(nt_module_t *p, uint32_t id);\n+nt_register_t *module_query_register(nt_module_t *p, uint32_t id);\n+int module_get_debug_mode(const nt_module_t *p);\n+void module_set_debug_mode(nt_module_t *p, unsigned int debug_mode);\n+uint32_t module_get_addr_base(const nt_module_t *p);\n+void module_unsuppported(const nt_module_t *p);\n+\n+void module_dump(const nt_module_t *p);\n+void module_dump_registers(const nt_module_t *p);\n+\n+nt_register_t *register_new(void);\n+void register_delete(nt_register_t *p);\n+void register_init(nt_register_t *p, nt_module_t *p_module,\n+\t\t   nt_fpga_register_init_t *p_init);\n+\n+nt_field_t *register_get_field(const nt_register_t *p, uint32_t id);\n+nt_field_t *register_query_field(const nt_register_t *p, uint32_t id);\n+\n+uint32_t register_get_address(const nt_register_t *p);\n+uint32_t register_get_addr_rel(const nt_register_t *p);\n+int register_get_bit_width(const nt_register_t *p);\n+int register_get_debug_mode(const nt_module_t *p);\n+void register_set_debug_mode(nt_register_t *p, unsigned int debug_mode);\n+\n+void register_get_val(const nt_register_t *p, uint32_t *p_data, uint32_t len);\n+uint32_t register_get_val32(const nt_register_t *p);\n+uint32_t register_get_val_updated32(const nt_register_t *p);\n+\n+void register_set_val(nt_register_t *p, const uint32_t *p_data, uint32_t len);\n+void register_set_val_flush(nt_register_t *p, const uint32_t *p_data,\n+\t\t\t  uint32_t len);\n+\n+void register_make_dirty(nt_register_t *p);\n+void register_update(const nt_register_t *p);\n+void register_reset(const nt_register_t *p);\n+void register_flush(const nt_register_t *p, uint32_t cnt);\n+void register_clr(nt_register_t *p);\n+void register_set(nt_register_t *p);\n+\n+void register_do_read_trig_ts(const nt_register_t *p, uint64_t *tsc1,\n+\t\t\t   uint64_t *tsc2);\n+\n+void register_dump(const nt_register_t *p);\n+void register_dump_fields(const nt_register_t *p);\n+\n+nt_field_t *field_new(void);\n+void field_delete(nt_field_t *p);\n+void field_init(nt_field_t *p, nt_register_t *p_reg,\n+\t\tconst nt_fpga_field_init_t *p_init);\n+\n+int field_get_debug_mode(const nt_module_t *p);\n+void field_set_debug_mode(nt_field_t *p, unsigned int n_debug_mode);\n+int field_get_bit_width(const nt_field_t *p);\n+int field_get_bit_pos_low(const nt_field_t *p);\n+int field_get_bit_pos_high(const nt_field_t *p);\n+uint32_t field_get_mask(const nt_field_t *p);\n+void field_reset(const nt_field_t *p);\n+uint32_t field_get_reset_val(const nt_field_t *p);\n+void field_get_val(const nt_field_t *p, uint32_t *p_data, uint32_t len);\n+void field_set_val(const nt_field_t *p, const uint32_t *p_data, uint32_t len);\n+void field_set_val_flush(const nt_field_t *p, const uint32_t *p_data,\n+\t\t       uint32_t len);\n+uint32_t field_get_val_mask(const nt_field_t *p);\n+uint32_t field_get_val32(const nt_field_t *p);\n+uint32_t field_get_updated(const nt_field_t *p);\n+void field_read_trig_with_tsc(const nt_field_t *p, uint64_t *tsc1, uint64_t *tsc2);\n+void field_update_register(const nt_field_t *p);\n+void field_flush_register(const nt_field_t *p);\n+void field_set_val32(const nt_field_t *p, uint32_t val);\n+void field_set_val_flush32(const nt_field_t *p, uint32_t val);\n+void field_clr_all(const nt_field_t *p);\n+void field_clr_flush(const nt_field_t *p);\n+void field_set_all(const nt_field_t *p);\n+void field_set_flush(const nt_field_t *p);\n+\n+int field_wait_clr_all32(const nt_field_t *p, int n_poll_iterations,\n+\t\t       int n_poll_interval);\n+int field_wait_set_all32(const nt_field_t *p, int n_poll_iterations,\n+\t\t       int n_poll_interval);\n+\n+int field_wait_clr_any32(const nt_field_t *p, int n_poll_iterations,\n+\t\t       int n_poll_interval);\n+int field_wait_set_any32(const nt_field_t *p, int n_poll_iterations,\n+\t\t       int n_poll_interval);\n+\n+int field_wait_val_mask32(const nt_field_t *p, uint32_t n_wait_cond_value,\n+\t\t\tuint32_t n_wait_cond_mask, int n_poll_iterations,\n+\t\t\tint n_poll_interval);\n+\n+void field_dump(const nt_field_t *p);\n+void field_dump_val(const nt_field_t *p);\n+void field_dump_init(const nt_fpga_field_init_t *p);\n+\n+/*\n+ * nthw helpers\n+ */\n+nt_fpga_t *nthw_get_fpga(struct fpga_info_s *p_fpga_info, uint64_t n_fpga_ident);\n+nt_module_t *nthw_get_module(nt_fpga_t *p_fpga, int n_mod, int n_instance);\n+nt_register_t *nthw_get_register(nt_module_t *p_mod, int n_reg);\n+nt_field_t *nthw_get_field(nt_register_t *p_reg, int n_fld);\n+\n+#endif /* __NTHW_FPGA_MODEL_H__ */\ndiff --git a/drivers/net/ntnic/nthw/nthw_helper.h b/drivers/net/ntnic/nthw/nthw_helper.h\nnew file mode 100644\nindex 0000000000..22f6a0d471\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_helper.h\n@@ -0,0 +1,21 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_HELPER_H__\n+#define __NTHW_HELPER_H__\n+\n+#include <unistd.h>\n+#include <stdint.h>\n+#include <inttypes.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <stdbool.h>\n+#include <string.h>\n+#include <assert.h>\n+\n+#ifndef ARRAY_SIZE\n+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))\n+#endif\n+\n+#endif /* __NTHW_HELPER_H__ */\ndiff --git a/drivers/net/ntnic/nthw/nthw_platform.c b/drivers/net/ntnic/nthw/nthw_platform.c\nnew file mode 100644\nindex 0000000000..203947e03a\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_platform.c\n@@ -0,0 +1,35 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"nthw_platform_drv.h\"\n+\n+nthw_adapter_id_t nthw_platform_get_nthw_adapter_id(const uint16_t n_pci_device_id)\n+{\n+\tswitch (n_pci_device_id) {\n+\tcase NT_HW_PCI_DEVICE_ID_NT40E3:\n+\t\treturn NT_HW_ADAPTER_ID_NT40E3;\n+\tcase NT_HW_PCI_DEVICE_ID_NT100E3:\n+\t\treturn NT_HW_ADAPTER_ID_NT100E3;\n+\tcase NT_HW_PCI_DEVICE_ID_NT80E3:\n+\t\treturn NT_HW_ADAPTER_ID_NT80E3;\n+\tcase NT_HW_PCI_DEVICE_ID_NT40A00:\n+\t\treturn NT_HW_ADAPTER_ID_NT40E3;\n+\tcase NT_HW_PCI_DEVICE_ID_NT40A01:\n+\t\treturn NT_HW_ADAPTER_ID_NT40E3;\n+\tcase NT_HW_PCI_DEVICE_ID_NT200E3:\n+\t\treturn NT_HW_ADAPTER_ID_NT200E3;\n+\tcase NT_HW_PCI_DEVICE_ID_NT200A01:\n+\t\treturn NT_HW_ADAPTER_ID_NT200A01;\n+\tcase NT_HW_PCI_DEVICE_ID_NT200D01:\n+\t\treturn NT_HW_ADAPTER_ID_NT200D01;\n+\tcase NT_HW_PCI_DEVICE_ID_NT200A02:\n+\t\treturn NT_HW_ADAPTER_ID_NT200A02;\n+\tcase NT_HW_PCI_DEVICE_ID_NT50B01:\n+\t\treturn NT_HW_ADAPTER_ID_NT50B01;\n+\tcase NT_HW_PCI_DEVICE_ID_NT100A01:\n+\t\treturn NT_HW_ADAPTER_ID_NT100A01;\n+\tdefault:\n+\t\treturn NT_HW_ADAPTER_ID_UNKNOWN;\n+\t}\n+}\ndiff --git a/drivers/net/ntnic/nthw/nthw_platform_drv.h b/drivers/net/ntnic/nthw/nthw_platform_drv.h\nnew file mode 100644\nindex 0000000000..fee2dc4853\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_platform_drv.h\n@@ -0,0 +1,42 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_PLATFORM_DRV_H__\n+#define __NTHW_PLATFORM_DRV_H__\n+\n+#include \"nthw_helper.h\"\n+\n+#define NT_HW_PCI_VENDOR_ID (0x18f4)\n+\n+#define NT_HW_PCI_DEVICE_ID_NT40E3 (0x145)\n+#define NT_HW_PCI_DEVICE_ID_NT100E3 (0x155)\n+#define NT_HW_PCI_DEVICE_ID_NT80E3 (0x165)\n+#define NT_HW_PCI_DEVICE_ID_NT40A00 (0x175)\n+#define NT_HW_PCI_DEVICE_ID_NT40A01 (0x185)\n+#define NT_HW_PCI_DEVICE_ID_NT200E3 (0x195)\n+#define NT_HW_PCI_DEVICE_ID_NT200A01 (0x1A5)\n+#define NT_HW_PCI_DEVICE_ID_NT200D01 (0x1B5)\n+#define NT_HW_PCI_DEVICE_ID_NT200A02 (0x1C5)\n+#define NT_HW_PCI_DEVICE_ID_NT50B01 (0x1D5)\n+#define NT_HW_PCI_DEVICE_ID_NT100A01 (0x1E5)\n+\n+enum nthw_adapter_id_e {\n+\tNT_HW_ADAPTER_ID_UNKNOWN = 0,\n+\tNT_HW_ADAPTER_ID_NT40E3,\n+\tNT_HW_ADAPTER_ID_NT40A01 = NT_HW_ADAPTER_ID_NT40E3,\n+\tNT_HW_ADAPTER_ID_NT50B01,\n+\tNT_HW_ADAPTER_ID_NT80E3,\n+\tNT_HW_ADAPTER_ID_NT100E3,\n+\tNT_HW_ADAPTER_ID_NT100A01,\n+\tNT_HW_ADAPTER_ID_NT200E3,\n+\tNT_HW_ADAPTER_ID_NT200A01,\n+\tNT_HW_ADAPTER_ID_NT200D01,\n+\tNT_HW_ADAPTER_ID_NT200A02,\n+};\n+\n+typedef enum nthw_adapter_id_e nthw_adapter_id_t;\n+\n+nthw_adapter_id_t nthw_platform_get_nthw_adapter_id(const uint16_t n_pci_device_id);\n+\n+#endif /* __NTHW_PLATFORM_DRV_H__ */\ndiff --git a/drivers/net/ntnic/nthw/nthw_profile.h b/drivers/net/ntnic/nthw/nthw_profile.h\nnew file mode 100644\nindex 0000000000..2fcb7b4adf\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_profile.h\n@@ -0,0 +1,15 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_PROFILE_H__\n+#define __NTHW_PROFILE_H__\n+\n+enum fpga_info_profile {\n+\tFPGA_INFO_PROFILE_UNKNOWN = 0,\n+\tFPGA_INFO_PROFILE_VSWITCH = 1,\n+\tFPGA_INFO_PROFILE_INLINE = 2,\n+\tFPGA_INFO_PROFILE_CAPTURE = 3,\n+};\n+\n+#endif /* __NTHW_PROFILE_H__ */\ndiff --git a/drivers/net/ntnic/nthw/nthw_rac.c b/drivers/net/ntnic/nthw/nthw_rac.c\nnew file mode 100644\nindex 0000000000..f3f6bee223\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_rac.c\n@@ -0,0 +1,976 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"nt_util.h\"\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+#include \"nthw_rac.h\"\n+\n+#include <pthread.h>\n+\n+/*\n+ * Prevent that RAB echo debug trace ever gets into a release build\n+ */\n+#if defined(DEBUG)\n+#undef RAB_DEBUG_ECHO\n+#else\n+#undef RAB_DEBUG_ECHO\n+#endif /* DEBUG */\n+\n+#define RAB_DMA_WAIT (1000000)\n+#define RAB_DMA_BUF_CNT (0x4000)\n+\n+#define RAB_READ (0x01)\n+#define RAB_WRITE (0x02)\n+#define RAB_ECHO (0x08)\n+#define RAB_COMPLETION (0x0F)\n+\n+#define RAB_READ_ECHO (RAB_READ | RAB_ECHO)\n+#define RAB_WRITE_ECHO (RAB_WRITE | RAB_ECHO)\n+\n+#define RAB_OPR_LO (28)\n+#define RAB_OPR_HI (31)\n+#define RAB_OPR_BW (4)\n+\n+#define RAB_CNT_LO (20)\n+#define RAB_CNT_HI (27)\n+#define RAB_CNT_BW (8)\n+\n+#define RAB_BUSID_LO (16)\n+#define RAB_BUSID_HI (19)\n+#define RAB_BUSID_BW (4)\n+\n+#define RAB_ADDR_LO (0)\n+#define RAB_ADDR_HI (15)\n+#define RAB_ADDR_BW (16)\n+\n+nthw_rac_t *nthw_rac_new(void)\n+{\n+\tnthw_rac_t *p = malloc(sizeof(nthw_rac_t));\n+\n+\tmemset(p, 0, sizeof(nthw_rac_t));\n+\treturn p;\n+}\n+\n+void nthw_rac_delete(nthw_rac_t *p)\n+{\n+\tif (p) {\n+\t\tmemset(p, 0, sizeof(nthw_rac_t));\n+\t\tfree(p);\n+\t}\n+}\n+\n+int nthw_rac_init(nthw_rac_t *p, nt_fpga_t *p_fpga, struct fpga_info_s *p_fpga_info)\n+{\n+\tassert(p_fpga_info);\n+\n+\tconst char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_RAC, 0);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: RAC %d: no such instance\\n\",\n+\t\t       p_adapter_id_str, 0);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mp_mod_rac = mod;\n+\n+\t{\n+\t\t/*\n+\t\t * RAC is a primary communication channel\n+\t\t * turn off debug by default\n+\t\t * except for rac_rab_init\n+\t\t */\n+\t\tconst int n_debug_mode = module_get_debug_mode(p->mp_mod_rac);\n+\n+\t\tif (n_debug_mode && n_debug_mode <= 0xff) {\n+\t\t\tmodule_set_debug_mode(p->mp_mod_rac, 0);\n+\t\t\tregister_set_debug_mode(p->mp_reg_rab_init, n_debug_mode);\n+\t\t}\n+\t}\n+\n+\t/* Params */\n+\tp->mn_param_rac_rab_interfaces =\n+\t\tfpga_get_product_param(p->mp_fpga, NT_RAC_RAB_INTERFACES, 3);\n+\tNT_LOG(DBG, NTHW, \"%s: NT_RAC_RAB_INTERFACES=%d\\n\", p_adapter_id_str,\n+\t       p->mn_param_rac_rab_interfaces);\n+\n+\tp->mn_param_rac_rab_ob_update =\n+\t\tfpga_get_product_param(p->mp_fpga, NT_RAC_RAB_OB_UPDATE, 0);\n+\tNT_LOG(DBG, NTHW, \"%s: NT_RAC_RAB_OB_UPDATE=%d\\n\", p_adapter_id_str,\n+\t       p->mn_param_rac_rab_ob_update);\n+\n+\t/* Optional dummy test registers */\n+\tp->mp_reg_dummy0 = module_query_register(p->mp_mod_rac, RAC_DUMMY0);\n+\tp->mp_reg_dummy1 = module_query_register(p->mp_mod_rac, RAC_DUMMY1);\n+\tp->mp_reg_dummy2 = module_query_register(p->mp_mod_rac, RAC_DUMMY2);\n+\n+\tp->mp_reg_rab_init = module_get_register(p->mp_mod_rac, RAC_RAB_INIT);\n+\tp->mp_fld_rab_init = register_get_field(p->mp_reg_rab_init, RAC_RAB_INIT_RAB);\n+\tp->mn_fld_rab_init_bw = field_get_bit_width(p->mp_fld_rab_init);\n+\tp->mn_fld_rab_init_mask = field_get_mask(p->mp_fld_rab_init);\n+\n+\t/* RAC_RAB_INIT_RAB reg/field sanity checks: */\n+\tassert(p->mn_fld_rab_init_mask == ((1UL << p->mn_fld_rab_init_bw) - 1));\n+\tassert(p->mn_fld_rab_init_bw == p->mn_param_rac_rab_interfaces);\n+\n+\tp->mp_reg_dbg_ctrl = module_query_register(p->mp_mod_rac, RAC_DBG_CTRL);\n+\tif (p->mp_reg_dbg_ctrl) {\n+\t\tp->mp_fld_dbg_ctrl =\n+\t\t\tregister_query_field(p->mp_reg_dbg_ctrl, RAC_DBG_CTRL_C);\n+\t} else {\n+\t\tp->mp_fld_dbg_ctrl = NULL;\n+\t}\n+\tp->mp_reg_dbg_data = module_query_register(p->mp_mod_rac, RAC_DBG_DATA);\n+\tif (p->mp_reg_dbg_data) {\n+\t\tp->mp_fld_dbg_data =\n+\t\t\tregister_query_field(p->mp_reg_dbg_data, RAC_DBG_DATA_D);\n+\t} else {\n+\t\tp->mp_reg_dbg_data = NULL;\n+\t}\n+\tp->mp_reg_rab_ib_data = module_get_register(p->mp_mod_rac, RAC_RAB_IB_DATA);\n+\tp->mp_fld_rab_ib_data =\n+\t\tregister_get_field(p->mp_reg_rab_ib_data, RAC_RAB_IB_DATA_D);\n+\n+\tp->mp_reg_rab_ob_data = module_get_register(p->mp_mod_rac, RAC_RAB_OB_DATA);\n+\tp->mp_fld_rab_ob_data =\n+\t\tregister_get_field(p->mp_reg_rab_ob_data, RAC_RAB_OB_DATA_D);\n+\n+\tp->mp_reg_rab_buf_free = module_get_register(p->mp_mod_rac, RAC_RAB_BUF_FREE);\n+\tp->mp_fld_rab_buf_free_ib_free =\n+\t\tregister_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_IB_FREE);\n+\tp->mp_fld_rab_buf_free_ib_ovf =\n+\t\tregister_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_IB_OVF);\n+\tp->mp_fld_rab_buf_free_ob_free =\n+\t\tregister_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_OB_FREE);\n+\tp->mp_fld_rab_buf_free_ob_ovf =\n+\t\tregister_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_OB_OVF);\n+\tp->mp_fld_rab_buf_free_timeout =\n+\t\tregister_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_TIMEOUT);\n+\n+\tp->mp_reg_rab_buf_used = module_get_register(p->mp_mod_rac, RAC_RAB_BUF_USED);\n+\tp->mp_fld_rab_buf_used_ib_used =\n+\t\tregister_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_IB_USED);\n+\tp->mp_fld_rab_buf_used_ob_used =\n+\t\tregister_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_OB_USED);\n+\tp->mp_fld_rab_buf_used_flush =\n+\t\tregister_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_FLUSH);\n+\n+\t/*\n+\t * RAC_RAB_DMA regs are optional - only found in real NT4GA - not found in 9231/9232 and\n+\t * earlier\n+\t */\n+\tp->mp_reg_rab_dma_ib_lo = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_LO);\n+\tp->mp_fld_rab_dma_ib_lo_phy_addr =\n+\t\tregister_get_field(p->mp_reg_rab_dma_ib_lo, RAC_RAB_DMA_IB_LO_PHYADDR);\n+\n+\tp->mp_reg_rab_dma_ib_hi = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_HI);\n+\tp->mp_fld_rab_dma_ib_hi_phy_addr =\n+\t\tregister_get_field(p->mp_reg_rab_dma_ib_hi, RAC_RAB_DMA_IB_HI_PHYADDR);\n+\n+\tp->mp_reg_rab_dma_ob_lo = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_LO);\n+\tp->mp_fld_rab_dma_ob_lo_phy_addr =\n+\t\tregister_get_field(p->mp_reg_rab_dma_ob_lo, RAC_RAB_DMA_OB_LO_PHYADDR);\n+\n+\tp->mp_reg_rab_dma_ob_hi = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_HI);\n+\tp->mp_fld_rab_dma_ob_hi_phy_addr =\n+\t\tregister_get_field(p->mp_reg_rab_dma_ob_hi, RAC_RAB_DMA_OB_HI_PHYADDR);\n+\n+\tp->mp_reg_rab_dma_ib_wr = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_WR);\n+\tp->mp_fld_rab_dma_ib_wr_ptr =\n+\t\tregister_get_field(p->mp_reg_rab_dma_ib_wr, RAC_RAB_DMA_IB_WR_PTR);\n+\n+\tp->mp_reg_rab_dma_ib_rd = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_RD);\n+\tp->mp_fld_rab_dma_ib_rd_ptr =\n+\t\tregister_get_field(p->mp_reg_rab_dma_ib_rd, RAC_RAB_DMA_IB_RD_PTR);\n+\n+\tp->mp_reg_rab_dma_ob_wr = module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_WR);\n+\tp->mp_fld_rab_dma_ob_wr_ptr =\n+\t\tregister_get_field(p->mp_reg_rab_dma_ob_wr, RAC_RAB_DMA_OB_WR_PTR);\n+\n+\tp->rac_rab_init_addr = register_get_address(p->mp_reg_rab_init);\n+\tp->rac_rab_ib_data_addr = register_get_address(p->mp_reg_rab_ib_data);\n+\tp->rac_rab_ob_data_addr = register_get_address(p->mp_reg_rab_ob_data);\n+\tp->rac_rab_buf_free_addr = register_get_address(p->mp_reg_rab_buf_free);\n+\tp->rac_rab_buf_used_addr = register_get_address(p->mp_reg_rab_buf_used);\n+\n+\t/*\n+\t * RAC_RAB_DMA regs are optional - only found in real NT4GA -\n+\t * not found in 9231/9232 and earlier\n+\t */\n+\n+\tp->rac_rab_dma_ib_lo_addr = register_get_address(p->mp_reg_rab_dma_ib_lo);\n+\tp->rac_rab_dma_ib_hi_addr = register_get_address(p->mp_reg_rab_dma_ib_hi);\n+\tp->rac_rab_dma_ob_lo_addr = register_get_address(p->mp_reg_rab_dma_ob_lo);\n+\tp->rac_rab_dma_ob_hi_addr = register_get_address(p->mp_reg_rab_dma_ob_hi);\n+\tp->rac_rab_dma_ib_rd_addr = register_get_address(p->mp_reg_rab_dma_ib_rd);\n+\tp->rac_rab_dma_ob_wr_addr = register_get_address(p->mp_reg_rab_dma_ob_wr);\n+\tp->rac_rab_dma_ib_wr_addr = register_get_address(p->mp_reg_rab_dma_ib_wr);\n+\n+\tp->rac_rab_buf_free_ib_free_mask =\n+\t\tfield_get_mask(p->mp_fld_rab_buf_free_ib_free);\n+\tp->rac_rab_buf_free_ob_free_mask =\n+\t\tfield_get_mask(p->mp_fld_rab_buf_free_ob_free);\n+\tp->rac_rab_buf_used_ib_used_mask =\n+\t\tfield_get_mask(p->mp_fld_rab_buf_used_ib_used);\n+\tp->rac_rab_buf_used_ob_used_mask =\n+\t\tfield_get_mask(p->mp_fld_rab_buf_used_ob_used);\n+\n+\tp->rac_rab_buf_used_flush_mask = field_get_mask(p->mp_fld_rab_buf_used_flush);\n+\n+\tp->rac_rab_buf_used_ob_used_low =\n+\t\tfield_get_bit_pos_low(p->mp_fld_rab_buf_used_ob_used);\n+\n+\tp->mp_reg_rab_nmb_rd = module_query_register(p->mp_mod_rac, RAC_NMB_RD_ADR);\n+\tif (p->mp_reg_rab_nmb_rd)\n+\t\tp->rac_nmb_rd_adr_addr = register_get_address(p->mp_reg_rab_nmb_rd);\n+\n+\tp->mp_reg_rab_nmb_data = module_query_register(p->mp_mod_rac, RAC_NMB_DATA);\n+\tif (p->mp_reg_rab_nmb_data)\n+\t\tp->rac_nmb_data_addr = register_get_address(p->mp_reg_rab_nmb_data);\n+\n+\tp->mp_reg_rab_nmb_wr = module_query_register(p->mp_mod_rac, RAC_NMB_WR_ADR);\n+\tif (p->mp_reg_rab_nmb_wr)\n+\t\tp->rac_nmb_wr_adr_addr = register_get_address(p->mp_reg_rab_nmb_wr);\n+\n+\tp->mp_reg_rab_nmb_status =\n+\t\tmodule_query_register(p->mp_mod_rac, RAC_NMB_STATUS);\n+\tif (p->mp_reg_rab_nmb_status) {\n+\t\tp->rac_nmb_status_addr =\n+\t\t\tregister_get_address(p->mp_reg_rab_nmb_status);\n+\t}\n+\n+\tp->m_dma = NULL;\n+\n+\tpthread_mutex_init(&p->m_mutex, NULL);\n+\n+\treturn 0;\n+}\n+\n+int nthw_rac_get_rab_interface_count(const nthw_rac_t *p)\n+{\n+\treturn p->mn_param_rac_rab_interfaces;\n+}\n+\n+static inline int nthw_rac_wait_for_rab_done(const nthw_rac_t *p, uint32_t address,\n+\t\tuint32_t word_cnt)\n+{\n+\tconst struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;\n+\tconst char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;\n+\tuint32_t used = 0;\n+\tuint32_t retry;\n+\n+\tfor (retry = 0; retry < 100000; retry++) {\n+\t\tnthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &used);\n+\t\tused = (used & p->rac_rab_buf_used_ob_used_mask) >>\n+\t\t       p->rac_rab_buf_used_ob_used_low;\n+\t\tif (used >= word_cnt)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (used < word_cnt) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: Fail rab bus r/w addr=0x%08X used=%x wordcount=%d\\n\",\n+\t\t       p_adapter_id_str, address, used, word_cnt);\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n+\n+/*\n+ * NT_PCI_REG_P9xyz_RAC_RAB_INIT\n+ *\n+ * Initializes (resets) the programmable registers on the Register Access Buses (RAB).\n+ * This initialization must be performed by software as part of the driver load procedure.\n+ *\n+ * Bit n of this field initializes the programmable registers on RAB interface n.\n+ * Software must write one to the bit and then clear the bit again.\n+ *\n+ * All RAB module registers will be reset to their defaults.\n+ * This includes the product specific RESET module (eg RST9xyz)\n+ * As a consequence of this behavior the official reset sequence\n+ * must be excersised - as all RAB modules will be held in reset.\n+ */\n+int nthw_rac_rab_init(nthw_rac_t *p, uint32_t n_rab_intf_mask)\n+{\n+\t/*\n+\t * Write rac_rab_init\n+\t * Perform operation twice - first to get trace of operation -\n+\t * second to get things done...\n+\t */\n+\tconst struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;\n+\n+\tfield_set_val_flush32(p->mp_fld_rab_init, n_rab_intf_mask);\n+\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_init_addr, n_rab_intf_mask);\n+\treturn 0;\n+}\n+\n+int nthw_rac_rab_reset(nthw_rac_t *p)\n+{\n+\tconst struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;\n+\n+\tconst char *const p_adapter_id_str _unused = p_fpga_info->mp_adapter_id_str;\n+\n+\t/* RAC RAB bus \"flip/flip\" reset */\n+\tconst int n_rac_rab_bus_count = nthw_rac_get_rab_interface_count(p);\n+\tconst int n_rac_rab_bus_mask = (1 << n_rac_rab_bus_count) - 1;\n+\n+\tNT_LOG(DBG, NTHW, \"%s: NT_RAC_RAB_INTERFACES=%d (0x%02X)\\n\",\n+\t       p_adapter_id_str, n_rac_rab_bus_count, n_rac_rab_bus_mask);\n+\tassert(n_rac_rab_bus_count);\n+\tassert(n_rac_rab_bus_mask);\n+\n+\t/* RAC RAB bus \"flip/flip\" reset first stage - new impl (ref RMT#37020) */\n+\tnthw_rac_rab_init(p, 0);\n+\tnthw_rac_rab_init(p, n_rac_rab_bus_mask);\n+\tnthw_rac_rab_init(p, n_rac_rab_bus_mask & ~0x01);\n+\n+\treturn 0;\n+}\n+\n+int nthw_rac_rab_setup(nthw_rac_t *p)\n+{\n+\tint rc = 0;\n+\n+\tconst struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;\n+\tuint32_t n_dma_buf_size = 2L * RAB_DMA_BUF_CNT * sizeof(uint32_t);\n+\tconst size_t align_size = ALIGN_SIZE(n_dma_buf_size);\n+\tint numa_node = p_fpga_info->numa_node;\n+\tuint64_t dma_addr;\n+\tuint32_t buf;\n+\n+\tif (!p->m_dma) {\n+\t\tstruct nt_dma_s *vfio_dma;\n+\t\t/* FPGA needs Page alignment (4K) */\n+\t\tvfio_dma = nt_dma_alloc(align_size, 0x1000, numa_node);\n+\n+\t\tif (vfio_dma == NULL) {\n+\t\t\tNT_LOG(ERR, ETHDEV, \"%s: nt_dma_alloc failed\\n\",\n+\t\t\t       __func__);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tp->m_dma_in_buf = (uint32_t *)vfio_dma->addr;\n+\t\tp->m_dma_out_buf = p->m_dma_in_buf + RAB_DMA_BUF_CNT;\n+\t\tp->m_dma = vfio_dma;\n+\t}\n+\n+\t/* Setup DMA on the adapter */\n+\tdma_addr = p->m_dma->iova;\n+\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ib_lo_addr,\n+\t\t\t   dma_addr & 0xffffffff);\n+\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ib_hi_addr,\n+\t\t\t   (uint32_t)(dma_addr >> 32) & 0xffffffff);\n+\tdma_addr += RAB_DMA_BUF_CNT * sizeof(uint32_t);\n+\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ob_lo_addr,\n+\t\t\t   dma_addr & 0xffffffff);\n+\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ob_hi_addr,\n+\t\t\t   (uint32_t)(dma_addr >> 32) & 0xffffffff);\n+\n+\t/* Set initial value of internal pointers */\n+\tnthw_rac_reg_read32(p_fpga_info, p->rac_rab_dma_ib_rd_addr, &buf);\n+\tp->m_dma_in_ptr_wr = (uint16_t)(buf / sizeof(uint32_t));\n+\tnthw_rac_reg_read32(p_fpga_info, p->rac_rab_dma_ob_wr_addr, &buf);\n+\tp->m_dma_out_ptr_rd = (uint16_t)(buf / sizeof(uint32_t));\n+\tp->m_in_free = RAB_DMA_BUF_CNT;\n+\n+\treturn rc;\n+}\n+\n+int nthw_rac_rab_dma_begin(nthw_rac_t *p)\n+{\n+\tconst struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;\n+\tconst char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;\n+\n+\tpthread_mutex_lock(&p->m_mutex);\n+\n+\tif (p->m_dma_active) {\n+\t\tpthread_mutex_unlock(&p->m_mutex);\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: DMA begin requested, but a DMA transaction is already active\\n\",\n+\t\t       p_adapter_id_str);\n+\t\treturn -1;\n+\t}\n+\n+\tp->m_dma_active = true;\n+\n+\treturn 0;\n+}\n+\n+static void nthw_rac_rab_dma_activate(nthw_rac_t *p)\n+{\n+\tconst struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;\n+\tconst uint32_t completion = RAB_COMPLETION << RAB_OPR_LO;\n+\n+\t/* Write completion word */\n+\tp->m_dma_in_buf[p->m_dma_in_ptr_wr] = completion;\n+\tp->m_dma_in_ptr_wr =\n+\t\t(uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1));\n+\n+\t/* Clear output completion word */\n+\tp->m_dma_out_buf[p->m_dma_out_ptr_rd] = 0;\n+\n+\t/* _update DMA pointer and start transfer */\n+\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_dma_ib_wr_addr,\n+\t\t\t   (uint32_t)(p->m_dma_in_ptr_wr * sizeof(uint32_t)));\n+}\n+\n+static int nthw_rac_rab_dma_wait(nthw_rac_t *p)\n+{\n+\tconst struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;\n+\tconst uint32_t completion = RAB_COMPLETION << RAB_OPR_LO;\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < RAB_DMA_WAIT; i++) {\n+\t\tNT_OS_WAIT_USEC_POLL(1);\n+\t\tif ((p->m_dma_out_buf[p->m_dma_out_ptr_rd] & completion) ==\n+\t\t\t\tcompletion)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (i == RAB_DMA_WAIT) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: RAB: Unexpected value of completion (0x%08X)\\n\",\n+\t\t       p_fpga_info->mp_adapter_id_str,\n+\t\t       p->m_dma_out_buf[p->m_dma_out_ptr_rd]);\n+\t\treturn -1;\n+\t}\n+\n+\tp->m_dma_out_ptr_rd =\n+\t\t(uint16_t)((p->m_dma_out_ptr_rd + 1) & (RAB_DMA_BUF_CNT - 1));\n+\tp->m_in_free = RAB_DMA_BUF_CNT;\n+\n+\treturn 0;\n+}\n+\n+int nthw_rac_rab_dma_commit(nthw_rac_t *p)\n+{\n+\tint ret;\n+\n+\tif (!p->m_dma_active) {\n+\t\t/* Expecting mutex not to be locked! */\n+\t\tassert(0); /* alert developer that something is wrong */\n+\t\treturn -1;\n+\t}\n+\n+\tnthw_rac_rab_dma_activate(p);\n+\tret = nthw_rac_rab_dma_wait(p);\n+\n+\tp->m_dma_active = false;\n+\n+\tpthread_mutex_unlock(&p->m_mutex);\n+\n+\treturn ret;\n+}\n+\n+void nthw_rac_reg_read32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,\n+\t\t       uint32_t *p_data)\n+{\n+\t*p_data = *(volatile uint32_t *)((uint8_t *)p_fpga_info->bar0_addr +\n+\t\t\t\t\treg_addr);\n+}\n+\n+void nthw_rac_reg_write32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,\n+\t\t\tuint32_t p_data)\n+{\n+\t*(volatile uint32_t *)((uint8_t *)p_fpga_info->bar0_addr + reg_addr) =\n+\t\tp_data;\n+}\n+\n+int nthw_rac_rab_write32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,\n+\t\t\t    uint32_t word_cnt, const uint32_t *p_data)\n+{\n+\tconst struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;\n+\n+\tif (word_cnt == 0 || word_cnt > 256) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: Failed rab dma write length check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X\\n\",\n+\t\t       p_fpga_info->mp_adapter_id_str, bus_id, address, word_cnt,\n+\t\t       p->m_in_free);\n+\t\tassert(0); /* alert developer that something is wrong */\n+\t\treturn -1;\n+\t}\n+\n+\tif (p->m_in_free < (word_cnt + 3)) {\n+\t\t/*\n+\t\t * No more memory available.\n+\t\t * nthw_rac_rab_dma_commit() needs to be called to start and finish pending\n+\t\t * transfers.\n+\t\t */\n+\t\treturn -1;\n+\t}\n+\n+\tp->m_in_free -= (word_cnt + 1);\n+\n+\t/* Write the command word */\n+#if defined(RAB_DEBUG_ECHO)\n+\tp->m_dma_in_buf[p->m_dma_in_ptr_wr] =\n+\t\t(RAB_WRITE_ECHO << RAB_OPR_LO) |\n+\t\t((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |\n+\t\t(bus_id << RAB_BUSID_LO) | address;\n+\tp->m_dma_out_ptr_rd = (uint16_t)((p->m_dma_out_ptr_rd + word_cnt + 1) &\n+\t\t\t\t     (RAB_DMA_BUF_CNT - 1));\n+#else\n+\tp->m_dma_in_buf[p->m_dma_in_ptr_wr] =\n+\t\t(RAB_WRITE << RAB_OPR_LO) |\n+\t\t((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |\n+\t\t(bus_id << RAB_BUSID_LO) | address;\n+#endif\n+\tp->m_dma_in_ptr_wr =\n+\t\t(uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1));\n+\n+\tfor (uint32_t i = 0; i < word_cnt; i++) {\n+\t\tp->m_dma_in_buf[p->m_dma_in_ptr_wr] = p_data[i];\n+\t\tp->m_dma_in_ptr_wr = (uint16_t)((p->m_dma_in_ptr_wr + 1) &\n+\t\t\t\t\t    (RAB_DMA_BUF_CNT - 1));\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int nthw_rac_rab_read32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,\n+\t\t\t   uint32_t word_cnt, struct dma_buf_ptr *buf_ptr)\n+{\n+\tconst struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;\n+\n+\tif (word_cnt == 0 || word_cnt > 256) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: Failed rab dma read length check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X\\n\",\n+\t\t       p_fpga_info->mp_adapter_id_str, bus_id, address, word_cnt,\n+\t\t       p->m_in_free);\n+\t\tassert(0); /* alert developer that something is wrong */\n+\t\treturn -1;\n+\t}\n+\n+\tif ((word_cnt + 3) > RAB_DMA_BUF_CNT) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: Failed rab dma read length check - bus: %d addr: 0x%08X wordcount: %d: 0x%08X\",\n+\t\t       p_fpga_info->mp_adapter_id_str, bus_id, address, word_cnt);\n+\t\treturn -1;\n+\t}\n+\n+\tif (p->m_in_free < 3) {\n+\t\t/*\n+\t\t * No more memory available.\n+\t\t * nthw_rac_rab_dma_commit() needs to be called to start and finish pending\n+\t\t * transfers.\n+\t\t */\n+\t\treturn -1;\n+\t}\n+\n+\tp->m_in_free -= 1;\n+\n+\t/* Write the command word */\n+#if defined(RAB_DEBUG_ECHO)\n+\tp->m_dma_in_buf[p->m_dma_in_ptr_wr] =\n+\t\t(RAB_READ_ECHO << RAB_OPR_LO) |\n+\t\t((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |\n+\t\t(bus_id << RAB_BUSID_LO) | address;\n+\tp->m_dma_out_ptr_rd =\n+\t\t(uint16_t)((p->m_dma_out_ptr_rd + 1) & (RAB_DMA_BUF_CNT - 1));\n+#else\n+\tp->m_dma_in_buf[p->m_dma_in_ptr_wr] =\n+\t\t(RAB_READ << RAB_OPR_LO) |\n+\t\t((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |\n+\t\t(bus_id << RAB_BUSID_LO) | address;\n+#endif\n+\tp->m_dma_in_ptr_wr =\n+\t\t(uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1));\n+\n+\tbuf_ptr->index = p->m_dma_out_ptr_rd;\n+\tbuf_ptr->size = RAB_DMA_BUF_CNT;\n+\tbuf_ptr->base = p->m_dma_out_buf;\n+\tp->m_dma_out_ptr_rd = (uint16_t)((p->m_dma_out_ptr_rd + word_cnt) &\n+\t\t\t\t     (RAB_DMA_BUF_CNT - 1U));\n+\n+\treturn 0;\n+}\n+\n+int nthw_rac_rab_write32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,\n+\t\t\tuint32_t word_cnt, const uint32_t *p_data)\n+{\n+\tconst struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;\n+\tconst char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;\n+\tint res = 0;\n+\tuint32_t rab_oper_wr;\n+\tuint32_t rab_oper_cmpl;\n+\tuint32_t rab_echo_oper_cmpl;\n+\tuint32_t word_cnt_expected;\n+\tuint32_t buf_used;\n+\tuint32_t buf_free;\n+\tuint32_t in_buf_free;\n+\tuint32_t out_buf_free;\n+\n+\tif (address > (1 << RAB_ADDR_BW)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: RAB: Illegal address: value too large %d - max %d\\n\",\n+\t\t       p_adapter_id_str, address, (1 << RAB_ADDR_BW));\n+\t\treturn -1;\n+\t}\n+\n+\tif (bus_id > (1 << RAB_BUSID_BW)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: RAB: Illegal bus id: value too large %d - max %d\\n\",\n+\t\t       p_adapter_id_str, bus_id, (1 << RAB_BUSID_BW));\n+\t\treturn -1;\n+\t}\n+\n+\tif (word_cnt == 0) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: RAB: Illegal word count: value is zero (%d)\\n\",\n+\t\t       p_adapter_id_str, word_cnt);\n+\t\treturn -1;\n+\t}\n+\n+\tif (word_cnt > (1 << RAB_CNT_BW)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: RAB: Illegal word count: value too large %d - max %d\\n\",\n+\t\t       p_adapter_id_str, word_cnt, (1 << RAB_CNT_BW));\n+\t\treturn -1;\n+\t}\n+\n+\tpthread_mutex_lock(&p->m_mutex);\n+\n+\tif (p->m_dma_active) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: RAB: Illegal operation: DMA enabled\\n\",\n+\t\t       p_adapter_id_str);\n+\t\tres = -1;\n+\t\tgoto exit_unlock_res;\n+\t}\n+\n+\t/* Read buffer free register */\n+\tnthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr, &buf_free);\n+\n+\tin_buf_free = buf_free & p->rac_rab_buf_free_ib_free_mask;\n+\tout_buf_free = (buf_free & p->rac_rab_buf_free_ob_free_mask) >> 16;\n+\n+\t/* Read buffer used register */\n+\tnthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &buf_used);\n+\n+\tbuf_used = buf_used & (p->rac_rab_buf_used_ib_used_mask |\n+\t\t\t     p->rac_rab_buf_used_ob_used_mask);\n+\n+\t/*\n+\t * Verify that output buffer can hold one completion word,\n+\t * input buffer can hold the number of words to be written +\n+\t * one write and one completion command\n+\t * and that the input and output \"used\" buffer is 0\n+\t */\n+\tif ((out_buf_free >= 1 && (in_buf_free >= word_cnt + 2)) && buf_used == 0) {\n+\t\tuint32_t i;\n+\n+\t\tword_cnt_expected = 0;\n+\n+\t\t/* Compose write command */\n+#if defined(RAB_DEBUG_ECHO)\n+\t\trab_oper_wr =\n+\t\t\t(RAB_WRITE_ECHO << RAB_OPR_LO) |\n+\t\t\t((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |\n+\t\t\t(bus_id << RAB_BUSID_LO) | address;\n+\t\tword_cnt_expected += word_cnt + 1;\n+#else\n+\t\trab_oper_wr =\n+\t\t\t(RAB_WRITE << RAB_OPR_LO) |\n+\t\t\t((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |\n+\t\t\t(bus_id << RAB_BUSID_LO) | address;\n+#endif /* RAB_DEBUG_ECHO */\n+\n+\t\t/* Write command */\n+\t\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr,\n+\t\t\t\t   rab_oper_wr);\n+\n+\t\t/* Write da to input buffer */\n+\t\tfor (i = 0; i < word_cnt; i++) {\n+\t\t\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr,\n+\t\t\t\t\t   *p_data);\n+\t\t\tp_data++;\n+\t\t}\n+\n+\t\t/* Compose completion command */\n+\t\trab_oper_cmpl = (RAB_COMPLETION << RAB_OPR_LO);\n+\t\tword_cnt_expected++;\n+\n+\t\t/* Write command */\n+\t\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr,\n+\t\t\t\t   rab_oper_cmpl);\n+\n+\t\t/* Wait until done */\n+\t\tif (nthw_rac_wait_for_rab_done(p, address, word_cnt_expected)) {\n+\t\t\tres = -1;\n+\t\t\tgoto exit_unlock_res;\n+\t\t}\n+\n+#if defined(RAB_DEBUG_ECHO)\n+\t\t{\n+\t\t\tuint32_t rab_echo_oper_wr;\n+\n+\t\t\tnthw_rac_reg_read32(p_fpga_info, p->rac_rab_ob_data_addr,\n+\t\t\t\t\t  &rab_echo_oper_wr);\n+\t\t\tif (p->mn_param_rac_rab_ob_update) {\n+\t\t\t\tnthw_rac_reg_write32(p_fpga_info,\n+\t\t\t\t\t\t   p->rac_rab_ob_data_addr, 0);\n+\t\t\t}\n+\t\t\tif (rab_oper_wr != rab_echo_oper_wr) {\n+\t\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t\t       \"%s: expected rab read echo oper (0x%08X) - read (0x%08X)\\n\",\n+\t\t\t\t       p_adapter_id_str, rab_oper_wr, rab_echo_oper_wr);\n+\t\t\t}\n+\t\t}\n+\n+\t\t{\n+\t\t\t/* Read data from output buffer */\n+\t\t\tuint32_t data;\n+\n+\t\t\tfor (i = 0; i < word_cnt; i++) {\n+\t\t\t\tnthw_rac_reg_read32(p_fpga_info,\n+\t\t\t\t\t\t  p->rac_rab_ob_data_addr,\n+\t\t\t\t\t\t  &data);\n+\t\t\t\tif (p->mn_param_rac_rab_ob_update) {\n+\t\t\t\t\tnthw_rac_reg_write32(p_fpga_info,\n+\t\t\t\t\t\t\t     p->rac_rab_ob_data_addr, 0);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+#endif /* RAB_DEBUG_ECHO */\n+\n+\t\t/* Read completion from out buffer */\n+\t\tnthw_rac_reg_read32(p_fpga_info, p->rac_rab_ob_data_addr,\n+\t\t\t\t  &rab_echo_oper_cmpl);\n+\t\tif (p->mn_param_rac_rab_ob_update) {\n+\t\t\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_ob_data_addr,\n+\t\t\t\t\t   0);\n+\t\t}\n+\t\tif (rab_echo_oper_cmpl != rab_oper_cmpl) {\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: RAB: Unexpected value of completion (0x%08X)- inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\\n\",\n+\t\t\t       p_adapter_id_str, rab_echo_oper_cmpl, in_buf_free,\n+\t\t\t       out_buf_free, buf_used);\n+\t\t\tres = -1;\n+\t\t\tgoto exit_unlock_res;\n+\t\t}\n+\n+\t\t/* Read buffer free register */\n+\t\tnthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr,\n+\t\t\t\t  &buf_free);\n+\t\tif (buf_free & 0x80000000) {\n+\t\t\t/* Clear Timeout and overflow bits */\n+\t\t\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_free_addr,\n+\t\t\t\t\t   0x0);\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: RAB: timeout - Access outside register - bus: %d addr: 0x%08X - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\\n\",\n+\t\t\t       p_adapter_id_str, bus_id, address, in_buf_free,\n+\t\t\t       out_buf_free, buf_used);\n+\t\t\tres = -1;\n+\t\t\tgoto exit_unlock_res;\n+\t\t}\n+\n+\t\tres = 0;\n+\t\tgoto exit_unlock_res;\n+\t} else {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: RAB: Fail rab bus buffer check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\\n\",\n+\t\t       p_adapter_id_str, bus_id, address, word_cnt, in_buf_free,\n+\t\t       out_buf_free, buf_used);\n+\t\tres = -1;\n+\t\tgoto exit_unlock_res;\n+\t}\n+\n+exit_unlock_res:\n+\tpthread_mutex_unlock(&p->m_mutex);\n+\treturn res;\n+}\n+\n+int nthw_rac_rab_read32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,\n+\t\t       uint32_t word_cnt, uint32_t *p_data)\n+{\n+\tconst struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;\n+\tconst char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;\n+\tint res = 0;\n+\tuint32_t rab_oper_rd;\n+\tuint32_t word_cnt_expected;\n+\tuint32_t buf_used;\n+\tuint32_t buf_free;\n+\tuint32_t in_buf_free;\n+\tuint32_t out_buf_free;\n+\n+\tpthread_mutex_lock(&p->m_mutex);\n+\n+\tif (address > (1 << RAB_ADDR_BW)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: RAB: Illegal address: value too large %d - max %d\\n\",\n+\t\t       p_adapter_id_str, address, (1 << RAB_ADDR_BW));\n+\t\tres = -1;\n+\t\tgoto exit_unlock_res;\n+\t}\n+\n+\tif (bus_id > (1 << RAB_BUSID_BW)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: RAB: Illegal bus id: value too large %d - max %d\\n\",\n+\t\t       p_adapter_id_str, bus_id, (1 << RAB_BUSID_BW));\n+\t\tres = -1;\n+\t\tgoto exit_unlock_res;\n+\t}\n+\n+\tif (word_cnt == 0) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: RAB: Illegal word count: value is zero (%d)\\n\",\n+\t\t       p_adapter_id_str, word_cnt);\n+\t\tres = -1;\n+\t\tgoto exit_unlock_res;\n+\t}\n+\n+\tif (word_cnt > (1 << RAB_CNT_BW)) {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: RAB: Illegal word count: value too large %d - max %d\\n\",\n+\t\t       p_adapter_id_str, word_cnt, (1 << RAB_CNT_BW));\n+\t\tres = -1;\n+\t\tgoto exit_unlock_res;\n+\t}\n+\n+\t/* Read buffer free register */\n+\tnthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr, &buf_free);\n+\n+\tin_buf_free = buf_free & p->rac_rab_buf_free_ib_free_mask;\n+\tout_buf_free = (buf_free & p->rac_rab_buf_free_ob_free_mask) >> 16;\n+\n+\t/* Read buffer used register */\n+\tnthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &buf_used);\n+\n+\tbuf_used = buf_used & (p->rac_rab_buf_used_ib_used_mask |\n+\t\t\t     p->rac_rab_buf_used_ob_used_mask);\n+\n+\t/*\n+\t * Verify that output buffer can hold the number of words to be read,\n+\t * input buffer can hold one read command\n+\t * and that the input and output \"used\" buffer is 0\n+\t */\n+\tif ((out_buf_free >= word_cnt && in_buf_free >= 1) && buf_used == 0) {\n+\t\tword_cnt_expected = word_cnt;\n+\n+#if defined(RAB_DEBUG_ECHO)\n+\t\trab_oper_rd =\n+\t\t\t(RAB_READ_ECHO << RAB_OPR_LO) |\n+\t\t\t((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |\n+\t\t\t(bus_id << RAB_BUSID_LO) | address;\n+\t\tword_cnt_expected++;\n+#else\n+\t\trab_oper_rd = (RAB_READ << RAB_OPR_LO) | (word_cnt << RAB_CNT_LO) |\n+\t\t\t    (bus_id << RAB_BUSID_LO) | address;\n+#endif /* RAB_DEBUG_ECHO */\n+\n+\t\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_ib_data_addr,\n+\t\t\t\t   rab_oper_rd);\n+\n+\t\t/* Wait until done */\n+\t\tif (nthw_rac_wait_for_rab_done(p, address, word_cnt_expected)) {\n+\t\t\tres = -1;\n+\t\t\tgoto exit_unlock_res;\n+\t\t}\n+\n+#if defined(RAB_DEBUG_ECHO)\n+\t\tuint32_t rab_echo_oper_rd;\n+\n+\t\tnthw_rac_reg_read32(p_fpga_info, p->rac_rab_ob_data_addr,\n+\t\t\t\t  &rab_echo_oper_rd);\n+\t\tif (p->mn_param_rac_rab_ob_update) {\n+\t\t\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_ob_data_addr,\n+\t\t\t\t\t   0);\n+\t\t}\n+\t\tif (rab_oper_rd != rab_echo_oper_rd) {\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: RAB: expected rab read echo oper (0x%08X) - read (0x%08X)\\n\",\n+\t\t\t       p_adapter_id_str, rab_oper_rd, rab_echo_oper_rd);\n+\t\t}\n+#endif /* RAB_DEBUG_ECHO */\n+\n+\t\t/* Read data from output buffer */\n+\t\t{\n+\t\t\tuint32_t i;\n+\n+\t\t\tfor (i = 0; i < word_cnt; i++) {\n+\t\t\t\tnthw_rac_reg_read32(p_fpga_info,\n+\t\t\t\t\t\t  p->rac_rab_ob_data_addr,\n+\t\t\t\t\t\t  p_data);\n+\t\t\t\tif (p->mn_param_rac_rab_ob_update) {\n+\t\t\t\t\tnthw_rac_reg_write32(p_fpga_info,\n+\t\t\t\t\t\t\t     p->rac_rab_ob_data_addr,\n+\t\t\t\t\t\t\t     0);\n+\t\t\t\t}\n+\t\t\t\tp_data++;\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* Read buffer free register */\n+\t\tnthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_free_addr,\n+\t\t\t\t  &buf_free);\n+\t\tif (buf_free & 0x80000000) {\n+\t\t\t/* Clear Timeout and overflow bits */\n+\t\t\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_free_addr,\n+\t\t\t\t\t   0x0);\n+\t\t\tNT_LOG(ERR, NTHW,\n+\t\t\t       \"%s: RAB: timeout - Access outside register - bus: %d addr: 0x%08X - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\\n\",\n+\t\t\t       p_adapter_id_str, bus_id, address, in_buf_free,\n+\t\t\t       out_buf_free, buf_used);\n+\t\t\tres = -1;\n+\t\t\tgoto exit_unlock_res;\n+\t\t}\n+\n+\t\tres = 0;\n+\t\tgoto exit_unlock_res;\n+\t} else {\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: RAB: Fail rab bus buffer check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X\\n\",\n+\t\t       p_adapter_id_str, bus_id, address, word_cnt, in_buf_free,\n+\t\t       out_buf_free, buf_used);\n+\t\tres = -1;\n+\t\tgoto exit_unlock_res;\n+\t}\n+\n+exit_unlock_res:\n+\tpthread_mutex_unlock(&p->m_mutex);\n+\treturn res;\n+}\n+\n+int nthw_rac_rab_flush(nthw_rac_t *p)\n+{\n+\tconst struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;\n+\tconst char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;\n+\tuint32_t data = 0;\n+\tuint32_t retry;\n+\tint res = 0;\n+\n+\tpthread_mutex_lock(&p->m_mutex);\n+\n+\t/* Set the flush bit */\n+\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_used_addr,\n+\t\t\t   p->rac_rab_buf_used_flush_mask);\n+\n+\t/* Reset BUF FREE register */\n+\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_free_addr, 0x0);\n+\n+\t/* Wait until OB_USED and IB_USED are 0 */\n+\tfor (retry = 0; retry < 100000; retry++) {\n+\t\tnthw_rac_reg_read32(p_fpga_info, p->rac_rab_buf_used_addr, &data);\n+\n+\t\tif ((data & 0xFFFFFFFF) == p->rac_rab_buf_used_flush_mask)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (data != p->rac_rab_buf_used_flush_mask) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: RAB: Rab bus flush error.\\n\",\n+\t\t       p_adapter_id_str);\n+\t\tres = -1;\n+\t}\n+\n+\t/* Clear flush bit when done */\n+\tnthw_rac_reg_write32(p_fpga_info, p->rac_rab_buf_used_addr, 0x0);\n+\n+\tpthread_mutex_unlock(&p->m_mutex);\n+\treturn res;\n+}\ndiff --git a/drivers/net/ntnic/nthw/nthw_rac.h b/drivers/net/ntnic/nthw/nthw_rac.h\nnew file mode 100644\nindex 0000000000..737598d95a\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_rac.h\n@@ -0,0 +1,161 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_RAC_H__\n+#define __NTHW_RAC_H__\n+\n+#include \"nt_util.h\"\n+#include \"nthw_bus.h\"\n+\n+#include <pthread.h>\n+\n+struct nthw_rac {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_rac;\n+\n+\tpthread_mutex_t m_mutex;\n+\n+\tint mn_param_rac_rab_interfaces;\n+\tint mn_param_rac_rab_ob_update;\n+\n+\tnt_register_t *mp_reg_dummy0;\n+\tnt_register_t *mp_reg_dummy1;\n+\tnt_register_t *mp_reg_dummy2;\n+\n+\tnt_register_t *mp_reg_rab_init;\n+\tnt_field_t *mp_fld_rab_init;\n+\n+\tint mn_fld_rab_init_bw;\n+\tuint32_t mn_fld_rab_init_mask;\n+\n+\tnt_register_t *mp_reg_dbg_ctrl;\n+\tnt_field_t *mp_fld_dbg_ctrl;\n+\n+\tnt_register_t *mp_reg_dbg_data;\n+\tnt_field_t *mp_fld_dbg_data;\n+\n+\tnt_register_t *mp_reg_rab_ib_data;\n+\tnt_field_t *mp_fld_rab_ib_data;\n+\n+\tnt_register_t *mp_reg_rab_ob_data;\n+\tnt_field_t *mp_fld_rab_ob_data;\n+\n+\tnt_register_t *mp_reg_rab_buf_free;\n+\tnt_field_t *mp_fld_rab_buf_free_ib_free;\n+\tnt_field_t *mp_fld_rab_buf_free_ib_ovf;\n+\tnt_field_t *mp_fld_rab_buf_free_ob_free;\n+\tnt_field_t *mp_fld_rab_buf_free_ob_ovf;\n+\tnt_field_t *mp_fld_rab_buf_free_timeout;\n+\n+\tnt_register_t *mp_reg_rab_buf_used;\n+\tnt_field_t *mp_fld_rab_buf_used_ib_used;\n+\tnt_field_t *mp_fld_rab_buf_used_ob_used;\n+\tnt_field_t *mp_fld_rab_buf_used_flush;\n+\n+\tnt_register_t *mp_reg_rab_dma_ib_lo;\n+\tnt_field_t *mp_fld_rab_dma_ib_lo_phy_addr;\n+\n+\tnt_register_t *mp_reg_rab_dma_ib_hi;\n+\tnt_field_t *mp_fld_rab_dma_ib_hi_phy_addr;\n+\n+\tnt_register_t *mp_reg_rab_dma_ob_hi;\n+\tnt_field_t *mp_fld_rab_dma_ob_hi_phy_addr;\n+\n+\tnt_register_t *mp_reg_rab_dma_ob_lo;\n+\tnt_field_t *mp_fld_rab_dma_ob_lo_phy_addr;\n+\n+\tnt_register_t *mp_reg_rab_dma_ib_wr;\n+\tnt_field_t *mp_fld_rab_dma_ib_wr_ptr;\n+\n+\tnt_register_t *mp_reg_rab_dma_ib_rd;\n+\tnt_field_t *mp_fld_rab_dma_ib_rd_ptr;\n+\n+\tnt_register_t *mp_reg_rab_dma_ob_wr;\n+\tnt_field_t *mp_fld_rab_dma_ob_wr_ptr;\n+\n+\tnt_register_t *mp_reg_rab_nmb_rd;\n+\tnt_register_t *mp_reg_rab_nmb_data;\n+\tnt_register_t *mp_reg_rab_nmb_wr;\n+\tnt_register_t *mp_reg_rab_nmb_status;\n+\n+\tuint32_t rac_rab_init_addr;\n+\tuint32_t rac_rab_ib_data_addr;\n+\tuint32_t rac_rab_ob_data_addr;\n+\tuint32_t rac_rab_buf_free_addr;\n+\tuint32_t rac_rab_buf_used_addr;\n+\n+\tuint32_t rac_rab_dma_ib_lo_addr;\n+\tuint32_t rac_rab_dma_ib_hi_addr;\n+\tuint32_t rac_rab_dma_ob_lo_addr;\n+\tuint32_t rac_rab_dma_ob_hi_addr;\n+\tuint32_t rac_rab_dma_ib_rd_addr;\n+\tuint32_t rac_rab_dma_ob_wr_addr;\n+\tuint32_t rac_rab_dma_ib_wr_addr;\n+\n+\tuint32_t rac_rab_buf_free_ib_free_mask;\n+\tuint32_t rac_rab_buf_free_ob_free_mask;\n+\tuint32_t rac_rab_buf_used_ib_used_mask;\n+\tuint32_t rac_rab_buf_used_ob_used_mask;\n+\tuint32_t rac_rab_buf_used_flush_mask;\n+\n+\tuint32_t rac_rab_buf_used_ob_used_low;\n+\n+\tuint32_t rac_nmb_rd_adr_addr;\n+\tuint32_t rac_nmb_data_addr;\n+\tuint32_t rac_nmb_wr_adr_addr;\n+\tuint32_t rac_nmb_status_addr;\n+\n+\tbool m_dma_active;\n+\n+\tstruct nt_dma_s *m_dma;\n+\n+\tvolatile uint32_t *m_dma_in_buf;\n+\tvolatile uint32_t *m_dma_out_buf;\n+\n+\tuint16_t m_dma_out_ptr_rd;\n+\tuint16_t m_dma_in_ptr_wr;\n+\tuint32_t m_in_free;\n+};\n+\n+typedef struct nthw_rac nthw_rac_t;\n+typedef struct nthw_rac nthw_rac;\n+\n+struct dma_buf_ptr {\n+\tuint32_t size;\n+\tuint32_t index;\n+\tvolatile uint32_t *base;\n+};\n+\n+nthw_rac_t *nthw_rac_new(void);\n+void nthw_rac_delete(nthw_rac_t *p);\n+int nthw_rac_init(nthw_rac_t *p, nt_fpga_t *p_fpga, struct fpga_info_s *p_fpga_info);\n+\n+int nthw_rac_get_rab_interface_count(const nthw_rac_t *p);\n+\n+int nthw_rac_rab_init(nthw_rac_t *p, uint32_t rab_intf_mask);\n+\n+int nthw_rac_rab_setup(nthw_rac_t *p);\n+\n+int nthw_rac_rab_reset(nthw_rac_t *p);\n+\n+int nthw_rac_rab_write32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,\n+\t\t\tuint32_t word_cnt, const uint32_t *p_data);\n+int nthw_rac_rab_write32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,\n+\t\t\t    uint32_t word_cnt, const uint32_t *p_data);\n+int nthw_rac_rab_read32(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,\n+\t\t       uint32_t word_cnt, uint32_t *p_data);\n+int nthw_rac_rab_read32_dma(nthw_rac_t *p, uint32_t address, rab_bus_id_t bus_id,\n+\t\t\t   uint32_t word_cnt, struct dma_buf_ptr *buf_ptr);\n+\n+int nthw_rac_rab_flush(nthw_rac_t *p);\n+\n+int nthw_rac_rab_dma_begin(nthw_rac_t *p);\n+int nthw_rac_rab_dma_commit(nthw_rac_t *p);\n+\n+void nthw_rac_reg_read32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,\n+\t\t       uint32_t *p_data);\n+void nthw_rac_reg_write32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,\n+\t\t\tuint32_t p_data);\n+\n+#endif /* __NTHW_RAC_H__ */\ndiff --git a/drivers/net/ntnic/nthw/nthw_register.h b/drivers/net/ntnic/nthw/nthw_register.h\nindex 5cdbd9fc5d..4fe3496b9f 100644\n--- a/drivers/net/ntnic/nthw/nthw_register.h\n+++ b/drivers/net/ntnic/nthw/nthw_register.h\n@@ -10,6 +10,8 @@\n #include <stdbool.h>\n #include <inttypes.h>\n \n+#include \"nthw_fpga_model.h\"\n+\n #include \"fpga_model.h\"\n \n #include \"nthw_fpga_modules_defs.h\"\ndiff --git a/drivers/net/ntnic/nthw/nthw_stat.c b/drivers/net/ntnic/nthw/nthw_stat.c\nnew file mode 100644\nindex 0000000000..fbecbc2dba\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_stat.c\n@@ -0,0 +1,266 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"nt_util.h\"\n+#include \"ntlog.h\"\n+\n+#include \"nthw_drv.h\"\n+#include \"nthw_register.h\"\n+\n+#include \"nthw_stat.h\"\n+\n+#include <malloc.h>\n+\n+nthw_stat_t *nthw_stat_new(void)\n+{\n+\tnthw_stat_t *p = malloc(sizeof(nthw_stat_t));\n+\n+\tif (p)\n+\t\tmemset(p, 0, sizeof(nthw_stat_t));\n+\treturn p;\n+}\n+\n+void nthw_stat_delete(nthw_stat_t *p)\n+{\n+\tif (p)\n+\t\tfree(p);\n+}\n+\n+int nthw_stat_init(nthw_stat_t *p, nt_fpga_t *p_fpga, int n_instance)\n+{\n+\tconst char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;\n+\tuint64_t n_module_version_packed64 = -1;\n+\tnt_module_t *mod = fpga_query_module(p_fpga, MOD_STA, n_instance);\n+\n+\tif (p == NULL)\n+\t\treturn mod == NULL ? -1 : 0;\n+\n+\tif (mod == NULL) {\n+\t\tNT_LOG(ERR, NTHW, \"%s: STAT %d: no such instance\\n\",\n+\t\t       p_adapter_id_str, n_instance);\n+\t\treturn -1;\n+\t}\n+\n+\tp->mp_fpga = p_fpga;\n+\tp->mn_instance = n_instance;\n+\tp->mp_mod_stat = mod;\n+\n+\tn_module_version_packed64 = module_get_version_packed64(p->mp_mod_stat);\n+\tNT_LOG(DBG, NTHW, \"%s: STAT %d: version=0x%08lX\\n\", p_adapter_id_str,\n+\t       p->mn_instance, n_module_version_packed64);\n+\n+\t{\n+\t\tnt_register_t *p_reg;\n+\t\t/* STA_CFG register */\n+\t\tp_reg = module_get_register(p->mp_mod_stat, STA_CFG);\n+\t\tp->mp_fld_dma_ena = register_get_field(p_reg, STA_CFG_DMA_ENA);\n+\t\tp->mp_fld_cnt_clear = register_get_field(p_reg, STA_CFG_CNT_CLEAR);\n+\n+\t\t/* CFG: fields NOT available from v. 3 */\n+\t\tp->mp_fld_tx_disable =\n+\t\t\tregister_query_field(p_reg, STA_CFG_TX_DISABLE);\n+\t\tp->mp_fld_cnt_freeze = register_query_field(p_reg, STA_CFG_CNT_FRZ);\n+\n+\t\t/* STA_STATUS register */\n+\t\tp_reg = module_get_register(p->mp_mod_stat, STA_STATUS);\n+\t\tp->mp_fld_stat_toggle_missed =\n+\t\t\tregister_get_field(p_reg, STA_STATUS_STAT_TOGGLE_MISSED);\n+\n+\t\t/* HOST_ADR registers */\n+\t\tp_reg = module_get_register(p->mp_mod_stat, STA_HOST_ADR_LSB);\n+\t\tp->mp_fld_dma_lsb = register_get_field(p_reg, STA_HOST_ADR_LSB_LSB);\n+\n+\t\tp_reg = module_get_register(p->mp_mod_stat, STA_HOST_ADR_MSB);\n+\t\tp->mp_fld_dma_msb = register_get_field(p_reg, STA_HOST_ADR_MSB_MSB);\n+\t}\n+\n+\t/* Params */\n+\tp->mb_is_vswitch = p_fpga->p_fpga_info->profile == FPGA_INFO_PROFILE_VSWITCH;\n+\n+\tp->m_nb_nim_ports = fpga_get_product_param(p_fpga, NT_NIMS, 0);\n+\tp->m_nb_phy_ports = fpga_get_product_param(p_fpga, NT_PHY_PORTS, 0);\n+\n+\tp->m_nb_rx_ports =\n+\t\tfpga_get_product_param(p_fpga, NT_STA_RX_PORTS, -1); /* VSWITCH */\n+\tif (p->m_nb_rx_ports == -1) {\n+\t\tp->m_nb_rx_ports = fpga_get_product_param(p_fpga, NT_RX_PORTS,\n+\t\t\t\t\t\t\t  -1); /* non-VSWITCH */\n+\t\tif (p->m_nb_rx_ports == -1) {\n+\t\t\tp->m_nb_rx_ports = fpga_get_product_param(p_fpga,\n+\t\t\t\t\t\t\t\t  NT_PORTS,\n+\t\t\t\t\t\t\t\t  0); /* non-VSWITCH */\n+\t\t}\n+\t}\n+\n+\tp->m_nb_tx_ports = fpga_get_product_param(p_fpga, NT_TX_PORTS, 0);\n+\tp->m_rx_port_replicate =\n+\t\tfpga_get_product_param(p_fpga, NT_RX_PORT_REPLICATE, 0);\n+\n+\tp->m_nb_color_counters = fpga_get_product_param(p_fpga, NT_STA_COLORS, 64) *\n+\t\t\t      2; /* VSWITCH */\n+\tif (p->m_nb_color_counters == 0) {\n+\t\tp->m_nb_color_counters =\n+\t\t\tfpga_get_product_param(p_fpga, NT_CAT_FUNCS, 0) *\n+\t\t\t2; /* non-VSWITCH */\n+\t}\n+\n+\tp->m_nb_rx_host_buffers = fpga_get_product_param(p_fpga, NT_QUEUES, 0);\n+\tp->m_nb_tx_host_buffers = p->m_nb_rx_host_buffers;\n+\n+\tp->m_dbs_present = fpga_get_product_param(p_fpga, NT_DBS_PRESENT, 0);\n+\n+\tp->m_nb_rx_hb_counters =\n+\t\t(p->m_nb_rx_host_buffers *\n+\t\t (6 + 2 * (n_module_version_packed64 >= VERSION_PACKED64(0, 6) ?\n+\t\t\t   p->m_dbs_present :\n+\t\t\t   0)));\n+\n+\tp->m_nb_tx_hb_counters = 0;\n+\n+\tp->m_nb_rx_port_counters =\n+\t\t42 + 2 * (n_module_version_packed64 >= VERSION_PACKED64(0, 6) ?\n+\t\t\t  p->m_dbs_present :\n+\t\t\t  0);\n+\tp->m_nb_tx_port_counters = 0;\n+\n+\tp->m_nb_counters =\n+\t\tp->m_nb_color_counters + p->m_nb_rx_hb_counters + p->m_nb_tx_hb_counters;\n+\n+\tp->mn_stat_layout_version = 0;\n+\tif (n_module_version_packed64 >= VERSION_PACKED64(0, 8)) {\n+\t\tp->mn_stat_layout_version = 6;\n+\t} else if (n_module_version_packed64 >= VERSION_PACKED64(0, 6)) {\n+\t\tp->mn_stat_layout_version = 5;\n+\t} else if (n_module_version_packed64 >= VERSION_PACKED64(0, 4)) {\n+\t\tp->mn_stat_layout_version = 4;\n+\t} else if (n_module_version_packed64 >= VERSION_PACKED64(0, 3)) {\n+\t\tp->mn_stat_layout_version = 3;\n+\t} else if (n_module_version_packed64 >= VERSION_PACKED64(0, 2)) {\n+\t\tp->mn_stat_layout_version = 2;\n+\t} else if (n_module_version_packed64 > VERSION_PACKED64(0, 0)) {\n+\t\tp->mn_stat_layout_version = 1;\n+\t} else {\n+\t\tp->mn_stat_layout_version = 0;\n+\t\tNT_LOG(ERR, NTHW,\n+\t\t       \"%s: unknown module_version 0x%08lX layout=%d\\n\",\n+\t\t       p_adapter_id_str, n_module_version_packed64,\n+\t\t       p->mn_stat_layout_version);\n+\t}\n+\tassert(p->mn_stat_layout_version);\n+\n+\t/* STA module 0.2+ adds IPF counters per port (Rx feature) */\n+\tif (n_module_version_packed64 >= VERSION_PACKED64(0, 2))\n+\t\tp->m_nb_rx_port_counters += 6;\n+\n+\t/* STA module 0.3+ adds TX stats */\n+\tif (n_module_version_packed64 >= VERSION_PACKED64(0, 3) ||\n+\t\t\tp->m_nb_tx_ports >= 1)\n+\t\tp->mb_has_tx_stats = true;\n+\n+\t/* STA module 0.3+ adds TX stat counters */\n+\tif (n_module_version_packed64 >= VERSION_PACKED64(0, 3))\n+\t\tp->m_nb_tx_port_counters += 22;\n+\n+\t/* STA module 0.4+ adds TX drop event counter */\n+\tif (n_module_version_packed64 >= VERSION_PACKED64(0, 4))\n+\t\tp->m_nb_tx_port_counters += 1; /* TX drop event counter */\n+\n+\t/*\n+\t * STA module 0.6+ adds pkt filter drop octets+pkts, retransmit and\n+\t * duplicate counters\n+\t */\n+\tif (n_module_version_packed64 >= VERSION_PACKED64(0, 6)) {\n+\t\tp->m_nb_rx_port_counters += 4;\n+\t\tp->m_nb_tx_port_counters += 1;\n+\t}\n+\n+\tif (p->mb_is_vswitch) {\n+\t\tp->m_nb_rx_port_counters = 5;\n+\t\tp->m_nb_tx_port_counters = 5;\n+\t}\n+\n+\tp->m_nb_counters += (p->m_nb_rx_ports * p->m_nb_rx_port_counters);\n+\n+\tif (p->mb_has_tx_stats)\n+\t\tp->m_nb_counters += (p->m_nb_tx_ports * p->m_nb_tx_port_counters);\n+\n+\t/* Output params (debug) */\n+\tNT_LOG(DBG, NTHW,\n+\t       \"%s: nims=%d rxports=%d txports=%d rxrepl=%d colors=%d queues=%d\\n\",\n+\t       p_adapter_id_str, p->m_nb_nim_ports, p->m_nb_rx_ports, p->m_nb_tx_ports,\n+\t       p->m_rx_port_replicate, p->m_nb_color_counters, p->m_nb_rx_host_buffers);\n+\tNT_LOG(DBG, NTHW,\n+\t       \"%s: hbs=%d hbcounters=%d rxcounters=%d txcounters=%d\\n\",\n+\t       p_adapter_id_str, p->m_nb_rx_host_buffers, p->m_nb_rx_hb_counters,\n+\t       p->m_nb_rx_port_counters, p->m_nb_tx_port_counters);\n+\tNT_LOG(DBG, NTHW, \"%s: layout=%d\\n\", p_adapter_id_str,\n+\t       p->mn_stat_layout_version);\n+\tNT_LOG(DBG, NTHW, \"%s: counters=%d (0x%X)\\n\", p_adapter_id_str,\n+\t       p->m_nb_counters, p->m_nb_counters);\n+\tNT_LOG(DBG, NTHW, \"%s: vswitch=%d\\n\", p_adapter_id_str, p->mb_is_vswitch);\n+\n+\t/* Init */\n+\tif (p->mp_fld_tx_disable)\n+\t\tfield_set_flush(p->mp_fld_tx_disable);\n+\n+\tfield_update_register(p->mp_fld_cnt_clear);\n+\tfield_set_flush(p->mp_fld_cnt_clear);\n+\tfield_clr_flush(p->mp_fld_cnt_clear);\n+\n+\tfield_update_register(p->mp_fld_stat_toggle_missed);\n+\tfield_set_flush(p->mp_fld_stat_toggle_missed);\n+\n+\tfield_update_register(p->mp_fld_dma_ena);\n+\tfield_clr_flush(p->mp_fld_dma_ena);\n+\tfield_update_register(p->mp_fld_dma_ena);\n+\n+\treturn 0;\n+}\n+\n+int nthw_stat_set_dma_address(nthw_stat_t *p, uint64_t stat_dma_physical,\n+\t\t\t   uint32_t *p_stat_dma_virtual)\n+{\n+\tassert(p_stat_dma_virtual);\n+\tp->mp_timestamp = NULL;\n+\n+\tp->m_stat_dma_physical = stat_dma_physical;\n+\tp->mp_stat_dma_virtual = p_stat_dma_virtual;\n+\n+\tmemset(p->mp_stat_dma_virtual, 0, (p->m_nb_counters * sizeof(uint32_t)));\n+\n+\tfield_set_val_flush32(p->mp_fld_dma_msb,\n+\t\t\t    (uint32_t)((p->m_stat_dma_physical >> 32) &\n+\t\t\t\t       0xffffffff));\n+\tfield_set_val_flush32(p->mp_fld_dma_lsb,\n+\t\t\t    (uint32_t)(p->m_stat_dma_physical & 0xffffffff));\n+\n+\tp->mp_timestamp = (uint64_t *)(p->mp_stat_dma_virtual + p->m_nb_counters);\n+\tNT_LOG(DBG, NTHW,\n+\t       \"%s: statDmaPhysical=%\" PRIX64 \" p_stat_dma_virtual=%\" PRIX64\n+\t       \" mp_timestamp=%\" PRIX64 \"\\n\",\n+\t       __func__, p->m_stat_dma_physical, p->mp_stat_dma_virtual,\n+\t       p->mp_timestamp);\n+\tif (p->mb_is_vswitch)\n+\t\t*p->mp_timestamp = NT_OS_GET_TIME_NS();\n+\n+\telse\n+\t\t*p->mp_timestamp = (uint64_t)(int64_t)-1;\n+\treturn 0;\n+}\n+\n+int nthw_stat_trigger(nthw_stat_t *p)\n+{\n+\tint n_toggle_miss = field_get_updated(p->mp_fld_stat_toggle_missed);\n+\n+\tif (n_toggle_miss)\n+\t\tfield_set_flush(p->mp_fld_stat_toggle_missed);\n+\n+\tif (p->mp_timestamp)\n+\t\t*p->mp_timestamp = -1; /* Clear old ts */\n+\n+\tfield_update_register(p->mp_fld_dma_ena);\n+\tfield_set_flush(p->mp_fld_dma_ena);\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ntnic/nthw/nthw_stat.h b/drivers/net/ntnic/nthw/nthw_stat.h\nnew file mode 100644\nindex 0000000000..7bce7ecd15\n--- /dev/null\n+++ b/drivers/net/ntnic/nthw/nthw_stat.h\n@@ -0,0 +1,72 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef __NTHW_STAT_H__\n+#define __NTHW_STAT_H__\n+\n+struct nthw_stat {\n+\tnt_fpga_t *mp_fpga;\n+\tnt_module_t *mp_mod_stat;\n+\tint mn_instance;\n+\n+\tint mn_stat_layout_version;\n+\n+\tbool mb_is_vswitch;\n+\tbool mb_has_tx_stats;\n+\n+\tint m_nb_phy_ports;\n+\tint m_nb_nim_ports;\n+\n+\tint m_nb_rx_ports;\n+\tint m_nb_tx_ports;\n+\n+\tint m_nb_rx_host_buffers;\n+\tint m_nb_tx_host_buffers;\n+\n+\tint m_dbs_present;\n+\n+\tint m_rx_port_replicate;\n+\n+\tint m_nb_color_counters;\n+\n+\tint m_nb_rx_hb_counters;\n+\tint m_nb_tx_hb_counters;\n+\n+\tint m_nb_rx_port_counters;\n+\tint m_nb_tx_port_counters;\n+\n+\tint m_nb_counters;\n+\n+\tnt_field_t *mp_fld_dma_ena;\n+\tnt_field_t *mp_fld_cnt_clear;\n+\n+\tnt_field_t *mp_fld_tx_disable;\n+\n+\tnt_field_t *mp_fld_cnt_freeze;\n+\n+\tnt_field_t *mp_fld_stat_toggle_missed;\n+\n+\tnt_field_t *mp_fld_dma_lsb;\n+\tnt_field_t *mp_fld_dma_msb;\n+\n+\tuint64_t m_stat_dma_physical;\n+\tuint32_t *mp_stat_dma_virtual;\n+\n+\tuint64_t last_ts;\n+\n+\tuint64_t *mp_timestamp;\n+};\n+\n+typedef struct nthw_stat nthw_stat_t;\n+typedef struct nthw_stat nthw_stat;\n+\n+nthw_stat_t *nthw_stat_new(void);\n+int nthw_stat_init(nthw_stat_t *p, nt_fpga_t *p_fpga, int n_instance);\n+void nthw_stat_delete(nthw_stat_t *p);\n+\n+int nthw_stat_set_dma_address(nthw_stat_t *p, uint64_t stat_dma_physical,\n+\t\t\t   uint32_t *p_stat_dma_virtual);\n+int nthw_stat_trigger(nthw_stat_t *p);\n+\n+#endif /* __NTHW_STAT_H__ */\ndiff --git a/drivers/net/ntnic/ntlog/include/ntlog.h b/drivers/net/ntnic/ntlog/include/ntlog.h\nnew file mode 100644\nindex 0000000000..81bc014d66\n--- /dev/null\n+++ b/drivers/net/ntnic/ntlog/include/ntlog.h\n@@ -0,0 +1,162 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef NTOSS_SYSTEM_NTLOG_H\n+#define NTOSS_SYSTEM_NTLOG_H\n+\n+#include <stdarg.h>\n+#include <stdint.h>\n+\n+#ifndef NT_LOG_MODULE_PREFIX\n+\n+/* DPDK modules */\n+#define NT_LOG_MODULE_EAL 0\n+#define NT_LOG_MODULE_MALLOC 1\n+#define NT_LOG_MODULE_RING 2\n+#define NT_LOG_MODULE_MEMPOOL 3\n+#define NT_LOG_MODULE_TIMER 4\n+#define NT_LOG_MODULE_PMD 5\n+#define NT_LOG_MODULE_HASH 6\n+#define NT_LOG_MODULE_LPM 7\n+#define NT_LOG_MODULE_KNI 8\n+#define NT_LOG_MODULE_ACL 9\n+#define NT_LOG_MODULE_POWER 10\n+#define NT_LOG_MODULE_METER 11\n+#define NT_LOG_MODULE_SCHED 12\n+#define NT_LOG_MODULE_PORT 13\n+#define NT_LOG_MODULE_TABLE 14\n+#define NT_LOG_MODULE_PIPELINE 15\n+#define NT_LOG_MODULE_MBUF 16\n+#define NT_LOG_MODULE_CRYPTODEV 17\n+#define NT_LOG_MODULE_EFD 18\n+#define NT_LOG_MODULE_EVENTDEV 19\n+#define NT_LOG_MODULE_GSO 20\n+#define NT_LOG_MODULE_USER1 24\n+#define NT_LOG_MODULE_USER2 25\n+#define NT_LOG_MODULE_USER3 26\n+#define NT_LOG_MODULE_USER4 27\n+#define NT_LOG_MODULE_USER5 28\n+#define NT_LOG_MODULE_USER6 29\n+#define NT_LOG_MODULE_USER7 30\n+#define NT_LOG_MODULE_USER8 31\n+\n+/* NT modules */\n+#define NT_LOG_MODULE_GENERAL 10000 /* Should always be a first (smallest) */\n+#define NT_LOG_MODULE_NTHW 10001\n+#define NT_LOG_MODULE_FILTER 10002\n+#define NT_LOG_MODULE_VDPA 10003\n+#define NT_LOG_MODULE_FPGA 10004\n+#define NT_LOG_MODULE_NTCONNECT 10005\n+#define NT_LOG_MODULE_ETHDEV 10006\n+#define NT_LOG_MODULE_END 10007 /* Mark for the range end of NT_LOG */\n+\n+#define NT_LOG_MODULE_COUNT (NT_LOG_MODULE_END - NT_LOG_MODULE_GENERAL)\n+#define NT_LOG_MODULE_INDEX(module) ((module) - NT_LOG_MODULE_GENERAL)\n+#define NT_LOG_MODULE_PREFIX(type) NT_LOG_MODULE_##type\n+\n+#endif\n+\n+#ifndef NT_LOG_ENABLE\n+#define NT_LOG_ENABLE 1\n+#endif\n+\n+#if defined NT_LOG_ENABLE && NT_LOG_ENABLE > 0\n+#ifndef NT_LOG_ENABLE_ERR\n+#define NT_LOG_ENABLE_ERR 1\n+#endif\n+#ifndef NT_LOG_ENABLE_WRN\n+#define NT_LOG_ENABLE_WRN 1\n+#endif\n+#ifndef NT_LOG_ENABLE_INF\n+#define NT_LOG_ENABLE_INF 1\n+#endif\n+#ifndef NT_LOG_ENABLE_DBG\n+#define NT_LOG_ENABLE_DBG 1\n+#endif\n+#ifndef NT_LOG_ENABLE_DB1\n+#define NT_LOG_ENABLE_DB1 0\n+#endif\n+#ifndef NT_LOG_ENABLE_DB2\n+#define NT_LOG_ENABLE_DB2 0\n+#endif\n+#endif\n+\n+#if defined NT_LOG_ENABLE_ERR && NT_LOG_ENABLE_ERR > 0\n+#define NT_LOG_NT_LOG_ERR(...) nt_log(__VA_ARGS__)\n+#else\n+#define NT_LOG_NT_LOG_ERR(...)\n+#endif\n+\n+#if defined NT_LOG_ENABLE_WRN && NT_LOG_ENABLE_WRN > 0\n+#define NT_LOG_NT_LOG_WRN(...) nt_log(__VA_ARGS__)\n+#else\n+#define NT_LOG_NT_LOG_WRN(...)\n+#endif\n+\n+#if defined NT_LOG_ENABLE_INF && NT_LOG_ENABLE_INF > 0\n+#define NT_LOG_NT_LOG_INF(...) nt_log(__VA_ARGS__)\n+#else\n+#define NT_LOG_NT_LOG_INF(...)\n+#endif\n+\n+#if defined NT_LOG_ENABLE_DBG && NT_LOG_ENABLE_DBG > 0\n+#define NT_LOG_NT_LOG_DBG(...) nt_log(__VA_ARGS__)\n+#else\n+#define NT_LOG_NT_LOG_DBG(...)\n+#endif\n+\n+#if defined NT_LOG_ENABLE_DB1 && NT_LOG_ENABLE_DB1 > 0\n+#define NT_LOG_NT_LOG_DB1(...) nt_log(__VA_ARGS__)\n+#else\n+#define NT_LOG_NT_LOG_DB1(...)\n+#endif\n+\n+#if defined NT_LOG_ENABLE_DB2 && NT_LOG_ENABLE_DB2 > 0\n+#define NT_LOG_NT_LOG_DB2(...) nt_log(__VA_ARGS__)\n+#else\n+#define NT_LOG_NT_LOG_DB2(...)\n+#endif\n+\n+#define NT_LOG(level, module, ...)                                          \\\n+\tNT_LOG_NT_LOG_##level(NT_LOG_##level, NT_LOG_MODULE_PREFIX(module), \\\n+\t\t\t      #module \": \" #level \": \" __VA_ARGS__)\n+\n+enum nt_log_level {\n+\tNT_LOG_ERR = 0x001,\n+\tNT_LOG_WRN = 0x002,\n+\tNT_LOG_INF = 0x004,\n+\tNT_LOG_DBG = 0x008,\n+\tNT_LOG_DB1 = 0x010,\n+\tNT_LOG_DB2 = 0x020,\n+};\n+\n+struct nt_log_impl {\n+\tint (*init)(void);\n+\tint (*log)(enum nt_log_level level, uint32_t module, const char *format,\n+\t\t   va_list args);\n+\tint (*is_debug)(uint32_t module);\n+};\n+\n+int nt_log_init(struct nt_log_impl *impl);\n+\n+int nt_log(enum nt_log_level level, uint32_t module, const char *format, ...);\n+\n+/* Returns 1 if RTE_DEBUG, 0 if lower log level, -1 if incorrect module */\n+int nt_log_is_debug(uint32_t module);\n+\n+/*\n+ * nt log helper functions\n+ * to create a string for NT_LOG usage to output a one-liner log\n+ * to use when one single function call to NT_LOG is not optimal - that is\n+ * you do not know the number of parameters at programming time or it is variable\n+ */\n+char *ntlog_helper_str_alloc(const char *sinit);\n+\n+void ntlog_helper_str_reset(char *s, const char *sinit);\n+\n+void ntlog_helper_str_add(char *s, const char *format, ...);\n+\n+void ntlog_helper_str_free(char *s);\n+\n+#endif /* NTOSS_SYSTEM_NTLOG_H */\ndiff --git a/drivers/net/ntnic/ntlog/ntlog.c b/drivers/net/ntnic/ntlog/ntlog.c\nnew file mode 100644\nindex 0000000000..def07f15d0\n--- /dev/null\n+++ b/drivers/net/ntnic/ntlog/ntlog.c\n@@ -0,0 +1,115 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include \"ntlog.h\"\n+\n+#include <stdarg.h>\n+#include <stddef.h>\n+#include <string.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <stdbool.h>\n+\n+#include <rte_string_fns.h>\n+\n+#define NTLOG_HELPER_STR_SIZE_MAX (1024)\n+\n+static struct nt_log_impl *user_impl;\n+\n+int nt_log_init(struct nt_log_impl *impl)\n+{\n+\tuser_impl = impl;\n+\treturn user_impl->init();\n+}\n+\n+static char *last_trailing_eol(char *s)\n+{\n+\tint i = strlen(s) - 1;\n+\t/* Skip spaces */\n+\twhile (i > 0 && s[i] == ' ')\n+\t\t--i;\n+\tif (s[i] != '\\n')\n+\t\treturn NULL;\n+\t/*\n+\t * Find the last trailing EOL \"hello_world\\n\\n\\n\"\n+\t *                                         ^\n+\t */\n+\twhile (i > 1 && s[i] == '\\n' && s[i - 1] == '\\n')\n+\t\t--i;\n+\treturn &s[i];\n+}\n+\n+/* Always terminates the NT_LOG statement with a !!!single!!! EOL. */\n+int nt_log(enum nt_log_level level, uint32_t module, const char *format, ...)\n+{\n+\tint rv = -1;\n+\tva_list args;\n+\n+\tif (user_impl == NULL)\n+\t\treturn rv;\n+\n+\tchar *actual_format = ntlog_helper_str_alloc(format);\n+\tchar *eol = last_trailing_eol(actual_format);\n+\n+\tif (!eol) { /* If log line is not terminated with '\\n' we add it. */\n+\t\tstrncat(actual_format, \"\\n\",\n+\t\t\tNTLOG_HELPER_STR_SIZE_MAX - strlen(actual_format));\n+\t} else {   /* If multiple trailing EOLs, then keep just one of them. */\n+\t\t*(eol + 1) = '\\0';\n+\t}\n+\n+\tva_start(args, format);\n+\trv = user_impl->log(level, module, actual_format, args);\n+\tva_end(args);\n+\n+\tntlog_helper_str_free(actual_format);\n+\treturn rv;\n+}\n+\n+int nt_log_is_debug(uint32_t module)\n+{\n+\treturn user_impl->is_debug(module);\n+}\n+\n+char *ntlog_helper_str_alloc(const char *sinit)\n+{\n+\tchar *s = malloc(NTLOG_HELPER_STR_SIZE_MAX);\n+\n+\tif (!s)\n+\t\treturn NULL;\n+\tif (sinit)\n+\t\trte_strscpy(s, sinit, NTLOG_HELPER_STR_SIZE_MAX);\n+\telse\n+\t\ts[0] = '\\0';\n+\treturn s;\n+}\n+\n+void ntlog_helper_str_reset(char *s, const char *sinit)\n+{\n+\tif (s) {\n+\t\tif (sinit)\n+\t\t\trte_strscpy(s, sinit, NTLOG_HELPER_STR_SIZE_MAX);\n+\t\telse\n+\t\t\ts[0] = '\\0';\n+\t}\n+}\n+\n+__rte_format_printf(2, 0)\n+void ntlog_helper_str_add(char *s, const char *format, ...)\n+{\n+\tif (!s)\n+\t\treturn;\n+\tva_list args;\n+\n+\tva_start(args, format);\n+\tint len = strlen(s);\n+\n+\tvsnprintf(&s[len], (NTLOG_HELPER_STR_SIZE_MAX - 1 - len), format, args);\n+\tva_end(args);\n+}\n+\n+void ntlog_helper_str_free(char *s)\n+{\n+\tfree(s);\n+}\ndiff --git a/drivers/net/ntnic/ntutil/include/nt_util.h b/drivers/net/ntnic/ntutil/include/nt_util.h\nnew file mode 100644\nindex 0000000000..cc6891e82c\n--- /dev/null\n+++ b/drivers/net/ntnic/ntutil/include/nt_util.h\n@@ -0,0 +1,72 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#ifndef NTOSS_SYSTEM_NT_UTIL_H\n+#define NTOSS_SYSTEM_NT_UTIL_H\n+\n+#include <rte_bitops.h>\n+#include <rte_cycles.h>\n+#include <rte_string_fns.h>\n+\n+#define _unused __rte_unused\n+\n+#define PCIIDENT_TO_DOMAIN(pci_ident) \\\n+\t((uint16_t)(((unsigned int)(pci_ident) >> 16) & 0xFFFFU))\n+#define PCIIDENT_TO_BUSNR(pci_ident) \\\n+\t((uint8_t)(((unsigned int)(pci_ident) >> 8) & 0xFFU))\n+#define PCIIDENT_TO_DEVNR(pci_ident) \\\n+\t((uint8_t)(((unsigned int)(pci_ident) >> 3) & 0x1FU))\n+#define PCIIDENT_TO_FUNCNR(pci_ident) \\\n+\t((uint8_t)(((unsigned int)(pci_ident) >> 0) & 0x7U))\n+\n+#define PCIIDENT_PRINT_STR \"%04x:%02x:%02x.%x\"\n+#define BDF_TO_PCIIDENT(dom, bus, dev, fnc) \\\n+\t(((dom) << 16) | ((bus) << 8) | ((dev) << 3) | (fnc))\n+\n+/* ALIGN: Align x to a boundary */\n+#define ALIGN(x, a)                           \\\n+\t({                                    \\\n+\t\t__typeof__(x) _a = (a);       \\\n+\t\t((x) + (_a - 1)) & ~(_a - 1); \\\n+\t})\n+\n+/* PALIGN: Align pointer p to a boundary */\n+#define PALIGN(p, a) ((__typeof__(p))ALIGN((unsigned long)(p), (a)))\n+\n+/* Allocation size matching minimum alignment of specified size */\n+#define ALIGN_SIZE(_size_) (1 << rte_log2_u64(_size_))\n+\n+#define NT_OS_WAIT_USEC(x)    \\\n+\trte_delay_us_sleep( \\\n+\t\tx) /* uses usleep which schedules out the calling thread */\n+/* spins in a waiting loop calling pause asm instruction uses RDTSC - precise wait */\n+#define NT_OS_WAIT_USEC_POLL(x) \\\n+\trte_delay_us(        \\\n+\t\tx)\n+\n+#define NT_OS_GET_TIME_US() \\\n+\t(rte_get_timer_cycles() / (rte_get_timer_hz() / 1000 / 1000))\n+#define NT_OS_GET_TIME_NS() \\\n+\t(rte_get_timer_cycles() * 10 / (rte_get_timer_hz() / 1000 / 1000 / 100))\n+#define NT_OS_GET_TIME_MONOTONIC_COUNTER() (rte_get_timer_cycles())\n+\n+struct nt_dma_s {\n+\tuint64_t iova;\n+\tuint64_t addr;\n+\tuint64_t size;\n+};\n+\n+struct nt_dma_s *nt_dma_alloc(uint64_t size, uint64_t align, int numa);\n+void nt_dma_free(struct nt_dma_s *vfio_addr);\n+\n+struct nt_util_vfio_impl {\n+\tint (*vfio_dma_map)(int vf_num, void *virt_addr, uint64_t *iova_addr,\n+\t\t\t    uint64_t size);\n+\tint (*vfio_dma_unmap)(int vf_num, void *virt_addr, uint64_t iova_addr,\n+\t\t\t      uint64_t size);\n+};\n+\n+void nt_util_vfio_init(struct nt_util_vfio_impl *impl);\n+\n+#endif /* NTOSS_SYSTEM_NT_UTIL_H */\ndiff --git a/drivers/net/ntnic/ntutil/nt_util.c b/drivers/net/ntnic/ntutil/nt_util.c\nnew file mode 100644\nindex 0000000000..8f5812bf8b\n--- /dev/null\n+++ b/drivers/net/ntnic/ntutil/nt_util.c\n@@ -0,0 +1,77 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Napatech A/S\n+ */\n+\n+#include <unistd.h>\n+#include <stdlib.h>\n+#include <stdint.h>\n+#include <inttypes.h>\n+#include <stdio.h>\n+#include <assert.h>\n+\n+#include <rte_malloc.h>\n+\n+#include \"ntlog.h\"\n+#include \"nt_util.h\"\n+\n+static struct nt_util_vfio_impl vfio_cb;\n+\n+void nt_util_vfio_init(struct nt_util_vfio_impl *impl)\n+{\n+\tvfio_cb = *impl;\n+}\n+\n+struct nt_dma_s *nt_dma_alloc(uint64_t size, uint64_t align, int numa)\n+{\n+\tint res;\n+\tstruct nt_dma_s *vfio_addr;\n+\n+\tvfio_addr = rte_malloc(NULL, sizeof(struct nt_dma_s), 0);\n+\tif (!vfio_addr) {\n+\t\tNT_LOG(ERR, GENERAL, \"VFIO rte_malloc failed\\n\");\n+\t\treturn NULL;\n+\t}\n+\tvoid *addr = rte_malloc_socket(NULL, size, align, numa);\n+\n+\tif (!addr) {\n+\t\trte_free(vfio_addr);\n+\t\tNT_LOG(ERR, GENERAL, \"VFIO rte_malloc_socket failed\\n\");\n+\t\treturn NULL;\n+\t}\n+\tres = vfio_cb.vfio_dma_map(0, addr, &vfio_addr->iova,\n+\t\t\t\t   ALIGN_SIZE(size));\n+\tif (res != 0) {\n+\t\trte_free(addr);\n+\t\trte_free(vfio_addr);\n+\t\tNT_LOG(ERR, GENERAL, \"VFIO nt_dma_map failed\\n\");\n+\t\treturn NULL;\n+\t}\n+\n+\tvfio_addr->addr = (uint64_t)addr;\n+\tvfio_addr->size = ALIGN_SIZE(size);\n+\n+\tNT_LOG(DBG, GENERAL,\n+\t       \"VFIO DMA alloc addr=%\" PRIX64 \", iova=%\" PRIX64\n+\t       \", size=%u, align=0x%X\\n\",\n+\t       vfio_addr->addr, vfio_addr->iova, vfio_addr->size, align);\n+\n+\treturn vfio_addr;\n+}\n+\n+void nt_dma_free(struct nt_dma_s *vfio_addr)\n+{\n+\tNT_LOG(DBG, GENERAL,\n+\t       \"VFIO DMA free addr=%\" PRIX64 \", iova=%\" PRIX64 \", size=%u\\n\",\n+\t       vfio_addr->addr, vfio_addr->iova, vfio_addr->size);\n+\n+\tint res = vfio_cb.vfio_dma_unmap(0, (void *)(vfio_addr->addr),\n+\t\t\t\t\t vfio_addr->iova, vfio_addr->size);\n+\tif (res != 0) {\n+\t\tNT_LOG(WRN, GENERAL,\n+\t\t       \"VFIO DMA free FAILED addr=%\" PRIX64 \", iova=%\" PRIX64\n+\t\t       \", size=%u\\n\",\n+\t\t       vfio_addr->addr, vfio_addr->iova, vfio_addr->size);\n+\t}\n+\trte_free((void *)(vfio_addr->addr));\n+\trte_free(vfio_addr);\n+}\n",
    "prefixes": [
        "v9",
        "2/8"
    ]
}