From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id DF16A45509;
	Thu, 27 Jun 2024 09:41:40 +0200 (CEST)
Received: from mails.dpdk.org (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id 4EF2540E6E;
	Thu, 27 Jun 2024 09:39:54 +0200 (CEST)
Received: from egress-ip42b.ess.de.barracuda.com
 (egress-ip42b.ess.de.barracuda.com [18.185.115.246])
 by mails.dpdk.org (Postfix) with ESMTP id 7632B40E1C
 for <dev@dpdk.org>; Thu, 27 Jun 2024 09:39:45 +0200 (CEST)
Received: from EUR05-DB8-obe.outbound.protection.outlook.com
 (mail-db8eur05lp2104.outbound.protection.outlook.com [104.47.17.104]) by
 mx-outbound43-83.eu-central-1c.ess.aws.cudaops.com (version=TLSv1.2
 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO);
 Thu, 27 Jun 2024 07:39:42 +0000
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
 b=oPkO18wSi4Dq2e5Yo1Q4QeQkTXQ9kqPoW7H1kp/ByUYpw6xeCbVHl0y1n60FFYbd0nTr4oPuOnl8gnc7QPTPbsXGTAMePO1abmwNqQD/ne6AahK+Ewalv/F2voyzMnPi+TI/x3KVxUhB0EIoSDNq9dFOjtxyIYFJ86b0ikKxin2TCAIOe34yI8jRoIukSRhKoNQ21laGJlYrVkLi5x2/6XTkBOtPkjrmBP98K4VReAu9ia0raPeh6o4+CNqCYXNo+D2levMzY3ilqxyrDfw43d72oA5jRvm/FwO1/G22WPbprH9SXVy2VR5HtTmH2O6UYs7lAihTGZNLSrXl4vQMcw==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; 
 s=arcselector9901;
 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;
 bh=6RKG6cLDXLppjmgZUEtZg62tYYSxnIsyfbxLs2Ahz4Q=;
 b=f5ERv11WuKR57UvzcbaQLL6yOnu+O5pMDRu6xhGutrJvDbHKQBPA0cwEWphWoRJEP5MI44NdhtB9bBw/IM2jAC0wUFvOmLSG6DSu8Gfx3qmpjEBwKZVjHgxBJWzOZ2zJ9NZ86UO9wl1YSKMSsuGt0D7bl+XxLhAeZ4pVWq6iBY+MhKrK6xA8I8Urm5BxaweV54w99lcoeCjo3GJW+lMxhtBx7EIWtVt99f1qHcVDLbqWd7RbiJu66J2zBniL+fAhAQ0v7Nn7m0nZERSR/sVwAvgG7bM9TuWr/dRtdmublzGFIPMVwEYTVYH0qTdkaDCRJY4v/hCG3T46NcSkVRt41g==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=fail (sender ip is
 178.72.21.4) smtp.rcpttodomain=dpdk.org smtp.mailfrom=napatech.com;
 dmarc=fail (p=reject sp=reject pct=100) action=oreject
 header.from=napatech.com; dkim=none (message not signed); arc=none (0)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=napatech.com;
 s=selector1;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=6RKG6cLDXLppjmgZUEtZg62tYYSxnIsyfbxLs2Ahz4Q=;
 b=GG6F4bUM8YUMpvrN9v9EDw5I6WgO05dE98/DYmeuAWbeBKPAHhc3jBmB52VR+j3wrvgfTFO1qwTGx/yraJexLPxSCLRgY5e2HFVC+bInJcZuDoXH/Tt2wZituJYHp7rNu4uOQFLRjl5+JGG2wJv6A8gIYCR+cnknFokfDWt7994=
Received: from DUZPR01CA0341.eurprd01.prod.exchangelabs.com
 (2603:10a6:10:4b8::11) by GV1P190MB1898.EURP190.PROD.OUTLOOK.COM
 (2603:10a6:150:51::15) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.32; Thu, 27 Jun
 2024 07:39:37 +0000
Received: from DB1PEPF000509E2.eurprd03.prod.outlook.com
 (2603:10a6:10:4b8:cafe::78) by DUZPR01CA0341.outlook.office365.com
 (2603:10a6:10:4b8::11) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7719.25 via Frontend
 Transport; Thu, 27 Jun 2024 07:39:34 +0000
X-MS-Exchange-Authentication-Results: spf=fail (sender IP is 178.72.21.4)
 smtp.mailfrom=napatech.com; dkim=none (message not signed)
 header.d=none;dmarc=fail action=oreject header.from=napatech.com;
Received-SPF: Fail (protection.outlook.com: domain of napatech.com does not
 designate 178.72.21.4 as permitted sender) receiver=protection.outlook.com;
 client-ip=178.72.21.4; helo=localhost.localdomain;
Received: from localhost.localdomain (178.72.21.4) by
 DB1PEPF000509E2.mail.protection.outlook.com (10.167.242.52) with Microsoft
 SMTP Server id 15.20.7677.15 via Frontend Transport; Thu, 27 Jun 2024
 07:39:34 +0000
From: Serhii Iliushyk <sil-plv@napatech.com>
To: dev@dpdk.org
Cc: mko-plv@napatech.com, sil-plv@napatech.com, ckm@napatech.com,
 andrew.rybchenko@oktetlabs.ru, ferruh.yigit@amd.com
Subject: [PATCH v5 13/23] net/ntnic: add reset module for the NT200A0X smartNIC
Date: Thu, 27 Jun 2024 09:38:54 +0200
Message-ID: <20240627073918.2039719-13-sil-plv@napatech.com>
X-Mailer: git-send-email 2.45.0
In-Reply-To: <20240627073918.2039719-1-sil-plv@napatech.com>
References: <20240530144929.4127931-1-sil-plv@napatech.com>
 <20240627073918.2039719-1-sil-plv@napatech.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-EOPAttributedMessage: 0
X-MS-PublicTrafficType: Email
X-MS-TrafficTypeDiagnostic: DB1PEPF000509E2:EE_|GV1P190MB1898:EE_
Content-Type: text/plain
X-MS-Office365-Filtering-Correlation-Id: 020e364c-776d-4a95-1ef2-08dc967c4a5e
X-MS-Exchange-SenderADCheck: 1
X-MS-Exchange-AntiSpam-Relay: 0
X-Microsoft-Antispam: BCL:0;
 ARA:13230040|1800799024|82310400026|376014|36860700013; 
X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?bzy57zLNgPwOSiBxPOsU4mxJ1hCcUZZAj1qqisumqTyxA4lrRQU280IxF5nG?=
 =?us-ascii?Q?CQhaYvSVznB9LDYYbZSWI9D0v+K873KY1VMpPwXG7zPC3Stw5JZMWiqZ352S?=
 =?us-ascii?Q?vMPfFcDxDKsNkv+SyY5XOanvQqMBkf4MooGp2yKZHB87iNdvipctWJVm1ck6?=
 =?us-ascii?Q?/5QcwRMazsWUG1L++gaF+m8YgENovxFOA60JPp7uHQrMSfzm7HCT1s1mdFGj?=
 =?us-ascii?Q?TpWsIFl/7TPTn+egE/LtestcdbrU1TYjGRHs03HY9GkYkqXPnr7KfVOd46kC?=
 =?us-ascii?Q?AYcyS3J1zdhMPaz6cv1t51Oym5fpyKckWHgY8DZyjFNWIlsxSfFVsaSbNyi/?=
 =?us-ascii?Q?FYkouHfTm87frP1L0e5aYWuReS4y3YY1Don1ay6GsFpgre0UlbMZFsl7fYyN?=
 =?us-ascii?Q?JCO0R/2mbiAJa2f6UOqkqQyq1tM6uelx97cLF8uHJnFyixZ0Vc8NqgUPpfUI?=
 =?us-ascii?Q?IUTv7bxCwFQWVW6j7DPsYjXo94E/WByHJlrFxpHdBJmw0Sgd58sShwssNKHn?=
 =?us-ascii?Q?E5KdtdT4A7A1wNGp6NJx7a+hxM5ILC65NgSSkoksjXp02cxmduO6jv1oxf9+?=
 =?us-ascii?Q?FOOdXKoHbj5fjFjpDerPFY8CWUKmBkwYzRB2aEGeb3eXU/d5ooUntHsOVIEc?=
 =?us-ascii?Q?oMLih05TvP978IupGABBtBSGc5Wi7I2JYDZy6uzwZDknovb6HGbG6N17h1ep?=
 =?us-ascii?Q?rBuRa+jZ8FCwpKk1wxS6y3H92VIpcW5uc/4H4edOXwt98GwPutqn+mdyMkV7?=
 =?us-ascii?Q?bnILV3cls5lN2MJJlRYx/IO9Px6XdHZILFiOtax6GK/Gs0X5n48a36MFxilY?=
 =?us-ascii?Q?D56y+xDK8qh5aBOXerLMhgPlNlNOpth0/VWwgXPqQ2DMLCIhpSuqBRS6+ivk?=
 =?us-ascii?Q?Q27/SH0To2lrTz8e01gz5dOUitxwd65Ih6J9eFWA2FYuvWiRnSfmj2HvkOvK?=
 =?us-ascii?Q?UImt3tvh8T6EC7rIxXUmd2Mt6HnKaRECqGXgDUR4C29GRHTErYgotYucmeg9?=
 =?us-ascii?Q?O8k+0qHdGuyd8ElrDfYXbxdYDqQtEklKJshs7pxa5/pSYpBObky5E49Tl7Bu?=
 =?us-ascii?Q?cckuefj0XdVWYReI/+PtJ46VYK+L33TL9TH3BR713YdB3hJTr+mTSOeFjtSN?=
 =?us-ascii?Q?j05HxTJ+kpeGXSHPdIK2xAdcrHbV9UMj6xuK7def9bD/PndJYMkPOv88CrAi?=
 =?us-ascii?Q?T59E1d01en+E4IJazNlbwMFbl9cBaMqUZJ6twgcxI5+O4lUCQ2mZxVhUtppu?=
 =?us-ascii?Q?fQ/aLNSSCFHJ4OeneU6WeEDpv/zN+lnIiLB9XNYV1/76l3esCir1v9qVgso1?=
 =?us-ascii?Q?sJxGqBNhi9i84qDGrOKIz/OT90Dd2HITz7KIlPAm8Dnn2lE+9J2cYFUylWbA?=
 =?us-ascii?Q?n2qQwMsNr39UXpOZaXXU/nPXvfHSnkri52/mvuJGVq93bDVUAZcM4v1NBi9v?=
 =?us-ascii?Q?Wd4TjeRPqB1JdZJLCnju+WJnEKWr3aXw?=
X-Forefront-Antispam-Report: CIP:178.72.21.4; CTRY:DK; LANG:en; SCL:1; SRV:;
 IPV:NLI; SFV:NSPM; H:localhost.localdomain; PTR:InfoDomainNonexistent;
 CAT:NONE; SFS:(13230040)(1800799024)(82310400026)(376014)(36860700013);
 DIR:OUT; SFP:1102; 
X-MS-Exchange-AntiSpam-ExternalHop-MessageData-ChunkCount: 1
X-MS-Exchange-AntiSpam-ExternalHop-MessageData-0: wUmRGvf9J4BUX1RKmrGlGpkDmWJfOaaSHur7xIZOLYSARIxfSsqjjjLMdNhxD0jIrQ50e8e1EPQpJ4g1mdASprxLOGTrCYrAjkHqNQQJtQj2m9f8peBpXSdZ9f/rkUiQyxV45iZAfYauwuUF6mow3nA+YCfm0QsuiC8x7CMImiIIutFq2ullMOuhF3KLGRxblpiFdJYUEa3JJIDDBZOPrTytroG4KaVj53RsxHar+2g5hJIGMQemj4hUSVar/oQOYZzXNbIE4riRZm7ZfyvMxOv/3sZ4VB51YSVUUT7sf66sxpvyKA8f9HI7HI+5NVhoqqVrCH5cw+tE4fNbS75w/hnEbdFknzkwlJMtVTPErHVbzvyVic0XbEwxpxlRKa7AGV4vJmlaXDGToBHOLyHJStiSOqwBQslGK6Bm89mF4iHbtdD5gt6yNKsJk86GhlAhDO1P/PMI8O48VIfXQMbnGr5TLoHo5UsXEVFu+m2oRo3qsK1ISMBLHjduSaP6R1siahkl+UlPD+IVrOLgmqcGg2Gqj9oZxloEkkzx4jMokEM0l4GioSyrgI7ZMrLLLpaog2c21LnuMX2ZSOmUSUJ1cCEYjI8EQ/mlpAiZ/6oJSx59Gg99mbY5492k8jeFzUBFEqvaZu7T83rJftboit4TPQ==
X-OriginatorOrg: napatech.com
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jun 2024 07:39:34.4748 (UTC)
X-MS-Exchange-CrossTenant-Network-Message-Id: 020e364c-776d-4a95-1ef2-08dc967c4a5e
X-MS-Exchange-CrossTenant-Id: c4540d0b-728a-4233-9da5-9ea30c7ec3ed
X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=c4540d0b-728a-4233-9da5-9ea30c7ec3ed; Ip=[178.72.21.4];
 Helo=[localhost.localdomain]
X-MS-Exchange-CrossTenant-AuthSource: DB1PEPF000509E2.eurprd03.prod.outlook.com
X-MS-Exchange-CrossTenant-AuthAs: Anonymous
X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem
X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1P190MB1898
X-BESS-ID: 1719473982-311091-12758-2362-1
X-BESS-VER: 2019.1_20240620.2317
X-BESS-Apparent-Source-IP: 104.47.17.104
X-BESS-Parts: H4sIAAAAAAACA4uuVkqtKFGyUioBkjpK+cVKViZmBhZmQGYGUDQp0TwtxSQ5LT
 k5xdzAwsDQJNHA1NggySgp0dTY0DLZQKk2FgDfCKoBQgAAAA==
X-BESS-Outbound-Spam-Score: 0.20
X-BESS-Outbound-Spam-Report: Code version 3.2,
 rules version 3.2.2.257231 [from 
 cloudscan18-141.eu-central-1b.ess.aws.cudaops.com]
 Rule breakdown below
 pts rule name              description
 ---- ---------------------- --------------------------------
 0.00 BSF_BESS_OUTBOUND      META: BESS Outbound 
 0.20 PR0N_SUBJECT META: Subject has letters around special characters (pr0n) 
X-BESS-Outbound-Spam-Status: SCORE=0.20 using account:ESS113687 scores of
 KILL_LEVEL=7.0 tests=BSF_BESS_OUTBOUND, PR0N_SUBJECT
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>,
 <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>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org

Add API for reset NT200 and FW 9563

Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
v5
* Fix Typo/Spelling
---
 .../include/ntnic_nthw_fpga_rst_nt200a0x.h    |  81 +++
 drivers/net/ntnic/meson.build                 |   3 +
 .../net/ntnic/nthw/core/include/nthw_core.h   |   2 +
 .../net/ntnic/nthw/core/include/nthw_fpga.h   |   6 +
 .../net/ntnic/nthw/core/include/nthw_sdc.h    |  42 ++
 .../nthw/core/nt200a0x/nthw_fpga_nt200a0x.c   |  24 +-
 .../core/nt200a0x/reset/nthw_fpga_rst9563.c   | 216 +++++++
 .../nt200a0x/reset/nthw_fpga_rst_nt200a0x.c   | 570 ++++++++++++++++++
 drivers/net/ntnic/nthw/core/nthw_fpga.c       |  82 +++
 drivers/net/ntnic/nthw/core/nthw_sdc.c        | 176 ++++++
 drivers/net/ntnic/ntnic_mod_reg.c             |  28 +
 drivers/net/ntnic/ntnic_mod_reg.h             |  20 +
 12 files changed, 1249 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ntnic/include/ntnic_nthw_fpga_rst_nt200a0x.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_sdc.h
 create mode 100644 drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst9563.c
 create mode 100644 drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_sdc.c

diff --git a/drivers/net/ntnic/include/ntnic_nthw_fpga_rst_nt200a0x.h b/drivers/net/ntnic/include/ntnic_nthw_fpga_rst_nt200a0x.h
new file mode 100644
index 0000000000..6ceec93bac
--- /dev/null
+++ b/drivers/net/ntnic/include/ntnic_nthw_fpga_rst_nt200a0x.h
@@ -0,0 +1,81 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+#ifndef __NTNIC_NTHW_FPGA_RST_NT200A0X_H__
+#define __NTNIC_NTHW_FPGA_RST_NT200A0X_H__
+
+#include "nthw_drv.h"
+#include "nthw_fpga_model.h"
+
+struct nthw_fpga_rst_nt200a0x {
+	int mn_fpga_product_id;
+	int mn_fpga_version;
+	int mn_fpga_revision;
+
+	int mn_hw_id;
+
+	int mn_si_labs_clock_synth_model;
+
+	nthw_field_t *mp_fld_rst_sys;
+	nthw_field_t *mp_fld_rst_sys_mmcm;
+	nthw_field_t *mp_fld_rst_core_mmcm;
+	nthw_field_t *mp_fld_rst_rpp;
+	nthw_field_t *mp_fld_rst_ddr4;
+	nthw_field_t *mp_fld_rst_sdc;
+	nthw_field_t *mp_fld_rst_phy;
+	nthw_field_t *mp_fld_rst_serdes_rx;
+	nthw_field_t *mp_fld_rst_serdes_tx;
+	nthw_field_t *mp_fld_rst_serdes_rx_datapath;
+	nthw_field_t *mp_fld_rst_pcs_rx;
+	nthw_field_t *mp_fld_rst_mac_rx;
+	nthw_field_t *mp_fld_rst_mac_tx;
+	nthw_field_t *mp_fld_rst_ptp;
+	nthw_field_t *mp_fld_rst_ts;
+	nthw_field_t *mp_fld_rst_ptp_mmcm;
+	nthw_field_t *mp_fld_rst_ts_mmcm;
+	nthw_field_t *mp_fld_rst_periph;
+	nthw_field_t *mp_fld_rst_tsm_ref_mmcm;
+	nthw_field_t *mp_fld_rst_tmc;
+
+	/* CTRL register field pointers */
+	nthw_field_t *mp_fld_ctrl_ts_clk_sel_override;
+	nthw_field_t *mp_fld_ctrl_ts_clk_sel;
+	nthw_field_t *mp_fld_ctrl_ts_clk_sel_ref;
+	nthw_field_t *mp_fld_ctrl_ptp_mmcm_clk_sel;
+
+	/* STAT register field pointers */
+	nthw_field_t *mp_fld_stat_ddr4_mmcm_locked;
+	nthw_field_t *mp_fld_stat_sys_mmcm_locked;
+	nthw_field_t *mp_fld_stat_core_mmcm_locked;
+	nthw_field_t *mp_fld_stat_ddr4_pll_locked;
+	nthw_field_t *mp_fld_stat_ptp_mmcm_locked;
+	nthw_field_t *mp_fld_stat_ts_mmcm_locked;
+	nthw_field_t *mp_fld_stat_tsm_ref_mmcm_locked;
+
+	/* STICKY register field pointers */
+	nthw_field_t *mp_fld_sticky_ptp_mmcm_unlocked;
+	nthw_field_t *mp_fld_sticky_ts_mmcm_unlocked;
+	nthw_field_t *mp_fld_sticky_ddr4_mmcm_unlocked;
+	nthw_field_t *mp_fld_sticky_ddr4_pll_unlocked;
+	nthw_field_t *mp_fld_sticky_core_mmcm_unlocked;
+	nthw_field_t *mp_fld_sticky_pci_sys_mmcm_unlocked;
+	nthw_field_t *mp_fld_sticky_tsm_ref_mmcm_unlocked;
+
+	/* POWER register field pointers */
+	nthw_field_t *mp_fld_power_pu_phy;
+	nthw_field_t *mp_fld_power_pu_nseb;
+
+	void (*reset_serdes_rx)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no, uint32_t rst);
+	void (*pcs_rx_rst)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no, uint32_t rst);
+	void (*get_serdes_rx_rst)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no,
+		uint32_t *p_set);
+	void (*get_pcs_rx_rst)(struct nthw_fpga_rst_nt200a0x *p, uint32_t intf_no,
+		uint32_t *p_set);
+	bool (*is_rst_serdes_rx_datapath_implemented)(struct nthw_fpga_rst_nt200a0x *p);
+};
+
+typedef struct nthw_fpga_rst_nt200a0x nthw_fpga_rst_nt200a0x_t;
+
+#endif	/* __NTHW_FPGA_RST_NT200A0X_H__ */
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 79d89b1031..4f7e57b5ad 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -31,10 +31,13 @@ sources = files(
     'nthw/supported/nthw_fpga_instances.c',
     'nthw/supported/nthw_fpga_mod_str_map.c',
     'nthw/core/nt200a0x/nthw_fpga_nt200a0x.c',
+    'nthw/core/nt200a0x/reset/nthw_fpga_rst9563.c',
+    'nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c',
     'nthw/core/nthw_fpga.c',
     'nthw/core/nthw_hif.c',
     'nthw/core/nthw_iic.c',
     'nthw/core/nthw_pcie3.c',
+    'nthw/core/nthw_sdc.c',
     'nthw/model/nthw_fpga_model.c',
     'nthw/nthw_platform.c',
     'nthw/nthw_rac.c',
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_core.h b/drivers/net/ntnic/nthw/core/include/nthw_core.h
index 69af113816..8bdf7ee01d 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_core.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_core.h
@@ -16,5 +16,7 @@
 #include "nthw_pcie3.h"
 #include "nthw_iic.h"
 
+#include "nthw_sdc.h"
+
 
 #endif	/* __NTHW_CORE_H__ */
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_fpga.h b/drivers/net/ntnic/nthw/core/include/nthw_fpga.h
index ba86b4d8d2..1df1480109 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_fpga.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_fpga.h
@@ -18,6 +18,12 @@ int nthw_fpga_shutdown(struct fpga_info_s *p_fpga_info);
 
 int nthw_fpga_get_param_info(struct fpga_info_s *p_fpga_info, nthw_fpga_t *p_fpga);
 
+int nthw_fpga_iic_scan(nthw_fpga_t *p_fpga, const int n_instance_no_begin,
+	const int n_instance_no_end);
+
+int nthw_fpga_silabs_detect(nthw_fpga_t *p_fpga, const int n_instance_no, const int n_dev_addr,
+	const int n_page_reg_addr);
+
 struct nt200a0x_ops {
 	int (*nthw_fpga_nt200a0x_init)(struct fpga_info_s *p_fpga_info);
 };
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_sdc.h b/drivers/net/ntnic/nthw/core/include/nthw_sdc.h
new file mode 100644
index 0000000000..58247d67f0
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/include/nthw_sdc.h
@@ -0,0 +1,42 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_SDC_H__
+#define __NTHW_SDC_H__
+
+struct nthw_sdc {
+	nthw_fpga_t *mp_fpga;
+	nthw_module_t *mp_mod_sdc;
+	int mn_instance;
+
+	nthw_field_t *mp_fld_ctrl_init;
+	nthw_field_t *mp_fld_ctrl_run_test;
+	nthw_field_t *mp_fld_ctrl_stop_client;
+	nthw_field_t *mp_fld_ctrl_test_enable;
+
+	nthw_field_t *mp_fld_stat_calib;
+	nthw_field_t *mp_fld_stat_cell_cnt_stopped;
+	nthw_field_t *mp_fld_stat_err_found;
+	nthw_field_t *mp_fld_stat_init_done;
+	nthw_field_t *mp_fld_stat_mmcm_lock;
+	nthw_field_t *mp_fld_stat_pll_lock;
+	nthw_field_t *mp_fld_stat_resetting;
+
+	nthw_field_t *mp_fld_cell_cnt;
+	nthw_field_t *mp_fld_cell_cnt_period;
+	nthw_field_t *mp_fld_fill_level;
+	nthw_field_t *mp_fld_max_fill_level;
+};
+
+typedef struct nthw_sdc nthw_sdc_t;
+
+nthw_sdc_t *nthw_sdc_new(void);
+int nthw_sdc_init(nthw_sdc_t *p, nthw_fpga_t *p_fpga, int n_instance);
+void nthw_sdc_delete(nthw_sdc_t *p);
+
+int nthw_sdc_wait_states(nthw_sdc_t *p, const int n_poll_iterations, const int n_poll_interval);
+int nthw_sdc_get_states(nthw_sdc_t *p, uint64_t *pn_result_mask);
+
+#endif	/* __NTHW_SDC_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nt200a0x/nthw_fpga_nt200a0x.c b/drivers/net/ntnic/nthw/core/nt200a0x/nthw_fpga_nt200a0x.c
index 7db6a03d88..3009e30670 100644
--- a/drivers/net/ntnic/nthw/core/nt200a0x/nthw_fpga_nt200a0x.c
+++ b/drivers/net/ntnic/nthw/core/nt200a0x/nthw_fpga_nt200a0x.c
@@ -13,14 +13,36 @@ static int nthw_fpga_nt200a0x_init(struct fpga_info_s *p_fpga_info)
 	assert(p_fpga_info);
 
 	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+	struct nthw_fpga_rst_nt200a0x rst;
 	int res = -1;
+	const struct rst_nt200a0x_ops *rst_nt200a0x_ops = get_rst_nt200a0x_ops();
+
+	if (rst_nt200a0x_ops == NULL) {
+		NT_LOG(ERR, NTHW, "RST NT200A0X NOT INCLUDED\n");
+		return -1;
+	}
+
+	/* reset common */
+	res = rst_nt200a0x_ops->nthw_fpga_rst_nt200a0x_init(p_fpga_info, &rst);
+
+	if (res) {
+		NT_LOG_DBGX(ERR, NTHW, "%s: FPGA=%04d res=%d\n", p_adapter_id_str,
+					p_fpga_info->n_fpga_prod_id, res);
+		return res;
+	}
 
 	bool included = true;
+	struct rst9563_ops *rst9563_ops = get_rst9563_ops();
 
 	/* reset specific */
 	switch (p_fpga_info->n_fpga_prod_id) {
 	case 9563:
-		included = false;
+		if (rst9563_ops != NULL)
+			res = rst9563_ops->nthw_fpga_rst9563_init(p_fpga_info, &rst);
+
+		else
+			included = false;
+
 		break;
 
 	default:
diff --git a/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst9563.c b/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst9563.c
new file mode 100644
index 0000000000..a3b6511b06
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst9563.c
@@ -0,0 +1,216 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+#include "nthw_fpga.h"
+
+#include "ntnic_mod_reg.h"
+
+static int nthw_fpga_rst9563_setup(nthw_fpga_t *p_fpga, struct nthw_fpga_rst_nt200a0x *const p)
+{
+	const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+	const int n_fpga_product_id = p_fpga->mn_product_id;
+	const int n_fpga_version = p_fpga->mn_fpga_version;
+	const int n_fpga_revision = p_fpga->mn_fpga_revision;
+
+	nthw_module_t *p_mod_rst;
+	nthw_register_t *p_curr_reg;
+
+	assert(p);
+	p->mn_fpga_product_id = n_fpga_product_id;
+	p->mn_fpga_version = n_fpga_version;
+	p->mn_fpga_revision = n_fpga_revision;
+
+	NT_LOG_DBGX(DEBUG, NTHW, "%s: FPGA reset setup: FPGA %04d-%02d-%02d\n", p_adapter_id_str,
+				n_fpga_product_id, n_fpga_version, n_fpga_revision);
+
+	p_mod_rst = nthw_fpga_query_module(p_fpga, MOD_RST9563, 0);
+
+	if (p_mod_rst == NULL) {
+		NT_LOG(ERR, NTHW, "%s: RST %d: no such instance\n", p_adapter_id_str, 0);
+		return -1;
+	}
+
+	p_mod_rst = nthw_fpga_query_module(p_fpga, MOD_RST9563, 0);
+
+	if (p_mod_rst == NULL) {
+		NT_LOG(ERR, NTHW, "%s: RST %d: no such instance\n", p_adapter_id_str, 0);
+		return -1;
+	}
+
+	/* RST register field pointers */
+	p_curr_reg = nthw_module_get_register(p_mod_rst, RST9563_RST);
+	p->mp_fld_rst_sys = nthw_register_get_field(p_curr_reg, RST9563_RST_SYS);
+	p->mp_fld_rst_sys_mmcm = nthw_register_get_field(p_curr_reg, RST9563_RST_SYS_MMCM);
+	p->mp_fld_rst_core_mmcm = nthw_register_get_field(p_curr_reg, RST9563_RST_CORE_MMCM);
+	p->mp_fld_rst_rpp = nthw_register_get_field(p_curr_reg, RST9563_RST_RPP);
+	p->mp_fld_rst_ddr4 = nthw_register_get_field(p_curr_reg, RST9563_RST_DDR4);
+	p->mp_fld_rst_sdc = nthw_register_get_field(p_curr_reg, RST9563_RST_SDC);
+	p->mp_fld_rst_phy = nthw_register_get_field(p_curr_reg, RST9563_RST_PHY);
+	p->mp_fld_rst_serdes_rx = NULL;	/* Field not present on 9563 */
+	p->mp_fld_rst_serdes_tx = NULL;	/* Field not present on 9563 */
+	p->mp_fld_rst_serdes_rx_datapath = NULL;/* Field not present on 9563 */
+	p->mp_fld_rst_pcs_rx = NULL;	/* Field not present on 9563 */
+	p->mp_fld_rst_mac_rx = nthw_register_get_field(p_curr_reg, RST9563_RST_MAC_RX);
+	p->mp_fld_rst_mac_tx = NULL;
+	p->mp_fld_rst_ptp = nthw_register_get_field(p_curr_reg, RST9563_RST_PTP);
+	p->mp_fld_rst_ptp = nthw_register_get_field(p_curr_reg, RST9563_RST_PTP);
+	p->mp_fld_rst_ts = nthw_register_get_field(p_curr_reg, RST9563_RST_TS);
+	p->mp_fld_rst_ptp_mmcm = nthw_register_get_field(p_curr_reg, RST9563_RST_PTP_MMCM);
+	p->mp_fld_rst_ts_mmcm = nthw_register_get_field(p_curr_reg, RST9563_RST_TS_MMCM);
+	/* referenced in separate function */
+	p->mp_fld_rst_periph = nthw_register_get_field(p_curr_reg, RST9563_RST_PERIPH);
+	p->mp_fld_rst_tsm_ref_mmcm =
+		nthw_register_query_field(p_curr_reg, RST9563_RST_TSM_REF_MMCM);
+	p->mp_fld_rst_tmc = nthw_register_query_field(p_curr_reg, RST9563_RST_TMC);
+
+	if (!p->mp_fld_rst_tsm_ref_mmcm)
+		NT_LOG(DBG, NTHW, "%s: No RST9563_RST_TSM_REF_MMCM found\n", p_adapter_id_str);
+
+	if (!p->mp_fld_rst_tmc)
+		NT_LOG(DBG, NTHW, "%s: No RST9563_RST_TMC found\n", p_adapter_id_str);
+
+	nthw_register_update(p_curr_reg);
+
+	/* CTRL register field pointers */
+	p_curr_reg = nthw_module_get_register(p_mod_rst, RST9563_CTRL);
+	p->mp_fld_ctrl_ts_clk_sel_override =
+		nthw_register_get_field(p_curr_reg, RST9563_CTRL_TS_CLKSEL_OVERRIDE);
+	/* Field not present on 9563 */
+	p->mp_fld_ctrl_ts_clk_sel = nthw_register_get_field(p_curr_reg, RST9563_CTRL_TS_CLKSEL);
+	p->mp_fld_ctrl_ts_clk_sel_ref = NULL;	/* Field not present on 9563 */
+	p->mp_fld_ctrl_ptp_mmcm_clk_sel =
+		nthw_register_get_field(p_curr_reg, RST9563_CTRL_PTP_MMCM_CLKSEL);
+	nthw_register_update(p_curr_reg);
+
+	/* STAT register field pointers */
+	p_curr_reg = nthw_module_get_register(p_mod_rst, RST9563_STAT);
+	p->mp_fld_stat_ddr4_mmcm_locked =
+		nthw_register_get_field(p_curr_reg, RST9563_STAT_DDR4_MMCM_LOCKED);
+	p->mp_fld_stat_sys_mmcm_locked =
+		nthw_register_get_field(p_curr_reg, RST9563_STAT_SYS_MMCM_LOCKED);
+	p->mp_fld_stat_core_mmcm_locked =
+		nthw_register_get_field(p_curr_reg, RST9563_STAT_CORE_MMCM_LOCKED);
+	p->mp_fld_stat_ddr4_pll_locked =
+		nthw_register_get_field(p_curr_reg, RST9563_STAT_DDR4_PLL_LOCKED);
+	p->mp_fld_stat_ptp_mmcm_locked =
+		nthw_register_get_field(p_curr_reg, RST9563_STAT_PTP_MMCM_LOCKED);
+	p->mp_fld_stat_ts_mmcm_locked =
+		nthw_register_get_field(p_curr_reg, RST9563_STAT_TS_MMCM_LOCKED);
+	p->mp_fld_stat_tsm_ref_mmcm_locked = NULL;	/* Field not present on 9563 */
+
+	if (!p->mp_fld_stat_tsm_ref_mmcm_locked) {
+		NT_LOG(DBG, NTHW, "%s: No RST9563_STAT_TSM_REF_MMCM_LOCKED found\n",
+			p_adapter_id_str);
+	}
+
+	nthw_register_update(p_curr_reg);
+
+	/* STICKY register field pointers */
+	p_curr_reg = nthw_module_get_register(p_mod_rst, RST9563_STICKY);
+	p->mp_fld_sticky_ptp_mmcm_unlocked =
+		nthw_register_get_field(p_curr_reg, RST9563_STICKY_PTP_MMCM_UNLOCKED);
+	p->mp_fld_sticky_ts_mmcm_unlocked =
+		nthw_register_get_field(p_curr_reg, RST9563_STICKY_TS_MMCM_UNLOCKED);
+	p->mp_fld_sticky_ddr4_mmcm_unlocked =
+		nthw_register_get_field(p_curr_reg, RST9563_STICKY_DDR4_MMCM_UNLOCKED);
+	p->mp_fld_sticky_ddr4_pll_unlocked =
+		nthw_register_get_field(p_curr_reg, RST9563_STICKY_DDR4_PLL_UNLOCKED);
+	p->mp_fld_sticky_core_mmcm_unlocked =
+		nthw_register_get_field(p_curr_reg, RST9563_STICKY_CORE_MMCM_UNLOCKED);
+	p->mp_fld_sticky_pci_sys_mmcm_unlocked = NULL;	/* Field not present on 9563 */
+	p->mp_fld_sticky_tsm_ref_mmcm_unlocked = NULL;	/* Field not present on 9563 */
+
+	if (!p->mp_fld_sticky_tsm_ref_mmcm_unlocked) {
+		NT_LOG(DBG, NTHW, "%s: No RST9563_STICKY_TSM_REF_MMCM_UNLOCKED found\n",
+			p_adapter_id_str);
+	}
+
+	nthw_register_update(p_curr_reg);
+
+	/* POWER register field pointers */
+	p_curr_reg = nthw_module_get_register(p_mod_rst, RST9563_POWER);
+	p->mp_fld_power_pu_phy = nthw_register_get_field(p_curr_reg, RST9563_POWER_PU_PHY);
+	p->mp_fld_power_pu_nseb = nthw_register_get_field(p_curr_reg, RST9563_POWER_PU_NSEB);
+	nthw_register_update(p_curr_reg);
+
+	return 0;
+}
+
+static int nthw_fpga_rst9563_periph_reset(nthw_fpga_t *p_fpga)
+{
+	const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+	(void)p_adapter_id_str;
+	nthw_module_t *p_mod_rst = nthw_fpga_query_module(p_fpga, MOD_RST9563, 0);
+
+	if (p_mod_rst) {
+		nthw_register_t *p_reg_rst;
+		nthw_field_t *p_fld_rst_periph;
+		NT_LOG(DBG, NTHW, "%s: PERIPH RST\n", p_adapter_id_str);
+		p_reg_rst = nthw_module_get_register(p_mod_rst, RST9563_RST);
+		p_fld_rst_periph = nthw_register_get_field(p_reg_rst, RST9563_RST_PERIPH);
+		nthw_field_set_flush(p_fld_rst_periph);
+		nthw_field_clr_flush(p_fld_rst_periph);
+
+	} else {
+		return -1;
+	}
+
+	return 0;
+}
+
+static int nthw_fpga_rst9563_init(struct fpga_info_s *p_fpga_info,
+	struct nthw_fpga_rst_nt200a0x *p_rst)
+{
+	assert(p_fpga_info);
+	assert(p_rst);
+
+	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+	(void)p_adapter_id_str;
+	int res = -1;
+	nthw_fpga_t *p_fpga = NULL;
+
+	p_fpga = p_fpga_info->mp_fpga;
+
+	res = nthw_fpga_rst9563_periph_reset(p_fpga);
+
+	if (res) {
+		NT_LOG_DBGX(DEBUG, NTHW, "%s: ERROR: res=%d\n", p_adapter_id_str, res);
+		return res;
+	}
+
+	if (res) {
+		NT_LOG_DBGX(DEBUG, NTHW, "%s: ERROR: res=%d\n", p_adapter_id_str, res);
+		return res;
+	}
+
+	res = nthw_fpga_rst9563_setup(p_fpga, p_rst);
+
+	if (res) {
+		NT_LOG_DBGX(DEBUG, NTHW, "%s: ERROR: res=%d\n", p_adapter_id_str, res);
+		return res;
+	}
+
+	const struct rst_nt200a0x_ops *rst_ops = get_rst_nt200a0x_ops();
+	res = rst_ops != NULL ? rst_ops->nthw_fpga_rst_nt200a0x_reset(p_fpga, p_rst) : -1;
+
+	if (res) {
+		NT_LOG_DBGX(DEBUG, NTHW, "%s: ERROR: res=%d\n", p_adapter_id_str, res);
+		return res;
+	}
+
+	return res;
+}
+
+static struct rst9563_ops rst9563_ops = { .nthw_fpga_rst9563_init = nthw_fpga_rst9563_init };
+
+void rst9563_ops_init(void)
+{
+	NT_LOG(INF, NTHW, "RST9563 OPS INIT\n");
+	register_rst9563_ops(&rst9563_ops);
+}
diff --git a/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c b/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c
new file mode 100644
index 0000000000..84f13e8371
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c
@@ -0,0 +1,570 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+#include "nthw_fpga.h"
+
+#include "ntnic_mod_reg.h"
+
+static const uint8_t si5338_u23_i2c_addr_7bit = 0x70;
+static const uint8_t si5340_u23_i2c_addr_7bit = 0x74;
+
+/*
+ * Wait until DDR4 PLL LOCKED
+ */
+static int nthw_fpga_rst_nt200a0x_wait_ddr4_pll_locked(nthw_fpga_t *p_fpga,
+	const struct nthw_fpga_rst_nt200a0x *p)
+{
+	const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+	uint32_t locked;
+	uint32_t retrycount = 5;
+	uint32_t timeout = 50000;	/* initial timeout must be set to 5 sec. */
+	/* 14: wait until DDR4 PLL LOCKED */
+	NT_LOG(DBG, NTHW, "%s: Waiting for DDR4 PLL to lock\n", p_adapter_id_str);
+
+	/*
+	 * The following retry count gives a total timeout of 1 * 5 + 5 * 8 = 45sec
+	 * It has been observed that at least 21sec can be necessary
+	 */
+	while (true) {
+		int locked =
+			nthw_field_wait_set_any32(p->mp_fld_stat_ddr4_pll_locked, timeout, 100);
+
+		if (locked == 0) {
+			break;
+
+		} else {
+			NT_LOG(DBG, NTHW, "%s: Waiting for DDR4 PLL to lock - timeout\n",
+				p_adapter_id_str);
+
+			if (retrycount <= 0) {
+				NT_LOG(ERR, NTHW, "%s: Waiting for DDR4 PLL to lock failed (%d)\n",
+					p_adapter_id_str, locked);
+				break;
+			}
+
+			nthw_field_set_flush(p->mp_fld_rst_ddr4);	/* Reset DDR PLL */
+			nthw_field_clr_flush(p->mp_fld_rst_ddr4);	/* Reset DDR PLL */
+			retrycount--;
+			timeout = 80000;/* Increase timeout for second attempt to 8 sec. */
+		}
+	}
+
+	NT_LOG(DBG, NTHW, "%s: Waiting for DDR4 MMCM to lock\n", p_adapter_id_str);
+	locked = nthw_field_wait_set_any32(p->mp_fld_stat_ddr4_mmcm_locked, -1, -1);
+
+	if (locked != 0) {
+		NT_LOG(ERR, NTHW, "%s: Waiting for DDR4 MMCM to lock failed (%d)\n",
+			p_adapter_id_str, locked);
+		return -1;
+	}
+
+	if (true && p->mp_fld_stat_tsm_ref_mmcm_locked) {
+		NT_LOG(DBG, NTHW, "%s: Waiting for TSM REF MMCM to lock\n", p_adapter_id_str);
+		locked = nthw_field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked, -1, -1);
+
+		if (locked != 0) {
+			NT_LOG(ERR, NTHW, "%s: Waiting for TSM REF MMCM to lock failed (%d)\n",
+				p_adapter_id_str, locked);
+			return -1;
+		}
+	}
+
+	/* 10: Clear all MMCM/PLL lock sticky bits before testing them */
+	NT_LOG(DBG, NTHW, "%s: Clear sticky MMCM unlock bits\n", p_adapter_id_str);
+	nthw_field_update_register(p->mp_fld_sticky_ptp_mmcm_unlocked);
+	/* Clear all sticky bits */
+	nthw_field_set_flush(p->mp_fld_sticky_ptp_mmcm_unlocked);
+	nthw_field_set_flush(p->mp_fld_sticky_ts_mmcm_unlocked);
+	nthw_field_set_flush(p->mp_fld_sticky_ddr4_mmcm_unlocked);
+	nthw_field_set_flush(p->mp_fld_sticky_ddr4_pll_unlocked);
+	nthw_field_set_flush(p->mp_fld_sticky_core_mmcm_unlocked);
+
+	if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked)
+		nthw_field_set_flush(p->mp_fld_sticky_tsm_ref_mmcm_unlocked);
+
+	if (p->mp_fld_sticky_pci_sys_mmcm_unlocked)
+		nthw_field_set_flush(p->mp_fld_sticky_pci_sys_mmcm_unlocked);
+
+	/* 11: Ensure sticky bits are not unlocked except PTP MMCM and TS MMCM */
+	if (nthw_field_get_updated(p->mp_fld_sticky_ddr4_mmcm_unlocked)) {
+		NT_LOG(ERR, NTHW, "%s: get_sticky_ddr4_mmcm_unlocked() returned true\n",
+			p_adapter_id_str);
+	}
+
+	if (nthw_field_get_updated(p->mp_fld_sticky_ddr4_pll_unlocked)) {
+		NT_LOG(ERR, NTHW, "%s: get_sticky_ddr4_pll_unlocked() returned true\n",
+			p_adapter_id_str);
+	}
+
+	return 0;
+}
+
+/*
+ * Wait for SDRAM controller has been calibrated - On some adapters we have seen
+ * calibration time of 2.3 seconds
+ */
+static int nthw_fpga_rst_nt200a0x_wait_sdc_calibrated(nthw_fpga_t *p_fpga,
+	const struct nthw_fpga_rst_nt200a0x *p)
+{
+	const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+	nthw_sdc_t *p_nthw_sdc = NULL;
+	const int n_retry_cnt_max = 5;
+	int n_retry_cnt;
+	int res;
+
+	res = nthw_sdc_init(NULL, p_fpga, 0);	/* probe for module */
+
+	if (res == 0) {
+		p_nthw_sdc = nthw_sdc_new();
+
+		if (p_nthw_sdc) {
+			res = nthw_sdc_init(p_nthw_sdc, p_fpga, 0);
+
+			if (res) {
+				NT_LOG_DBGX(ERR, NTHW, "%s: SDC init failed: res=%d\n",
+					p_adapter_id_str, res);
+				nthw_sdc_delete(p_nthw_sdc);
+				p_nthw_sdc = NULL;
+				return -1;
+			}
+
+		} else {
+			nthw_sdc_delete(p_nthw_sdc);
+			p_nthw_sdc = NULL;
+		}
+
+	} else {
+		NT_LOG(DBG, NTHW, "%s: No SDC found\n", p_adapter_id_str);
+	}
+
+	n_retry_cnt = 0;
+	res = -1;
+
+	while ((res != 0) && (n_retry_cnt <= n_retry_cnt_max)) {
+		/* wait until DDR4 PLL LOCKED */
+		res = nthw_fpga_rst_nt200a0x_wait_ddr4_pll_locked(p_fpga, p);
+
+		if (res == 0) {
+			if (p_nthw_sdc) {
+				/*
+				 * Wait for SDRAM controller has been calibrated
+				 * On some adapters we have seen calibration time of 2.3 seconds
+				 */
+				NT_LOG(DBG, NTHW, "%s: Waiting for SDRAM to calibrate\n",
+					p_adapter_id_str);
+				res = nthw_sdc_wait_states(p_nthw_sdc, 10000, 1000);
+				{
+					uint64_t n_result_mask;
+					int n_state_code =
+						nthw_sdc_get_states(p_nthw_sdc, &n_result_mask);
+					(void)n_state_code;
+					NT_LOG(DBG, NTHW,
+						"%s: SDRAM state=0x%08lX state_code=%d retry=%d code=%d\n",
+						p_adapter_id_str, n_result_mask, n_state_code,
+						n_retry_cnt, res);
+				}
+
+				if (res == 0)
+					break;
+			}
+
+			if (n_retry_cnt >= n_retry_cnt_max) {
+				uint64_t n_result_mask;
+				int n_state_code = nthw_sdc_get_states(p_nthw_sdc, &n_result_mask);
+				(void)n_state_code;
+
+				NT_LOG(DBG, NTHW,
+					"%s: SDRAM state=0x%08lX state_code=%d retry=%d code=%d\n",
+					p_adapter_id_str, n_result_mask, n_state_code, n_retry_cnt,
+					res);
+
+				if (res != 0) {
+					NT_LOG(ERR, NTHW,
+						"%s: Timeout waiting for SDRAM controller calibration\n",
+						p_adapter_id_str);
+				}
+			}
+		}
+
+		/*
+		 * SDRAM controller is not calibrated with DDR4 ram blocks:
+		 * reset DDR and perform calibration retry
+		 */
+		nthw_field_set_flush(p->mp_fld_rst_ddr4);	/* Reset DDR PLL */
+		nt_os_wait_usec(100);
+		nthw_field_clr_flush(p->mp_fld_rst_ddr4);
+
+		n_retry_cnt++;
+	}
+
+	nthw_sdc_delete(p_nthw_sdc);
+
+	return res;
+}
+
+static int nthw_fpga_rst_nt200a0x_reset(nthw_fpga_t *p_fpga,
+	const struct nthw_fpga_rst_nt200a0x *p)
+{
+	const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+	const fpga_info_t *const p_fpga_info = p_fpga->p_fpga_info;
+
+	const int n_fpga_product_id = p->mn_fpga_product_id;
+	const int n_fpga_version = p->mn_fpga_version;
+	const int n_fpga_revision = p->mn_fpga_revision;
+	const int n_hw_id = p_fpga_info->nthw_hw_info.hw_id;
+	int locked;
+	int res = -1;
+
+	NT_LOG_DBGX(DEBUG, NTHW, "%s: FPGA reset sequence: FPGA %04d-%02d-%02d @ HWId%d\n",
+		p_adapter_id_str, n_fpga_product_id, n_fpga_version, n_fpga_revision,
+		n_hw_id);
+	assert(n_fpga_product_id == p_fpga->mn_product_id);
+
+	/*
+	 * Reset all domains / modules except peripherals
+	 * Set default reset values to ensure that all modules are reset correctly
+	 * no matter if nic has been powercycled or ntservice has been reloaded
+	 */
+
+	/*
+	 * reset to defaults
+	 * 1: Reset all domains
+	 */
+	NT_LOG(DBG, NTHW, "%s: RST defaults\n", p_adapter_id_str);
+
+	nthw_field_update_register(p->mp_fld_rst_sys);
+	nthw_field_set_flush(p->mp_fld_rst_sys);
+
+	if (p->mp_fld_rst_tmc)
+		nthw_field_set_flush(p->mp_fld_rst_tmc);
+
+	nthw_field_set_flush(p->mp_fld_rst_rpp);
+	nthw_field_set_flush(p->mp_fld_rst_ddr4);	/* 0x07 3 banks */
+	nthw_field_set_flush(p->mp_fld_rst_sdc);
+
+	/* Reset port 0 and 1 in the following registers: */
+	nthw_field_set_flush(p->mp_fld_rst_phy);/* 0x03 2 ports */
+
+	if (p->mp_fld_rst_mac_rx)
+		nthw_field_set_flush(p->mp_fld_rst_mac_rx);	/* 0x03 2 ports */
+
+	if (p->mp_fld_rst_mac_tx)
+		nthw_field_set_flush(p->mp_fld_rst_mac_tx);	/* 0x03 2 ports */
+
+	if (p->mp_fld_rst_pcs_rx)
+		nthw_field_set_flush(p->mp_fld_rst_pcs_rx);	/* 0x03 2 ports */
+
+	if (p->mp_fld_rst_serdes_rx)
+		nthw_field_set_flush(p->mp_fld_rst_serdes_rx);	/* 0x03 2 ports */
+
+	if (p->mp_fld_rst_serdes_rx_datapath) {
+		nthw_field_set_flush(p->mp_fld_rst_serdes_rx_datapath);
+		nthw_field_clr_flush(p->mp_fld_rst_serdes_rx);
+	}
+
+	if (p->mp_fld_rst_serdes_tx)
+		nthw_field_set_flush(p->mp_fld_rst_serdes_tx);
+
+	nthw_field_set_flush(p->mp_fld_rst_ptp);
+	nthw_field_set_flush(p->mp_fld_rst_ts);
+	nthw_field_set_flush(p->mp_fld_rst_sys_mmcm);
+	nthw_field_set_flush(p->mp_fld_rst_core_mmcm);
+	nthw_field_set_flush(p->mp_fld_rst_ptp_mmcm);
+	nthw_field_set_flush(p->mp_fld_rst_ts_mmcm);
+
+	if (true && p->mp_fld_rst_tsm_ref_mmcm)
+		nthw_field_set_flush(p->mp_fld_rst_tsm_ref_mmcm);
+
+	/* Write all changes to register */
+	nthw_field_flush_register(p->mp_fld_rst_sys);
+
+	/*
+	 * 2: Force use of 50 MHz reference clock for timesync;
+	 * NOTE: From 9508-05-18 this is a 20 MHz clock
+	 */
+	NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL OVERRIDE\n", p_adapter_id_str);
+	nthw_field_update_register(p->mp_fld_ctrl_ts_clk_sel_override);
+	nthw_field_set_flush(p->mp_fld_ctrl_ts_clk_sel_override);
+
+	NT_LOG(DBG, NTHW, "%s: Setting TS CLK SEL\n", p_adapter_id_str);
+	nthw_field_update_register(p->mp_fld_ctrl_ts_clk_sel);
+	nthw_field_set_flush(p->mp_fld_ctrl_ts_clk_sel);
+
+	/* 4: De-assert sys reset, CORE and SYS MMCM resets */
+	NT_LOG(DBG, NTHW, "%s: De-asserting SYS, CORE and SYS MMCM resets\n", p_adapter_id_str);
+	nthw_field_update_register(p->mp_fld_rst_sys);
+	nthw_field_clr_flush(p->mp_fld_rst_sys);
+	nthw_field_clr_flush(p->mp_fld_rst_sys_mmcm);
+	nthw_field_clr_flush(p->mp_fld_rst_core_mmcm);
+
+	/* 5: wait until CORE MMCM and SYS MMCM are LOCKED */
+	NT_LOG(DBG, NTHW, "%s: Waiting for SYS MMCM to lock\n", p_adapter_id_str);
+	locked = nthw_field_wait_set_any32(p->mp_fld_stat_sys_mmcm_locked, -1, -1);
+
+	if (locked != 0) {
+		NT_LOG(ERR, NTHW, "%s: Waiting for SYS MMCM to lock failed (%d)\n",
+			p_adapter_id_str, locked);
+	}
+
+	NT_LOG(DBG, NTHW, "%s: Waiting for CORE MMCM to lock\n", p_adapter_id_str);
+	locked = nthw_field_wait_set_any32(p->mp_fld_stat_core_mmcm_locked, -1, -1);
+
+	if (locked != 0) {
+		NT_LOG(ERR, NTHW, "%s: Waiting for CORE MMCM to lock failed (%d)\n",
+			p_adapter_id_str, locked);
+	}
+
+	/*
+	 * RAC RAB bus "flip/flip" reset second stage - new impl (ref RMT#37020)
+	 * RAC/RAB init - SYS/CORE MMCM is locked - pull the remaining RAB buses out of reset
+	 */
+	{
+		nthw_rac_t *p_nthw_rac = p_fpga_info->mp_nthw_rac;
+		NT_LOG(DBG, NTHW, "%s: De-asserting remaining RAB buses\n", p_adapter_id_str);
+		nthw_rac_rab_init(p_nthw_rac, 0);
+	}
+
+	if (true && p->mp_fld_rst_tsm_ref_mmcm) {
+		NT_LOG(DBG, NTHW, "%s: De-asserting TSM REF MMCM\n", p_adapter_id_str);
+		nthw_field_clr_flush(p->mp_fld_rst_tsm_ref_mmcm);
+
+		if (p->mp_fld_stat_tsm_ref_mmcm_locked) {
+			NT_LOG(DBG, NTHW, "%s: Waiting for TSM REF MMCM to lock\n",
+				p_adapter_id_str);
+			locked = nthw_field_wait_set_any32(p->mp_fld_stat_tsm_ref_mmcm_locked, -1,
+					-1);
+
+			if (locked != 0) {
+				NT_LOG(ERR, NTHW,
+					"%s: Waiting for TSM REF MMCM to lock failed (%d)\n",
+					p_adapter_id_str, locked);
+			}
+		}
+	}
+
+	NT_LOG(DBG, NTHW, "%s: De-asserting all PHY resets\n", p_adapter_id_str);
+	nthw_field_update_register(p->mp_fld_rst_phy);
+	nthw_field_clr_flush(p->mp_fld_rst_phy);
+
+	/*
+	 * 8: De-assert reset for remaining domains/modules resets except
+	 * TS, PTP, PTP_MMCM and TS_MMCM
+	 */
+	NT_LOG(DBG, NTHW, "%s: De-asserting TMC RST\n", p_adapter_id_str);
+
+	if (p->mp_fld_rst_tmc) {
+		nthw_field_update_register(p->mp_fld_rst_tmc);
+		nthw_field_clr_flush(p->mp_fld_rst_tmc);
+	}
+
+	NT_LOG(DBG, NTHW, "%s: De-asserting RPP RST\n", p_adapter_id_str);
+	nthw_field_update_register(p->mp_fld_rst_rpp);
+	nthw_field_clr_flush(p->mp_fld_rst_rpp);
+
+	NT_LOG(DBG, NTHW, "%s: De-asserting DDR4 RST\n", p_adapter_id_str);
+	nthw_field_update_register(p->mp_fld_rst_ddr4);
+	nthw_field_clr_flush(p->mp_fld_rst_ddr4);
+
+	NT_LOG(DBG, NTHW, "%s: De-asserting SDC RST\n", p_adapter_id_str);
+	nthw_field_update_register(p->mp_fld_rst_sdc);
+	nthw_field_clr_flush(p->mp_fld_rst_sdc);
+
+	/* NOTE: 9522 implements PHY10G_QPLL reset and lock at this stage in mac_rx_rst() */
+	NT_LOG(DBG, NTHW, "%s: De-asserting MAC RX RST\n", p_adapter_id_str);
+
+	if (p->mp_fld_rst_mac_rx) {
+		nthw_field_update_register(p->mp_fld_rst_mac_rx);
+		nthw_field_clr_flush(p->mp_fld_rst_mac_rx);
+	}
+
+	/* await until DDR4 PLL LOCKED and SDRAM controller has been calibrated */
+	res = nthw_fpga_rst_nt200a0x_wait_sdc_calibrated(p_fpga, p);
+
+	if (res) {
+		NT_LOG(ERR, NTHW,
+			"%s: nthw_fpga_rst_nt200a0x_wait_sdc_calibrated() returned true\n",
+			p_adapter_id_str);
+		return -1;
+	}
+
+	if (nthw_field_get_updated(p->mp_fld_sticky_core_mmcm_unlocked)) {
+		NT_LOG(ERR, NTHW, "%s: get_sticky_core_mmcm_unlocked() returned true\n",
+			p_adapter_id_str);
+		return -1;
+	}
+
+	if (p->mp_fld_sticky_pci_sys_mmcm_unlocked &&
+		nthw_field_get_updated(p->mp_fld_sticky_pci_sys_mmcm_unlocked)) {
+		NT_LOG(ERR, NTHW, "%s: get_sticky_pci_sys_mmcm_unlocked() returned true\n",
+			p_adapter_id_str);
+		return -1;
+	}
+
+	/*
+	 * Timesync/PTP reset sequence
+	 * De-assert TS_MMCM reset
+	 */
+	NT_LOG(DBG, NTHW, "%s: De-asserting TS MMCM RST\n", p_adapter_id_str);
+	nthw_field_clr_flush(p->mp_fld_rst_ts_mmcm);
+
+	/* Wait until TS_MMCM LOCKED (NT_RAB0_REG_P9508_RST9508_STAT_TS_MMCM_LOCKED=1); */
+	NT_LOG(DBG, NTHW, "%s: Waiting for TS MMCM to lock\n", p_adapter_id_str);
+	locked = nthw_field_wait_set_any32(p->mp_fld_stat_ts_mmcm_locked, -1, -1);
+
+	if (locked != 0) {
+		NT_LOG(ERR, NTHW, "%s: Waiting for TS MMCM to lock failed (%d)\n",
+			p_adapter_id_str, locked);
+	}
+
+	NT_LOG(DBG, NTHW, "%s: Calling clear_sticky_mmcm_unlock_bits()\n", p_adapter_id_str);
+	nthw_field_update_register(p->mp_fld_sticky_ptp_mmcm_unlocked);
+	/* Clear all sticky bits */
+	nthw_field_set_flush(p->mp_fld_sticky_ptp_mmcm_unlocked);
+	nthw_field_set_flush(p->mp_fld_sticky_ts_mmcm_unlocked);
+	nthw_field_set_flush(p->mp_fld_sticky_ddr4_mmcm_unlocked);
+	nthw_field_set_flush(p->mp_fld_sticky_ddr4_pll_unlocked);
+	nthw_field_set_flush(p->mp_fld_sticky_core_mmcm_unlocked);
+
+	if (p->mp_fld_sticky_tsm_ref_mmcm_unlocked)
+		nthw_field_set_flush(p->mp_fld_sticky_tsm_ref_mmcm_unlocked);
+
+	if (p->mp_fld_sticky_pci_sys_mmcm_unlocked)
+		nthw_field_set_flush(p->mp_fld_sticky_pci_sys_mmcm_unlocked);
+
+	/* De-assert TS reset bit */
+	NT_LOG(DBG, NTHW, "%s: De-asserting TS RST\n", p_adapter_id_str);
+	nthw_field_clr_flush(p->mp_fld_rst_ts);
+
+	if (nthw_field_get_updated(p->mp_fld_sticky_ts_mmcm_unlocked)) {
+		NT_LOG(ERR, NTHW, "%s: get_sticky_ts_mmcm_unlocked() returned true\n",
+			p_adapter_id_str);
+		return -1;
+	}
+
+	if (nthw_field_get_updated(p->mp_fld_sticky_ddr4_mmcm_unlocked)) {
+		NT_LOG(ERR, NTHW, "%s: get_sticky_ddr4_mmcm_unlocked() returned true\n",
+			p_adapter_id_str);
+		return -1;
+	}
+
+	if (nthw_field_get_updated(p->mp_fld_sticky_ddr4_pll_unlocked)) {
+		NT_LOG(ERR, NTHW, "%s: get_sticky_ddr4_pll_unlocked() returned true\n",
+			p_adapter_id_str);
+		return -1;
+	}
+
+	if (nthw_field_get_updated(p->mp_fld_sticky_core_mmcm_unlocked)) {
+		NT_LOG(ERR, NTHW, "%s: get_sticky_core_mmcm_unlocked() returned true\n",
+			p_adapter_id_str);
+		return -1;
+	}
+
+	if (p->mp_fld_sticky_pci_sys_mmcm_unlocked &&
+		nthw_field_get_updated(p->mp_fld_sticky_pci_sys_mmcm_unlocked)) {
+		NT_LOG(ERR, NTHW, "%s: get_sticky_pci_sys_mmcm_unlocked() returned true\n",
+			p_adapter_id_str);
+		return -1;
+	}
+
+
+	if (false) {
+		/* Deassert PTP_MMCM */
+		NT_LOG(DBG, NTHW, "%s: De-asserting PTP MMCM RST\n", p_adapter_id_str);
+		nthw_field_clr_flush(p->mp_fld_rst_ptp_mmcm);
+
+		/* Switch PTP MMCM sel to use ptp clk */
+		NT_LOG(DBG, NTHW, "%s: Setting PTP MMCM CLK SEL\n", p_adapter_id_str);
+		nthw_field_set_flush(p->mp_fld_ctrl_ptp_mmcm_clk_sel);
+
+		/* Wait until TS_MMCM LOCKED (NT_RAB0_REG_P9508_RST9508_STAT_TS_MMCM_LOCKED=1); */
+		NT_LOG(DBG, NTHW, "%s: Waiting for TS MMCM to re-lock\n", p_adapter_id_str);
+		locked = nthw_field_wait_set_any32(p->mp_fld_stat_ts_mmcm_locked, -1, -1);
+
+		if (locked != 0) {
+			NT_LOG(ERR, NTHW, "%s: Waiting for TS MMCM to re-lock failed (%d)\n",
+				p_adapter_id_str, locked);
+		}
+	}
+
+	NT_LOG(DBG, NTHW, "%s: De-asserting PTP RST\n", p_adapter_id_str);
+	nthw_field_clr_flush(p->mp_fld_rst_ptp);
+
+	/* POWER staging introduced in 9508-05-09 and always for 9512 */
+	if (n_fpga_product_id == 9508 && n_fpga_version <= 5 && n_fpga_revision <= 8) {
+		NT_LOG(DBG, NTHW, "%s: No power staging\n", p_adapter_id_str);
+
+	} else {
+		NT_LOG(DBG, NTHW, "%s: Staging power\n", p_adapter_id_str);
+		nthw_field_set_flush(p->mp_fld_power_pu_phy);	/* PHY power up */
+		nthw_field_clr_flush(p->mp_fld_power_pu_nseb);	/* NSEB power down */
+	}
+
+	NT_LOG_DBGX(DEBUG, NTHW, "%s END\n", p_adapter_id_str);
+
+	return 0;
+}
+
+static int nthw_fpga_rst_nt200a0x_init(struct fpga_info_s *p_fpga_info,
+	struct nthw_fpga_rst_nt200a0x *p_rst)
+{
+	assert(p_fpga_info);
+
+	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+	int res = -1;
+	int n_si_labs_clock_synth_model = -1;
+	uint8_t n_si_labs_clock_synth_i2c_addr = 0;
+	nthw_fpga_t *p_fpga = NULL;
+
+	p_fpga = p_fpga_info->mp_fpga;
+
+	NT_LOG_DBGX(DEBUG, NTHW, "%s: RAB init/reset\n", p_adapter_id_str);
+	nthw_rac_rab_reset(p_fpga_info->mp_nthw_rac);
+	nthw_rac_rab_setup(p_fpga_info->mp_nthw_rac);
+
+	res = nthw_fpga_iic_scan(p_fpga, 0, 0);
+	res = nthw_fpga_iic_scan(p_fpga, 2, 3);
+
+	/*
+	 * Detect clock synth model
+	 * check for NT200A02/NT200A01 HW-build2 - most commonly seen
+	 */
+	n_si_labs_clock_synth_i2c_addr = si5340_u23_i2c_addr_7bit;
+	n_si_labs_clock_synth_model =
+		nthw_fpga_silabs_detect(p_fpga, 0, n_si_labs_clock_synth_i2c_addr, 1);
+
+	if (n_si_labs_clock_synth_model == -1) {
+		/* check for old NT200A01 HW-build1 */
+		n_si_labs_clock_synth_i2c_addr = si5338_u23_i2c_addr_7bit;
+		n_si_labs_clock_synth_model =
+			nthw_fpga_silabs_detect(p_fpga, 0, n_si_labs_clock_synth_i2c_addr, 255);
+
+		if (n_si_labs_clock_synth_model == -1) {
+			NT_LOG(ERR, NTHW, "%s: Failed to detect clock synth model (%d)\n",
+				p_adapter_id_str, n_si_labs_clock_synth_model);
+			return -1;
+		}
+	}
+
+	p_rst->mn_si_labs_clock_synth_model = n_si_labs_clock_synth_model;
+	p_rst->mn_hw_id = p_fpga_info->nthw_hw_info.hw_id;
+
+	return res;
+}
+
+static struct rst_nt200a0x_ops rst_nt200a0x_ops = { .nthw_fpga_rst_nt200a0x_init =
+		nthw_fpga_rst_nt200a0x_init,
+		.nthw_fpga_rst_nt200a0x_reset =
+			nthw_fpga_rst_nt200a0x_reset
+};
+
+void rst_nt200a0x_ops_init(void)
+{
+	NT_LOG(INF, NTHW, "RST NT200A0X OPS INIT\n");
+	register_rst_nt200a0x_ops(&rst_nt200a0x_ops);
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga.c b/drivers/net/ntnic/nthw/core/nthw_fpga.c
index 98d29744cb..1650bb8a5c 100644
--- a/drivers/net/ntnic/nthw/core/nthw_fpga.c
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga.c
@@ -65,6 +65,88 @@ int nthw_fpga_get_param_info(struct fpga_info_s *p_fpga_info, nthw_fpga_t *p_fpg
 	return 0;
 }
 
+int nthw_fpga_iic_scan(nthw_fpga_t *p_fpga, const int n_instance_no_begin,
+	const int n_instance_no_end)
+{
+	int i;
+
+	assert(n_instance_no_begin <= n_instance_no_end);
+
+	for (i = n_instance_no_begin; i <= n_instance_no_end; i++) {
+		nthw_iic_t *p_nthw_iic = nthw_iic_new();
+
+		if (p_nthw_iic) {
+			const int rc = nthw_iic_init(p_nthw_iic, p_fpga, i, 8);
+
+			if (rc == 0) {
+				nthw_iic_set_retry_params(p_nthw_iic, -1, 100, 100, 3, 3);
+				nthw_iic_scan(p_nthw_iic);
+			}
+
+			nthw_iic_delete(p_nthw_iic);
+			p_nthw_iic = NULL;
+		}
+	}
+
+	return 0;
+}
+
+int nthw_fpga_silabs_detect(nthw_fpga_t *p_fpga, const int n_instance_no, const int n_dev_addr,
+	const int n_page_reg_addr)
+{
+	const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+	(void)p_adapter_id_str;
+	uint64_t ident = -1;
+	int res = -1;
+
+	nthw_iic_t *p_nthw_iic = nthw_iic_new();
+
+	if (p_nthw_iic) {
+		uint8_t data;
+		uint8_t a_silabs_ident[8];
+		nthw_iic_init(p_nthw_iic, p_fpga, n_instance_no, 8);
+
+		data = 0;
+		/* switch to page 0 */
+		nthw_iic_write_data(p_nthw_iic, (uint8_t)n_dev_addr, (uint8_t)n_page_reg_addr, 1,
+			&data);
+		res = nthw_iic_read_data(p_nthw_iic, (uint8_t)n_dev_addr, 0x00,
+				sizeof(a_silabs_ident), a_silabs_ident);
+
+		if (res == 0) {
+			int i;
+
+			for (i = 0; i < (int)sizeof(a_silabs_ident); i++) {
+				ident <<= 8;
+				ident |= a_silabs_ident[i];
+			}
+		}
+
+		nthw_iic_delete(p_nthw_iic);
+		p_nthw_iic = NULL;
+
+		/* Conclude SiLabs part */
+		if (res == 0) {
+			if (a_silabs_ident[3] == 0x53) {
+				if (a_silabs_ident[2] == 0x40)
+					res = 5340;
+
+				else if (a_silabs_ident[2] == 0x41)
+					res = 5341;
+
+			} else if (a_silabs_ident[2] == 38) {
+				res = 5338;
+
+			} else {
+				res = -1;
+			}
+		}
+	}
+
+	NT_LOG(DBG, NTHW, "%s: %016" PRIX64 ": %d\n", p_adapter_id_str, ident, res);
+	return res;
+}
+
 int nthw_fpga_init(struct fpga_info_s *p_fpga_info)
 {
 	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
diff --git a/drivers/net/ntnic/nthw/core/nthw_sdc.c b/drivers/net/ntnic/nthw/core/nthw_sdc.c
new file mode 100644
index 0000000000..7666af7e5a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_sdc.c
@@ -0,0 +1,176 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_sdc.h"
+
+nthw_sdc_t *nthw_sdc_new(void)
+{
+	nthw_sdc_t *p = malloc(sizeof(nthw_sdc_t));
+
+	if (p)
+		memset(p, 0, sizeof(nthw_sdc_t));
+
+	return p;
+}
+
+void nthw_sdc_delete(nthw_sdc_t *p)
+{
+	if (p) {
+		memset(p, 0, sizeof(nthw_sdc_t));
+		free(p);
+	}
+}
+
+int nthw_sdc_init(nthw_sdc_t *p, nthw_fpga_t *p_fpga, int n_instance)
+{
+	const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+	nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_SDC, n_instance);
+
+	if (p == NULL)
+		return mod == NULL ? -1 : 0;
+
+	if (mod == NULL) {
+		NT_LOG(ERR, NTHW, "%s: SDC %d: no such instance\n", p_adapter_id_str, n_instance);
+		return -1;
+	}
+
+	p->mp_fpga = p_fpga;
+	p->mn_instance = n_instance;
+	p->mp_mod_sdc = mod;
+
+	{
+		nthw_register_t *p_reg;
+
+		p_reg = nthw_module_get_register(p->mp_mod_sdc, SDC_CTRL);
+		p->mp_fld_ctrl_init = nthw_register_get_field(p_reg, SDC_CTRL_INIT);
+		p->mp_fld_ctrl_run_test = nthw_register_get_field(p_reg, SDC_CTRL_RUN_TEST);
+		p->mp_fld_ctrl_stop_client = nthw_register_get_field(p_reg, SDC_CTRL_STOP_CLIENT);
+		p->mp_fld_ctrl_test_enable = nthw_register_get_field(p_reg, SDC_CTRL_TEST_EN);
+
+		p_reg = nthw_module_get_register(p->mp_mod_sdc, SDC_STAT);
+		p->mp_fld_stat_calib = nthw_register_get_field(p_reg, SDC_STAT_CALIB);
+		p->mp_fld_stat_cell_cnt_stopped =
+			nthw_register_get_field(p_reg, SDC_STAT_CELL_CNT_STOPPED);
+		p->mp_fld_stat_err_found = nthw_register_get_field(p_reg, SDC_STAT_ERR_FOUND);
+		p->mp_fld_stat_init_done = nthw_register_get_field(p_reg, SDC_STAT_INIT_DONE);
+		p->mp_fld_stat_mmcm_lock = nthw_register_get_field(p_reg, SDC_STAT_MMCM_LOCK);
+		p->mp_fld_stat_pll_lock = nthw_register_get_field(p_reg, SDC_STAT_PLL_LOCK);
+		p->mp_fld_stat_resetting = nthw_register_get_field(p_reg, SDC_STAT_RESETTING);
+
+		p_reg = nthw_module_get_register(p->mp_mod_sdc, SDC_CELL_CNT);
+		p->mp_fld_cell_cnt = nthw_register_get_field(p_reg, SDC_CELL_CNT_CELL_CNT);
+
+		p_reg = nthw_module_get_register(p->mp_mod_sdc, SDC_CELL_CNT_PERIOD);
+		p->mp_fld_cell_cnt_period =
+			nthw_register_get_field(p_reg, SDC_CELL_CNT_PERIOD_CELL_CNT_PERIOD);
+
+		p_reg = nthw_module_get_register(p->mp_mod_sdc, SDC_FILL_LVL);
+		p->mp_fld_fill_level = nthw_register_get_field(p_reg, SDC_FILL_LVL_FILL_LVL);
+
+		p_reg = nthw_module_get_register(p->mp_mod_sdc, SDC_MAX_FILL_LVL);
+		p->mp_fld_max_fill_level =
+			nthw_register_get_field(p_reg, SDC_MAX_FILL_LVL_MAX_FILL_LVL);
+	}
+	return 0;
+}
+
+int nthw_sdc_get_states(nthw_sdc_t *p, uint64_t *pn_result_mask)
+{
+	int n_err_cnt = 0;
+	uint64_t n_mask = 0;
+	uint32_t val;
+	uint32_t val_mask;
+	int n_val_width;
+
+	if (!p || !pn_result_mask)
+		return -1;
+
+	val = nthw_field_get_updated(p->mp_fld_stat_calib);
+	n_val_width = nthw_field_get_bit_width(p->mp_fld_stat_calib);
+	val_mask = ((1 << n_val_width) - 1);
+	n_mask = (n_mask << n_val_width) | (val & val_mask);
+
+	if (val != val_mask)
+		n_err_cnt++;
+
+	val = nthw_field_get_updated(p->mp_fld_stat_init_done);
+	n_val_width = nthw_field_get_bit_width(p->mp_fld_stat_init_done);
+	val_mask = ((1 << n_val_width) - 1);
+	n_mask = (n_mask << n_val_width) | (val & val_mask);
+
+	if (val != val_mask)
+		n_err_cnt++;
+
+	val = nthw_field_get_updated(p->mp_fld_stat_mmcm_lock);
+	n_val_width = nthw_field_get_bit_width(p->mp_fld_stat_mmcm_lock);
+	val_mask = ((1 << n_val_width) - 1);
+	n_mask = (n_mask << n_val_width) | (val & val_mask);
+
+	if (val != val_mask)
+		n_err_cnt++;
+
+	val = nthw_field_get_updated(p->mp_fld_stat_pll_lock);
+	n_val_width = nthw_field_get_bit_width(p->mp_fld_stat_pll_lock);
+	val_mask = ((1 << n_val_width) - 1);
+	n_mask = (n_mask << n_val_width) | (val & val_mask);
+
+	if (val != val_mask)
+		n_err_cnt++;
+
+	val = nthw_field_get_updated(p->mp_fld_stat_resetting);
+	n_val_width = nthw_field_get_bit_width(p->mp_fld_stat_resetting);
+	val_mask = ((1 << n_val_width) - 1);
+	n_mask = (n_mask << n_val_width) | (val & val_mask);
+
+	if (val != 0)
+		n_err_cnt++;
+
+	if (pn_result_mask)
+		*pn_result_mask = n_mask;
+
+	return n_err_cnt;	/* 0 = all ok */
+}
+
+int nthw_sdc_wait_states(nthw_sdc_t *p, const int n_poll_iterations, const int n_poll_interval)
+{
+	int res;
+	int n_err_cnt = 0;
+
+	res = nthw_field_wait_set_all32(p->mp_fld_stat_calib, n_poll_iterations, n_poll_interval);
+
+	if (res)
+		n_err_cnt++;
+
+	res = nthw_field_wait_set_all32(p->mp_fld_stat_init_done, n_poll_iterations,
+			n_poll_interval);
+
+	if (res)
+		n_err_cnt++;
+
+	res = nthw_field_wait_set_all32(p->mp_fld_stat_mmcm_lock, n_poll_iterations,
+			n_poll_interval);
+
+	if (res)
+		n_err_cnt++;
+
+	res = nthw_field_wait_set_all32(p->mp_fld_stat_pll_lock, n_poll_iterations,
+			n_poll_interval);
+
+	if (res)
+		n_err_cnt++;
+
+	res = nthw_field_wait_clr_all32(p->mp_fld_stat_resetting, n_poll_iterations,
+			n_poll_interval);
+
+	if (res)
+		n_err_cnt++;
+
+	return n_err_cnt;	/* 0 = all ok */
+}
diff --git a/drivers/net/ntnic/ntnic_mod_reg.c b/drivers/net/ntnic/ntnic_mod_reg.c
index 006221bbe3..bd0a966be2 100644
--- a/drivers/net/ntnic/ntnic_mod_reg.c
+++ b/drivers/net/ntnic/ntnic_mod_reg.c
@@ -18,3 +18,31 @@ const struct adapter_ops *get_adapter_ops(void)
 		adapter_init();
 	return adapter_ops;
 }
+
+static struct rst_nt200a0x_ops *rst_nt200a0x_ops;
+
+void register_rst_nt200a0x_ops(struct rst_nt200a0x_ops *ops)
+{
+	rst_nt200a0x_ops = ops;
+}
+
+struct rst_nt200a0x_ops *get_rst_nt200a0x_ops(void)
+{
+	if (rst_nt200a0x_ops == NULL)
+		rst_nt200a0x_ops_init();
+	return rst_nt200a0x_ops;
+}
+
+static struct rst9563_ops *rst9563_ops;
+
+void register_rst9563_ops(struct rst9563_ops *ops)
+{
+	rst9563_ops = ops;
+}
+
+struct rst9563_ops *get_rst9563_ops(void)
+{
+	if (rst9563_ops == NULL)
+		rst9563_ops_init();
+	return rst9563_ops;
+}
diff --git a/drivers/net/ntnic/ntnic_mod_reg.h b/drivers/net/ntnic/ntnic_mod_reg.h
index 96fc829399..df8a8b9aca 100644
--- a/drivers/net/ntnic/ntnic_mod_reg.h
+++ b/drivers/net/ntnic/ntnic_mod_reg.h
@@ -11,6 +11,7 @@
 #include "nthw_platform_drv.h"
 #include "nthw_drv.h"
 #include "nt4ga_adapter.h"
+#include "ntnic_nthw_fpga_rst_nt200a0x.h"
 #include "ntos_drv.h"
 
 struct adapter_ops {
@@ -24,5 +25,24 @@ void register_adapter_ops(const struct adapter_ops *ops);
 const struct adapter_ops *get_adapter_ops(void);
 void adapter_init(void);
 
+struct rst_nt200a0x_ops {
+	int (*nthw_fpga_rst_nt200a0x_init)(struct fpga_info_s *p_fpga_info,
+		struct nthw_fpga_rst_nt200a0x *p_rst);
+	int (*nthw_fpga_rst_nt200a0x_reset)(nthw_fpga_t *p_fpga,
+		const struct nthw_fpga_rst_nt200a0x *p);
+};
+
+void register_rst_nt200a0x_ops(struct rst_nt200a0x_ops *ops);
+struct rst_nt200a0x_ops *get_rst_nt200a0x_ops(void);
+void rst_nt200a0x_ops_init(void);
+
+struct rst9563_ops {
+	int (*nthw_fpga_rst9563_init)(struct fpga_info_s *p_fpga_info,
+		struct nthw_fpga_rst_nt200a0x *const p);
+};
+
+void register_rst9563_ops(struct rst9563_ops *ops);
+struct rst9563_ops *get_rst9563_ops(void);
+void rst9563_ops_init(void);
 
 #endif	/* __NTNIC_MOD_REG_H__ */
-- 
2.45.0