DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH v1 00/32] add new adapter NT400D13
@ 2025-02-20 22:03 Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 01/32] net/ntnic: add link agx 100g Serhii Iliushyk
                   ` (32 more replies)
  0 siblings, 33 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen

This patchset adds support for the new adapter NT400D13.

Danylo Vodopianov (23):
  net/ntnic: add link agx 100g
  net/ntnic: add link state machine
  net/ntnic: add rpf and gfg init
  net/ntnic: add agx setup for port
  net/ntnic: add host loopback init
  net/ntnic: add line loopback init
  net/ntnic: add 100 gbps port init
  net/ntnic: add port post init
  net/ntnic: add nim low power API
  net/ntnic: add link handling API
  net/ntnic: add port init to the state machine
  net/ntnic: add port disable API
  net/ntnic: add nt400d13 pcm init
  net/ntnic: add HIF clock test
  net/ntnic: add nt400d13 PRM module init
  net/ntnic: add nt400d13 PRM module reset
  net/ntnic: add SPI v3 support for FPGA
  net/ntnic: add i2cm init
  net/ntnic: add pca init
  net/ntnic: add pcal init
  net/ntnic: add reset PHY init
  net/ntnic: add igam module init
  net/ntnic: init IGAM and config PLL for FPGA

Serhii Iliushyk (9):
  net/ntnic: add minimal initialization new NIC NT400D13
  net/ntnic: add minimal reset FPGA
  net/ntnic: add FPGA modules and registers
  net/ntnic: add setup for fpga reset
  net/ntnic: add default reset setting for NT400D13
  net/ntnic: add DDR calibration to reset stage
  net/ntnic: add PHY ftile reset
  net/ntnic: add clock init
  net/ntnic: revert untrusted loop bound

 doc/guides/nics/ntnic.rst                     |    7 +-
 doc/guides/rel_notes/release_25_03.rst        |    4 +
 drivers/net/ntnic/adapter/nt4ga_adapter.c     |    9 +
 drivers/net/ntnic/include/nt4ga_link.h        |    7 +
 drivers/net/ntnic/include/nthw_gfg.h          |   33 +
 drivers/net/ntnic/include/ntnic_nim.h         |    5 +
 .../include/ntnic_nthw_fpga_rst_nt400dxx.h    |   34 +
 .../link_agx_100g/nt4ga_agx_link_100g.c       | 1029 ++++++
 drivers/net/ntnic/meson.build                 |   16 +
 drivers/net/ntnic/nim/i2c_nim.c               |  158 +-
 drivers/net/ntnic/nim/i2c_nim.h               |    6 +
 ...00D13_U62_Si5332-GM2-RevD-1_V5-Registers.h |  425 +++
 .../net/ntnic/nthw/core/include/nthw_fpga.h   |   10 +
 .../net/ntnic/nthw/core/include/nthw_gmf.h    |    2 +
 .../net/ntnic/nthw/core/include/nthw_hif.h    |    4 +
 .../net/ntnic/nthw/core/include/nthw_i2cm.h   |    3 +
 .../net/ntnic/nthw/core/include/nthw_igam.h   |   40 +
 .../ntnic/nthw/core/include/nthw_pca9532.h    |   25 +
 .../ntnic/nthw/core/include/nthw_pcal6416a.h  |   33 +
 .../nthw/core/include/nthw_pcm_nt400dxx.h     |   40 +
 .../ntnic/nthw/core/include/nthw_phy_tile.h   |  156 +
 .../nthw/core/include/nthw_prm_nt400dxx.h     |   32 +
 .../nthw/core/include/nthw_si5332_si5156.h    |   63 +
 .../net/ntnic/nthw/core/include/nthw_spi_v3.h |  107 +
 .../net/ntnic/nthw/core/include/nthw_spim.h   |   58 +
 .../net/ntnic/nthw/core/include/nthw_spis.h   |   63 +
 .../nthw/core/nt400dxx/nthw_fpga_nt400dxx.c   |  220 ++
 .../core/nt400dxx/reset/nthw_fpga_rst9574.c   |  377 ++
 .../nt400dxx/reset/nthw_fpga_rst_nt400dxx.c   |  427 +++
 drivers/net/ntnic/nthw/core/nthw_fpga.c       |  464 +++
 drivers/net/ntnic/nthw/core/nthw_gfg.c        |  340 ++
 drivers/net/ntnic/nthw/core/nthw_gmf.c        |   41 +
 drivers/net/ntnic/nthw/core/nthw_hif.c        |   92 +
 drivers/net/ntnic/nthw/core/nthw_i2cm.c       |  139 +
 drivers/net/ntnic/nthw/core/nthw_igam.c       |   93 +
 drivers/net/ntnic/nthw/core/nthw_pca9532.c    |   60 +
 drivers/net/ntnic/nthw/core/nthw_pcal6416a.c  |  103 +
 .../net/ntnic/nthw/core/nthw_pcm_nt400dxx.c   |   80 +
 drivers/net/ntnic/nthw/core/nthw_phy_tile.c   | 1242 +++++++
 .../net/ntnic/nthw/core/nthw_prm_nt400dxx.c   |   55 +
 .../net/ntnic/nthw/core/nthw_si5332_si5156.c  |  142 +
 drivers/net/ntnic/nthw/core/nthw_spi_v3.c     |  358 ++
 drivers/net/ntnic/nthw/core/nthw_spim.c       |  113 +
 drivers/net/ntnic/nthw/core/nthw_spis.c       |  121 +
 drivers/net/ntnic/nthw/nthw_drv.h             |   31 +
 drivers/net/ntnic/nthw/nthw_platform.c        |    3 +
 drivers/net/ntnic/nthw/nthw_platform_drv.h    |    2 +
 .../supported/nthw_fpga_9574_055_049_0000.c   | 3124 +++++++++++++++++
 .../nthw/supported/nthw_fpga_instances.c      |    5 +-
 .../nthw/supported/nthw_fpga_instances.h      |    1 +
 .../ntnic/nthw/supported/nthw_fpga_mod_defs.h |   11 +
 .../nthw/supported/nthw_fpga_mod_str_map.c    |   11 +
 .../ntnic/nthw/supported/nthw_fpga_reg_defs.h |   11 +
 .../nthw/supported/nthw_fpga_reg_defs_igam.h  |   32 +
 .../supported/nthw_fpga_reg_defs_pci_ta.h     |   33 +
 .../nthw_fpga_reg_defs_pcm_nt400dxx.h         |   29 +
 .../nthw/supported/nthw_fpga_reg_defs_pdi.h   |   49 +
 .../supported/nthw_fpga_reg_defs_phy_tile.h   |  213 ++
 .../nthw_fpga_reg_defs_prm_nt400dxx.h         |   26 +
 .../nthw/supported/nthw_fpga_reg_defs_rfd.h   |   38 +
 .../supported/nthw_fpga_reg_defs_rst9574.h    |   35 +
 .../nthw/supported/nthw_fpga_reg_defs_spim.h  |   76 +
 .../nthw/supported/nthw_fpga_reg_defs_spis.h  |   51 +
 .../nthw/supported/nthw_fpga_reg_defs_tint.h  |   28 +
 drivers/net/ntnic/ntnic_ethdev.c              |    1 +
 drivers/net/ntnic/ntnic_filter/ntnic_filter.c |    2 +-
 drivers/net/ntnic/ntnic_mod_reg.c             |   47 +
 drivers/net/ntnic/ntnic_mod_reg.h             |   25 +
 68 files changed, 10709 insertions(+), 11 deletions(-)
 create mode 100644 drivers/net/ntnic/include/nthw_gfg.h
 create mode 100644 drivers/net/ntnic/include/ntnic_nthw_fpga_rst_nt400dxx.h
 create mode 100644 drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
 create mode 100644 drivers/net/ntnic/nthw/core/include/NT400D13_U62_Si5332-GM2-RevD-1_V5-Registers.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_igam.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_pca9532.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_prm_nt400dxx.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_spi_v3.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_spim.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_spis.h
 create mode 100644 drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c
 create mode 100644 drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
 create mode 100644 drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_gfg.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_igam.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_pca9532.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcm_nt400dxx.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_phy_tile.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_prm_nt400dxx.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_spi_v3.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_spim.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_spis.c
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_9574_055_049_0000.c
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_igam.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pci_ta.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pcm_nt400dxx.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pdi.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_phy_tile.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_prm_nt400dxx.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_rfd.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_rst9574.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_spim.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_spis.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_tint.h

-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 01/32] net/ntnic: add link agx 100g
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 02/32] net/ntnic: add link state machine Serhii Iliushyk
                   ` (31 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Minimal implementation for link agx 100g was added.
Add support for NT400D13 (Intel Agilex FPGA) link operations.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 drivers/net/ntnic/adapter/nt4ga_adapter.c     |  9 ++++
 .../link_agx_100g/nt4ga_agx_link_100g.c       | 42 +++++++++++++++++++
 drivers/net/ntnic/meson.build                 |  1 +
 drivers/net/ntnic/ntnic_mod_reg.c             | 17 ++++++++
 drivers/net/ntnic/ntnic_mod_reg.h             |  4 ++
 5 files changed, 73 insertions(+)
 create mode 100644 drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c

diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.c b/drivers/net/ntnic/adapter/nt4ga_adapter.c
index fa72dfda8d..fe9d397293 100644
--- a/drivers/net/ntnic/adapter/nt4ga_adapter.c
+++ b/drivers/net/ntnic/adapter/nt4ga_adapter.c
@@ -196,6 +196,15 @@ static int nt4ga_adapter_init(struct adapter_info_s *p_adapter_info)
 
 			res = link_ops->link_init(p_adapter_info, p_fpga);
 			break;
+		case 9574: /* NT400D13 (Intel Agilex FPGA) */
+			link_ops = get_agx_100g_link_ops();
+			if (link_ops == NULL) {
+				NT_LOG(ERR, NTNIC, "NT400D11 100G link module uninitialized");
+				res = -1;
+				break;
+			}
+			res = link_ops->link_init(p_adapter_info, p_fpga);
+			break;
 
 		default:
 			NT_LOG(ERR, NTNIC, "Unsupported FPGA product: %04d",
diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
new file mode 100644
index 0000000000..ad3398500f
--- /dev/null
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -0,0 +1,42 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+#include "i2c_nim.h"
+#include "nt4ga_adapter.h"
+
+#include <string.h>
+#include "ntnic_mod_reg.h"
+#include "nim_defines.h"
+
+static int nt4ga_agx_link_100g_ports_init(struct adapter_info_s *p_adapter_info,
+	nthw_fpga_t *fpga);
+
+/*
+ * Init AGX 100G link ops variables
+ */
+static struct link_ops_s link_agx_100g_ops = {
+	.link_init = nt4ga_agx_link_100g_ports_init,
+};
+
+void link_agx_100g_init(void)
+{
+	register_agx_100g_link_ops(&link_agx_100g_ops);
+}
+
+/*
+ * Initialize all ports
+ * The driver calls this function during initialization (of the driver).
+ */
+int nt4ga_agx_link_100g_ports_init(struct adapter_info_s *p_adapter_info, nthw_fpga_t *fpga)
+{
+	(void)fpga;
+	int res = 0;
+
+	NT_LOG(DBG, NTNIC, "%s: Initializing ports", p_adapter_info->mp_adapter_id_str);
+
+	return res;
+}
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 8ae6817dea..7e4f47b1e6 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -32,6 +32,7 @@ sources = files(
         'adapter/nt4ga_stat/nt4ga_stat.c',
         'dbsconfig/ntnic_dbsconfig.c',
         'link_mgmt/link_100g/nt4ga_link_100g.c',
+        'link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c',
         'link_mgmt/nt4ga_link.c',
         'nim/i2c_nim.c',
         'ntnic_filter/ntnic_filter.c',
diff --git a/drivers/net/ntnic/ntnic_mod_reg.c b/drivers/net/ntnic/ntnic_mod_reg.c
index 658fac72c0..598df08fb7 100644
--- a/drivers/net/ntnic/ntnic_mod_reg.c
+++ b/drivers/net/ntnic/ntnic_mod_reg.c
@@ -69,6 +69,23 @@ const struct link_ops_s *get_100g_link_ops(void)
 	return link_100g_ops;
 }
 
+/*
+ *
+ */
+static struct link_ops_s *link_agx_100g_ops;
+
+void register_agx_100g_link_ops(struct link_ops_s *ops)
+{
+	link_agx_100g_ops = ops;
+}
+
+const struct link_ops_s *get_agx_100g_link_ops(void)
+{
+	if (link_agx_100g_ops == NULL)
+		link_agx_100g_init();
+	return link_agx_100g_ops;
+}
+
 static const struct port_ops *port_ops;
 
 void register_port_ops(const struct port_ops *ops)
diff --git a/drivers/net/ntnic/ntnic_mod_reg.h b/drivers/net/ntnic/ntnic_mod_reg.h
index bddae823c8..3e84beaa62 100644
--- a/drivers/net/ntnic/ntnic_mod_reg.h
+++ b/drivers/net/ntnic/ntnic_mod_reg.h
@@ -144,6 +144,10 @@ void register_100g_link_ops(struct link_ops_s *ops);
 const struct link_ops_s *get_100g_link_ops(void);
 void link_100g_init(void);
 
+void register_agx_100g_link_ops(struct link_ops_s *ops);
+const struct link_ops_s *get_agx_100g_link_ops(void);
+void link_agx_100g_init(void);
+
 struct port_ops {
 	bool (*get_nim_present)(struct adapter_info_s *p, int port);
 
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 02/32] net/ntnic: add link state machine
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 01/32] net/ntnic: add link agx 100g Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 03/32] net/ntnic: add rpf and gfg init Serhii Iliushyk
                   ` (30 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Minimal 100g agx link state machine implementation was added.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 drivers/net/ntnic/include/nt4ga_link.h        |   5 +
 .../link_agx_100g/nt4ga_agx_link_100g.c       | 111 ++++++++++++++++++
 2 files changed, 116 insertions(+)

diff --git a/drivers/net/ntnic/include/nt4ga_link.h b/drivers/net/ntnic/include/nt4ga_link.h
index 8366484830..af7ea4a9f2 100644
--- a/drivers/net/ntnic/include/nt4ga_link.h
+++ b/drivers/net/ntnic/include/nt4ga_link.h
@@ -82,9 +82,14 @@ typedef struct adapter_100g_s {
 	nthw_gpio_phy_t gpio_phy[NUM_ADAPTER_PORTS_MAX];
 } adapter_100g_t;
 
+typedef struct adapter_agx_100g_s {
+	nim_i2c_ctx_t nim_ctx[NUM_ADAPTER_PORTS_MAX];	/* should be the first field */
+} adapter_agx_100g_t;
+
 typedef union adapter_var_s {
 	nim_i2c_ctx_t nim_ctx[NUM_ADAPTER_PORTS_MAX];	/* First field in all the adapters type */
 	adapter_100g_t var100g;
+	adapter_agx_100g_t var_a100g;
 } adapter_var_u;
 
 typedef struct nt4ga_link_s {
diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
index ad3398500f..369b9b601f 100644
--- a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -27,6 +27,106 @@ void link_agx_100g_init(void)
 	register_agx_100g_link_ops(&link_agx_100g_ops);
 }
 
+/*
+ * Link state machine
+ */
+static void *_common_ptp_nim_state_machine(void *data)
+{
+	adapter_info_t *drv = (adapter_info_t *)data;
+	fpga_info_t *fpga_info = &drv->fpga_info;
+	nt4ga_link_t *link_info = &drv->nt4ga_link;
+	nthw_fpga_t *fpga = fpga_info->mp_fpga;
+	const int adapter_no = drv->adapter_no;
+	const int nb_ports = fpga_info->n_phy_ports;
+	uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX];
+	/* link_state_t new_link_state; */
+
+	link_state_t *link_state = link_info->link_state;
+
+	if (!fpga) {
+		NT_LOG(ERR, NTNIC, "%s: fpga is NULL", drv->mp_adapter_id_str);
+		goto NT4GA_LINK_100G_MON_EXIT;
+	}
+
+	assert(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX);
+
+	monitor_task_is_running[adapter_no] = 1;
+	memset(last_lpbk_mode, 0, sizeof(last_lpbk_mode));
+
+	/* Initialize link state */
+	for (int i = 0; i < nb_ports; i++) {
+		link_state[i].link_disabled = true;
+		link_state[i].nim_present = false;
+		link_state[i].lh_nim_absent = true;
+		link_state[i].link_up = false;
+		link_state[i].link_state = NT_LINK_STATE_UNKNOWN;
+		link_state[i].link_state_latched = NT_LINK_STATE_UNKNOWN;
+	}
+
+	if (monitor_task_is_running[adapter_no])
+		NT_LOG(DBG, NTNIC, "%s: link state machine running...", drv->mp_adapter_id_str);
+
+	while (monitor_task_is_running[adapter_no]) {
+		int i;
+
+		for (i = 0; i < nb_ports; i++) {
+			const bool is_port_disabled = link_info->port_action[i].port_disable;
+			const bool was_port_disabled = link_state[i].link_disabled;
+			const bool disable_port = is_port_disabled && !was_port_disabled;
+			const bool enable_port = !is_port_disabled && was_port_disabled;
+
+			if (!monitor_task_is_running[adapter_no])
+				break;
+
+			/*
+			 * Has the administrative port state changed?
+			 */
+			assert(!(disable_port && enable_port));
+
+			if (enable_port) {
+				link_state[i].link_disabled = false;
+				NT_LOG(DBG, NTNIC, "%s: Port %i is enabled",
+					drv->mp_port_id_str[i], i);
+			}
+
+			if (is_port_disabled)
+				continue;
+
+			link_state[i].link_disabled = is_port_disabled;
+
+			if (!link_state[i].nim_present) {
+				if (!link_state[i].lh_nim_absent) {
+					NT_LOG(INF, NTNIC, "%s: NIM module removed",
+						drv->mp_port_id_str[i]);
+					link_state[i].link_up = false;
+					link_state[i].lh_nim_absent = true;
+
+				} else {
+					NT_LOG(DBG, NTNIC, "%s: No NIM module, skip",
+						drv->mp_port_id_str[i]);
+				}
+
+				continue;
+			}
+		}
+
+		if (monitor_task_is_running[adapter_no])
+			nt_os_wait_usec(5 * 100000U);	/*  5 x 0.1s = 0.5s */
+	}
+
+NT4GA_LINK_100G_MON_EXIT:
+	NT_LOG(DBG, NTNIC, "%s: Stopped NT4GA 100 Gbps link monitoring thread.",
+		drv->mp_adapter_id_str);
+	return NULL;
+}
+
+static uint32_t nt4ga_agx_link_100g_mon(void *data)
+{
+	(void)_common_ptp_nim_state_machine(data);
+
+	return 0;
+}
+
 /*
  * Initialize all ports
  * The driver calls this function during initialization (of the driver).
@@ -34,9 +134,20 @@ void link_agx_100g_init(void)
 int nt4ga_agx_link_100g_ports_init(struct adapter_info_s *p_adapter_info, nthw_fpga_t *fpga)
 {
 	(void)fpga;
+	const int adapter_no = p_adapter_info->adapter_no;
 	int res = 0;
 
 	NT_LOG(DBG, NTNIC, "%s: Initializing ports", p_adapter_info->mp_adapter_id_str);
 
+	/*
+	 * Create state-machine thread
+	 */
+	if (res == 0) {
+		if (!monitor_task_is_running[adapter_no]) {
+			res = rte_thread_create(&monitor_tasks[adapter_no], NULL,
+					nt4ga_agx_link_100g_mon, p_adapter_info);
+		}
+	}
+
 	return res;
 }
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 03/32] net/ntnic: add rpf and gfg init
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 01/32] net/ntnic: add link agx 100g Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 02/32] net/ntnic: add link state machine Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 04/32] net/ntnic: add agx setup for port Serhii Iliushyk
                   ` (29 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

RPF and GFG modules initialization were added.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 drivers/net/ntnic/include/nt4ga_link.h        |   2 +
 drivers/net/ntnic/include/nthw_gfg.h          |  33 ++
 .../link_agx_100g/nt4ga_agx_link_100g.c       |  24 ++
 drivers/net/ntnic/meson.build                 |   1 +
 drivers/net/ntnic/nthw/core/nthw_gfg.c        | 340 ++++++++++++++++++
 drivers/net/ntnic/nthw/nthw_drv.h             |  10 +
 6 files changed, 410 insertions(+)
 create mode 100644 drivers/net/ntnic/include/nthw_gfg.h
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_gfg.c

diff --git a/drivers/net/ntnic/include/nt4ga_link.h b/drivers/net/ntnic/include/nt4ga_link.h
index af7ea4a9f2..e3dc3d4d5d 100644
--- a/drivers/net/ntnic/include/nt4ga_link.h
+++ b/drivers/net/ntnic/include/nt4ga_link.h
@@ -8,6 +8,7 @@
 
 #include "ntos_drv.h"
 #include "ntnic_nim.h"
+#include "nthw_gfg.h"
 
 enum nt_link_state_e {
 	NT_LINK_STATE_UNKNOWN = 0,	/* The link state has not been read yet */
@@ -84,6 +85,7 @@ typedef struct adapter_100g_s {
 
 typedef struct adapter_agx_100g_s {
 	nim_i2c_ctx_t nim_ctx[NUM_ADAPTER_PORTS_MAX];	/* should be the first field */
+	nthw_gfg_t gfg[NUM_ADAPTER_PORTS_MAX];
 } adapter_agx_100g_t;
 
 typedef union adapter_var_s {
diff --git a/drivers/net/ntnic/include/nthw_gfg.h b/drivers/net/ntnic/include/nthw_gfg.h
new file mode 100644
index 0000000000..4583fd9ebd
--- /dev/null
+++ b/drivers/net/ntnic/include/nthw_gfg.h
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_GFG_H_
+#define NTHW_GFG_H_
+
+#include "nthw_fpga_model.h"
+struct nthw_gfg {
+	nthw_fpga_t *mp_fpga;
+	nthw_module_t *mp_mod_gfg;
+	int mn_instance;
+
+	int mn_param_gfg_present;
+
+	nthw_field_t *mpa_fld_ctrl_enable[8];
+	nthw_field_t *mpa_fld_ctrl_mode[8];
+	nthw_field_t *mpa_fld_ctrl_prbs_en[8];
+	nthw_field_t *mpa_fld_ctrl_size[8];
+	nthw_field_t *mpa_fld_stream_id_val[8];
+	nthw_field_t *mpa_fld_run_run[8];
+	nthw_field_t *mpa_fld_size_mask[8];
+	nthw_field_t *mpa_fld_burst_size_val[8];
+};
+
+typedef struct nthw_gfg nthw_gfg_t;
+
+int nthw_gfg_init(nthw_gfg_t *p, nthw_fpga_t *p_fpga, int n_instance);
+
+int nthw_gfg_stop(nthw_gfg_t *p, const int n_intf_no);
+
+#endif	/* NTHW_GFG_H_ */
diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
index 369b9b601f..9db32443fc 100644
--- a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -11,6 +11,7 @@
 #include <string.h>
 #include "ntnic_mod_reg.h"
 #include "nim_defines.h"
+#include "nthw_gfg.h"
 
 static int nt4ga_agx_link_100g_ports_init(struct adapter_info_s *p_adapter_info,
 	nthw_fpga_t *fpga);
@@ -134,11 +135,34 @@ static uint32_t nt4ga_agx_link_100g_mon(void *data)
 int nt4ga_agx_link_100g_ports_init(struct adapter_info_s *p_adapter_info, nthw_fpga_t *fpga)
 {
 	(void)fpga;
+	nt4ga_link_t *nt4ga_link = &p_adapter_info->nt4ga_link;
 	const int adapter_no = p_adapter_info->adapter_no;
 	int res = 0;
 
 	NT_LOG(DBG, NTNIC, "%s: Initializing ports", p_adapter_info->mp_adapter_id_str);
 
+	if (!nt4ga_link->variables_initialized) {
+		nthw_gfg_t *gfg_mod = p_adapter_info->nt4ga_link.u.var_a100g.gfg;
+		nthw_agx_t *p_nthw_agx = &p_adapter_info->fpga_info.mp_nthw_agx;
+
+		p_nthw_agx->p_rpf = nthw_rpf_new();
+		res = nthw_rpf_init(p_nthw_agx->p_rpf, fpga, adapter_no);
+
+		if (res != 0) {
+			NT_LOG(ERR, NTNIC, "%s: Failed to initialize RPF module (%u)",
+				p_adapter_info->mp_adapter_id_str, res);
+			return res;
+		}
+
+		res = nthw_gfg_init(&gfg_mod[adapter_no], fpga, 0 /* Only one instance */);
+
+		if (res != 0) {
+			NT_LOG(ERR, NTNIC, "%s: Failed to initialize GFG module (%u)",
+				p_adapter_info->mp_adapter_id_str, res);
+			return res;
+		}
+	}
+
 	/*
 	 * Create state-machine thread
 	 */
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 7e4f47b1e6..68d7fdafd4 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -47,6 +47,7 @@ sources = files(
         'nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c',
         'nthw/core/nthw_fpga.c',
         'nthw/core/nthw_gmf.c',
+        'nthw/core/nthw_gfg.c',
         'nthw/core/nthw_tsm.c',
         'nthw/core/nthw_gpio_phy.c',
         'nthw/core/nthw_hif.c',
diff --git a/drivers/net/ntnic/nthw/core/nthw_gfg.c b/drivers/net/ntnic/nthw/core/nthw_gfg.c
new file mode 100644
index 0000000000..aa71624457
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_gfg.c
@@ -0,0 +1,340 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nt_util.h"
+#include "nthw_gfg.h"
+
+int nthw_gfg_init(nthw_gfg_t *p, nthw_fpga_t *p_fpga, int n_instance)
+{
+	nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_GFG, n_instance);
+	const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+	nthw_register_t *p_reg;
+
+	if (p == NULL)
+		return mod == NULL ? -1 : 0;
+
+	if (mod == NULL) {
+		NT_LOG(ERR, NTHW, "%s: GFG %d: no such instance", p_adapter_id_str, n_instance);
+		return -1;
+	}
+
+	p->mp_fpga = p_fpga;
+	p->mn_instance = n_instance;
+	p->mp_mod_gfg = mod;
+
+	p->mn_param_gfg_present = nthw_fpga_get_product_param(p_fpga, NT_GFG_PRESENT, 0);
+
+	if (!p->mn_param_gfg_present) {
+		NT_LOG(ERR,
+			NTHW,
+			"%s: %s: GFG %d module found - but logically not present - failing",
+			__func__,
+			p_adapter_id_str,
+			p->mn_instance);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_CTRL0);
+
+	if (p_reg) {
+		p->mpa_fld_ctrl_enable[0] = nthw_register_query_field(p_reg, GFG_CTRL0_ENABLE);
+		p->mpa_fld_ctrl_mode[0] = nthw_register_query_field(p_reg, GFG_CTRL0_MODE);
+		p->mpa_fld_ctrl_prbs_en[0] = nthw_register_query_field(p_reg, GFG_CTRL0_PRBS_EN);
+		p->mpa_fld_ctrl_size[0] = nthw_register_query_field(p_reg, GFG_CTRL0_SIZE);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_CTRL1);
+
+	if (p_reg) {
+		p->mpa_fld_ctrl_enable[1] = nthw_register_query_field(p_reg, GFG_CTRL1_ENABLE);
+		p->mpa_fld_ctrl_mode[1] = nthw_register_query_field(p_reg, GFG_CTRL1_MODE);
+		p->mpa_fld_ctrl_prbs_en[1] = nthw_register_query_field(p_reg, GFG_CTRL1_PRBS_EN);
+		p->mpa_fld_ctrl_size[1] = nthw_register_query_field(p_reg, GFG_CTRL1_SIZE);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_CTRL2);
+
+	if (p_reg) {
+		p->mpa_fld_ctrl_enable[2] = nthw_register_query_field(p_reg, GFG_CTRL2_ENABLE);
+		p->mpa_fld_ctrl_mode[2] = nthw_register_query_field(p_reg, GFG_CTRL2_MODE);
+		p->mpa_fld_ctrl_prbs_en[2] = nthw_register_query_field(p_reg, GFG_CTRL2_PRBS_EN);
+		p->mpa_fld_ctrl_size[2] = nthw_register_query_field(p_reg, GFG_CTRL2_SIZE);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_CTRL3);
+
+	if (p_reg) {
+		p->mpa_fld_ctrl_enable[3] = nthw_register_query_field(p_reg, GFG_CTRL3_ENABLE);
+		p->mpa_fld_ctrl_mode[3] = nthw_register_query_field(p_reg, GFG_CTRL3_MODE);
+		p->mpa_fld_ctrl_prbs_en[3] = nthw_register_query_field(p_reg, GFG_CTRL3_PRBS_EN);
+		p->mpa_fld_ctrl_size[3] = nthw_register_query_field(p_reg, GFG_CTRL3_SIZE);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_CTRL4);
+
+	if (p_reg) {
+		p->mpa_fld_ctrl_enable[4] = nthw_register_query_field(p_reg, GFG_CTRL4_ENABLE);
+		p->mpa_fld_ctrl_mode[4] = nthw_register_query_field(p_reg, GFG_CTRL4_MODE);
+		p->mpa_fld_ctrl_prbs_en[4] = nthw_register_query_field(p_reg, GFG_CTRL4_PRBS_EN);
+		p->mpa_fld_ctrl_size[4] = nthw_register_query_field(p_reg, GFG_CTRL4_SIZE);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_CTRL5);
+
+	if (p_reg) {
+		p->mpa_fld_ctrl_enable[5] = nthw_register_query_field(p_reg, GFG_CTRL5_ENABLE);
+		p->mpa_fld_ctrl_mode[5] = nthw_register_query_field(p_reg, GFG_CTRL5_MODE);
+		p->mpa_fld_ctrl_prbs_en[5] = nthw_register_query_field(p_reg, GFG_CTRL5_PRBS_EN);
+		p->mpa_fld_ctrl_size[5] = nthw_register_query_field(p_reg, GFG_CTRL5_SIZE);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_CTRL6);
+
+	if (p_reg) {
+		p->mpa_fld_ctrl_enable[6] = nthw_register_query_field(p_reg, GFG_CTRL6_ENABLE);
+		p->mpa_fld_ctrl_mode[6] = nthw_register_query_field(p_reg, GFG_CTRL6_MODE);
+		p->mpa_fld_ctrl_prbs_en[6] = nthw_register_query_field(p_reg, GFG_CTRL6_PRBS_EN);
+		p->mpa_fld_ctrl_size[6] = nthw_register_query_field(p_reg, GFG_CTRL6_SIZE);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_CTRL7);
+
+	if (p_reg) {
+		p->mpa_fld_ctrl_enable[7] = nthw_register_query_field(p_reg, GFG_CTRL7_ENABLE);
+		p->mpa_fld_ctrl_mode[7] = nthw_register_query_field(p_reg, GFG_CTRL7_MODE);
+		p->mpa_fld_ctrl_prbs_en[7] = nthw_register_query_field(p_reg, GFG_CTRL7_PRBS_EN);
+		p->mpa_fld_ctrl_size[7] = nthw_register_query_field(p_reg, GFG_CTRL7_SIZE);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_RUN0);
+
+	if (p_reg)
+		p->mpa_fld_run_run[0] = nthw_register_query_field(p_reg, GFG_RUN0_RUN);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_RUN1);
+
+	if (p_reg)
+		p->mpa_fld_run_run[1] = nthw_register_query_field(p_reg, GFG_RUN1_RUN);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_RUN2);
+
+	if (p_reg)
+		p->mpa_fld_run_run[2] = nthw_register_query_field(p_reg, GFG_RUN2_RUN);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_RUN3);
+
+	if (p_reg)
+		p->mpa_fld_run_run[3] = nthw_register_query_field(p_reg, GFG_RUN3_RUN);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_RUN4);
+
+	if (p_reg)
+		p->mpa_fld_run_run[4] = nthw_register_query_field(p_reg, GFG_RUN4_RUN);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_RUN5);
+
+	if (p_reg)
+		p->mpa_fld_run_run[5] = nthw_register_query_field(p_reg, GFG_RUN5_RUN);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_RUN6);
+
+	if (p_reg)
+		p->mpa_fld_run_run[6] = nthw_register_query_field(p_reg, GFG_RUN6_RUN);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_RUN7);
+
+	if (p_reg)
+		p->mpa_fld_run_run[7] = nthw_register_query_field(p_reg, GFG_RUN7_RUN);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_STREAMID0);
+
+	if (p_reg)
+		p->mpa_fld_stream_id_val[0] = nthw_register_query_field(p_reg, GFG_STREAMID0_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_STREAMID1);
+
+	if (p_reg)
+		p->mpa_fld_stream_id_val[1] = nthw_register_query_field(p_reg, GFG_STREAMID1_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_STREAMID2);
+
+	if (p_reg)
+		p->mpa_fld_stream_id_val[2] = nthw_register_query_field(p_reg, GFG_STREAMID2_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_STREAMID3);
+
+	if (p_reg)
+		p->mpa_fld_stream_id_val[3] = nthw_register_query_field(p_reg, GFG_STREAMID3_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_STREAMID4);
+
+	if (p_reg)
+		p->mpa_fld_stream_id_val[4] = nthw_register_query_field(p_reg, GFG_STREAMID4_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_STREAMID5);
+
+	if (p_reg)
+		p->mpa_fld_stream_id_val[5] = nthw_register_query_field(p_reg, GFG_STREAMID5_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_STREAMID6);
+
+	if (p_reg)
+		p->mpa_fld_stream_id_val[6] = nthw_register_query_field(p_reg, GFG_STREAMID6_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_STREAMID7);
+
+	if (p_reg)
+		p->mpa_fld_stream_id_val[7] = nthw_register_query_field(p_reg, GFG_STREAMID7_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_SIZEMASK0);
+
+	if (p_reg)
+		p->mpa_fld_size_mask[0] = nthw_register_query_field(p_reg, GFG_SIZEMASK0_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_SIZEMASK1);
+
+	if (p_reg)
+		p->mpa_fld_size_mask[1] = nthw_register_query_field(p_reg, GFG_SIZEMASK1_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_SIZEMASK2);
+
+	if (p_reg)
+		p->mpa_fld_size_mask[2] = nthw_register_query_field(p_reg, GFG_SIZEMASK2_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_SIZEMASK3);
+
+	if (p_reg)
+		p->mpa_fld_size_mask[3] = nthw_register_query_field(p_reg, GFG_SIZEMASK3_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_SIZEMASK4);
+
+	if (p_reg)
+		p->mpa_fld_size_mask[4] = nthw_register_query_field(p_reg, GFG_SIZEMASK4_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_SIZEMASK5);
+
+	if (p_reg)
+		p->mpa_fld_size_mask[5] = nthw_register_query_field(p_reg, GFG_SIZEMASK5_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_SIZEMASK6);
+
+	if (p_reg)
+		p->mpa_fld_size_mask[6] = nthw_register_query_field(p_reg, GFG_SIZEMASK6_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_SIZEMASK7);
+
+	if (p_reg)
+		p->mpa_fld_size_mask[7] = nthw_register_query_field(p_reg, GFG_SIZEMASK7_VAL);
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_BURSTSIZE0);
+
+	if (p_reg) {
+		p->mpa_fld_burst_size_val[0] =
+			nthw_register_query_field(p_reg, GFG_BURSTSIZE0_VAL);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_BURSTSIZE1);
+
+	if (p_reg) {
+		p->mpa_fld_burst_size_val[1] =
+			nthw_register_query_field(p_reg, GFG_BURSTSIZE1_VAL);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_BURSTSIZE2);
+
+	if (p_reg) {
+		p->mpa_fld_burst_size_val[2] =
+			nthw_register_query_field(p_reg, GFG_BURSTSIZE2_VAL);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_BURSTSIZE3);
+
+	if (p_reg) {
+		p->mpa_fld_burst_size_val[3] =
+			nthw_register_query_field(p_reg, GFG_BURSTSIZE3_VAL);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_BURSTSIZE4);
+
+	if (p_reg) {
+		p->mpa_fld_burst_size_val[4] =
+			nthw_register_query_field(p_reg, GFG_BURSTSIZE4_VAL);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_BURSTSIZE5);
+
+	if (p_reg) {
+		p->mpa_fld_burst_size_val[5] =
+			nthw_register_query_field(p_reg, GFG_BURSTSIZE5_VAL);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_BURSTSIZE6);
+
+	if (p_reg) {
+		p->mpa_fld_burst_size_val[6] =
+			nthw_register_query_field(p_reg, GFG_BURSTSIZE6_VAL);
+	}
+
+	p_reg = nthw_module_query_register(p->mp_mod_gfg, GFG_BURSTSIZE7);
+
+	if (p_reg) {
+		p->mpa_fld_burst_size_val[7] =
+			nthw_register_query_field(p_reg, GFG_BURSTSIZE7_VAL);
+	}
+
+	return 0;
+}
+
+static int nthw_gfg_setup(nthw_gfg_t *p,
+	const size_t n_intf_no,
+	const int n_enable,
+	const int n_frame_count,
+	const int n_frame_size,
+	const int n_frame_fill_mode,
+	const int n_frame_stream_id)
+{
+	if ((size_t)n_intf_no >= ARRAY_SIZE(p->mpa_fld_ctrl_enable) ||
+		n_intf_no >= ARRAY_SIZE(p->mpa_fld_ctrl_mode) ||
+		(size_t)n_intf_no >= ARRAY_SIZE(p->mpa_fld_ctrl_size) ||
+		n_intf_no >= ARRAY_SIZE(p->mpa_fld_stream_id_val) ||
+		(size_t)n_intf_no >= ARRAY_SIZE(p->mpa_fld_burst_size_val)) {
+		assert(false);
+		return -1;
+	}
+
+	if (p->mpa_fld_ctrl_enable[n_intf_no] == NULL || p->mpa_fld_ctrl_mode[n_intf_no] == NULL ||
+		p->mpa_fld_ctrl_size[n_intf_no] == NULL ||
+		p->mpa_fld_stream_id_val[n_intf_no] == NULL ||
+		p->mpa_fld_burst_size_val[n_intf_no] == NULL) {
+		assert(false);
+		return -1;
+	}
+
+	nthw_field_set_val_flush32(p->mpa_fld_stream_id_val[n_intf_no], n_frame_stream_id);
+	nthw_field_set_val_flush32(p->mpa_fld_burst_size_val[n_intf_no], n_frame_count);
+
+	if (p->mpa_fld_size_mask[n_intf_no])
+		nthw_field_set_val_flush32(p->mpa_fld_size_mask[n_intf_no], 0);
+
+	nthw_field_set_val32(p->mpa_fld_ctrl_mode[n_intf_no], n_frame_fill_mode);
+	nthw_field_set_val32(p->mpa_fld_ctrl_size[n_intf_no], n_frame_size);
+
+	if (p->mpa_fld_ctrl_prbs_en[n_intf_no])
+		nthw_field_set_val32(p->mpa_fld_ctrl_prbs_en[n_intf_no], 0);
+
+	nthw_field_set_val_flush32(p->mpa_fld_ctrl_enable[n_intf_no],
+		n_enable);	/* write enable and flush */
+
+	return 0;
+}
+
+int nthw_gfg_stop(nthw_gfg_t *p, const int n_intf_no)
+{
+	return nthw_gfg_setup(p, n_intf_no, 0, 1, 0x666, 0, n_intf_no);
+}
diff --git a/drivers/net/ntnic/nthw/nthw_drv.h b/drivers/net/ntnic/nthw/nthw_drv.h
index 69e0360f5f..9dc839c83c 100644
--- a/drivers/net/ntnic/nthw/nthw_drv.h
+++ b/drivers/net/ntnic/nthw/nthw_drv.h
@@ -9,6 +9,15 @@
 #include "nthw_core.h"
 #include "ntnic_dbs.h"
 
+#include "nthw_rpf.h"
+
+/*
+ * Structs for controlling Agilex based NT400DXX adapter
+ */
+typedef struct nthw_agx_s {
+	nthw_rpf_t *p_rpf;
+} nthw_agx_t;
+
 typedef enum nt_meta_port_type_e {
 	PORT_TYPE_PHYSICAL,
 	PORT_TYPE_VIRTUAL,
@@ -88,6 +97,7 @@ typedef struct fpga_info_s {
 
 	nthw_adapter_id_t n_nthw_adapter_id;
 
+	nthw_agx_t mp_nthw_agx;	/* For the Agilex based NT400DXX */
 } fpga_info_t;
 
 
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 04/32] net/ntnic: add agx setup for port
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (2 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 03/32] net/ntnic: add rpf and gfg init Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 05/32] net/ntnic: add host loopback init Serhii Iliushyk
                   ` (28 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Initialize NIM and PHY settings for Agilex FPGA ports

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 drivers/net/ntnic/include/ntnic_nim.h         |   5 +
 .../link_agx_100g/nt4ga_agx_link_100g.c       |  86 ++++++++-
 drivers/net/ntnic/meson.build                 |   1 +
 drivers/net/ntnic/nim/i2c_nim.c               |   8 +
 drivers/net/ntnic/nim/i2c_nim.h               |   3 +
 .../ntnic/nthw/core/include/nthw_pcal6416a.h  |  19 ++
 .../ntnic/nthw/core/include/nthw_phy_tile.h   |  62 +++++++
 .../nthw/core/include/nthw_si5332_si5156.h    |  18 ++
 drivers/net/ntnic/nthw/core/nthw_phy_tile.c   | 173 ++++++++++++++++++
 drivers/net/ntnic/nthw/nthw_drv.h             |   8 +
 10 files changed, 382 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_phy_tile.c

diff --git a/drivers/net/ntnic/include/ntnic_nim.h b/drivers/net/ntnic/include/ntnic_nim.h
index 58daa8435f..3e97a9a8b2 100644
--- a/drivers/net/ntnic/include/ntnic_nim.h
+++ b/drivers/net/ntnic/include/ntnic_nim.h
@@ -7,9 +7,12 @@
 #define _NTNIC_NIM_H_
 
 #include <stdint.h>
+#include "nthw_pcal6416a.h"
+#include "nthw_i2cm.h"
 
 typedef enum i2c_type {
 	I2C_HWIIC,
+	I2C_HWAGX
 } i2c_type_e;
 
 enum nt_port_type_e {
@@ -38,7 +41,9 @@ typedef struct nim_i2c_ctx {
 	union {
 		nthw_iic_t hwiic;	/* depends on *Fpga_t, instance number, and cycle time */
 		struct {
+			nthw_pcal6416a_t *p_io_nim;
 			nthw_i2cm_t *p_nt_i2cm;
+			nthw_pca9849_t *p_ca9849;
 			int mux_channel;
 		} hwagx;
 	};
diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
index 9db32443fc..a6455ee598 100644
--- a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -12,6 +12,7 @@
 #include "ntnic_mod_reg.h"
 #include "nim_defines.h"
 #include "nthw_gfg.h"
+#include "nthw_phy_tile.h"
 
 static int nt4ga_agx_link_100g_ports_init(struct adapter_info_s *p_adapter_info,
 	nthw_fpga_t *fpga);
@@ -28,6 +29,58 @@ void link_agx_100g_init(void)
 	register_agx_100g_link_ops(&link_agx_100g_ops);
 }
 
+/*
+ * Utility functions
+ */
+
+static int swap_tx_rx_polarity(adapter_info_t *drv, int port, bool swap)
+{
+	/*
+	 * Mapping according to schematics
+	 * I: Inversion, N: Non-inversion
+	 *
+	 *  Port 0: PMA0/FGT0
+	 *  FPGA QSFP Tx Rx
+	 *  ---------------
+	 *  Q3C0 Ch4  I  I
+	 *  Q3C1 Ch2  I  I
+	 *  Q3C2 Ch1  I  N
+	 *  Q3C3 Ch3  I  I
+	 *
+	 *  Port 1: PMA1/FGT1
+	 *  FPGA QSFP Tx Rx
+	 *  ---------------
+	 *  Q2C0 Ch4  I  I
+	 *  Q2C1 Ch2  I  I
+	 *  Q2C2 Ch1  N  I
+	 *  Q2C3 Ch3  N  N
+	 */
+
+	bool rx_polarity_swap[2][4] = { { false, true, true, true }, { true, false, true, true } };
+	bool tx_polarity_swap[2][4] = { { false, false, true, true }, { true, true, true, true } };
+
+	nthw_phy_tile_t *p = drv->fpga_info.mp_nthw_agx.p_phy_tile;
+
+	if (p) {
+		for (uint8_t lane = 0; lane < 4; lane++) {
+			if (swap) {
+				nthw_phy_tile_set_tx_pol_inv(p, port, lane,
+					tx_polarity_swap[port][lane]);
+				nthw_phy_tile_set_rx_pol_inv(p, port, lane,
+					rx_polarity_swap[port][lane]);
+
+			} else {
+				nthw_phy_tile_set_tx_pol_inv(p, port, lane, false);
+				nthw_phy_tile_set_rx_pol_inv(p, port, lane, false);
+			}
+		}
+
+		return 0;
+	}
+
+	return -1;
+}
+
 /*
  * Link state machine
  */
@@ -134,15 +187,18 @@ static uint32_t nt4ga_agx_link_100g_mon(void *data)
  */
 int nt4ga_agx_link_100g_ports_init(struct adapter_info_s *p_adapter_info, nthw_fpga_t *fpga)
 {
-	(void)fpga;
+	fpga_info_t *fpga_info = &p_adapter_info->fpga_info;
 	nt4ga_link_t *nt4ga_link = &p_adapter_info->nt4ga_link;
 	const int adapter_no = p_adapter_info->adapter_no;
+	const int nb_ports = fpga_info->n_phy_ports;
 	int res = 0;
+	int i;
 
 	NT_LOG(DBG, NTNIC, "%s: Initializing ports", p_adapter_info->mp_adapter_id_str);
 
 	if (!nt4ga_link->variables_initialized) {
 		nthw_gfg_t *gfg_mod = p_adapter_info->nt4ga_link.u.var_a100g.gfg;
+		nim_i2c_ctx_t *nim_ctx = p_adapter_info->nt4ga_link.u.var_a100g.nim_ctx;
 		nthw_agx_t *p_nthw_agx = &p_adapter_info->fpga_info.mp_nthw_agx;
 
 		p_nthw_agx->p_rpf = nthw_rpf_new();
@@ -161,6 +217,34 @@ int nt4ga_agx_link_100g_ports_init(struct adapter_info_s *p_adapter_info, nthw_f
 				p_adapter_info->mp_adapter_id_str, res);
 			return res;
 		}
+
+		for (i = 0; i < nb_ports; i++) {
+			/* 2 + adapter port number */
+			const uint8_t instance = (uint8_t)(2U + i);
+			nim_agx_setup(&nim_ctx[i], p_nthw_agx->p_io_nim, p_nthw_agx->p_i2cm,
+				p_nthw_agx->p_pca9849);
+			nim_ctx[i].hwagx.mux_channel = i;
+			nim_ctx[i].instance = instance;	/* not used */
+			nim_ctx[i].devaddr = 0;	/* not used */
+			nim_ctx[i].regaddr = 0;	/* not used */
+			nim_ctx[i].type = I2C_HWAGX;
+
+			nthw_gfg_stop(&gfg_mod[adapter_no], i);
+
+			for (uint8_t lane = 0; lane < 4; lane++) {
+				nthw_phy_tile_set_host_loopback(p_nthw_agx->p_phy_tile, i, lane,
+					false);
+			}
+
+			swap_tx_rx_polarity(p_adapter_info, i, true);
+		}
+
+		nthw_rpf_set_ts_at_eof(p_nthw_agx->p_rpf, true);
+
+		if (res == 0) {
+			p_adapter_info->nt4ga_link.speed_capa = NT_LINK_SPEED_100G;
+			p_adapter_info->nt4ga_link.variables_initialized = true;
+		}
 	}
 
 	/*
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 68d7fdafd4..4799ebfb8e 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -55,6 +55,7 @@ sources = files(
         'nthw/core/nthw_iic.c',
         'nthw/core/nthw_mac_pcs.c',
         'nthw/core/nthw_pcie3.c',
+        'nthw/core/nthw_phy_tile.c',
         'nthw/core/nthw_rpf.c',
         'nthw/core/nthw_rmc.c',
         'nthw/core/nthw_sdc.c',
diff --git a/drivers/net/ntnic/nim/i2c_nim.c b/drivers/net/ntnic/nim/i2c_nim.c
index e6f7755ded..7dbbdb8873 100644
--- a/drivers/net/ntnic/nim/i2c_nim.c
+++ b/drivers/net/ntnic/nim/i2c_nim.c
@@ -795,3 +795,11 @@ int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra)
 
 	return res;
 }
+
+void nim_agx_setup(struct nim_i2c_ctx *ctx, nthw_pcal6416a_t *p_io_nim, nthw_i2cm_t *p_nt_i2cm,
+	nthw_pca9849_t *p_ca9849)
+{
+	ctx->hwagx.p_nt_i2cm = p_nt_i2cm;
+	ctx->hwagx.p_ca9849 = p_ca9849;
+	ctx->hwagx.p_io_nim = p_io_nim;
+}
diff --git a/drivers/net/ntnic/nim/i2c_nim.h b/drivers/net/ntnic/nim/i2c_nim.h
index edb6dcf1b6..09837448c6 100644
--- a/drivers/net/ntnic/nim/i2c_nim.h
+++ b/drivers/net/ntnic/nim/i2c_nim.h
@@ -33,4 +33,7 @@ int nim_qsfp_plus_nim_set_tx_laser_disable(nim_i2c_ctx_t *ctx, bool disable, int
  */
 int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra);
 
+void nim_agx_setup(struct nim_i2c_ctx *ctx, nthw_pcal6416a_t *p_io_nim, nthw_i2cm_t *p_nt_i2cm,
+	nthw_pca9849_t *p_ca9849);
+
 #endif	/* I2C_NIM_H_ */
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h b/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
new file mode 100644
index 0000000000..636d2beb85
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
@@ -0,0 +1,19 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+#ifndef __NTHW_PCAL6416A_H__
+#define __NTHW_PCAL6416A_H__
+
+#include <stdint.h>
+
+/*
+ * PCAL6416A I/O expander class
+ */
+
+struct nthw_pcal6416a {
+};
+
+typedef struct nthw_pcal6416a nthw_pcal6416a_t;
+
+#endif	/* __NTHW_PCAL6416A_H__ */
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
new file mode 100644
index 0000000000..930c897046
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
@@ -0,0 +1,62 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PHY_TILE_H__
+#define __NTHW_PHY_TILE_H__
+
+#include "nthw_fpga_model.h"
+
+struct nt_phy_tile {
+	nthw_fpga_t *mp_fpga;
+
+	int mn_phy_tile_instance;
+
+	int mn_fpga_version;
+	int mn_fpga_revision;
+
+	nthw_register_t *mp_reg_port_xcvr_base[2][4];
+	nthw_field_t *mp_fld_port_xcvr_base_ptr[2][4];
+	nthw_field_t *mp_fld_port_xcvr_base_busy[2][4];
+	nthw_field_t *mp_fld_port_xcvr_base_cmd[2][4];
+
+	nthw_field_t *mp_fld_port_xcvr_data_data[2][4];
+
+	nthw_register_t *mp_reg_port_eth_base[2];
+	nthw_field_t *mp_fld_port_eth_base_ptr[2];
+	nthw_field_t *mp_fld_port_eth_base_busy[2];
+	nthw_field_t *mp_fld_port_eth_base_cmd[2];
+
+	nthw_field_t *mp_fld_port_eth_data_data[2];
+
+	nthw_register_t *mp_reg_link_summary[2];
+	nthw_field_t *mp_fld_link_summary_nt_phy_link_state[2];
+	nthw_field_t *mp_fld_link_summary_ll_nt_phy_link_state[2];
+	nthw_field_t *mp_fld_link_summary_link_down_cnt[2];
+	nthw_field_t *mp_fld_link_summary_lh_remote_fault[2];
+
+	nthw_field_t *mp_fld_port_status_tx_reset_ackn[2];
+	nthw_field_t *mp_fld_port_status_rx_reset_ackn[2];
+
+	nthw_field_t *mp_fld_port_config_rx_reset[2];
+	nthw_field_t *mp_fld_port_config_tx_reset[2];
+
+	nthw_field_t *mp_fld_scratch_data;
+};
+
+typedef struct nt_phy_tile nthw_phy_tile_t;
+typedef struct nt_phy_tile nt_phy_tile;
+
+void nthw_phy_tile_set_tx_pol_inv(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane, bool invert);
+void nthw_phy_tile_set_rx_pol_inv(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane, bool invert);
+void nthw_phy_tile_set_host_loopback(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
+	bool enable);
+void nthw_phy_tile_set_rx_reset(nthw_phy_tile_t *p, uint8_t intf_no, bool reset);
+
+uint32_t nthw_phy_tile_read_xcvr(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
+	uint32_t address);
+void nthw_phy_tile_write_xcvr(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane, uint32_t address,
+	uint32_t data);
+
+#endif	/* __NTHW_PHY_TILE_H__ */
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h b/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
new file mode 100644
index 0000000000..fb44c62f12
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
@@ -0,0 +1,18 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_SI5332_SI5156_H__
+#define __NTHW_SI5332_SI5156_H__
+
+/*
+ * PCA9849 I2c mux class
+ */
+
+struct nthw_pca9849 {
+};
+
+typedef struct nthw_pca9849 nthw_pca9849_t;
+
+#endif	/* __NTHW_SI5332_SI5156_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_phy_tile.c b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
new file mode 100644
index 0000000000..fd7a1e1214
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
@@ -0,0 +1,173 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_phy_tile.h"
+#include "nthw_helper.h"
+
+static const uint32_t link_addr = 0x9003C;
+static const uint32_t phy_addr = 0x90040;
+/* CPI option flags */
+static const uint32_t cpi_set = 0x2000;	/* 1 << 13 */
+static const uint32_t cpi_in_reset = 0x4000;	/* 1 << 14 */
+static const uint32_t bit_cpi_assert = 0x8000;	/* 1 << 15 */
+/*
+ * Base Addresses for Avalon MM Secondary Components
+ * static const uint32_t ADDR_AVMM_DR_CTRL_INT                  =  0x10035000 << 0;
+ * static const uint32_t ADDR_GDR_P0_XCVR_RECONFIG_INT          =  0x00800000 << 0;
+ * static const uint32_t ADDR_GDR_P1_XCVR_RECONFIG_INT          =  0x00900000 << 0;
+ * static const uint32_t ADDR_GDR_P2_XCVR_RECONFIG_INT          =  0x00A00000 << 0;
+ * static const uint32_t ADDR_GDR_P3_XCVR_RECONFIG_INT          =  0x00B00000 << 0;
+ * static const uint32_t ADDR_GDR_P0_ETH_RECONFIG_INT           =  0x00000000 << 0;
+ * static const uint32_t ADDR_GDR_P1_ETH_RECONFIG_INT           =  0x00010000 << 0;
+ * static const uint32_t ADDR_GDR_P2_ETH_RECONFIG_INT           =  0x00020000 << 0;
+ * static const uint32_t ADDR_GDR_P3_ETH_RECONFIG_INT           =  0x00030000 << 0;
+ * static const uint32_t ADDR_GDR_PKT_CLIENT_CONFIG_INT         =  0x000100000 << 0;
+ * static const uint32_t ADDR_GDR_P0_25G_PKT_CLIENT_CONFIG_INT  =  0x000200000 << 0;
+ * static const uint32_t ADDR_GDR_P0_50G_PKT_CLIENT_CONFIG_INT  =  0x000300000 << 0;
+ *
+ * ETH AVMM USER SPACE Registers Address Map
+ */
+
+void nthw_phy_tile_set_rx_reset(nthw_phy_tile_t *p, uint8_t intf_no, bool reset)
+{
+	/* Reset is active low */
+	nthw_field_get_updated(p->mp_fld_port_config_rx_reset[intf_no]);
+
+	if (reset) {
+		nthw_field_clr_flush(p->mp_fld_port_config_rx_reset[intf_no]);
+
+		/* Wait for ack */
+		if (p->mp_fld_port_status_rx_reset_ackn[intf_no]) {
+			int32_t count = 1000;
+
+			do {
+				nt_os_wait_usec(1000);	/* 1ms */
+			} while (nthw_field_get_updated(p->mp_fld_port_status_rx_reset_ackn
+				[intf_no]) && (--count > 0));
+
+			if (count <= 0) {
+				NT_LOG(ERR, NTHW, "intf_no %u: Time-out waiting for RxResetAck",
+					intf_no);
+			}
+		}
+
+	} else {
+		nthw_field_set_flush(p->mp_fld_port_config_rx_reset[intf_no]);
+	}
+}
+
+uint32_t nthw_phy_tile_read_xcvr(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
+	uint32_t address)
+{
+	nthw_register_update(p->mp_reg_port_xcvr_base[intf_no][lane]);
+	nthw_field_set_val32(p->mp_fld_port_xcvr_base_cmd[intf_no][lane], 0);
+	nthw_field_set_val_flush32(p->mp_fld_port_xcvr_base_ptr[intf_no][lane], address);
+
+	while (nthw_field_get_updated(p->mp_fld_port_xcvr_base_busy[intf_no][lane]) == 1)
+		nt_os_wait_usec(100);
+
+	return nthw_field_get_updated(p->mp_fld_port_xcvr_data_data[intf_no][lane]);
+}
+
+void nthw_phy_tile_write_xcvr(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane, uint32_t address,
+	uint32_t data)
+{
+	nthw_field_set_val_flush32(p->mp_fld_port_xcvr_data_data[intf_no][lane], data);
+	nthw_register_update(p->mp_reg_port_xcvr_base[intf_no][lane]);
+	nthw_field_set_val32(p->mp_fld_port_xcvr_base_ptr[intf_no][lane], address);
+	nthw_field_set_val_flush32(p->mp_fld_port_xcvr_base_cmd[intf_no][lane], 1);
+
+	while (nthw_field_get_updated(p->mp_fld_port_xcvr_base_busy[intf_no][lane]) == 1)
+		/* NT_LOG(INF, NTHW, "busy"); */
+		nt_os_wait_usec(100);
+}
+
+static uint32_t nthw_phy_tile_cpi_request(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
+	uint32_t data, uint8_t op_code, uint32_t cpi_assert,
+	uint32_t cpi_set_get)
+{
+	uint32_t cpi_cmd;
+	uint32_t value = 0;
+	uint32_t xcvr_instance = lane;
+	uint32_t lane_offset = 0;
+	uint32_t quad_lane = 0;
+
+	/* Find quad lane */
+	quad_lane = nthw_phy_tile_read_xcvr(p, intf_no, lane, 0xFFFFC) & 0x3;
+
+	xcvr_instance = lane;
+	lane_offset = (uint32_t)(lane << 20);
+
+	cpi_cmd = (data << 16) | cpi_assert | cpi_set_get | (quad_lane << 8) | op_code;
+
+	nthw_phy_tile_write_xcvr(p, intf_no, lane, link_addr + lane_offset, cpi_cmd);
+
+	nt_os_wait_usec(10000);
+
+	for (int i = 20; i > 0; i--) {
+		data = nthw_phy_tile_read_xcvr(p, intf_no, lane, phy_addr + lane_offset);
+
+		value =
+			nthw_field_get_updated(p->mp_fld_port_xcvr_data_data
+				[intf_no][xcvr_instance]);
+
+		if (((value & bit_cpi_assert) == cpi_assert) && ((value & cpi_in_reset) == 0))
+			break;
+
+		nt_os_wait_usec(10000);
+
+		if (i == 0)
+			NT_LOG(ERR, NTHW, "Time out");
+	}
+
+	return value;
+}
+
+static void nthw_phy_tile_write_attribute(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
+	uint8_t op_code, uint8_t data)
+{
+	/*
+	 * p->cpi_set_get = 0x2000 #bit13: (1: set, 0: get)
+	 * cpi_assert = 0x0000 #bit15: (1: assert, 0: deassert)
+	 */
+	nthw_phy_tile_cpi_request(p, intf_no, lane, data, op_code, bit_cpi_assert, cpi_set);
+	nthw_phy_tile_cpi_request(p, intf_no, lane, data, op_code, 0x0000, cpi_set);
+}
+
+void nthw_phy_tile_set_tx_pol_inv(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane, bool invert)
+{
+	nthw_phy_tile_write_attribute(p, intf_no, lane, 0x65, invert ? 1 : 0);
+	/*
+	 * NT_LOG(INF, NTHW, "setTxPolInv intf_no %d, lane %d, inv %d ", intf_no, lane, invert);
+	 * nthw_phy_tile_get_tx_pol_inv(p, intf_no, lane);
+	 */
+}
+
+void nthw_phy_tile_set_rx_pol_inv(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane, bool invert)
+{
+	nthw_phy_tile_write_attribute(p, intf_no, lane, 0x66, invert ? 1 : 0);
+	/*
+	 * NT_LOG(INF, NTHW, "setRxPolInv intf_no %d, lane %d, inv %d ", intf_no, lane, invert);
+	 * nthw_phy_tile_get_rx_pol_inv(p, intf_no, lane);
+	 */
+}
+
+void nthw_phy_tile_set_host_loopback(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
+	bool enable)
+{
+	nthw_phy_tile_set_rx_reset(p, intf_no, true);
+	nthw_phy_tile_write_attribute(p, intf_no, lane, 0x40, enable ? 0x06 : 0);
+	nthw_phy_tile_set_rx_reset(p, intf_no, false);
+	/*
+	 * NT_LOG(INF, NTHW, "setLoopback intf_no %d, lane %d, enable %d ",
+	 * intf_no, lane, enable);
+	 */
+}
diff --git a/drivers/net/ntnic/nthw/nthw_drv.h b/drivers/net/ntnic/nthw/nthw_drv.h
index 9dc839c83c..1fc8df52ce 100644
--- a/drivers/net/ntnic/nthw/nthw_drv.h
+++ b/drivers/net/ntnic/nthw/nthw_drv.h
@@ -9,12 +9,20 @@
 #include "nthw_core.h"
 #include "ntnic_dbs.h"
 
+#include "nthw_si5332_si5156.h"
+#include "nthw_pcal6416a.h"
+#include "nthw_phy_tile.h"
 #include "nthw_rpf.h"
+#include "nthw_phy_tile.h"
 
 /*
  * Structs for controlling Agilex based NT400DXX adapter
  */
 typedef struct nthw_agx_s {
+	nthw_i2cm_t *p_i2cm;
+	nthw_pca9849_t *p_pca9849;
+	nthw_pcal6416a_t *p_io_nim;	/* PCAL6416A I/O expander for controlling TS */
+	nthw_phy_tile_t *p_phy_tile;
 	nthw_rpf_t *p_rpf;
 } nthw_agx_t;
 
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 05/32] net/ntnic: add host loopback init
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (3 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 04/32] net/ntnic: add agx setup for port Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 06/32] net/ntnic: add line " Serhii Iliushyk
                   ` (27 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Implement PHY line loopback configuration for Agilex FPGA

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../link_agx_100g/nt4ga_agx_link_100g.c       | 111 ++++++++++++++++++
 .../ntnic/nthw/core/include/nthw_phy_tile.h   |   1 +
 drivers/net/ntnic/nthw/core/nthw_phy_tile.c   |  28 +++++
 3 files changed, 140 insertions(+)

diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
index a6455ee598..f3862b7fe3 100644
--- a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -14,6 +14,11 @@
 #include "nthw_gfg.h"
 #include "nthw_phy_tile.h"
 
+typedef enum {
+	LOOPBACK_HOST_NONE,
+	LOOPBACK_HOST
+} loopback_host_t;
+
 static int nt4ga_agx_link_100g_ports_init(struct adapter_info_s *p_adapter_info,
 	nthw_fpga_t *fpga);
 
@@ -29,6 +34,65 @@ void link_agx_100g_init(void)
 	register_agx_100g_link_ops(&link_agx_100g_ops);
 }
 
+/*
+ * Phy handling
+ */
+
+static void phy_rx_path_rst(adapter_info_t *drv, int port, bool reset)
+{
+	nthw_phy_tile_t *p = drv->fpga_info.mp_nthw_agx.p_phy_tile;
+	NT_LOG(DBG, NTNIC, "Port %d: %s", port, reset ? "assert" : "deassert");
+	nthw_phy_tile_set_rx_reset(p, port, reset);
+}
+
+static void phy_tx_path_rst(adapter_info_t *drv, int port, bool reset)
+{
+	nthw_phy_tile_t *p = drv->fpga_info.mp_nthw_agx.p_phy_tile;
+	NT_LOG(DBG, NTNIC, "Port %d: %s", port, reset ? "assert" : "deassert");
+	nthw_phy_tile_set_tx_reset(p, port, reset);
+}
+
+static void phy_reset_rx(adapter_info_t *drv, int port)
+{
+	phy_rx_path_rst(drv, port, true);
+	nt_os_wait_usec(10000);	/* 10ms */
+	phy_rx_path_rst(drv, port, false);
+	nt_os_wait_usec(10000);	/* 10ms */
+}
+
+static void phy_reset_tx(adapter_info_t *drv, int port)
+{
+	phy_tx_path_rst(drv, port, true);
+	nt_os_wait_usec(10000);	/* 10ms */
+	phy_tx_path_rst(drv, port, false);
+	nt_os_wait_usec(10000);	/* 10ms */
+}
+
+static int phy_set_host_loopback(adapter_info_t *drv, int port, loopback_host_t loopback)
+{
+	nthw_phy_tile_t *p = drv->fpga_info.mp_nthw_agx.p_phy_tile;
+
+	switch (loopback) {
+	case LOOPBACK_HOST_NONE:
+		for (uint8_t lane = 0; lane < 4; lane++)
+			nthw_phy_tile_set_host_loopback(p, port, lane, false);
+
+		break;
+
+	case LOOPBACK_HOST:
+		for (uint8_t lane = 0; lane < 4; lane++)
+			nthw_phy_tile_set_host_loopback(p, port, lane, true);
+
+		break;
+
+	default:
+		NT_LOG(ERR, NTNIC, "Port %d: Unhandled loopback value (%d)", port, loopback);
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
  * Utility functions
  */
@@ -81,6 +145,40 @@ static int swap_tx_rx_polarity(adapter_info_t *drv, int port, bool swap)
 	return -1;
 }
 
+static void
+set_loopback(struct adapter_info_s *p_adapter_info, int port, uint32_t mode, uint32_t last_mode)
+{
+	switch (mode) {
+	case 1:
+		NT_LOG(INF, NTNIC, "%s: Applying host loopback",
+			p_adapter_info->mp_port_id_str[port]);
+		phy_set_host_loopback(p_adapter_info, port, LOOPBACK_HOST);
+		swap_tx_rx_polarity(p_adapter_info, port, false);
+		break;
+
+	default:
+		switch (last_mode) {
+		case 1:
+			NT_LOG(INF, NTNIC, "%s: Removing host loopback",
+				p_adapter_info->mp_port_id_str[port]);
+			phy_set_host_loopback(p_adapter_info, port, LOOPBACK_HOST_NONE);
+			swap_tx_rx_polarity(p_adapter_info, port, true);
+			break;
+
+		default:
+			/* do nothing */
+			break;
+		}
+
+		break;
+	}
+
+	/* After changing the loopback the system must be properly reset */
+	phy_reset_rx(p_adapter_info, port);
+	phy_reset_tx(p_adapter_info, port);
+	nt_os_wait_usec(10000);	/* 10ms - arbitrary choice */
+}
+
 /*
  * Link state machine
  */
@@ -146,6 +244,19 @@ static void *_common_ptp_nim_state_machine(void *data)
 			if (is_port_disabled)
 				continue;
 
+			if (link_info->port_action[i].port_lpbk_mode != last_lpbk_mode[i]) {
+				set_loopback(drv,
+					i,
+					link_info->port_action[i].port_lpbk_mode,
+					last_lpbk_mode[i]);
+
+				if (link_info->port_action[i].port_lpbk_mode == 1)
+					link_state[i].link_up = true;
+
+				last_lpbk_mode[i] = link_info->port_action[i].port_lpbk_mode;
+				continue;
+			}
+
 			link_state[i].link_disabled = is_port_disabled;
 
 			if (!link_state[i].nim_present) {
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
index 930c897046..5577f95944 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
@@ -52,6 +52,7 @@ void nthw_phy_tile_set_tx_pol_inv(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t l
 void nthw_phy_tile_set_rx_pol_inv(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane, bool invert);
 void nthw_phy_tile_set_host_loopback(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
 	bool enable);
+void nthw_phy_tile_set_tx_reset(nthw_phy_tile_t *p, uint8_t intf_no, bool reset);
 void nthw_phy_tile_set_rx_reset(nthw_phy_tile_t *p, uint8_t intf_no, bool reset);
 
 uint32_t nthw_phy_tile_read_xcvr(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
diff --git a/drivers/net/ntnic/nthw/core/nthw_phy_tile.c b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
index fd7a1e1214..6402e5caf3 100644
--- a/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
+++ b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
@@ -64,6 +64,34 @@ void nthw_phy_tile_set_rx_reset(nthw_phy_tile_t *p, uint8_t intf_no, bool reset)
 	}
 }
 
+void nthw_phy_tile_set_tx_reset(nthw_phy_tile_t *p, uint8_t intf_no, bool reset)
+{
+	/* Reset is active low */
+	nthw_field_get_updated(p->mp_fld_port_config_tx_reset[intf_no]);
+
+	if (reset) {
+		nthw_field_clr_flush(p->mp_fld_port_config_tx_reset[intf_no]);
+
+		/* Wait for ack */
+		if (p->mp_fld_port_status_tx_reset_ackn[intf_no]) {
+			int32_t count = 1000;
+
+			do {
+				nt_os_wait_usec(1000);	/* 1ms */
+			} while (nthw_field_get_updated(p->mp_fld_port_status_tx_reset_ackn
+				[intf_no]) && (--count > 0));
+
+			if (count <= 0) {
+				NT_LOG(ERR, NTHW, "intf_no %u: Time-out waiting for TxResetAck",
+					intf_no);
+			}
+		}
+
+	} else {
+		nthw_field_set_flush(p->mp_fld_port_config_tx_reset[intf_no]);
+	}
+}
+
 uint32_t nthw_phy_tile_read_xcvr(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
 	uint32_t address)
 {
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 06/32] net/ntnic: add line loopback init
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (4 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 05/32] net/ntnic: add host loopback init Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 07/32] net/ntnic: add 100 gbps port init Serhii Iliushyk
                   ` (26 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Implement PHY host loopback configuration for Agilex FPGA

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../link_agx_100g/nt4ga_agx_link_100g.c       | 116 ++++++++++++++++++
 drivers/net/ntnic/meson.build                 |   1 +
 drivers/net/ntnic/nim/i2c_nim.c               |  70 +++++++++--
 .../nthw/core/include/nthw_si5332_si5156.h    |   6 +
 .../net/ntnic/nthw/core/nthw_si5332_si5156.c  |  31 +++++
 5 files changed, 216 insertions(+), 8 deletions(-)
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c

diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
index f3862b7fe3..9551dfdfdc 100644
--- a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -19,6 +19,11 @@ typedef enum {
 	LOOPBACK_HOST
 } loopback_host_t;
 
+typedef enum {
+	LOOPBACK_LINE_NONE,
+	LOOPBACK_LINE
+} loopback_line_t;
+
 static int nt4ga_agx_link_100g_ports_init(struct adapter_info_s *p_adapter_info,
 	nthw_fpga_t *fpga);
 
@@ -93,6 +98,105 @@ static int phy_set_host_loopback(adapter_info_t *drv, int port, loopback_host_t
 	return 0;
 }
 
+static int phy_set_line_loopback(adapter_info_t *drv, int port, loopback_line_t loopback)
+{
+	nthw_phy_tile_t *p = drv->fpga_info.mp_nthw_agx.p_phy_tile;
+	uint32_t addr;
+
+	switch (loopback) {
+	case LOOPBACK_LINE_NONE:
+		for (uint8_t lane = 0; lane < 4; lane++) {
+			uint8_t quad_lane;
+
+			for (uint8_t fgt = 0; fgt < 4; fgt++) {
+				uint8_t quad_and_lane_no =
+					(uint8_t)nthw_phy_tile_read_xcvr(p, port, lane, 0xFFFFC);
+				quad_lane = quad_and_lane_no & 0x3;	/* bits[1:0] */
+
+				if (quad_lane == lane)
+					break;
+			}
+
+			nthw_phy_tile_write_xcvr(p, port, 0, 0x41830u + (0x8000u * quad_lane),
+				0x03);
+
+			addr = nthw_phy_tile_read_xcvr(p, 0, 0, 0x41768u + (0x8000u * quad_lane)) |
+				(1u << 24u);
+			nthw_phy_tile_write_xcvr(p, port, 0, 0x41768u + (0x8000u * quad_lane),
+				addr);
+
+			addr = nthw_phy_tile_read_xcvr(p, 0, 0, 0x41414u + (0x8000u * quad_lane)) &
+				~(1u << 29u);
+			nthw_phy_tile_write_xcvr(p, port, 0, 0x41414u + (0x8000u * quad_lane),
+				addr);
+
+			addr = nthw_phy_tile_read_xcvr(p, 0, 0, 0x4141Cu + (0x8000u * quad_lane)) &
+				~(1u << 30u);
+			nthw_phy_tile_write_xcvr(p, port, 0, 0x4141Cu + (0x8000u * quad_lane),
+				addr);
+
+			addr = nthw_phy_tile_read_xcvr(p, 0, 0, 0x41418u + (0x8000u * quad_lane)) &
+				~(1u << 31u);
+			nthw_phy_tile_write_xcvr(p, port, 0, 0x41418u + (0x8000u * quad_lane),
+				addr);
+		}
+
+		break;
+
+	case LOOPBACK_LINE:
+		for (uint8_t lane = 0; lane < 4; lane++) {
+			uint8_t quad_lane;
+
+			for (uint8_t fgt = 0; fgt < 4; fgt++) {
+				uint8_t quad_and_lane_no =
+					(uint8_t)nthw_phy_tile_read_xcvr(p, port, lane, 0xFFFFC);
+				quad_lane = quad_and_lane_no & 0x3;	/* bits[1:0] */
+
+				if (quad_lane == lane)
+					break;
+			}
+
+			addr = nthw_phy_tile_read_xcvr(p, port, 0,
+					0x41830u + (0x8000u * quad_lane)) &
+				0u;
+			nthw_phy_tile_write_xcvr(p, port, 0, 0x41830u + (0x8000u * quad_lane),
+				addr);
+
+			addr = nthw_phy_tile_read_xcvr(p, port, 0,
+					0x41768u + (0x8000u * quad_lane)) &
+				~(1u << 24u);
+			nthw_phy_tile_write_xcvr(p, port, 0, 0x41768u + (0x8000u * quad_lane),
+				addr);
+
+			addr = nthw_phy_tile_read_xcvr(p, port, 0,
+					0x41414u + (0x8000u * quad_lane)) |
+				(1u << 29u);
+			nthw_phy_tile_write_xcvr(p, port, 0, 0x41414u + (0x8000u * quad_lane),
+				addr);
+
+			addr = nthw_phy_tile_read_xcvr(p, port, 0,
+					0x4141Cu + (0x8000u * quad_lane)) |
+				(1u << 30u);
+			nthw_phy_tile_write_xcvr(p, port, 0, 0x4141Cu + (0x8000u * quad_lane),
+				addr);
+
+			addr = nthw_phy_tile_read_xcvr(p, port, 0,
+					0x41418u + (0x8000u * quad_lane)) |
+				(1u << 31u);
+			nthw_phy_tile_write_xcvr(p, port, 0, 0x41418u + (0x8000u * quad_lane),
+				addr);
+		}
+
+		break;
+
+	default:
+		NT_LOG(ERR, NTNIC, "Port %d: Unhandled loopback value (%d)", port, loopback);
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
  * Utility functions
  */
@@ -156,6 +260,12 @@ set_loopback(struct adapter_info_s *p_adapter_info, int port, uint32_t mode, uin
 		swap_tx_rx_polarity(p_adapter_info, port, false);
 		break;
 
+	case 2:
+		NT_LOG(INF, NTNIC, "%s: Applying line loopback",
+			p_adapter_info->mp_port_id_str[port]);
+		phy_set_line_loopback(p_adapter_info, port, LOOPBACK_LINE);
+		break;
+
 	default:
 		switch (last_mode) {
 		case 1:
@@ -165,6 +275,12 @@ set_loopback(struct adapter_info_s *p_adapter_info, int port, uint32_t mode, uin
 			swap_tx_rx_polarity(p_adapter_info, port, true);
 			break;
 
+		case 2:
+			NT_LOG(INF, NTNIC, "%s: Removing line loopback",
+				p_adapter_info->mp_port_id_str[port]);
+			phy_set_line_loopback(p_adapter_info, port, LOOPBACK_LINE_NONE);
+			break;
+
 		default:
 			/* do nothing */
 			break;
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 4799ebfb8e..271115cdd3 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -56,6 +56,7 @@ sources = files(
         'nthw/core/nthw_mac_pcs.c',
         'nthw/core/nthw_pcie3.c',
         'nthw/core/nthw_phy_tile.c',
+        'nthw/core/nthw_si5332_si5156.c',
         'nthw/core/nthw_rpf.c',
         'nthw/core/nthw_rmc.c',
         'nthw/core/nthw_sdc.c',
diff --git a/drivers/net/ntnic/nim/i2c_nim.c b/drivers/net/ntnic/nim/i2c_nim.c
index 7dbbdb8873..f3cca9e555 100644
--- a/drivers/net/ntnic/nim/i2c_nim.c
+++ b/drivers/net/ntnic/nim/i2c_nim.c
@@ -13,6 +13,12 @@
 #include "qsfp_registers.h"
 #include "nim_defines.h"
 
+int nim_agx_read_id(struct nim_i2c_ctx *ctx);
+static void nim_agx_read(struct nim_i2c_ctx *ctx, uint8_t dev_addr, uint8_t reg_addr,
+	uint8_t data_len, void *p_data);
+static void nim_agx_write(struct nim_i2c_ctx *ctx, uint8_t dev_addr, uint8_t reg_addr,
+	uint8_t data_len, void *p_data);
+
 #define NIM_READ false
 #define NIM_WRITE true
 #define NIM_PAGE_SEL_REGISTER 127
@@ -50,17 +56,17 @@ static int nim_read_write_i2c_data(nim_i2c_ctx_p ctx, bool do_write, uint16_t li
 		if (ctx->type == I2C_HWIIC) {
 			return nthw_iic_write_data(&ctx->hwiic, i2c_devaddr, a_reg_addr, seq_cnt,
 					p_data);
-
-		} else {
-			return 0;
 		}
 
-	} else if (ctx->type == I2C_HWIIC) {
-		return nthw_iic_read_data(&ctx->hwiic, i2c_devaddr, a_reg_addr, seq_cnt, p_data);
-
-	} else {
+		nim_agx_write(ctx, i2c_addr, a_reg_addr, seq_cnt, p_data);
 		return 0;
 	}
+
+	if (ctx->type == I2C_HWIIC)
+		return nthw_iic_read_data(&ctx->hwiic, i2c_devaddr, a_reg_addr, seq_cnt, p_data);
+
+	nim_agx_read(ctx, i2c_addr, a_reg_addr, seq_cnt, p_data);
+	return 0;
 }
 
 /*
@@ -216,7 +222,7 @@ static int i2c_nim_common_construct(nim_i2c_ctx_p ctx)
 		res = nim_read_id(ctx);
 
 	else
-		res = -1;
+		res = nim_agx_read_id(ctx);
 
 	if (res) {
 		NT_LOG(ERR, NTNIC, "Can't read NIM id.");
@@ -803,3 +809,51 @@ void nim_agx_setup(struct nim_i2c_ctx *ctx, nthw_pcal6416a_t *p_io_nim, nthw_i2c
 	ctx->hwagx.p_ca9849 = p_ca9849;
 	ctx->hwagx.p_io_nim = p_io_nim;
 }
+
+static void nim_agx_read(struct nim_i2c_ctx *ctx,
+	uint8_t dev_addr,
+	uint8_t reg_addr,
+	uint8_t data_len,
+	void *p_data)
+{
+	nthw_i2cm_t *p_nt_i2cm = ctx->hwagx.p_nt_i2cm;
+	nthw_pca9849_t *p_ca9849 = ctx->hwagx.p_ca9849;
+	uint8_t *data = (uint8_t *)p_data;
+
+	rte_spinlock_lock(&p_nt_i2cm->i2cmmutex);
+	nthw_pca9849_set_channel(p_ca9849, ctx->hwagx.mux_channel);
+
+	for (uint8_t i = 0; i < data_len; i++) {
+		nthw_i2cm_read(p_nt_i2cm, (uint8_t)(dev_addr >> 1), (uint8_t)(reg_addr + i), data);
+		data++;
+	}
+
+	rte_spinlock_unlock(&p_nt_i2cm->i2cmmutex);
+}
+
+static void nim_agx_write(struct nim_i2c_ctx *ctx,
+	uint8_t dev_addr,
+	uint8_t reg_addr,
+	uint8_t data_len,
+	void *p_data)
+{
+	nthw_i2cm_t *p_nt_i2cm = ctx->hwagx.p_nt_i2cm;
+	nthw_pca9849_t *p_ca9849 = ctx->hwagx.p_ca9849;
+	uint8_t *data = (uint8_t *)p_data;
+
+	rte_spinlock_lock(&p_nt_i2cm->i2cmmutex);
+	nthw_pca9849_set_channel(p_ca9849, ctx->hwagx.mux_channel);
+
+	for (uint8_t i = 0; i < data_len; i++) {
+		nthw_i2cm_write(p_nt_i2cm, (uint8_t)(dev_addr >> 1), (uint8_t)(reg_addr + i),
+			*data++);
+	}
+
+	rte_spinlock_unlock(&p_nt_i2cm->i2cmmutex);
+}
+
+int nim_agx_read_id(struct nim_i2c_ctx *ctx)
+{
+	nim_agx_read(ctx, 0xA0, 0, sizeof(ctx->nim_id), &ctx->nim_id);
+	return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h b/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
index fb44c62f12..968d7eb74a 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
@@ -6,13 +6,19 @@
 #ifndef __NTHW_SI5332_SI5156_H__
 #define __NTHW_SI5332_SI5156_H__
 
+#include "nthw_i2cm.h"
 /*
  * PCA9849 I2c mux class
  */
 
 struct nthw_pca9849 {
+	nthw_i2cm_t *mp_nt_i2cm;
+	uint8_t m_current_channel;
+	uint8_t m_dev_address;
 };
 
 typedef struct nthw_pca9849 nthw_pca9849_t;
 
+int nthw_pca9849_set_channel(nthw_pca9849_t *p, uint8_t channel);
+
 #endif	/* __NTHW_SI5332_SI5156_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c b/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
new file mode 100644
index 0000000000..b5560e2990
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
@@ -0,0 +1,31 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <pthread.h>
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_si5332_si5156.h"
+
+int nthw_pca9849_set_channel(nthw_pca9849_t *p, uint8_t channel)
+{
+	int res;
+
+	if (p->m_current_channel != channel) {
+		uint8_t data = channel + 4;
+		res = nthw_i2cm_write(p->mp_nt_i2cm, p->m_dev_address, 0, data);
+
+		if (res)
+			return res;
+
+		p->m_current_channel = channel;
+		nt_os_wait_usec(10000);
+	}
+
+	return 0;
+}
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 07/32] net/ntnic: add 100 gbps port init
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (5 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 06/32] net/ntnic: add line " Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 08/32] net/ntnic: add port post init Serhii Iliushyk
                   ` (25 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Initialize NIM and 100G port for Agilex FPGA

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../link_agx_100g/nt4ga_agx_link_100g.c       | 143 ++++++++++++++++++
 drivers/net/ntnic/meson.build                 |   1 +
 .../net/ntnic/nthw/core/include/nthw_gmf.h    |   2 +
 .../ntnic/nthw/core/include/nthw_pcal6416a.h  |  10 ++
 drivers/net/ntnic/nthw/core/nthw_gmf.c        |  41 +++++
 drivers/net/ntnic/nthw/core/nthw_pcal6416a.c  |  41 +++++
 6 files changed, 238 insertions(+)
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcal6416a.c

diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
index 9551dfdfdc..6593c90ca5 100644
--- a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -197,6 +197,26 @@ static int phy_set_line_loopback(adapter_info_t *drv, int port, loopback_line_t
 	return 0;
 }
 
+/*
+ * Nim handling
+ */
+
+static bool nim_is_present(nim_i2c_ctx_p ctx, uint8_t nim_idx)
+{
+	assert(nim_idx < NUM_ADAPTER_PORTS_MAX);
+
+	nthw_pcal6416a_t *p = ctx->hwagx.p_io_nim;
+	uint8_t data = 0;
+
+	if (nim_idx == 0)
+		nthw_pcal6416a_read(p, 3, &data);
+
+	else if (nim_idx == 1)
+		nthw_pcal6416a_read(p, 7, &data);
+
+	return data == 0;
+}
+
 /*
  * Utility functions
  */
@@ -295,6 +315,119 @@ set_loopback(struct adapter_info_s *p_adapter_info, int port, uint32_t mode, uin
 	nt_os_wait_usec(10000);	/* 10ms - arbitrary choice */
 }
 
+/*
+ * Initialize NIM, Code based on nt400d1x.cpp: MyPort::createNim()
+ */
+
+static int create_nim(adapter_info_t *drv, int port, bool enable)
+{
+	int res = 0;
+	const uint8_t valid_nim_id = NT_NIM_QSFP28;
+	sfp_nim_state_t nim;
+	nt4ga_link_t *link_info = &drv->nt4ga_link;
+	nim_i2c_ctx_t *nim_ctx = &link_info->u.nim_ctx[port];
+
+	assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX);
+	assert(link_info->variables_initialized);
+
+	if (!enable) {
+		phy_reset_rx(drv, port);
+		phy_reset_tx(drv, port);
+	}
+
+	/*
+	 * Wait a little after a module has been inserted before trying to access I2C
+	 * data, otherwise the module will not respond correctly.
+	 */
+	nt_os_wait_usec(1000000);	/* pause 1.0s */
+
+	res = construct_and_preinit_nim(nim_ctx, NULL);
+
+	if (res)
+		return res;
+
+	res = nim_state_build(nim_ctx, &nim);
+
+	if (res)
+		return res;
+
+	/* Set FEC to be enabled by default */
+	nim_ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ena = true;
+
+	NT_LOG(DBG, NTHW, "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'",
+		drv->mp_port_id_str[port], nim_ctx->nim_id, nim_id_to_text(nim_ctx->nim_id), nim.br,
+		nim_ctx->vendor_name, nim_ctx->prod_no, nim_ctx->serial_no);
+
+	/*
+	 * Does the driver support the NIM module type?
+	 */
+	if (nim_ctx->nim_id != valid_nim_id) {
+		NT_LOG(ERR, NTHW, "%s: The driver does not support the NIM module type %s",
+			drv->mp_port_id_str[port], nim_id_to_text(nim_ctx->nim_id));
+		NT_LOG(DBG, NTHW, "%s: The driver supports the NIM module type %s",
+			drv->mp_port_id_str[port], nim_id_to_text(valid_nim_id));
+		return -1;
+	}
+
+	return res;
+}
+
+/*
+ * Initialize one 100 Gbps port.
+ */
+static int _port_init(adapter_info_t *p_info, nthw_fpga_t *fpga, int port)
+{
+	uint8_t adapter_no = p_info->adapter_no;
+	int res;
+
+	nt4ga_link_t *link_info = &p_info->nt4ga_link;
+	nthw_gfg_t *p_gfg = &link_info->u.var_a100g.gfg[adapter_no];
+	nthw_phy_tile_t *p_phy_tile = p_info->fpga_info.mp_nthw_agx.p_phy_tile;
+	nthw_rpf_t *p_rpf = p_info->fpga_info.mp_nthw_agx.p_rpf;
+
+	assert(port >= 0 && port < NUM_ADAPTER_PORTS_MAX);
+	assert(link_info->variables_initialized);
+
+	link_info->link_info[port].link_speed = NT_LINK_SPEED_100G;
+	link_info->link_info[port].link_duplex = NT_LINK_DUPLEX_FULL;
+	link_info->link_info[port].link_auto_neg = NT_LINK_AUTONEG_OFF;
+	link_info->speed_capa |= NT_LINK_SPEED_100G;
+
+	nthw_gfg_stop(p_gfg, port);
+
+	for (uint8_t lane = 0; lane < 4; lane++)
+		nthw_phy_tile_set_host_loopback(p_phy_tile, port, lane, false);
+
+	swap_tx_rx_polarity(p_info, port, true);
+	nthw_rpf_set_ts_at_eof(p_rpf, true);
+
+	NT_LOG(DBG, NTNIC, "%s: Setting up port %d", p_info->mp_port_id_str[port], port);
+
+	phy_reset_rx(p_info, port);
+
+	if (nthw_gmf_init(NULL, fpga, port) == 0) {
+		nthw_gmf_t gmf;
+
+		if (nthw_gmf_init(&gmf, fpga, port) == 0)
+			nthw_gmf_set_enable_tsi(&gmf, true, 0, 0, false);
+	}
+
+	nthw_rpf_unblock(p_rpf);
+
+	res = create_nim(p_info, port, true);
+
+	if (res) {
+		NT_LOG(WRN, NTNIC, "%s: NIM initialization failed",
+			p_info->mp_port_id_str[port]);
+		return res;
+	}
+
+	NT_LOG(DBG, NTNIC, "%s: NIM initialized", p_info->mp_port_id_str[port]);
+
+	phy_reset_rx(p_info, port);
+	return res;
+}
+
 /*
  * Link state machine
  */
@@ -310,6 +443,7 @@ static void *_common_ptp_nim_state_machine(void *data)
 	/* link_state_t new_link_state; */
 
 	link_state_t *link_state = link_info->link_state;
+	nim_i2c_ctx_t *nim_ctx = link_info->u.var_a100g.nim_ctx;
 
 	if (!fpga) {
 		NT_LOG(ERR, NTNIC, "%s: fpga is NULL", drv->mp_adapter_id_str);
@@ -361,6 +495,15 @@ static void *_common_ptp_nim_state_machine(void *data)
 				continue;
 
 			if (link_info->port_action[i].port_lpbk_mode != last_lpbk_mode[i]) {
+				/* Loopback mode has changed. Do something */
+				if (!nim_is_present(&nim_ctx[i], i)) {
+					/*
+					 * If there is no Nim present, we need to initialize the
+					 * port  anyway
+					 */
+					_port_init(drv, fpga, i);
+				}
+
 				set_loopback(drv,
 					i,
 					link_info->port_action[i].port_lpbk_mode,
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 271115cdd3..b1505c5549 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -55,6 +55,7 @@ sources = files(
         'nthw/core/nthw_iic.c',
         'nthw/core/nthw_mac_pcs.c',
         'nthw/core/nthw_pcie3.c',
+        'nthw/core/nthw_pcal6416a.c',
         'nthw/core/nthw_phy_tile.c',
         'nthw/core/nthw_si5332_si5156.c',
         'nthw/core/nthw_rpf.c',
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_gmf.h b/drivers/net/ntnic/nthw/core/include/nthw_gmf.h
index cc5be85154..c8beb2117c 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_gmf.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_gmf.h
@@ -58,6 +58,8 @@ struct nthw_gmf {
 typedef struct nthw_gmf nthw_gmf_t;
 
 int nthw_gmf_init(nthw_gmf_t *p, nthw_fpga_t *p_fpga, int n_instance);
+void nthw_gmf_set_enable_tsi(nthw_gmf_t *p, bool enable, int tsi_dynamic_offset,
+	int tsi_static_offset, bool tsi_always);
 
 void nthw_gmf_set_enable(nthw_gmf_t *p, bool enable);
 
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h b/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
index 636d2beb85..5ef14a0bc9 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
@@ -7,13 +7,23 @@
 
 #include <stdint.h>
 
+#include "nthw_i2cm.h"
+#include "nthw_si5332_si5156.h"
+
 /*
  * PCAL6416A I/O expander class
  */
 
 struct nthw_pcal6416a {
+	nthw_i2cm_t *mp_nt_i2cm;
+	uint8_t m_dev_address;
+	nthw_pca9849_t *mp_ca9849;
+	uint8_t m_mux_channel;
+	uint8_t m_config_data[2];
 };
 
 typedef struct nthw_pcal6416a nthw_pcal6416a_t;
 
+void nthw_pcal6416a_read(nthw_pcal6416a_t *p, uint8_t pin, uint8_t *value);
+
 #endif	/* __NTHW_PCAL6416A_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_gmf.c b/drivers/net/ntnic/nthw/core/nthw_gmf.c
index 16a4c288bd..9fb708bc50 100644
--- a/drivers/net/ntnic/nthw/core/nthw_gmf.c
+++ b/drivers/net/ntnic/nthw/core/nthw_gmf.c
@@ -131,3 +131,44 @@ void nthw_gmf_set_enable(nthw_gmf_t *p, bool enable)
 	if (!p->m_administrative_block)
 		nthw_field_set_val_flush32(p->mp_ctrl_enable, enable ? 1 : 0);
 }
+
+void nthw_gmf_set_enable_tsi(nthw_gmf_t *p, bool enable, int tsi_dynamic_offset,
+	int tsi_static_offset, bool tsi_always)
+{
+	if (!p->m_administrative_block) {
+		nthw_field_update_register(p->mp_ctrl_enable);
+
+		if (p->mp_ctrl_ts_inject_always) {
+			/*
+			 * Do not force timestamp Inject- let the TBH control this now
+			 * Later we could consider an ini-setting for controlling this
+			 */
+			nthw_field_set_val_flush32(p->mp_ctrl_ts_inject_always,
+				tsi_always ? 1 : 0);
+		}
+
+		if (p->mp_ctrl_fcs_always) {
+			/*
+			 * Do not force FSC calculation - let the TBH control this
+			 * Later we could consider an ini-setting for controlling this
+			 */
+			nthw_field_set_val_flush32(p->mp_ctrl_fcs_always, 0);
+		}
+
+		if (p->mp_ts_inject) {
+			nthw_register_update(p->mp_ts_inject);
+
+			if (p->mp_ts_inject_pos) {
+				nthw_field_set_val_flush32(p->mp_ts_inject_pos,
+					(uint32_t)tsi_dynamic_offset);
+			}
+
+			if (p->mp_ts_inject_offset) {
+				nthw_field_set_val_flush32(p->mp_ts_inject_offset,
+					(uint32_t)tsi_static_offset);
+			}
+		}
+
+		nthw_field_set_val_flush32(p->mp_ctrl_enable, enable ? 1 : 0);
+	}
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c b/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
new file mode 100644
index 0000000000..37b6e7ec57
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
@@ -0,0 +1,41 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+#include <pthread.h>
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_pcal6416a.h"
+
+static const uint8_t read_port[2] = { 0x00, 0x01 };
+
+/*
+ * PCAL6416A I/O expander class
+ */
+
+void nthw_pcal6416a_read(nthw_pcal6416a_t *p, uint8_t pin, uint8_t *value)
+{
+	uint8_t port;
+	uint8_t data;
+
+	rte_spinlock_lock(&p->mp_nt_i2cm->i2cmmutex);
+	nthw_pca9849_set_channel(p->mp_ca9849, p->m_mux_channel);
+
+	if (pin < 8) {
+		port = 0;
+
+	} else {
+		port = 1;
+		pin = (uint8_t)(pin - 8);
+	}
+
+	nthw_i2cm_read(p->mp_nt_i2cm, p->m_dev_address, read_port[port], &data);
+
+	*value = (data >> pin) & 0x1;
+	rte_spinlock_unlock(&p->mp_nt_i2cm->i2cmmutex);
+}
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 08/32] net/ntnic: add port post init
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (6 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 07/32] net/ntnic: add 100 gbps port init Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 09/32] net/ntnic: add nim low power API Serhii Iliushyk
                   ` (24 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Configure FEC and TX equalization for 100G NIM on Agilex FPGA

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../link_agx_100g/nt4ga_agx_link_100g.c       | 122 ++++++++
 drivers/net/ntnic/nim/i2c_nim.c               |  80 +++++
 drivers/net/ntnic/nim/i2c_nim.h               |   3 +
 .../ntnic/nthw/core/include/nthw_phy_tile.h   |  25 ++
 drivers/net/ntnic/nthw/core/nthw_phy_tile.c   | 295 ++++++++++++++++++
 5 files changed, 525 insertions(+)

diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
index 6593c90ca5..fe2acef612 100644
--- a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -372,6 +372,121 @@ static int create_nim(adapter_info_t *drv, int port, bool enable)
 	return res;
 }
 
+static int nim_ready_100_gb(adapter_info_t *p_info, int port)
+{
+	nt4ga_link_t *link_info = &p_info->nt4ga_link;
+	nim_i2c_ctx_t *nim_ctx = &link_info->u.nim_ctx[port];
+	nthw_phy_tile_t *p_phy_tile = p_info->fpga_info.mp_nthw_agx.p_phy_tile;
+
+	bool disable_fec_by_port_type = (nim_ctx->port_type == NT_PORT_TYPE_QSFP28_LR4);
+	bool enable_fec = nim_ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ena &&
+		!disable_fec_by_port_type;
+
+	NT_LOG(DBG, NTNIC, "Port %s: DisableFec = %d", p_info->mp_port_id_str[port], !enable_fec);
+	/*
+	 * FecAutonegotiation at 100G is not supported for Napatech adapters and therefore
+	 * not relevant at this speed
+	 */
+
+	/* Adjust NIM power level */
+	if (nim_ctx->pwr_level_req > 4) {
+		qsfp28_set_high_power(nim_ctx);
+		nim_ctx->pwr_level_cur = nim_ctx->pwr_level_req;
+	}
+
+	/* enable_fec is what the end result should be, now find out if it's possible */
+	if (enable_fec) {
+		if (qsfp28_set_fec_enable(nim_ctx, true, false)) {
+			/* Prefer NIM media FEC since the NIM is assumed to know the right FEC */
+			NT_LOG(DBG, NTNIC, "Port %s: NIM media FEC enabled",
+				p_info->mp_port_id_str[port]);
+
+			/* The NIM has been set to FEC on the media side so turn FPGA FEC off */
+			if (nthw_phy_tile_configure_fec(p_phy_tile, port, true)) {
+				NT_LOG(DBG, NTNIC, "Port %s: FPGA FEC disabled",
+					p_info->mp_port_id_str[port]);
+
+			} else {
+				NT_LOG(DBG, NTNIC,
+					"Port %s: FPGA does not support disabling of FEC",
+					p_info->mp_port_id_str[port]);
+				return 1;
+			}
+
+		} else if (qsfp28_set_fec_enable(nim_ctx, false, false)) {
+			/* The NIM does not support FEC at all so turn FPGA FEC on instead */
+			/* This is relevant to SR4 modules */
+			NT_LOG(DBG, NTNIC, "Port %s: No NIM FEC", p_info->mp_port_id_str[port]);
+			nthw_phy_tile_configure_fec(p_phy_tile, port, false);
+			NT_LOG(DBG, NTNIC, "Port %s: FPGA FEC enabled",
+				p_info->mp_port_id_str[port]);
+
+		} else if (qsfp28_set_fec_enable(nim_ctx, true, true)) {
+			/* This probably not a likely scenario */
+			nthw_phy_tile_configure_fec(p_phy_tile, port, false);
+			NT_LOG(DBG, NTNIC, "Port %s: FPGA FEC enabled",
+				p_info->mp_port_id_str[port]);
+			NT_LOG(DBG, NTNIC, "Port %s: FPGA FEC terminated, NIM media FEC enabled",
+				p_info->mp_port_id_str[port]);
+
+		} else {
+			NT_LOG(ERR, NTNIC, "Port %s: Could not enable FEC",
+				p_info->mp_port_id_str[port]);
+			return 1;
+		}
+
+	} else if (qsfp28_set_fec_enable(nim_ctx, false, false)) {
+		/* The NIM does not support FEC at all - this is relevant to LR4 modules */
+		NT_LOG(DBG, NTNIC, "Port %s: No NIM FEC", p_info->mp_port_id_str[port]);
+
+		if (nthw_phy_tile_configure_fec(p_phy_tile, port, true)) {
+			NT_LOG(DBG, NTNIC, "Port %s: FPGA FEC disabled",
+				p_info->mp_port_id_str[port]);
+
+		} else {
+			NT_LOG(ERR, NTNIC, "Port %s: FPGA does not support disabling of FEC",
+				p_info->mp_port_id_str[port]);
+			return 1;
+		}
+
+	} else if (qsfp28_set_fec_enable(nim_ctx, false, true)) {
+		nthw_phy_tile_configure_fec(p_phy_tile, port, false);
+		/* This probably not a likely scenario */
+		NT_LOG(DBG, NTNIC, "Port %s: FPGA FEC enabled", p_info->mp_port_id_str[port]);
+		NT_LOG(DBG, NTNIC, "Port %s: FPGA FEC terminated, NIM media FEC disabled",
+			p_info->mp_port_id_str[port]);
+
+	} else {
+		NT_LOG(ERR, NTNIC, "Port %s: Could not disable FEC",
+			p_info->mp_port_id_str[port]);
+		return 1;
+	}
+
+	if (port == 0) {
+		/* setTxEqualization(uint8_t intf_no, uint8_t lane, uint32_t pre_tap2,
+		 * uint32_t main_tap, uint32_t pre_tap1, uint32_t post_tap1)
+		 */
+		nthw_phy_tile_set_tx_equalization(p_phy_tile, port, 0, 0, 44, 2, 9);
+		nthw_phy_tile_set_tx_equalization(p_phy_tile, port, 1, 0, 44, 2, 9);
+		nthw_phy_tile_set_tx_equalization(p_phy_tile, port, 2, 0, 44, 2, 9);
+		nthw_phy_tile_set_tx_equalization(p_phy_tile, port, 3, 0, 44, 2, 9);
+
+	} else {
+		nthw_phy_tile_set_tx_equalization(p_phy_tile, port, 0, 0, 44, 2, 9);
+		nthw_phy_tile_set_tx_equalization(p_phy_tile, port, 1, 0, 44, 2, 9);
+		nthw_phy_tile_set_tx_equalization(p_phy_tile, port, 2, 0, 44, 2, 9);
+		nthw_phy_tile_set_tx_equalization(p_phy_tile, port, 3, 0, 44, 2, 9);
+	}
+
+	/*
+	 * Perform a full reset. If the RX is in reset from the start this sequence will
+	 * take it out of reset and this is necessary in order to read block/lane lock
+	 * in getLinkState()
+	 */
+	phy_reset_rx(p_info, port);
+	return 0;
+}
+
 /*
  * Initialize one 100 Gbps port.
  */
@@ -424,6 +539,13 @@ static int _port_init(adapter_info_t *p_info, nthw_fpga_t *fpga, int port)
 
 	NT_LOG(DBG, NTNIC, "%s: NIM initialized", p_info->mp_port_id_str[port]);
 
+	res = nim_ready_100_gb(p_info, port);
+
+	if (res) {
+		NT_LOG(WRN, NTNIC, "%s: NIM failed to get ready", p_info->mp_port_id_str[port]);
+		return res;
+	}
+
 	phy_reset_rx(p_info, port);
 	return res;
 }
diff --git a/drivers/net/ntnic/nim/i2c_nim.c b/drivers/net/ntnic/nim/i2c_nim.c
index f3cca9e555..892e1b58b7 100644
--- a/drivers/net/ntnic/nim/i2c_nim.c
+++ b/drivers/net/ntnic/nim/i2c_nim.c
@@ -192,6 +192,13 @@ static int read_data_lin(nim_i2c_ctx_p ctx, uint16_t lin_addr, uint16_t length,
 			NIM_READ);
 }
 
+static int write_data_lin(nim_i2c_ctx_p ctx, uint16_t lin_addr, uint16_t length, void *data)
+{
+	/* Wrapper for using Mutex for QSFP TODO */
+	return nim_read_write_data_lin(ctx, page_addressing(ctx->nim_id), lin_addr, length, data,
+		NIM_WRITE);
+}
+
 /* Read and return a single byte */
 static uint8_t read_byte(nim_i2c_ctx_p ctx, uint16_t addr)
 {
@@ -802,6 +809,79 @@ int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra)
 	return res;
 }
 
+/*
+ * Enables high power according to SFF-8636 Rev 2.7, Table 6-9, Page 35:
+ * When set (= 1b) enables Power Classes 5 to 7 in Byte 129 to exceed 3.5W.
+ * When cleared (= 0b), modules with power classes 5 to 7 must dissipate less
+ * than 3.5W (but are not required to be fully functional). Default 0.
+ */
+void qsfp28_set_high_power(nim_i2c_ctx_p ctx)
+{
+	const uint16_t addr = 93;
+	uint8_t data;
+
+	/* Enable high power class; Set Page 00h, Byte 93 bit 2 to 1 */
+	read_data_lin(ctx, addr, sizeof(data), &data);
+	data |= (1 << 2);
+	write_data_lin(ctx, addr, sizeof(data), &data);
+}
+
+/*
+ * Enable FEC on media and/or host side. If the operation could be carried out
+ * return true. For some modules media side FEC is enabled but cannot be changed
+ *  while others allow changing the FEC state.
+ * For LR4 modules write operations (which are also not necessary) to the control
+ *  register must be avoided as this introduces I2C errors on NT200A01.
+ */
+
+bool qsfp28_set_fec_enable(nim_i2c_ctx_p ctx, bool media_side_fec, bool host_side_fec)
+{
+	/*
+	 * If the current FEC state does not match the wanted and the FEC cannot be
+	 * controlled then the operation cannot be carried out
+	 */
+	if (ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ena != media_side_fec &&
+		!ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ctrl)
+		return false;
+
+	if (ctx->specific_u.qsfp.specific_u.qsfp28.host_side_fec_ena != host_side_fec &&
+		!ctx->specific_u.qsfp.specific_u.qsfp28.host_side_fec_ctrl)
+		return false;
+
+	/*
+	 * If the current media and host side FEC state matches the wanted states then
+	 * no need to do more
+	 */
+	if (ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ena == media_side_fec &&
+		ctx->specific_u.qsfp.specific_u.qsfp28.host_side_fec_ena == host_side_fec)
+		return true;
+
+	/*
+	 * SFF-8636, Rev 2.10a TABLE 6-29 Optional Channel Control)
+	 * (Page 03h, Bytes 230-241)
+	 */
+	const uint16_t addr = 230 + 3 * 128;
+	uint8_t data = 0;
+	read_data_lin(ctx, addr, sizeof(data), &data);
+
+	if (media_side_fec)
+		data &= (uint8_t)(~(1 << 6));
+
+	else
+		data |= (uint8_t)(1 << 6);
+
+	if (host_side_fec)
+		data |= (uint8_t)(1 << 7);
+
+	else
+		data &= (uint8_t)(~(1 << 7));
+
+	write_data_lin(ctx, addr, sizeof(data), &data);
+	ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ena = media_side_fec;
+	ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ena = host_side_fec;
+	return true;
+}
+
 void nim_agx_setup(struct nim_i2c_ctx *ctx, nthw_pcal6416a_t *p_io_nim, nthw_i2cm_t *p_nt_i2cm,
 	nthw_pca9849_t *p_ca9849)
 {
diff --git a/drivers/net/ntnic/nim/i2c_nim.h b/drivers/net/ntnic/nim/i2c_nim.h
index 09837448c6..888b709135 100644
--- a/drivers/net/ntnic/nim/i2c_nim.h
+++ b/drivers/net/ntnic/nim/i2c_nim.h
@@ -33,6 +33,9 @@ int nim_qsfp_plus_nim_set_tx_laser_disable(nim_i2c_ctx_t *ctx, bool disable, int
  */
 int construct_and_preinit_nim(nim_i2c_ctx_p ctx, void *extra);
 
+void qsfp28_set_high_power(nim_i2c_ctx_p ctx);
+bool qsfp28_set_fec_enable(nim_i2c_ctx_p ctx, bool media_side_fec, bool host_side_fec);
+
 void nim_agx_setup(struct nim_i2c_ctx *ctx, nthw_pcal6416a_t *p_io_nim, nthw_i2cm_t *p_nt_i2cm,
 	nthw_pca9849_t *p_ca9849);
 
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
index 5577f95944..c810f55c0d 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
@@ -34,15 +34,34 @@ struct nt_phy_tile {
 	nthw_field_t *mp_fld_link_summary_nt_phy_link_state[2];
 	nthw_field_t *mp_fld_link_summary_ll_nt_phy_link_state[2];
 	nthw_field_t *mp_fld_link_summary_link_down_cnt[2];
+	nthw_field_t *mp_fld_link_summary_lh_received_local_fault[2];
 	nthw_field_t *mp_fld_link_summary_lh_remote_fault[2];
 
+	nthw_field_t *mp_fld_port_status_rx_hi_ber[2];
+	nthw_field_t *mp_fld_port_status_rx_am_lock[2];
 	nthw_field_t *mp_fld_port_status_tx_reset_ackn[2];
 	nthw_field_t *mp_fld_port_status_rx_reset_ackn[2];
 
+	nthw_field_t *mp_fld_port_config_reset[2];
 	nthw_field_t *mp_fld_port_config_rx_reset[2];
 	nthw_field_t *mp_fld_port_config_tx_reset[2];
 
+	nthw_field_t *mp_fld_port_comp_rx_compensation[2];
+
+	nthw_register_t *mp_reg_dyn_reconfig_base;
+	nthw_field_t *mp_fld_dyn_reconfig_base_ptr;
+	nthw_field_t *mp_fld_dyn_reconfig_base_busy;
+	nthw_field_t *mp_fld_dyn_reconfig_base_cmd;
+
+	nthw_register_t *mp_reg_dyn_reconfig_data;
+	nthw_field_t *mp_fld_dyn_reconfig_data_data;
+
 	nthw_field_t *mp_fld_scratch_data;
+
+	nthw_register_t *mp_reg_dr_cfg_status;
+	nthw_field_t *mp_fld_dr_cfg_status_curr_profile_id;
+	nthw_field_t *mp_fld_dr_cfg_status_in_progress;
+	nthw_field_t *mp_fld_dr_cfg_status_error;
 };
 
 typedef struct nt_phy_tile nthw_phy_tile_t;
@@ -52,9 +71,15 @@ void nthw_phy_tile_set_tx_pol_inv(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t l
 void nthw_phy_tile_set_rx_pol_inv(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane, bool invert);
 void nthw_phy_tile_set_host_loopback(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
 	bool enable);
+void nthw_phy_tile_set_tx_equalization(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
+	uint32_t pre_tap2, uint32_t main_tap, uint32_t pre_tap1,
+	uint32_t post_tap1);
 void nthw_phy_tile_set_tx_reset(nthw_phy_tile_t *p, uint8_t intf_no, bool reset);
 void nthw_phy_tile_set_rx_reset(nthw_phy_tile_t *p, uint8_t intf_no, bool reset);
 
+uint32_t nthw_phy_tile_read_eth(nthw_phy_tile_t *p, uint8_t intf_no, uint32_t address);
+void nthw_phy_tile_write_eth(nthw_phy_tile_t *p, uint8_t intf_no, uint32_t address, uint32_t data);
+bool nthw_phy_tile_configure_fec(nthw_phy_tile_t *p, uint8_t intf_no, bool enable);
 uint32_t nthw_phy_tile_read_xcvr(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
 	uint32_t address);
 void nthw_phy_tile_write_xcvr(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane, uint32_t address,
diff --git a/drivers/net/ntnic/nthw/core/nthw_phy_tile.c b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
index 6402e5caf3..42e2782f99 100644
--- a/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
+++ b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
@@ -14,10 +14,15 @@
 
 static const uint32_t link_addr = 0x9003C;
 static const uint32_t phy_addr = 0x90040;
+static const uint32_t tx_eq_addr = 0x47830;
 /* CPI option flags */
 static const uint32_t cpi_set = 0x2000;	/* 1 << 13 */
 static const uint32_t cpi_in_reset = 0x4000;	/* 1 << 14 */
 static const uint32_t bit_cpi_assert = 0x8000;	/* 1 << 15 */
+static const uint32_t dyn_rcfg_dr_trigger_reg;
+static const uint32_t dyn_rcfg_dr_next_profile_0_reg = 0x4;
+static const uint32_t dyn_rcfg_dr_next_profile_1_reg = 0x8;
+static const uint32_t dyn_rcfg_dr_next_profile_2_reg = 0xc;
 /*
  * Base Addresses for Avalon MM Secondary Components
  * static const uint32_t ADDR_AVMM_DR_CTRL_INT                  =  0x10035000 << 0;
@@ -35,6 +40,21 @@ static const uint32_t bit_cpi_assert = 0x8000;	/* 1 << 15 */
  *
  * ETH AVMM USER SPACE Registers Address Map
  */
+static const uint32_t eth_soft_csr1 = 0x200;
+static const uint32_t eth_soft_csr2 = 0x204;
+static const uint32_t eth_soft_csr3 = 0x208;
+
+static void nthw_phy_tile_set_reset(nthw_phy_tile_t *p, uint8_t intf_no, bool reset)
+{
+	/* Reset is active low */
+	nthw_field_get_updated(p->mp_fld_port_config_reset[intf_no]);
+
+	if (reset)
+		nthw_field_clr_flush(p->mp_fld_port_config_reset[intf_no]);
+
+	else
+		nthw_field_set_flush(p->mp_fld_port_config_reset[intf_no]);
+}
 
 void nthw_phy_tile_set_rx_reset(nthw_phy_tile_t *p, uint8_t intf_no, bool reset)
 {
@@ -118,6 +138,38 @@ void nthw_phy_tile_write_xcvr(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
 		nt_os_wait_usec(100);
 }
 
+static uint32_t nthw_phy_tile_read_dyn_reconfig(nthw_phy_tile_t *p, uint32_t address)
+{
+	nthw_register_update(p->mp_reg_dyn_reconfig_base);
+	nthw_field_set_val32(p->mp_fld_dyn_reconfig_base_cmd, 0);
+	nthw_field_set_val_flush32(p->mp_fld_dyn_reconfig_base_ptr, address);
+
+	while (nthw_field_get_updated(p->mp_fld_dyn_reconfig_base_busy) == 1)
+		nt_os_wait_usec(100);
+
+	uint32_t value = nthw_field_get_updated(p->mp_fld_dyn_reconfig_data_data);
+	/*
+	 * NT_LOG(INF, NTHW, "nthw_phy_tile_read_dyn_reconfig address %0x value,
+	 * %0x", address, value);
+	 */
+	return value;
+	/* return nthw_field_get_updated(p->mp_fld_dyn_reconfig_data_data); */
+}
+
+static void nthw_phy_tile_write_dyn_reconfig(nthw_phy_tile_t *p, uint32_t address, uint32_t data)
+{
+	nthw_register_update(p->mp_reg_dyn_reconfig_data);
+	nthw_field_set_val_flush32(p->mp_fld_dyn_reconfig_data_data, data);
+
+	nthw_register_update(p->mp_reg_dyn_reconfig_base);
+	nthw_field_set_val32(p->mp_fld_dyn_reconfig_base_ptr, address);
+	nthw_field_set_val_flush32(p->mp_fld_dyn_reconfig_base_cmd, 1);
+
+	while (nthw_field_get_updated(p->mp_fld_dyn_reconfig_base_busy) == 1)
+		/* NT_LOG(INF, NTHW, "busy"); */
+		nt_os_wait_usec(100);
+}
+
 static uint32_t nthw_phy_tile_cpi_request(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
 	uint32_t data, uint8_t op_code, uint32_t cpi_assert,
 	uint32_t cpi_set_get)
@@ -199,3 +251,246 @@ void nthw_phy_tile_set_host_loopback(nthw_phy_tile_t *p, uint8_t intf_no, uint8_
 	 * intf_no, lane, enable);
 	 */
 }
+
+void nthw_phy_tile_set_tx_equalization(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
+	uint32_t pre_tap2, uint32_t main_tap, uint32_t pre_tap1,
+	uint32_t post_tap1)
+{
+	uint32_t data = (pre_tap2 << 16) + (main_tap << 10) + (pre_tap1 << 5) + (post_tap1);
+	NT_LOG(DBG, NTHW,
+		"intf_no %u: setTxEq lane %u, pre_tap2 %u, main_tap %u, pre_tap1 %u, post_tap1 %u data %x",
+		intf_no, lane, pre_tap2, main_tap, pre_tap1, post_tap1, data);
+	nthw_phy_tile_write_xcvr(p, intf_no, lane, tx_eq_addr + 0x8000U * lane, data);
+}
+
+static bool nthw_phy_tile_read_fec_enabled_by_scratch(nthw_phy_tile_t *p, uint8_t intf_no)
+{
+	bool fec_enabled = false;
+
+	if (p->mp_fld_scratch_data) {
+		fec_enabled =
+			!((nthw_field_get_updated(p->mp_fld_scratch_data) >> (intf_no)) & 0x1);
+	}
+
+	/*
+	 * log(INF,"intf_no: %d FEC state read from inverted port specificscratch register
+	 * value %u ", intf_no,fec_enabled);
+	 */
+	return fec_enabled;
+}
+
+static void nthw_phy_tile_write_fec_enabled_by_scratch(nthw_phy_tile_t *p, uint8_t intf_no,
+	bool fec_enabled)
+{
+	const uint8_t mask = intf_no == 0U ? 0xf0U : 0xfU;
+	const uint8_t status_other_port =
+		(uint8_t)(nthw_field_get_updated(p->mp_fld_scratch_data) & mask);
+	const uint8_t disablebit = (uint8_t)(1U << (4 * intf_no));
+	const uint8_t val =
+		fec_enabled ? status_other_port : (uint8_t)(status_other_port | disablebit);
+	/*  NT_LOG(INF, NTHW, "intf_no: %u write ScratchFEC value %u", intf_no, val); */
+	nthw_field_set_val_flush32(p->mp_fld_scratch_data, val);
+}
+
+uint32_t nthw_phy_tile_read_eth(nthw_phy_tile_t *p, uint8_t intf_no, uint32_t address)
+{
+	nthw_register_update(p->mp_reg_port_eth_base[intf_no]);
+	nthw_field_set_val32(p->mp_fld_port_eth_base_cmd[intf_no], 0);
+	nthw_field_set_val_flush32(p->mp_fld_port_eth_base_ptr[intf_no], address);
+
+	while (nthw_field_get_updated(p->mp_fld_port_eth_base_busy[intf_no]) == 1)
+		nt_os_wait_usec(100);
+
+	return nthw_field_get_updated(p->mp_fld_port_eth_data_data[intf_no]);
+}
+
+void nthw_phy_tile_write_eth(nthw_phy_tile_t *p, uint8_t intf_no, uint32_t address, uint32_t data)
+{
+	nthw_field_set_val_flush32(p->mp_fld_port_eth_data_data[intf_no], data);
+	nthw_register_update(p->mp_reg_port_eth_base[intf_no]);
+	nthw_field_set_val32(p->mp_fld_port_eth_base_ptr[intf_no], address);
+	nthw_field_set_val_flush32(p->mp_fld_port_eth_base_cmd[intf_no], 1);
+
+	while (nthw_field_get_updated(p->mp_fld_port_eth_base_busy[intf_no]) == 1)
+		/* NT_LOG(INF, NTHW, "busy"); */
+		nt_os_wait_usec(100);
+}
+
+bool nthw_phy_tile_configure_fec(nthw_phy_tile_t *p, uint8_t intf_no, bool enable)
+{
+	/*
+	 * FPGA must have the Dynamic Reconfig register for FEC configuration to work.
+	 * Previous versions of the FPGA enable FEC statically.
+	 */
+	if (!p->mp_reg_dyn_reconfig_base)
+		return false;
+
+	/*
+	 * NT_LOG(INF, NTHW, "void nthw_phy_tile_configure_fec(intf_no %u, enable %u)",
+	 * intf_no, enable);
+	 */
+
+	/* Available DR profiles related to FEC */
+	/* Used as end symbol in profile sequence fed to NIOS processor - not really a profile. */
+	const uint32_t neutral_dr_profile = 0;
+
+	/* DR Fec profiles port 0*/
+	const uint32_t intf_no0_with_fec_dr_profile = 1;
+	const uint32_t intf_no0_no_fec_dr_profile = 2;
+
+	/* DR Fec profiles port 1 */
+	const uint32_t intf_no1_with_fec_dr_profile = 3;
+	const uint32_t intf_no1_no_fec_dr_profile = 4;
+
+	const uint32_t fec_profile_none = 0x00;
+	const uint32_t fec_profile_cl91 = 0x02;
+
+	uint32_t original_dr_profile_id = 0x00;
+	uint32_t destination_dr_profile_id = 0x00;
+	uint32_t final_fec_profile = 0x00;
+
+	if (intf_no == 0) {
+		original_dr_profile_id =
+			enable ? intf_no0_no_fec_dr_profile : intf_no0_with_fec_dr_profile;
+		destination_dr_profile_id =
+			enable ? intf_no0_with_fec_dr_profile : intf_no0_no_fec_dr_profile;
+
+	} else if (intf_no == 1) {
+		original_dr_profile_id =
+			enable ? intf_no1_no_fec_dr_profile : intf_no1_with_fec_dr_profile;
+		destination_dr_profile_id =
+			enable ? intf_no1_with_fec_dr_profile : intf_no1_no_fec_dr_profile;
+	}
+
+	final_fec_profile = enable ? fec_profile_cl91 : fec_profile_none;
+
+	/*
+	 * These steps are copied from a code example provided by Intel: ftile_eth_dr_test.tcl
+	 * Step 6: Program DUT soft CSR
+	 * The CSR registers are reset by the FPGA reset sequence so
+	 * they need to be set every time the driver is restarted.
+	 * This is why we perform step 6 first before step 1.
+	 */
+	uint32_t current_fec_profile = nthw_phy_tile_read_eth(p, intf_no, eth_soft_csr2);
+
+	if (current_fec_profile != final_fec_profile) {
+		nthw_phy_tile_set_reset(p, intf_no, true);
+		nthw_phy_tile_set_tx_reset(p, intf_no, true);
+		NT_LOG(DBG, NTHW, "intf_no %u: Program DUT soft CSR", intf_no);
+		/* Select profile */
+		nthw_phy_tile_write_eth(p, intf_no, eth_soft_csr1, 0x00);
+
+		/* Select FEC-Mode */
+		nthw_phy_tile_write_eth(p, intf_no, eth_soft_csr2,
+			(0 << 9) + (0 << 6) + (0 << 3) + (final_fec_profile << 0));
+
+		nt_os_wait_usec(10000);
+		nthw_phy_tile_set_reset(p, intf_no, false);
+		nthw_phy_tile_set_tx_reset(p, intf_no, false);
+
+		NT_LOG(DBG, NTHW, "intf_no %u: Register eth_soft_csr1 profile_sel: 0x%2.2x",
+			intf_no, nthw_phy_tile_read_eth(p, intf_no, eth_soft_csr1));
+		NT_LOG(DBG, NTHW, "intf_no %u: Register eth_soft_csr2 fec_mode:    0x%2.2x",
+			intf_no, nthw_phy_tile_read_eth(p, intf_no, eth_soft_csr2));
+		NT_LOG(DBG, NTHW, "intf_no %u: Register eth_soft_csr3 sel:         0x%2.2x",
+			intf_no, nthw_phy_tile_read_eth(p, intf_no, eth_soft_csr3));
+	}
+
+	/*
+	 * The FEC profile applied with Dynamic Reconfiguration is persistent through
+	 * a driver restart. Additionally, the operation is not idempotent, meaning that
+	 * the operations must only be performed when actual reconfiguration is necessary.
+	 * We use a persistent scratch register provided by the FPGA to store the FEC
+	 * state since we have not been able to get any of the methods suggested
+	 * by Intel to function properly.
+	 */
+	if (nthw_phy_tile_read_fec_enabled_by_scratch(p, intf_no) == enable)
+		return true;
+
+	/* Step 1: Wait for DR NIOS to be ready */
+	NT_LOG(DBG, NTHW, "intf_no %u: Step 1 Wait for DR NIOS", intf_no);
+
+	while ((nthw_phy_tile_read_dyn_reconfig(p, dyn_rcfg_dr_trigger_reg) & 0x02) != 0x02)
+		nt_os_wait_usec(10000);
+
+	/* Step 2: Triggering Reconfiguration */
+	NT_LOG(DBG, NTHW, "intf_no %u: Step 2: Triggering Reconfiguration", intf_no);
+
+	nthw_phy_tile_set_reset(p, intf_no, true);
+	nthw_phy_tile_set_rx_reset(p, intf_no, true);
+	nthw_phy_tile_set_tx_reset(p, intf_no, true);
+	nt_os_wait_usec(10000);
+
+	/* Disable original profile */
+	nthw_phy_tile_write_dyn_reconfig(p, dyn_rcfg_dr_next_profile_0_reg,
+		(1U << 18) + (0U << 15) + original_dr_profile_id);
+	nt_os_wait_usec(10000);
+	NT_LOG(DBG, NTHW, "intf_no %u: dyn_rcfg_dr_next_profile_0_reg: %#010x", intf_no,
+		nthw_phy_tile_read_dyn_reconfig(p, dyn_rcfg_dr_next_profile_0_reg));
+
+	nthw_phy_tile_write_dyn_reconfig(p, dyn_rcfg_dr_next_profile_1_reg,
+		(1U << 15) + destination_dr_profile_id + (0U << 31) +
+		(neutral_dr_profile << 16));
+	/*
+	 * Enable profile 2 and terminate dyn reconfig by
+	 * setting next profile to 0 and deactivate it
+	 */
+	nt_os_wait_usec(10000);
+	NT_LOG(DBG, NTHW, "intf_no %u: dyn_rcfg_dr_next_profile_1_reg: %#010x", intf_no,
+		nthw_phy_tile_read_dyn_reconfig(p, dyn_rcfg_dr_next_profile_1_reg));
+
+	/*
+	 * We do not know if this neutral profile is necessary.
+	 * It is done in the example design and INTEL has not
+	 * answered our question if it is necessary or not.
+	 */
+	nthw_phy_tile_write_dyn_reconfig(p, dyn_rcfg_dr_next_profile_2_reg,
+		(0U << 15) + neutral_dr_profile + (0U << 31) +
+		(neutral_dr_profile << 16));
+	nt_os_wait_usec(10000);
+	NT_LOG(DBG, NTHW, "intf_no %u: dyn_rcfg_dr_next_profile_2_reg: %#010x", intf_no,
+		nthw_phy_tile_read_dyn_reconfig(p, dyn_rcfg_dr_next_profile_2_reg));
+
+	nt_os_wait_usec(10000);
+
+	/* Step 3: Trigger DR interrupt */
+	NT_LOG(DBG, NTHW, "intf_no %u: Step 3: Trigger DR interrupt", intf_no);
+	nthw_phy_tile_write_dyn_reconfig(p, dyn_rcfg_dr_trigger_reg, 0x00000001);
+
+	nt_os_wait_usec(1000000);
+
+	/* Step 4: Wait for interrupt Acknowledge */
+	NT_LOG(DBG, NTHW, "intf_no %u: Step 4: Wait for interrupt Acknowledge", intf_no);
+
+	while ((nthw_phy_tile_read_dyn_reconfig(p, dyn_rcfg_dr_trigger_reg) & 0x01) != 0x00)
+		nt_os_wait_usec(10000);
+
+	nt_os_wait_usec(10000);
+
+	/* Step 5: Wait Until DR config is done */
+	NT_LOG(DBG, NTHW, "intf_no %u: Step 5: Wait Until DR config is done", intf_no);
+
+	while ((nthw_phy_tile_read_dyn_reconfig(p, dyn_rcfg_dr_trigger_reg) & 0x02) != 0x02)
+		nt_os_wait_usec(10000);
+
+	nt_os_wait_usec(1000000);
+
+	/* Write Fec status to scratch register */
+	nthw_phy_tile_write_fec_enabled_by_scratch(p, intf_no, enable);
+
+	nt_os_wait_usec(1000000);
+
+	nthw_phy_tile_set_reset(p, intf_no, false);
+	nthw_phy_tile_set_tx_reset(p, intf_no, false);
+	nthw_phy_tile_set_rx_reset(p, intf_no, false);
+
+	nthw_register_update(p->mp_reg_dr_cfg_status);
+	NT_LOG(DBG, NTHW, "intf_no %u: DrCfgStatusCurrPofileId: %u", intf_no,
+		nthw_field_get_val32(p->mp_fld_dr_cfg_status_curr_profile_id));
+	NT_LOG(DBG, NTHW, "intf_no %u: DrCfgStatusInProgress:  %u", intf_no,
+		nthw_field_get_val32(p->mp_fld_dr_cfg_status_in_progress));
+	NT_LOG(DBG, NTHW, "intf_no %u: DrCfgStatusError: %u", intf_no,
+		nthw_field_get_val32(p->mp_fld_dr_cfg_status_error));
+
+	return true;
+}
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 09/32] net/ntnic: add nim low power API
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (7 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 08/32] net/ntnic: add port post init Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 10/32] net/ntnic: add link handling API Serhii Iliushyk
                   ` (23 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Add NIM reset and low power functions with presence check

- Implement nim_set_reset function to handle NIM reset.
- Implement set_nim_low_power function to manage
NIM power state.
- Add code to check NIM presence before performing reset.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../link_agx_100g/nt4ga_agx_link_100g.c       | 53 +++++++++++++++++++
 .../ntnic/nthw/core/include/nthw_pcal6416a.h  |  1 +
 drivers/net/ntnic/nthw/core/nthw_pcal6416a.c  | 39 ++++++++++++++
 3 files changed, 93 insertions(+)

diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
index fe2acef612..9193f21f6f 100644
--- a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -201,6 +201,17 @@ static int phy_set_line_loopback(adapter_info_t *drv, int port, loopback_line_t
  * Nim handling
  */
 
+static void nim_set_reset(struct nim_i2c_ctx *ctx, uint8_t nim_idx, bool reset)
+{
+	nthw_pcal6416a_t *p = ctx->hwagx.p_io_nim;
+
+	if (nim_idx == 0)
+		nthw_pcal6416a_write(p, 0, reset ? 0 : 1);
+
+	else if (nim_idx == 1)
+		nthw_pcal6416a_write(p, 4, reset ? 0 : 1);
+}
+
 static bool nim_is_present(nim_i2c_ctx_p ctx, uint8_t nim_idx)
 {
 	assert(nim_idx < NUM_ADAPTER_PORTS_MAX);
@@ -217,6 +228,20 @@ static bool nim_is_present(nim_i2c_ctx_p ctx, uint8_t nim_idx)
 	return data == 0;
 }
 
+static void set_nim_low_power(nim_i2c_ctx_p ctx, uint8_t nim_idx, bool low_power)
+{
+	nthw_pcal6416a_t *p = ctx->hwagx.p_io_nim;
+
+	if (nim_idx == 0) {
+		/* De-asserting LP mode pin 1 */
+		nthw_pcal6416a_write(p, 1, low_power ? 1 : 0);
+
+	} else if (nim_idx == 1) {
+		/* De-asserting LP mode pin 5 */
+		nthw_pcal6416a_write(p, 5, low_power ? 1 : 0);
+	}
+}
+
 /*
  * Utility functions
  */
@@ -335,6 +360,25 @@ static int create_nim(adapter_info_t *drv, int port, bool enable)
 		phy_reset_tx(drv, port);
 	}
 
+	/*
+	 * Check NIM is present before doing reset.
+	 */
+
+	if (!nim_is_present(nim_ctx, port)) {
+		NT_LOG(DBG, NTNIC, "%s: NIM module is no longer absent!",
+			drv->mp_port_id_str[port]);
+		return -1;
+	}
+
+	/*
+	 * Reset NIM
+	 */
+
+	NT_LOG(DBG, NTNIC, "%s: Performing NIM reset", drv->mp_port_id_str[port]);
+	nim_set_reset(nim_ctx, (uint8_t)port, true);
+	nt_os_wait_usec(100000);/*  pause 0.1s */
+	nim_set_reset(nim_ctx, (uint8_t)port, false);
+
 	/*
 	 * Wait a little after a module has been inserted before trying to access I2C
 	 * data, otherwise the module will not respond correctly.
@@ -369,6 +413,15 @@ static int create_nim(adapter_info_t *drv, int port, bool enable)
 		return -1;
 	}
 
+	if (enable) {
+		NT_LOG(DBG, NTNIC, "%s: De-asserting low power", drv->mp_port_id_str[port]);
+		set_nim_low_power(nim_ctx, port, false);
+
+	} else {
+		NT_LOG(DBG, NTNIC, "%s: Asserting low power", drv->mp_port_id_str[port]);
+		set_nim_low_power(nim_ctx, port, true);
+	}
+
 	return res;
 }
 
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h b/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
index 5ef14a0bc9..a718b59a29 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
@@ -24,6 +24,7 @@ struct nthw_pcal6416a {
 
 typedef struct nthw_pcal6416a nthw_pcal6416a_t;
 
+void nthw_pcal6416a_write(nthw_pcal6416a_t *p, uint8_t pin, uint8_t value);
 void nthw_pcal6416a_read(nthw_pcal6416a_t *p, uint8_t pin, uint8_t *value);
 
 #endif	/* __NTHW_PCAL6416A_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c b/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
index 37b6e7ec57..dd803ac66d 100644
--- a/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
+++ b/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
@@ -13,11 +13,50 @@
 #include "nthw_pcal6416a.h"
 
 static const uint8_t read_port[2] = { 0x00, 0x01 };
+static const uint8_t write_port[2] = { 0x02, 0x03 };
+static const uint8_t config_port[2] = { 0x06, 0x07 };
 
 /*
  * PCAL6416A I/O expander class
  */
 
+void nthw_pcal6416a_write(nthw_pcal6416a_t *p, uint8_t pin, uint8_t value)
+{
+	uint8_t port;
+	uint8_t data;
+
+	rte_spinlock_lock(&p->mp_nt_i2cm->i2cmmutex);
+	nthw_pca9849_set_channel(p->mp_ca9849, p->m_mux_channel);
+
+	if (pin < 8) {
+		port = 0;
+
+	} else {
+		port = 1;
+		pin = (uint8_t)(pin - 8);
+	}
+
+	nthw_i2cm_read(p->mp_nt_i2cm, p->m_dev_address, write_port[port], &data);
+
+	if (value == 0)
+		data = (uint8_t)(data & (~(uint8_t)(1 << pin)));
+
+	else
+		data = (uint8_t)(data | (1 << pin));
+
+	nthw_i2cm_write(p->mp_nt_i2cm, p->m_dev_address, write_port[port], data);
+
+	/* Enable pin as output pin when writing to it first time */
+	data = (uint8_t)(p->m_config_data[port] & (~(uint8_t)(1 << pin)));
+
+	if (data != p->m_config_data[port]) {
+		nthw_i2cm_write(p->mp_nt_i2cm, p->m_dev_address, config_port[port], data);
+		p->m_config_data[port] = data;
+	}
+
+	rte_spinlock_unlock(&p->mp_nt_i2cm->i2cmmutex);
+}
+
 void nthw_pcal6416a_read(nthw_pcal6416a_t *p, uint8_t pin, uint8_t *value)
 {
 	uint8_t port;
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 10/32] net/ntnic: add link handling API
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (8 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 09/32] net/ntnic: add nim low power API Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 11/32] net/ntnic: add port init to the state machine Serhii Iliushyk
                   ` (22 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Add link state management and NIM reset functionality

- Implement phy_get_link_state to retrieve PHY link state.
- Implement adjust_maturing_delay to adjust link maturing delay.
- Implement get/set to operate current link state.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../link_agx_100g/nt4ga_agx_link_100g.c       | 171 ++++++++++++++++++
 drivers/net/ntnic/meson.build                 |   1 +
 .../ntnic/nthw/core/include/nthw_pca9532.h    |  22 +++
 .../ntnic/nthw/core/include/nthw_phy_tile.h   |   9 +
 drivers/net/ntnic/nthw/core/nthw_pca9532.c    |  40 ++++
 drivers/net/ntnic/nthw/core/nthw_phy_tile.c   |  51 +++++-
 drivers/net/ntnic/nthw/nthw_drv.h             |   2 +
 7 files changed, 295 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_pca9532.h
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_pca9532.c

diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
index 9193f21f6f..00a30f24a5 100644
--- a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -43,6 +43,38 @@ void link_agx_100g_init(void)
  * Phy handling
  */
 
+static void phy_get_link_state(adapter_info_t *drv,
+	int port,
+	nt_link_state_p p_curr_link_state,
+	nt_link_state_p p_latched_links_state,
+	uint32_t *p_local_fault,
+	uint32_t *p_remote_fault)
+{
+	uint32_t status = 0;
+	uint32_t status_latch = 0;
+
+	nthw_phy_tile_t *p = drv->fpga_info.mp_nthw_agx.p_phy_tile;
+
+	nthw_phy_tile_get_link_summary(p,
+		&status,
+		&status_latch,
+		p_local_fault,
+		p_remote_fault,
+		port);
+
+	if (status == 0x0)
+		*p_curr_link_state = NT_LINK_STATE_DOWN;
+
+	else
+		*p_curr_link_state = NT_LINK_STATE_UP;
+
+	if (status_latch == 0x0)
+		*p_latched_links_state = NT_LINK_STATE_DOWN;
+
+	else
+		*p_latched_links_state = NT_LINK_STATE_UP;
+}
+
 static void phy_rx_path_rst(adapter_info_t *drv, int port, bool reset)
 {
 	nthw_phy_tile_t *p = drv->fpga_info.mp_nthw_agx.p_phy_tile;
@@ -242,6 +274,135 @@ static void set_nim_low_power(nim_i2c_ctx_p ctx, uint8_t nim_idx, bool low_power
 	}
 }
 
+/*
+ * Link handling
+ */
+
+static void adjust_maturing_delay(adapter_info_t *drv, int port)
+{
+	nthw_phy_tile_t *p = drv->fpga_info.mp_nthw_agx.p_phy_tile;
+	nthw_rpf_t *p_rpf = drv->fpga_info.mp_nthw_agx.p_rpf;
+	/*
+	 * Find the maximum of the absolute values of the RX componensation for all
+	 * ports (the RX componensation may not be set for some of the other ports).
+	 */
+	const int16_t unset_rx_compensation = -1;	/* 0xffff */
+	int16_t max_comp = 0;
+
+	for (int i = 0; i < drv->fpga_info.n_phy_ports; i++) {
+		int16_t comp = (int16_t)nthw_phy_tile_get_timestamp_comp_rx(p, i);
+
+		if (comp != unset_rx_compensation && abs(comp) > abs(max_comp))
+			max_comp = comp;
+	}
+
+	int delay = nthw_rpf_get_maturing_delay(p_rpf) - max_comp;
+
+	/*
+	 * For SOF time-stamping account for jumbo frame.
+	 * Frame size = 80000 b. divided by Gb link speed = processing time in ns.
+	 */
+	if (!nthw_rpf_get_ts_at_eof(p_rpf)) {
+		uint32_t jumbo_frame_processing_time_ns = 80000U / 100U;
+		delay -= (int)jumbo_frame_processing_time_ns;
+	}
+
+	const unsigned int delay_bit_width = 19;/* 19 bits maturing delay */
+	const int min_delay = -(1 << (delay_bit_width - 1));
+	const int max_delay = 0;
+
+	if (delay >= min_delay && delay <= max_delay) {
+		nthw_rpf_set_maturing_delay(p_rpf, delay);
+
+	} else {
+		NT_LOG(WRN, NTNIC,
+			"Port %u: Cannot set the RPF adjusted maturing delay to %i because "
+			"that value is outside the legal range [%i:%i]",
+			port, delay, min_delay, max_delay);
+	}
+}
+
+static void set_link_state(adapter_info_t *drv, nim_i2c_ctx_p ctx, link_state_t *state, int port)
+{
+	nthw_phy_tile_t *p = drv->fpga_info.mp_nthw_agx.p_phy_tile;
+	/*
+	 * 100G: 4 LEDs per port
+	 */
+
+	bool led_on = state->nim_present && state->link_state == NT_LINK_STATE_UP;
+	uint8_t led_pos = (uint8_t)(port * ctx->lane_count);
+
+	for (uint8_t i = 0; i < ctx->lane_count; i++) {
+		nthw_pca9532_set_led_on(drv->fpga_info.mp_nthw_agx.p_pca9532_led, led_pos + 1,
+			led_on);
+	}
+
+	nthw_phy_tile_set_timestamp_comp_rx(p, port, 0);
+
+	if (ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ena) {
+		/* Updated after mail from JKH 2023-02-07 */
+		nthw_phy_tile_set_timestamp_comp_rx(p, port, 0x9E);
+		/* TODO Hermosa Awaiting comp values to use */
+
+	} else {
+		/* TODO Hermosa Awaiting comp values to use */
+		nthw_phy_tile_set_timestamp_comp_rx(p, port, 0);
+	}
+
+	adjust_maturing_delay(drv, port);	/* MUST be called after timestampCompRx */
+}
+
+static void get_link_state(adapter_info_t *drv, nim_i2c_ctx_p ctx, link_state_t *state, int port)
+{
+	uint32_t local_fault;
+	uint32_t remote_fault;
+	nt_link_state_t curr_link_state;
+
+	nthw_phy_tile_t *p = drv->fpga_info.mp_nthw_agx.p_phy_tile;
+
+	/* Save the current state before reading the new */
+	curr_link_state = state->link_state;
+
+	phy_get_link_state(drv, port, &state->link_state, &state->link_state_latched, &local_fault,
+		&remote_fault);
+
+	if (curr_link_state != state->link_state)
+		NT_LOG(DBG, NTNIC, "Port %d: Faults(Local = %d, Remote = %d)", port, local_fault,
+			remote_fault);
+
+	state->nim_present = nim_is_present(ctx, port);
+
+	if (!state->nim_present)
+		return;	/* No nim so no need to do anything */
+
+	state->link_up = state->link_state == NT_LINK_STATE_UP ? true : false;
+
+	if (state->link_state == NT_LINK_STATE_UP)
+		return;	/* The link is up so no need to do anything else */
+
+	if (remote_fault == 0) {
+		phy_reset_rx(drv, port);
+		NT_LOG(DBG, NTNIC, "Port %u: resetRx due to local fault.", port);
+		return;
+	}
+
+	/* In case of too many errors perform a reset */
+	if (nthw_phy_tile_get_rx_hi_ber(p, port)) {
+		NT_LOG(INF, NTNIC, "Port %u: HiBer", port);
+		phy_reset_rx(drv, port);
+		return;
+	}
+
+	/* If FEC is not enabled then no reason to look at FEC state */
+	if (!ctx->specific_u.qsfp.specific_u.qsfp28.media_side_fec_ena ||
+		nthw_phy_tile_read_fec_enabled_by_scratch(p, port)) {
+		return;
+	}
+
+	if (!nthw_phy_tile_get_rx_am_lock(p, port))
+		phy_reset_rx(drv, port);
+}
+
 /*
  * Utility functions
  */
@@ -645,6 +806,7 @@ static void *_common_ptp_nim_state_machine(void *data)
 
 	while (monitor_task_is_running[adapter_no]) {
 		int i;
+		static bool reported_link[NUM_ADAPTER_PORTS_MAX] = { false };
 
 		for (i = 0; i < nb_ports; i++) {
 			const bool is_port_disabled = link_info->port_action[i].port_disable;
@@ -691,12 +853,14 @@ static void *_common_ptp_nim_state_machine(void *data)
 				continue;
 			}
 
+			get_link_state(drv, nim_ctx, &link_state[i], i);
 			link_state[i].link_disabled = is_port_disabled;
 
 			if (!link_state[i].nim_present) {
 				if (!link_state[i].lh_nim_absent) {
 					NT_LOG(INF, NTNIC, "%s: NIM module removed",
 						drv->mp_port_id_str[i]);
+					reported_link[i] = false;
 					link_state[i].link_up = false;
 					link_state[i].lh_nim_absent = true;
 
@@ -707,6 +871,13 @@ static void *_common_ptp_nim_state_machine(void *data)
 
 				continue;
 			}
+
+			if (reported_link[i] != link_state[i].link_up) {
+				NT_LOG(INF, NTNIC, "%s: link is %s", drv->mp_port_id_str[i],
+					(link_state[i].link_up ? "up" : "down"));
+				reported_link[i] = link_state[i].link_up;
+				set_link_state(drv, nim_ctx, &link_state[i], i);
+			}
 		}
 
 		if (monitor_task_is_running[adapter_no])
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index b1505c5549..92aad6f94d 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -55,6 +55,7 @@ sources = files(
         'nthw/core/nthw_iic.c',
         'nthw/core/nthw_mac_pcs.c',
         'nthw/core/nthw_pcie3.c',
+        'nthw/core/nthw_pca9532.c',
         'nthw/core/nthw_pcal6416a.c',
         'nthw/core/nthw_phy_tile.c',
         'nthw/core/nthw_si5332_si5156.c',
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_pca9532.h b/drivers/net/ntnic/nthw/core/include/nthw_pca9532.h
new file mode 100644
index 0000000000..24da937a18
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/include/nthw_pca9532.h
@@ -0,0 +1,22 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_PCA9532_H__
+#define __NTHW_PCA9532_H__
+
+#include "nthw_si5332_si5156.h"
+
+struct nthw_pca9532 {
+	nthw_i2cm_t *mp_nt_i2cm;
+	uint8_t m_dev_address;
+	nthw_pca9849_t *mp_ca9849;
+	uint8_t m_mux_channel;
+};
+
+typedef struct nthw_pca9532 nthw_pca9532_t;
+
+void nthw_pca9532_set_led_on(nthw_pca9532_t *p, uint8_t led_pos, bool state_on);
+
+#endif	/* __NTHW_PCA9532_H__ */
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
index c810f55c0d..f84aef44a9 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
@@ -74,8 +74,17 @@ void nthw_phy_tile_set_host_loopback(nthw_phy_tile_t *p, uint8_t intf_no, uint8_
 void nthw_phy_tile_set_tx_equalization(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
 	uint32_t pre_tap2, uint32_t main_tap, uint32_t pre_tap1,
 	uint32_t post_tap1);
+void nthw_phy_tile_get_link_summary(nthw_phy_tile_t *p, uint32_t *p_nt_phy_link_state,
+	uint32_t *p_ll_nt_phy_link_state, uint32_t *p_lh_local_fault,
+	uint32_t *p_lh_remote_fault, uint8_t index);
 void nthw_phy_tile_set_tx_reset(nthw_phy_tile_t *p, uint8_t intf_no, bool reset);
 void nthw_phy_tile_set_rx_reset(nthw_phy_tile_t *p, uint8_t intf_no, bool reset);
+bool nthw_phy_tile_read_fec_enabled_by_scratch(nthw_phy_tile_t *p, uint8_t intf_no);
+
+bool nthw_phy_tile_get_rx_hi_ber(nthw_phy_tile_t *p, uint8_t intf_no);
+bool nthw_phy_tile_get_rx_am_lock(nthw_phy_tile_t *p, uint8_t intf_no);
+void nthw_phy_tile_set_timestamp_comp_rx(nthw_phy_tile_t *p, uint8_t intf_no, uint32_t value);
+uint32_t nthw_phy_tile_get_timestamp_comp_rx(nthw_phy_tile_t *p, uint8_t intf_no);
 
 uint32_t nthw_phy_tile_read_eth(nthw_phy_tile_t *p, uint8_t intf_no, uint32_t address);
 void nthw_phy_tile_write_eth(nthw_phy_tile_t *p, uint8_t intf_no, uint32_t address, uint32_t data);
diff --git a/drivers/net/ntnic/nthw/core/nthw_pca9532.c b/drivers/net/ntnic/nthw/core/nthw_pca9532.c
new file mode 100644
index 0000000000..fcf5463fcb
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pca9532.c
@@ -0,0 +1,40 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include <pthread.h>
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_pca9532.h"
+
+static const uint8_t led_sel_reg[4] = { 6, 7, 8, 9 };
+
+void nthw_pca9532_set_led_on(nthw_pca9532_t *p, uint8_t led_pos, bool state_on)
+{
+	if (led_pos >= 16) {
+		NT_LOG(ERR, NTHW, "Led pos (%u) out of range", led_pos);
+		return;
+	}
+
+	rte_spinlock_lock(&p->mp_nt_i2cm->i2cmmutex);
+	nthw_pca9849_set_channel(p->mp_ca9849, p->m_mux_channel);
+
+	uint8_t reg_addr = led_sel_reg[led_pos / 4];
+	uint8_t bit_pos = (uint8_t)((led_pos % 4) * 2);
+	uint8_t data = 0U;
+
+	nthw_i2cm_read(p->mp_nt_i2cm, p->m_dev_address, reg_addr, &data);
+	data = data & (uint8_t)(~(0b11 << bit_pos));	/* Set bits to "00" aka off */
+
+	if (state_on)
+		data = (uint8_t)(data | (0b01 << bit_pos));
+
+	nthw_i2cm_write(p->mp_nt_i2cm, p->m_dev_address, reg_addr, data);
+	rte_spinlock_unlock(&p->mp_nt_i2cm->i2cmmutex);
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_phy_tile.c b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
index 42e2782f99..b057e9e88c 100644
--- a/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
+++ b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
@@ -263,7 +263,34 @@ void nthw_phy_tile_set_tx_equalization(nthw_phy_tile_t *p, uint8_t intf_no, uint
 	nthw_phy_tile_write_xcvr(p, intf_no, lane, tx_eq_addr + 0x8000U * lane, data);
 }
 
-static bool nthw_phy_tile_read_fec_enabled_by_scratch(nthw_phy_tile_t *p, uint8_t intf_no)
+void nthw_phy_tile_get_link_summary(nthw_phy_tile_t *p, uint32_t *p_nt_phy_link_state,
+	uint32_t *p_ll_nt_phy_link_state, uint32_t *p_lh_local_fault,
+	uint32_t *p_lh_remote_fault, uint8_t index)
+{
+	nthw_register_update(p->mp_reg_link_summary[index]);
+
+	if (p_nt_phy_link_state) {
+		*p_nt_phy_link_state =
+			nthw_field_get_val32(p->mp_fld_link_summary_nt_phy_link_state[index]);
+	}
+
+	if (p_ll_nt_phy_link_state) {
+		*p_ll_nt_phy_link_state =
+			nthw_field_get_val32(p->mp_fld_link_summary_ll_nt_phy_link_state[index]);
+	}
+
+	if (p_lh_local_fault) {
+		*p_lh_local_fault =
+			nthw_field_get_val32(p->mp_fld_link_summary_lh_received_local_fault[index]);
+	}
+
+	if (p_lh_remote_fault) {
+		*p_lh_remote_fault =
+			nthw_field_get_val32(p->mp_fld_link_summary_lh_remote_fault[index]);
+	}
+}
+
+bool nthw_phy_tile_read_fec_enabled_by_scratch(nthw_phy_tile_t *p, uint8_t intf_no)
 {
 	bool fec_enabled = false;
 
@@ -292,6 +319,28 @@ static void nthw_phy_tile_write_fec_enabled_by_scratch(nthw_phy_tile_t *p, uint8
 	nthw_field_set_val_flush32(p->mp_fld_scratch_data, val);
 }
 
+bool nthw_phy_tile_get_rx_hi_ber(nthw_phy_tile_t *p, uint8_t intf_no)
+{
+	return nthw_field_get_updated(p->mp_fld_port_status_rx_hi_ber[intf_no]);
+}
+
+bool nthw_phy_tile_get_rx_am_lock(nthw_phy_tile_t *p, uint8_t intf_no)
+{
+	return nthw_field_get_updated(p->mp_fld_port_status_rx_am_lock[intf_no]);
+}
+
+void nthw_phy_tile_set_timestamp_comp_rx(nthw_phy_tile_t *p, uint8_t intf_no, uint32_t value)
+{
+	nthw_field_get_updated(p->mp_fld_port_comp_rx_compensation[intf_no]);
+	nthw_field_set_val_flush32(p->mp_fld_port_comp_rx_compensation[intf_no], value);
+}
+
+uint32_t nthw_phy_tile_get_timestamp_comp_rx(nthw_phy_tile_t *p, uint8_t intf_no)
+{
+	nthw_field_get_updated(p->mp_fld_port_comp_rx_compensation[intf_no]);
+	return nthw_field_get_val32(p->mp_fld_port_comp_rx_compensation[intf_no]);
+}
+
 uint32_t nthw_phy_tile_read_eth(nthw_phy_tile_t *p, uint8_t intf_no, uint32_t address)
 {
 	nthw_register_update(p->mp_reg_port_eth_base[intf_no]);
diff --git a/drivers/net/ntnic/nthw/nthw_drv.h b/drivers/net/ntnic/nthw/nthw_drv.h
index 1fc8df52ce..a3c54846f5 100644
--- a/drivers/net/ntnic/nthw/nthw_drv.h
+++ b/drivers/net/ntnic/nthw/nthw_drv.h
@@ -11,6 +11,7 @@
 
 #include "nthw_si5332_si5156.h"
 #include "nthw_pcal6416a.h"
+#include "nthw_pca9532.h"
 #include "nthw_phy_tile.h"
 #include "nthw_rpf.h"
 #include "nthw_phy_tile.h"
@@ -22,6 +23,7 @@ typedef struct nthw_agx_s {
 	nthw_i2cm_t *p_i2cm;
 	nthw_pca9849_t *p_pca9849;
 	nthw_pcal6416a_t *p_io_nim;	/* PCAL6416A I/O expander for controlling TS */
+	nthw_pca9532_t *p_pca9532_led;
 	nthw_phy_tile_t *p_phy_tile;
 	nthw_rpf_t *p_rpf;
 } nthw_agx_t;
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 11/32] net/ntnic: add port init to the state machine
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (9 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 10/32] net/ntnic: add link handling API Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 12/32] net/ntnic: add port disable API Serhii Iliushyk
                   ` (21 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Handle NIM module insertion and initialization

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../link_agx_100g/nt4ga_agx_link_100g.c       | 33 +++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
index 00a30f24a5..33d39ce62f 100644
--- a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -872,6 +872,39 @@ static void *_common_ptp_nim_state_machine(void *data)
 				continue;
 			}
 
+			/*
+			 * NIM module is present
+			 */
+			if (link_state[i].lh_nim_absent && link_state[i].nim_present) {
+				sfp_nim_state_t new_state;
+				NT_LOG(INF, NTNIC, "%s: NIM module inserted",
+					drv->mp_port_id_str[i]);
+
+				if (_port_init(drv, fpga, i)) {
+					NT_LOG(ERR, NTNIC,
+						"%s: Failed to initialize NIM module",
+						drv->mp_port_id_str[i]);
+					continue;
+				}
+
+				if (nim_state_build(&nim_ctx[i], &new_state)) {
+					NT_LOG(ERR, NTNIC, "%s: Cannot read basic NIM data",
+						drv->mp_port_id_str[i]);
+					continue;
+				}
+
+				assert(new_state.br);	/* Cannot be zero if NIM is present */
+				NT_LOG(DBG, NTNIC,
+					"%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'",
+					drv->mp_port_id_str[i], nim_ctx->nim_id,
+					nim_id_to_text(nim_ctx->nim_id), (unsigned int)new_state.br,
+					nim_ctx->vendor_name, nim_ctx->prod_no, nim_ctx->serial_no);
+				link_state[i].lh_nim_absent = false;
+				NT_LOG(DBG, NTNIC, "%s: NIM module initialized",
+					drv->mp_port_id_str[i]);
+				continue;
+			}
+
 			if (reported_link[i] != link_state[i].link_up) {
 				NT_LOG(INF, NTNIC, "%s: link is %s", drv->mp_port_id_str[i],
 					(link_state[i].link_up ? "up" : "down"));
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 12/32] net/ntnic: add port disable API
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (10 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 11/32] net/ntnic: add port init to the state machine Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 13/32] net/ntnic: add minimal initialization new NIC NT400D13 Serhii Iliushyk
                   ` (20 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Added logic to check if the administrative port state
has changed.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../link_agx_100g/nt4ga_agx_link_100g.c       | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
index 33d39ce62f..3f59c4a6b8 100644
--- a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -501,6 +501,14 @@ set_loopback(struct adapter_info_s *p_adapter_info, int port, uint32_t mode, uin
 	nt_os_wait_usec(10000);	/* 10ms - arbitrary choice */
 }
 
+static void port_disable(adapter_info_t *drv, int port)
+{
+	nim_i2c_ctx_t *nim_ctx = &drv->nt4ga_link.u.nim_ctx[port];
+	phy_reset_rx(drv, port);
+	phy_reset_tx(drv, port);
+	set_nim_low_power(nim_ctx, port, true);
+}
+
 /*
  * Initialize NIM, Code based on nt400d1x.cpp: MyPort::createNim()
  */
@@ -822,6 +830,17 @@ static void *_common_ptp_nim_state_machine(void *data)
 			 */
 			assert(!(disable_port && enable_port));
 
+			if (disable_port) {
+				memset(&link_state[i], 0, sizeof(link_state[i]));
+				link_state[i].link_disabled = true;
+				link_state[i].lh_nim_absent = true;
+				reported_link[i] = false;
+				port_disable(drv, i);
+				NT_LOG(INF, NTNIC, "%s: Port %i is disabled",
+					drv->mp_port_id_str[i], i);
+				continue;
+			}
+
 			if (enable_port) {
 				link_state[i].link_disabled = false;
 				NT_LOG(DBG, NTNIC, "%s: Port %i is enabled",
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 13/32] net/ntnic: add minimal initialization new NIC NT400D13
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (11 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 12/32] net/ntnic: add port disable API Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 14/32] net/ntnic: add minimal reset FPGA Serhii Iliushyk
                   ` (19 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen

Add function and structures required to init the new NIC NT400D13

Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
 doc/guides/nics/ntnic.rst                     |  7 +++++-
 doc/guides/rel_notes/release_25_03.rst        |  4 ++++
 drivers/net/ntnic/meson.build                 |  1 +
 .../net/ntnic/nthw/core/include/nthw_fpga.h   |  8 +++++++
 .../nthw/core/nt400dxx/nthw_fpga_nt400dxx.c   | 23 +++++++++++++++++++
 drivers/net/ntnic/nthw/core/nthw_fpga.c       | 20 ++++++++++++++++
 drivers/net/ntnic/nthw/nthw_platform.c        |  3 +++
 drivers/net/ntnic/nthw/nthw_platform_drv.h    |  2 ++
 drivers/net/ntnic/ntnic_ethdev.c              |  1 +
 9 files changed, 68 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c

diff --git a/doc/guides/nics/ntnic.rst b/doc/guides/nics/ntnic.rst
index f186822504..f519a9f083 100644
--- a/doc/guides/nics/ntnic.rst
+++ b/doc/guides/nics/ntnic.rst
@@ -27,8 +27,13 @@ Supported NICs
 
     - FPGA ID 9563 (Inline Flow Management)
 
-All information about NT200A02 can be found by link below:
+- NT400D13 2x100G SmartNIC
+
+    - FPGA ID 9574 (Inline Flow Management)
+
+All information about NT200A02 and NT400D13 can be found by links below:
 https://www.napatech.com/products/nt200a02-smartnic-inline/
+https://www.napatech.com/support/resources/data-sheets/link-inline-software-for-napatech/
 
 
 Features
diff --git a/doc/guides/rel_notes/release_25_03.rst b/doc/guides/rel_notes/release_25_03.rst
index 8867a4bd74..8064a2e688 100644
--- a/doc/guides/rel_notes/release_25_03.rst
+++ b/doc/guides/rel_notes/release_25_03.rst
@@ -123,6 +123,10 @@ New Features
     This feature enhances the efficiency of probing VF/SFs on a large scale
     by significantly reducing the probing time.
 
+* **Updated Napatech ntnic driver.**
+
+  * Added support for the NT400D13 adapter.
+
 * **Updated Wangxun ngbe driver.**
 
   * Added support for virtual function (VF).
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 92aad6f94d..d56e85dd66 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -43,6 +43,7 @@ sources = files(
         'nthw/supported/nthw_fpga_mod_str_map.c',
         'nthw/core/nt200a0x/clock_profiles/nthw_fpga_clk9563.c',
         'nthw/core/nt200a0x/nthw_fpga_nt200a0x.c',
+        'nthw/core/nt400dxx/nthw_fpga_nt400dxx.c',
         'nthw/core/nt200a0x/reset/nthw_fpga_rst9563.c',
         'nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c',
         'nthw/core/nthw_fpga.c',
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_fpga.h b/drivers/net/ntnic/nthw/core/include/nthw_fpga.h
index cee1d23090..8b1d548a25 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_fpga.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_fpga.h
@@ -36,4 +36,12 @@ void register_nt200a0x_ops(struct nt200a0x_ops *ops);
 struct nt200a0x_ops *get_nt200a0x_ops(void);
 void nt200a0x_ops_init(void);
 
+struct nt400dxx_ops {
+	int (*nthw_fpga_nt400dxx_init)(struct fpga_info_s *p_fpga_info);
+};
+
+void register_nt400dxx_ops(struct nt400dxx_ops *ops);
+struct nt400dxx_ops *get_nt400dxx_ops(void);
+void nt400dxx_ops_init(void);
+
 #endif	/* __NTHW_FPGA_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c
new file mode 100644
index 0000000000..3f86843ff3
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c
@@ -0,0 +1,23 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nthw_fpga.h"
+#include "ntnic_mod_reg.h"
+
+
+static int nthw_fpga_nt400dxx_init(struct fpga_info_s *p_fpga_info)
+{
+	assert(p_fpga_info);
+	int res = -1;
+
+	return res;
+}
+
+static struct nt400dxx_ops nt400dxx_ops = { .nthw_fpga_nt400dxx_init = nthw_fpga_nt400dxx_init };
+
+void nt400dxx_ops_init(void)
+{
+	register_nt400dxx_ops(&nt400dxx_ops);
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga.c b/drivers/net/ntnic/nthw/core/nthw_fpga.c
index 5ca186209a..e54a210c9f 100644
--- a/drivers/net/ntnic/nthw/core/nthw_fpga.c
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga.c
@@ -266,6 +266,7 @@ int nthw_fpga_init(struct fpga_info_s *p_fpga_info)
 	p_fpga_info->mp_nthw_rac = p_nthw_rac;
 
 	struct nt200a0x_ops *nt200a0x_ops = get_nt200a0x_ops();
+	struct nt400dxx_ops *nt400dxx_ops = get_nt400dxx_ops();
 
 	switch (p_fpga_info->n_nthw_adapter_id) {
 	case NT_HW_ADAPTER_ID_NT200A02:
@@ -273,6 +274,11 @@ int nthw_fpga_init(struct fpga_info_s *p_fpga_info)
 			res = nt200a0x_ops->nthw_fpga_nt200a0x_init(p_fpga_info);
 		break;
 
+	case NT_HW_ADAPTER_ID_NT400D13:
+		if (nt400dxx_ops != NULL)
+			res = nt400dxx_ops->nthw_fpga_nt400dxx_init(p_fpga_info);
+		break;
+
 	default:
 		NT_LOG(ERR, NTHW, "%s: Unsupported HW product id: %d", p_adapter_id_str,
 			p_fpga_info->n_nthw_adapter_id);
@@ -398,3 +404,17 @@ struct nt200a0x_ops *get_nt200a0x_ops(void)
 		nt200a0x_ops_init();
 	return nt200a0x_ops;
 }
+
+static struct nt400dxx_ops *nt400dxx_ops;
+
+void register_nt400dxx_ops(struct nt400dxx_ops *ops)
+{
+	nt400dxx_ops = ops;
+}
+
+struct nt400dxx_ops *get_nt400dxx_ops(void)
+{
+	if (nt400dxx_ops == NULL)
+		nt400dxx_ops_init();
+	return nt400dxx_ops;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_platform.c b/drivers/net/ntnic/nthw/nthw_platform.c
index 33e18e549f..80063c9d25 100644
--- a/drivers/net/ntnic/nthw/nthw_platform.c
+++ b/drivers/net/ntnic/nthw/nthw_platform.c
@@ -11,6 +11,9 @@ nthw_adapter_id_t nthw_platform_get_nthw_adapter_id(const uint16_t n_pci_device_
 	case NT_HW_PCI_DEVICE_ID_NT200A02:
 		return NT_HW_ADAPTER_ID_NT200A02;
 
+	case NT_HW_PCI_DEVICE_ID_NT400D13:
+		return NT_HW_ADAPTER_ID_NT400D13;
+
 	default:
 		return NT_HW_ADAPTER_ID_UNKNOWN;
 	}
diff --git a/drivers/net/ntnic/nthw/nthw_platform_drv.h b/drivers/net/ntnic/nthw/nthw_platform_drv.h
index 42eb0b8b05..df54dcead0 100644
--- a/drivers/net/ntnic/nthw/nthw_platform_drv.h
+++ b/drivers/net/ntnic/nthw/nthw_platform_drv.h
@@ -10,10 +10,12 @@
 
 #define NT_HW_PCI_VENDOR_ID (0x18f4)
 #define NT_HW_PCI_DEVICE_ID_NT200A02 (0x1C5)
+#define NT_HW_PCI_DEVICE_ID_NT400D13 (0x295)
 
 enum nthw_adapter_id_e {
 	NT_HW_ADAPTER_ID_UNKNOWN = 0,
 	NT_HW_ADAPTER_ID_NT200A02,
+	NT_HW_ADAPTER_ID_NT400D13,
 };
 
 typedef enum nthw_adapter_id_e nthw_adapter_id_t;
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
index 1b6b222c9d..88f6b6af6b 100644
--- a/drivers/net/ntnic/ntnic_ethdev.c
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -91,6 +91,7 @@ static const char *const valid_arguments[] = {
 
 static const struct rte_pci_id nthw_pci_id_map[] = {
 	{ RTE_PCI_DEVICE(NT_HW_PCI_VENDOR_ID, NT_HW_PCI_DEVICE_ID_NT200A02) },
+	{ RTE_PCI_DEVICE(NT_HW_PCI_VENDOR_ID, NT_HW_PCI_DEVICE_ID_NT400D13) },
 	{
 		.vendor_id = 0,
 	},	/* sentinel */
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 14/32] net/ntnic: add minimal reset FPGA
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (12 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 13/32] net/ntnic: add minimal initialization new NIC NT400D13 Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 15/32] net/ntnic: add FPGA modules and registers Serhii Iliushyk
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen

Define and register FPGA reset operations.

Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
 .../include/ntnic_nthw_fpga_rst_nt400dxx.h    | 34 +++++++
 drivers/net/ntnic/meson.build                 |  2 +
 .../nthw/core/nt400dxx/nthw_fpga_nt400dxx.c   | 88 ++++++++++++++++++-
 .../core/nt400dxx/reset/nthw_fpga_rst9574.c   | 40 +++++++++
 .../nt400dxx/reset/nthw_fpga_rst_nt400dxx.c   | 33 +++++++
 drivers/net/ntnic/ntnic_mod_reg.c             | 30 +++++++
 drivers/net/ntnic/ntnic_mod_reg.h             | 21 +++++
 7 files changed, 247 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ntnic/include/ntnic_nthw_fpga_rst_nt400dxx.h
 create mode 100644 drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
 create mode 100644 drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c

diff --git a/drivers/net/ntnic/include/ntnic_nthw_fpga_rst_nt400dxx.h b/drivers/net/ntnic/include/ntnic_nthw_fpga_rst_nt400dxx.h
new file mode 100644
index 0000000000..2f04907ac9
--- /dev/null
+++ b/drivers/net/ntnic/include/ntnic_nthw_fpga_rst_nt400dxx.h
@@ -0,0 +1,34 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+#ifndef __NTNIC_NTHW_FPGA_RST_NT400DXX_H__
+#define __NTNIC_NTHW_FPGA_RST_NT400DXX_H__
+
+#include "nthw_drv.h"
+#include "nthw_fpga_model.h"
+
+struct nthw_fpga_rst_nt400dxx {
+	int n_fpga_product_id;
+	int n_fpga_version;
+	int n_fpga_revision;
+	int n_hw_id;
+	bool mb_is_nt400d11;
+
+	nthw_field_t *p_fld_rst_sys;
+	nthw_field_t *p_fld_rst_ddr4;
+	nthw_field_t *p_fld_rst_phy_ftile;
+
+	nthw_field_t *p_fld_stat_ddr4_calib_complete;
+	nthw_field_t *p_fld_stat_phy_ftile_rst_done;
+	nthw_field_t *p_fld_stat_phy_ftile_rdy;
+
+	nthw_field_t *p_fld_latch_ddr4_calib_complete;
+	nthw_field_t *p_fld_latch_phy_ftile_rst_done;
+	nthw_field_t *p_fld_latch_phy_ftile_rdy;
+};
+
+typedef struct nthw_fpga_rst_nt400dxx nthw_fpga_rst_nt400dxx_t;
+
+#endif	/* __NTHW_FPGA_RST_NT400DXX_H__ */
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index d56e85dd66..5a159f8bc6 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -45,7 +45,9 @@ sources = files(
         'nthw/core/nt200a0x/nthw_fpga_nt200a0x.c',
         'nthw/core/nt400dxx/nthw_fpga_nt400dxx.c',
         'nthw/core/nt200a0x/reset/nthw_fpga_rst9563.c',
+        'nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c',
         'nthw/core/nt200a0x/reset/nthw_fpga_rst_nt200a0x.c',
+        'nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c',
         'nthw/core/nthw_fpga.c',
         'nthw/core/nthw_gmf.c',
         'nthw/core/nthw_gfg.c',
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c
index 3f86843ff3..0a5add60e0 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c
@@ -5,13 +5,99 @@
 
 #include "nthw_fpga.h"
 #include "ntnic_mod_reg.h"
-
+#include "ntlog.h"
 
 static int nthw_fpga_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 {
 	assert(p_fpga_info);
+	struct rst9574_ops *rst9574_ops = NULL;
+
+	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+	struct nthw_fpga_rst_nt400dxx rst;
 	int res = -1;
 
+	nthw_fpga_t *p_fpga = p_fpga_info->mp_fpga;
+	assert(p_fpga);
+
+	switch (p_fpga_info->n_fpga_prod_id) {
+	case 9574:
+		rst9574_ops = get_rst9574_ops();
+
+		if (rst9574_ops == NULL) {
+			NT_LOG(ERR, NTHW, "%s: RST 9574 NOT INCLUDED", p_adapter_id_str);
+			return -1;
+		}
+
+		res = rst9574_ops->nthw_fpga_rst9574_setup(p_fpga, &rst);
+
+		if (res) {
+			NT_LOG(ERR, NTHW,
+				"%s: %s: FPGA=%04d Failed to create reset module res=%d",
+				p_adapter_id_str, __func__, p_fpga_info->n_fpga_prod_id, res);
+			return res;
+		}
+
+		break;
+
+	default:
+		NT_LOG(ERR, NTHW, "%s: Unsupported FPGA product: %04d",
+			p_adapter_id_str, p_fpga_info->n_fpga_prod_id);
+		return -1;
+	}
+
+	struct rst_nt400dxx_ops *rst_nt400dxx_ops = get_rst_nt400dxx_ops();
+
+	if (rst_nt400dxx_ops == NULL) {
+		NT_LOG(ERR, NTHW, "RST NT400DXX NOT INCLUDED");
+		return -1;
+	}
+
+	/* reset common */
+	res = rst_nt400dxx_ops->nthw_fpga_rst_nt400dxx_init(p_fpga_info);
+
+	if (res) {
+		NT_LOG(ERR, NTHW, "%s: %s: FPGA=%04d - Failed to init common modules res=%d",
+			p_adapter_id_str, __func__, p_fpga_info->n_fpga_prod_id, res);
+		return res;
+	}
+
+	res = rst_nt400dxx_ops->nthw_fpga_rst_nt400dxx_reset(p_fpga_info);
+
+	if (res) {
+		NT_LOG(ERR, NTHW,
+			"%s: %s: FPGA=%04d - Failed to reset common modules res=%d",
+			p_adapter_id_str, __func__, p_fpga_info->n_fpga_prod_id, res);
+		return res;
+	}
+
+		/* reset specific */
+	switch (p_fpga_info->n_fpga_prod_id) {
+	case 9574:
+		if (rst9574_ops)
+			res = rst9574_ops->nthw_fpga_rst9574_init(p_fpga_info, &rst);
+
+		if (res) {
+			NT_LOG(ERR, NTHW,
+				"%s: %s: FPGA=%04d - Failed to reset 9574 modules res=%d",
+				p_adapter_id_str, __func__, p_fpga_info->n_fpga_prod_id, res);
+			return res;
+		}
+
+		break;
+
+	default:
+		NT_LOG(ERR, NTHW, "%s: Unsupported FPGA product: %04d",
+			p_adapter_id_str, p_fpga_info->n_fpga_prod_id);
+		res = -1;
+		break;
+	}
+
+	if (res) {
+		NT_LOG(ERR, NTHW, "%s: %s: loc=%u: FPGA=%04d res=%d", p_adapter_id_str,
+			__func__, __LINE__, p_fpga_info->n_fpga_prod_id, res);
+		return res;
+	}
+
 	return res;
 }
 
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
new file mode 100644
index 0000000000..9ab26583df
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
@@ -0,0 +1,40 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+#include "nthw_drv.h"
+#include "nthw_register.h"
+#include "nthw_fpga.h"
+
+#include "ntnic_nthw_fpga_rst_nt400dxx.h"
+#include "ntnic_mod_reg.h"
+
+static int nthw_fpga_rst9574_setup(nthw_fpga_t *p_fpga, struct nthw_fpga_rst_nt400dxx *const p)
+{
+	assert(p_fpga);
+	assert(p);
+
+	return 0;
+};
+
+
+
+static int nthw_fpga_rst9574_init(struct fpga_info_s *p_fpga_info,
+	struct nthw_fpga_rst_nt400dxx *p_rst)
+{
+	assert(p_fpga_info);
+	assert(p_rst);
+	int res = -1;
+
+	return res;
+}
+
+static struct rst9574_ops rst9574_ops = {
+	.nthw_fpga_rst9574_init = nthw_fpga_rst9574_init,
+	.nthw_fpga_rst9574_setup = nthw_fpga_rst9574_setup,
+};
+
+void rst9574_ops_init(void)
+{
+	register_rst9574_ops(&rst9574_ops);
+}
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
new file mode 100644
index 0000000000..e0e4bc0861
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
@@ -0,0 +1,33 @@
+/*
+ * 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 "nthw_hif.h"
+#include "ntnic_mod_reg.h"
+
+static int nthw_fpga_rst_nt400dxx_init(struct fpga_info_s *p_fpga_info)
+{
+	assert(p_fpga_info);
+	return 0;
+}
+
+static int nthw_fpga_rst_nt400dxx_reset(struct fpga_info_s *p_fpga_info)
+{
+	assert(p_fpga_info);
+	return 0;
+}
+
+static struct rst_nt400dxx_ops rst_nt400dxx_ops = {
+	.nthw_fpga_rst_nt400dxx_init = nthw_fpga_rst_nt400dxx_init,
+	.nthw_fpga_rst_nt400dxx_reset = nthw_fpga_rst_nt400dxx_reset
+};
+
+void rst_nt400dxx_ops_init(void)
+{
+	register_rst_nt400dxx_ops(&rst_nt400dxx_ops);
+}
diff --git a/drivers/net/ntnic/ntnic_mod_reg.c b/drivers/net/ntnic/ntnic_mod_reg.c
index 598df08fb7..054b343fe7 100644
--- a/drivers/net/ntnic/ntnic_mod_reg.c
+++ b/drivers/net/ntnic/ntnic_mod_reg.c
@@ -178,6 +178,36 @@ void register_flow_backend_ops(const struct flow_backend_ops *ops)
 	flow_backend_ops = ops;
 }
 
+static struct rst9574_ops *rst9574_ops;
+
+void register_rst9574_ops(struct rst9574_ops *ops)
+{
+	rst9574_ops = ops;
+}
+
+struct rst9574_ops *get_rst9574_ops(void)
+{
+	if (rst9574_ops == NULL)
+		rst9574_ops_init();
+
+	return rst9574_ops;
+}
+
+static struct rst_nt400dxx_ops *rst_nt400dxx_ops;
+
+void register_rst_nt400dxx_ops(struct rst_nt400dxx_ops *ops)
+{
+	rst_nt400dxx_ops = ops;
+}
+
+struct rst_nt400dxx_ops *get_rst_nt400dxx_ops(void)
+{
+	if (rst_nt400dxx_ops == NULL)
+		rst_nt400dxx_ops_init();
+
+	return rst_nt400dxx_ops;
+}
+
 const struct flow_backend_ops *get_flow_backend_ops(void)
 {
 	if (flow_backend_ops == NULL)
diff --git a/drivers/net/ntnic/ntnic_mod_reg.h b/drivers/net/ntnic/ntnic_mod_reg.h
index 3e84beaa62..9b3650da89 100644
--- a/drivers/net/ntnic/ntnic_mod_reg.h
+++ b/drivers/net/ntnic/ntnic_mod_reg.h
@@ -19,6 +19,7 @@
 #include "nthw_drv.h"
 #include "nt4ga_adapter.h"
 #include "ntnic_nthw_fpga_rst_nt200a0x.h"
+#include "ntnic_nthw_fpga_rst_nt400dxx.h"
 #include "ntnic_virt_queue.h"
 #include "create_elements.h"
 
@@ -255,6 +256,26 @@ void register_rst9563_ops(struct rst9563_ops *ops);
 struct rst9563_ops *get_rst9563_ops(void);
 void rst9563_ops_init(void);
 
+struct rst9574_ops {
+	int (*nthw_fpga_rst9574_init)(struct fpga_info_s *p_fpga_info,
+		struct nthw_fpga_rst_nt400dxx *const p);
+	int (*nthw_fpga_rst9574_setup)(nthw_fpga_t *p_fpga,
+		struct nthw_fpga_rst_nt400dxx *const p);
+};
+
+void register_rst9574_ops(struct rst9574_ops *ops);
+struct rst9574_ops *get_rst9574_ops(void);
+void rst9574_ops_init(void);
+
+struct rst_nt400dxx_ops {
+	int (*nthw_fpga_rst_nt400dxx_init)(struct fpga_info_s *p_fpga_info);
+	int (*nthw_fpga_rst_nt400dxx_reset)(struct fpga_info_s *p_fpga_info);
+};
+
+void register_rst_nt400dxx_ops(struct rst_nt400dxx_ops *ops);
+struct rst_nt400dxx_ops *get_rst_nt400dxx_ops(void);
+void rst_nt400dxx_ops_init(void);
+
 struct flow_backend_ops {
 	const struct flow_api_backend_ops *(*bin_flow_backend_init)(nthw_fpga_t *p_fpga,
 		void **be_dev);
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 15/32] net/ntnic: add FPGA modules and registers
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (13 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 14/32] net/ntnic: add minimal reset FPGA Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 16/32] net/ntnic: add setup for fpga reset Serhii Iliushyk
                   ` (17 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen

Extend driver with new fpga modules for NT400DXX card.

Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
 drivers/net/ntnic/meson.build                 |    1 +
 .../supported/nthw_fpga_9574_055_049_0000.c   | 3124 +++++++++++++++++
 .../nthw/supported/nthw_fpga_instances.c      |    5 +-
 .../nthw/supported/nthw_fpga_instances.h      |    1 +
 .../ntnic/nthw/supported/nthw_fpga_mod_defs.h |   11 +
 .../nthw/supported/nthw_fpga_mod_str_map.c    |   11 +
 .../ntnic/nthw/supported/nthw_fpga_reg_defs.h |   11 +
 .../nthw/supported/nthw_fpga_reg_defs_igam.h  |   32 +
 .../supported/nthw_fpga_reg_defs_pci_ta.h     |   33 +
 .../nthw_fpga_reg_defs_pcm_nt400dxx.h         |   29 +
 .../nthw/supported/nthw_fpga_reg_defs_pdi.h   |   49 +
 .../supported/nthw_fpga_reg_defs_phy_tile.h   |  213 ++
 .../nthw_fpga_reg_defs_prm_nt400dxx.h         |   26 +
 .../nthw/supported/nthw_fpga_reg_defs_rfd.h   |   38 +
 .../supported/nthw_fpga_reg_defs_rst9574.h    |   35 +
 .../nthw/supported/nthw_fpga_reg_defs_spim.h  |   76 +
 .../nthw/supported/nthw_fpga_reg_defs_spis.h  |   51 +
 .../nthw/supported/nthw_fpga_reg_defs_tint.h  |   28 +
 18 files changed, 3773 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_9574_055_049_0000.c
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_igam.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pci_ta.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pcm_nt400dxx.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pdi.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_phy_tile.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_prm_nt400dxx.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_rfd.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_rst9574.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_spim.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_spis.h
 create mode 100644 drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_tint.h

diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 5a159f8bc6..aec7b52714 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -39,6 +39,7 @@ sources = files(
         'ntnic_xstats/ntnic_xstats.c',
         'nthw/dbs/nthw_dbs.c',
         'nthw/supported/nthw_fpga_9563_055_049_0000.c',
+        'nthw/supported/nthw_fpga_9574_055_049_0000.c',
         'nthw/supported/nthw_fpga_instances.c',
         'nthw/supported/nthw_fpga_mod_str_map.c',
         'nthw/core/nt200a0x/clock_profiles/nthw_fpga_clk9563.c',
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_9574_055_049_0000.c b/drivers/net/ntnic/nthw/supported/nthw_fpga_9574_055_049_0000.c
new file mode 100644
index 0000000000..700012ca06
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_9574_055_049_0000.c
@@ -0,0 +1,3124 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+#include "nthw_register.h"
+
+static nthw_fpga_field_init_s cat_cct_ctrl_fields[] = {
+	{ CAT_CCT_CTRL_ADR, 8, 0, 0x0000 },
+	{ CAT_CCT_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_cct_data_fields[] = {
+	{ CAT_CCT_DATA_COLOR, 32, 0, 0x0000 },
+	{ CAT_CCT_DATA_KM, 4, 32, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_cfn_ctrl_fields[] = {
+	{ CAT_CFN_CTRL_ADR, 6, 0, 0x0000 },
+	{ CAT_CFN_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_cfn_data_fields[] = {
+	{ CAT_CFN_DATA_ENABLE, 1, 0, 0x0000 },
+	{ CAT_CFN_DATA_ERR_CV, 2, 99, 0x0000 },
+	{ CAT_CFN_DATA_ERR_FCS, 2, 101, 0x0000 },
+	{ CAT_CFN_DATA_ERR_INV, 1, 98, 0x0000 },
+	{ CAT_CFN_DATA_ERR_L3_CS, 2, 105, 0x0000 },
+	{ CAT_CFN_DATA_ERR_L4_CS, 2, 107, 0x0000 },
+	{ CAT_CFN_DATA_ERR_TNL_L3_CS, 2, 109, 0x0000 },
+	{ CAT_CFN_DATA_ERR_TNL_L4_CS, 2, 111, 0x0000 },
+	{ CAT_CFN_DATA_ERR_TNL_TTL_EXP, 2, 115, 0x0000 },
+	{ CAT_CFN_DATA_ERR_TRUNC, 2, 103, 0x0000 },
+	{ CAT_CFN_DATA_ERR_TTL_EXP, 2, 113, 0x0000 },
+	{ CAT_CFN_DATA_INV, 1, 1, 0x0000 },
+	{ CAT_CFN_DATA_KM0_OR, 3, 173, 0x0000 },
+	{ CAT_CFN_DATA_KM1_OR, 3, 176, 0x0000 },
+	{ CAT_CFN_DATA_LC, 8, 164, 0x0000 },
+	{ CAT_CFN_DATA_LC_INV, 1, 172, 0x0000 },
+	{ CAT_CFN_DATA_MAC_PORT, 2, 117, 0x0000 },
+	{ CAT_CFN_DATA_PM_AND_INV, 1, 161, 0x0000 },
+	{ CAT_CFN_DATA_PM_CMB, 4, 157, 0x0000 },
+	{ CAT_CFN_DATA_PM_CMP, 32, 119, 0x0000 },
+	{ CAT_CFN_DATA_PM_DCT, 2, 151, 0x0000 },
+	{ CAT_CFN_DATA_PM_EXT_INV, 4, 153, 0x0000 },
+	{ CAT_CFN_DATA_PM_INV, 1, 163, 0x0000 },
+	{ CAT_CFN_DATA_PM_OR_INV, 1, 162, 0x0000 },
+	{ CAT_CFN_DATA_PTC_CFP, 2, 5, 0x0000 },
+	{ CAT_CFN_DATA_PTC_FRAG, 4, 36, 0x0000 },
+	{ CAT_CFN_DATA_PTC_INV, 1, 2, 0x0000 },
+	{ CAT_CFN_DATA_PTC_IP_PROT, 8, 40, 0x0000 },
+	{ CAT_CFN_DATA_PTC_ISL, 2, 3, 0x0000 },
+	{ CAT_CFN_DATA_PTC_L2, 7, 12, 0x0000 },
+	{ CAT_CFN_DATA_PTC_L3, 3, 33, 0x0000 },
+	{ CAT_CFN_DATA_PTC_L4, 5, 48, 0x0000 },
+	{ CAT_CFN_DATA_PTC_MAC, 5, 7, 0x0000 },
+	{ CAT_CFN_DATA_PTC_MPLS, 8, 25, 0x0000 },
+	{ CAT_CFN_DATA_PTC_TNL_FRAG, 4, 81, 0x0000 },
+	{ CAT_CFN_DATA_PTC_TNL_IP_PROT, 8, 85, 0x0000 },
+	{ CAT_CFN_DATA_PTC_TNL_L2, 2, 64, 0x0000 },
+	{ CAT_CFN_DATA_PTC_TNL_L3, 3, 78, 0x0000 },
+	{ CAT_CFN_DATA_PTC_TNL_L4, 5, 93, 0x0000 },
+	{ CAT_CFN_DATA_PTC_TNL_MPLS, 8, 70, 0x0000 },
+	{ CAT_CFN_DATA_PTC_TNL_VLAN, 4, 66, 0x0000 },
+	{ CAT_CFN_DATA_PTC_TUNNEL, 11, 53, 0x0000 },
+	{ CAT_CFN_DATA_PTC_VLAN, 4, 21, 0x0000 },
+	{ CAT_CFN_DATA_PTC_VNTAG, 2, 19, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_cot_ctrl_fields[] = {
+	{ CAT_COT_CTRL_ADR, 6, 0, 0x0000 },
+	{ CAT_COT_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_cot_data_fields[] = {
+	{ CAT_COT_DATA_COLOR, 32, 0, 0x0000 },
+	{ CAT_COT_DATA_KM, 4, 32, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_cte_ctrl_fields[] = {
+	{ CAT_CTE_CTRL_ADR, 6, 0, 0x0000 },
+	{ CAT_CTE_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_cte_data_fields[] = {
+	{ CAT_CTE_DATA_COL_ENABLE, 1, 0, 0x0000 }, { CAT_CTE_DATA_COR_ENABLE, 1, 1, 0x0000 },
+	{ CAT_CTE_DATA_EPP_ENABLE, 1, 9, 0x0000 }, { CAT_CTE_DATA_HSH_ENABLE, 1, 2, 0x0000 },
+	{ CAT_CTE_DATA_HST_ENABLE, 1, 8, 0x0000 }, { CAT_CTE_DATA_IPF_ENABLE, 1, 4, 0x0000 },
+	{ CAT_CTE_DATA_MSK_ENABLE, 1, 7, 0x0000 }, { CAT_CTE_DATA_PDB_ENABLE, 1, 6, 0x0000 },
+	{ CAT_CTE_DATA_QSL_ENABLE, 1, 3, 0x0000 }, { CAT_CTE_DATA_SLC_ENABLE, 1, 5, 0x0000 },
+	{ CAT_CTE_DATA_TPE_ENABLE, 1, 10, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_cts_ctrl_fields[] = {
+	{ CAT_CTS_CTRL_ADR, 9, 0, 0x0000 },
+	{ CAT_CTS_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_cts_data_fields[] = {
+	{ CAT_CTS_DATA_CAT_A, 6, 0, 0x0000 },
+	{ CAT_CTS_DATA_CAT_B, 6, 6, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_dct_ctrl_fields[] = {
+	{ CAT_DCT_CTRL_ADR, 13, 0, 0x0000 },
+	{ CAT_DCT_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_dct_data_fields[] = {
+	{ CAT_DCT_DATA_RES, 16, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_dct_sel_fields[] = {
+	{ CAT_DCT_SEL_LU, 2, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_exo_ctrl_fields[] = {
+	{ CAT_EXO_CTRL_ADR, 2, 0, 0x0000 },
+	{ CAT_EXO_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_exo_data_fields[] = {
+	{ CAT_EXO_DATA_DYN, 5, 0, 0x0000 },
+	{ CAT_EXO_DATA_OFS, 11, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_fte0_ctrl_fields[] = {
+	{ CAT_FTE0_CTRL_ADR, 9, 0, 0x0000 },
+	{ CAT_FTE0_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_fte0_data_fields[] = {
+	{ CAT_FTE0_DATA_ENABLE, 8, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_fte1_ctrl_fields[] = {
+	{ CAT_FTE1_CTRL_ADR, 9, 0, 0x0000 },
+	{ CAT_FTE1_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_fte1_data_fields[] = {
+	{ CAT_FTE1_DATA_ENABLE, 8, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_join_fields[] = {
+	{ CAT_JOIN_J1, 2, 0, 0x0000 },
+	{ CAT_JOIN_J2, 1, 8, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_kcc_ctrl_fields[] = {
+	{ CAT_KCC_CTRL_ADR, 11, 0, 0x0000 },
+	{ CAT_KCC_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_kcc_data_fields[] = {
+	{ CAT_KCC_DATA_CATEGORY, 8, 64, 0x0000 },
+	{ CAT_KCC_DATA_ID, 12, 72, 0x0000 },
+	{ CAT_KCC_DATA_KEY, 64, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_kce0_ctrl_fields[] = {
+	{ CAT_KCE0_CTRL_ADR, 3, 0, 0x0000 },
+	{ CAT_KCE0_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_kce0_data_fields[] = {
+	{ CAT_KCE0_DATA_ENABLE, 8, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_kce1_ctrl_fields[] = {
+	{ CAT_KCE1_CTRL_ADR, 3, 0, 0x0000 },
+	{ CAT_KCE1_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_kce1_data_fields[] = {
+	{ CAT_KCE1_DATA_ENABLE, 8, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_kcs0_ctrl_fields[] = {
+	{ CAT_KCS0_CTRL_ADR, 6, 0, 0x0000 },
+	{ CAT_KCS0_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_kcs0_data_fields[] = {
+	{ CAT_KCS0_DATA_CATEGORY, 6, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_kcs1_ctrl_fields[] = {
+	{ CAT_KCS1_CTRL_ADR, 6, 0, 0x0000 },
+	{ CAT_KCS1_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_kcs1_data_fields[] = {
+	{ CAT_KCS1_DATA_CATEGORY, 6, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_len_ctrl_fields[] = {
+	{ CAT_LEN_CTRL_ADR, 3, 0, 0x0000 },
+	{ CAT_LEN_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_len_data_fields[] = {
+	{ CAT_LEN_DATA_DYN1, 5, 28, 0x0000 }, { CAT_LEN_DATA_DYN2, 5, 33, 0x0000 },
+	{ CAT_LEN_DATA_INV, 1, 38, 0x0000 }, { CAT_LEN_DATA_LOWER, 14, 0, 0x0000 },
+	{ CAT_LEN_DATA_UPPER, 14, 14, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_rck_ctrl_fields[] = {
+	{ CAT_RCK_CTRL_ADR, 8, 0, 0x0000 },
+	{ CAT_RCK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cat_rck_data_fields[] = {
+	{ CAT_RCK_DATA_CM0U, 1, 1, 0x0000 }, { CAT_RCK_DATA_CM1U, 1, 5, 0x0000 },
+	{ CAT_RCK_DATA_CM2U, 1, 9, 0x0000 }, { CAT_RCK_DATA_CM3U, 1, 13, 0x0000 },
+	{ CAT_RCK_DATA_CM4U, 1, 17, 0x0000 }, { CAT_RCK_DATA_CM5U, 1, 21, 0x0000 },
+	{ CAT_RCK_DATA_CM6U, 1, 25, 0x0000 }, { CAT_RCK_DATA_CM7U, 1, 29, 0x0000 },
+	{ CAT_RCK_DATA_CML0, 1, 0, 0x0000 }, { CAT_RCK_DATA_CML1, 1, 4, 0x0000 },
+	{ CAT_RCK_DATA_CML2, 1, 8, 0x0000 }, { CAT_RCK_DATA_CML3, 1, 12, 0x0000 },
+	{ CAT_RCK_DATA_CML4, 1, 16, 0x0000 }, { CAT_RCK_DATA_CML5, 1, 20, 0x0000 },
+	{ CAT_RCK_DATA_CML6, 1, 24, 0x0000 }, { CAT_RCK_DATA_CML7, 1, 28, 0x0000 },
+	{ CAT_RCK_DATA_SEL0, 1, 2, 0x0000 }, { CAT_RCK_DATA_SEL1, 1, 6, 0x0000 },
+	{ CAT_RCK_DATA_SEL2, 1, 10, 0x0000 }, { CAT_RCK_DATA_SEL3, 1, 14, 0x0000 },
+	{ CAT_RCK_DATA_SEL4, 1, 18, 0x0000 }, { CAT_RCK_DATA_SEL5, 1, 22, 0x0000 },
+	{ CAT_RCK_DATA_SEL6, 1, 26, 0x0000 }, { CAT_RCK_DATA_SEL7, 1, 30, 0x0000 },
+	{ CAT_RCK_DATA_SEU0, 1, 3, 0x0000 }, { CAT_RCK_DATA_SEU1, 1, 7, 0x0000 },
+	{ CAT_RCK_DATA_SEU2, 1, 11, 0x0000 }, { CAT_RCK_DATA_SEU3, 1, 15, 0x0000 },
+	{ CAT_RCK_DATA_SEU4, 1, 19, 0x0000 }, { CAT_RCK_DATA_SEU5, 1, 23, 0x0000 },
+	{ CAT_RCK_DATA_SEU6, 1, 27, 0x0000 }, { CAT_RCK_DATA_SEU7, 1, 31, 0x0000 },
+};
+
+static nthw_fpga_register_init_s cat_registers[] = {
+	{ CAT_CCT_CTRL, 30, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_cct_ctrl_fields },
+	{ CAT_CCT_DATA, 31, 36, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_cct_data_fields },
+	{ CAT_CFN_CTRL, 10, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_cfn_ctrl_fields },
+	{ CAT_CFN_DATA, 11, 179, NTHW_FPGA_REG_TYPE_WO, 0, 44, cat_cfn_data_fields },
+	{ CAT_COT_CTRL, 28, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_cot_ctrl_fields },
+	{ CAT_COT_DATA, 29, 36, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_cot_data_fields },
+	{ CAT_CTE_CTRL, 24, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_cte_ctrl_fields },
+	{ CAT_CTE_DATA, 25, 11, NTHW_FPGA_REG_TYPE_WO, 0, 11, cat_cte_data_fields },
+	{ CAT_CTS_CTRL, 26, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_cts_ctrl_fields },
+	{ CAT_CTS_DATA, 27, 12, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_cts_data_fields },
+	{ CAT_DCT_CTRL, 6, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_dct_ctrl_fields },
+	{ CAT_DCT_DATA, 7, 16, NTHW_FPGA_REG_TYPE_WO, 0, 1, cat_dct_data_fields },
+	{ CAT_DCT_SEL, 4, 2, NTHW_FPGA_REG_TYPE_WO, 0, 1, cat_dct_sel_fields },
+	{ CAT_EXO_CTRL, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_exo_ctrl_fields },
+	{ CAT_EXO_DATA, 1, 27, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_exo_data_fields },
+	{ CAT_FTE0_CTRL, 16, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_fte0_ctrl_fields },
+	{ CAT_FTE0_DATA, 17, 8, NTHW_FPGA_REG_TYPE_WO, 0, 1, cat_fte0_data_fields },
+	{ CAT_FTE1_CTRL, 22, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_fte1_ctrl_fields },
+	{ CAT_FTE1_DATA, 23, 8, NTHW_FPGA_REG_TYPE_WO, 0, 1, cat_fte1_data_fields },
+	{ CAT_JOIN, 5, 9, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_join_fields },
+	{ CAT_KCC_CTRL, 32, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_kcc_ctrl_fields },
+	{ CAT_KCC_DATA, 33, 84, NTHW_FPGA_REG_TYPE_WO, 0, 3, cat_kcc_data_fields },
+	{ CAT_KCE0_CTRL, 12, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_kce0_ctrl_fields },
+	{ CAT_KCE0_DATA, 13, 8, NTHW_FPGA_REG_TYPE_WO, 0, 1, cat_kce0_data_fields },
+	{ CAT_KCE1_CTRL, 18, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_kce1_ctrl_fields },
+	{ CAT_KCE1_DATA, 19, 8, NTHW_FPGA_REG_TYPE_WO, 0, 1, cat_kce1_data_fields },
+	{ CAT_KCS0_CTRL, 14, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_kcs0_ctrl_fields },
+	{ CAT_KCS0_DATA, 15, 6, NTHW_FPGA_REG_TYPE_WO, 0, 1, cat_kcs0_data_fields },
+	{ CAT_KCS1_CTRL, 20, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_kcs1_ctrl_fields },
+	{ CAT_KCS1_DATA, 21, 6, NTHW_FPGA_REG_TYPE_WO, 0, 1, cat_kcs1_data_fields },
+	{ CAT_LEN_CTRL, 8, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_len_ctrl_fields },
+	{ CAT_LEN_DATA, 9, 39, NTHW_FPGA_REG_TYPE_WO, 0, 5, cat_len_data_fields },
+	{ CAT_RCK_CTRL, 2, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cat_rck_ctrl_fields },
+	{ CAT_RCK_DATA, 3, 32, NTHW_FPGA_REG_TYPE_WO, 0, 32, cat_rck_data_fields },
+};
+
+static nthw_fpga_field_init_s cpy_packet_reader0_ctrl_fields[] = {
+	{ CPY_PACKET_READER0_CTRL_ADR, 4, 0, 0x0000 },
+	{ CPY_PACKET_READER0_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_packet_reader0_data_fields[] = {
+	{ CPY_PACKET_READER0_DATA_DYN, 5, 10, 0x0000 },
+	{ CPY_PACKET_READER0_DATA_OFS, 10, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer0_ctrl_fields[] = {
+	{ CPY_WRITER0_CTRL_ADR, 4, 0, 0x0000 },
+	{ CPY_WRITER0_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer0_data_fields[] = {
+	{ CPY_WRITER0_DATA_DYN, 5, 17, 0x0000 }, { CPY_WRITER0_DATA_LEN, 5, 22, 0x0000 },
+	{ CPY_WRITER0_DATA_MASK_POINTER, 4, 27, 0x0000 }, { CPY_WRITER0_DATA_OFS, 14, 3, 0x0000 },
+	{ CPY_WRITER0_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer0_mask_ctrl_fields[] = {
+	{ CPY_WRITER0_MASK_CTRL_ADR, 4, 0, 0x0000 },
+	{ CPY_WRITER0_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer0_mask_data_fields[] = {
+	{ CPY_WRITER0_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer1_ctrl_fields[] = {
+	{ CPY_WRITER1_CTRL_ADR, 4, 0, 0x0000 },
+	{ CPY_WRITER1_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer1_data_fields[] = {
+	{ CPY_WRITER1_DATA_DYN, 5, 17, 0x0000 }, { CPY_WRITER1_DATA_LEN, 5, 22, 0x0000 },
+	{ CPY_WRITER1_DATA_MASK_POINTER, 4, 27, 0x0000 }, { CPY_WRITER1_DATA_OFS, 14, 3, 0x0000 },
+	{ CPY_WRITER1_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer1_mask_ctrl_fields[] = {
+	{ CPY_WRITER1_MASK_CTRL_ADR, 4, 0, 0x0000 },
+	{ CPY_WRITER1_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer1_mask_data_fields[] = {
+	{ CPY_WRITER1_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer2_ctrl_fields[] = {
+	{ CPY_WRITER2_CTRL_ADR, 4, 0, 0x0000 },
+	{ CPY_WRITER2_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer2_data_fields[] = {
+	{ CPY_WRITER2_DATA_DYN, 5, 17, 0x0000 }, { CPY_WRITER2_DATA_LEN, 5, 22, 0x0000 },
+	{ CPY_WRITER2_DATA_MASK_POINTER, 4, 27, 0x0000 }, { CPY_WRITER2_DATA_OFS, 14, 3, 0x0000 },
+	{ CPY_WRITER2_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer2_mask_ctrl_fields[] = {
+	{ CPY_WRITER2_MASK_CTRL_ADR, 4, 0, 0x0000 },
+	{ CPY_WRITER2_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer2_mask_data_fields[] = {
+	{ CPY_WRITER2_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer3_ctrl_fields[] = {
+	{ CPY_WRITER3_CTRL_ADR, 4, 0, 0x0000 },
+	{ CPY_WRITER3_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer3_data_fields[] = {
+	{ CPY_WRITER3_DATA_DYN, 5, 17, 0x0000 }, { CPY_WRITER3_DATA_LEN, 5, 22, 0x0000 },
+	{ CPY_WRITER3_DATA_MASK_POINTER, 4, 27, 0x0000 }, { CPY_WRITER3_DATA_OFS, 14, 3, 0x0000 },
+	{ CPY_WRITER3_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer3_mask_ctrl_fields[] = {
+	{ CPY_WRITER3_MASK_CTRL_ADR, 4, 0, 0x0000 },
+	{ CPY_WRITER3_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer3_mask_data_fields[] = {
+	{ CPY_WRITER3_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer4_ctrl_fields[] = {
+	{ CPY_WRITER4_CTRL_ADR, 4, 0, 0x0000 },
+	{ CPY_WRITER4_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer4_data_fields[] = {
+	{ CPY_WRITER4_DATA_DYN, 5, 17, 0x0000 }, { CPY_WRITER4_DATA_LEN, 5, 22, 0x0000 },
+	{ CPY_WRITER4_DATA_MASK_POINTER, 4, 27, 0x0000 }, { CPY_WRITER4_DATA_OFS, 14, 3, 0x0000 },
+	{ CPY_WRITER4_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer4_mask_ctrl_fields[] = {
+	{ CPY_WRITER4_MASK_CTRL_ADR, 4, 0, 0x0000 },
+	{ CPY_WRITER4_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer4_mask_data_fields[] = {
+	{ CPY_WRITER4_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer5_ctrl_fields[] = {
+	{ CPY_WRITER5_CTRL_ADR, 4, 0, 0x0000 },
+	{ CPY_WRITER5_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer5_data_fields[] = {
+	{ CPY_WRITER5_DATA_DYN, 5, 17, 0x0000 }, { CPY_WRITER5_DATA_LEN, 5, 22, 0x0000 },
+	{ CPY_WRITER5_DATA_MASK_POINTER, 4, 27, 0x0000 }, { CPY_WRITER5_DATA_OFS, 14, 3, 0x0000 },
+	{ CPY_WRITER5_DATA_READER_SELECT, 3, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer5_mask_ctrl_fields[] = {
+	{ CPY_WRITER5_MASK_CTRL_ADR, 4, 0, 0x0000 },
+	{ CPY_WRITER5_MASK_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s cpy_writer5_mask_data_fields[] = {
+	{ CPY_WRITER5_MASK_DATA_BYTE_MASK, 16, 0, 0x0000 },
+};
+
+static nthw_fpga_register_init_s cpy_registers[] = {
+	{
+		CPY_PACKET_READER0_CTRL, 24, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2,
+		cpy_packet_reader0_ctrl_fields
+	},
+	{
+		CPY_PACKET_READER0_DATA, 25, 15, NTHW_FPGA_REG_TYPE_WO, 0, 2,
+		cpy_packet_reader0_data_fields
+	},
+	{ CPY_WRITER0_CTRL, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cpy_writer0_ctrl_fields },
+	{ CPY_WRITER0_DATA, 1, 31, NTHW_FPGA_REG_TYPE_WO, 0, 5, cpy_writer0_data_fields },
+	{
+		CPY_WRITER0_MASK_CTRL, 2, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2,
+		cpy_writer0_mask_ctrl_fields
+	},
+	{
+		CPY_WRITER0_MASK_DATA, 3, 16, NTHW_FPGA_REG_TYPE_WO, 0, 1,
+		cpy_writer0_mask_data_fields
+	},
+	{ CPY_WRITER1_CTRL, 4, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cpy_writer1_ctrl_fields },
+	{ CPY_WRITER1_DATA, 5, 31, NTHW_FPGA_REG_TYPE_WO, 0, 5, cpy_writer1_data_fields },
+	{
+		CPY_WRITER1_MASK_CTRL, 6, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2,
+		cpy_writer1_mask_ctrl_fields
+	},
+	{
+		CPY_WRITER1_MASK_DATA, 7, 16, NTHW_FPGA_REG_TYPE_WO, 0, 1,
+		cpy_writer1_mask_data_fields
+	},
+	{ CPY_WRITER2_CTRL, 8, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cpy_writer2_ctrl_fields },
+	{ CPY_WRITER2_DATA, 9, 31, NTHW_FPGA_REG_TYPE_WO, 0, 5, cpy_writer2_data_fields },
+	{
+		CPY_WRITER2_MASK_CTRL, 10, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2,
+		cpy_writer2_mask_ctrl_fields
+	},
+	{
+		CPY_WRITER2_MASK_DATA, 11, 16, NTHW_FPGA_REG_TYPE_WO, 0, 1,
+		cpy_writer2_mask_data_fields
+	},
+	{ CPY_WRITER3_CTRL, 12, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cpy_writer3_ctrl_fields },
+	{ CPY_WRITER3_DATA, 13, 31, NTHW_FPGA_REG_TYPE_WO, 0, 5, cpy_writer3_data_fields },
+	{
+		CPY_WRITER3_MASK_CTRL, 14, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2,
+		cpy_writer3_mask_ctrl_fields
+	},
+	{
+		CPY_WRITER3_MASK_DATA, 15, 16, NTHW_FPGA_REG_TYPE_WO, 0, 1,
+		cpy_writer3_mask_data_fields
+	},
+	{ CPY_WRITER4_CTRL, 16, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cpy_writer4_ctrl_fields },
+	{ CPY_WRITER4_DATA, 17, 31, NTHW_FPGA_REG_TYPE_WO, 0, 5, cpy_writer4_data_fields },
+	{
+		CPY_WRITER4_MASK_CTRL, 18, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2,
+		cpy_writer4_mask_ctrl_fields
+	},
+	{
+		CPY_WRITER4_MASK_DATA, 19, 16, NTHW_FPGA_REG_TYPE_WO, 0, 1,
+		cpy_writer4_mask_data_fields
+	},
+	{ CPY_WRITER5_CTRL, 20, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, cpy_writer5_ctrl_fields },
+	{ CPY_WRITER5_DATA, 21, 31, NTHW_FPGA_REG_TYPE_WO, 0, 5, cpy_writer5_data_fields },
+	{
+		CPY_WRITER5_MASK_CTRL, 22, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2,
+		cpy_writer5_mask_ctrl_fields
+	},
+	{
+		CPY_WRITER5_MASK_DATA, 23, 16, NTHW_FPGA_REG_TYPE_WO, 0, 1,
+		cpy_writer5_mask_data_fields
+	},
+};
+
+static nthw_fpga_field_init_s csu_rcp_ctrl_fields[] = {
+	{ CSU_RCP_CTRL_ADR, 4, 0, 0x0000 },
+	{ CSU_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s csu_rcp_data_fields[] = {
+	{ CSU_RCP_DATA_IL3_CMD, 2, 5, 0x0000 },
+	{ CSU_RCP_DATA_IL4_CMD, 3, 7, 0x0000 },
+	{ CSU_RCP_DATA_OL3_CMD, 2, 0, 0x0000 },
+	{ CSU_RCP_DATA_OL4_CMD, 3, 2, 0x0000 },
+};
+
+static nthw_fpga_register_init_s csu_registers[] = {
+	{ CSU_RCP_CTRL, 1, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, csu_rcp_ctrl_fields },
+	{ CSU_RCP_DATA, 2, 10, NTHW_FPGA_REG_TYPE_WO, 0, 4, csu_rcp_data_fields },
+};
+
+static nthw_fpga_field_init_s dbs_rx_am_ctrl_fields[] = {
+	{ DBS_RX_AM_CTRL_ADR, 7, 0, 0x0000 },
+	{ DBS_RX_AM_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_rx_am_data_fields[] = {
+	{ DBS_RX_AM_DATA_ENABLE, 1, 72, 0x0000 }, { DBS_RX_AM_DATA_GPA, 64, 0, 0x0000 },
+	{ DBS_RX_AM_DATA_HID, 8, 64, 0x0000 }, { DBS_RX_AM_DATA_INT, 1, 74, 0x0000 },
+	{ DBS_RX_AM_DATA_PCKED, 1, 73, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_rx_control_fields[] = {
+	{ DBS_RX_CONTROL_AME, 1, 7, 0 }, { DBS_RX_CONTROL_AMS, 4, 8, 8 },
+	{ DBS_RX_CONTROL_LQ, 7, 0, 0 }, { DBS_RX_CONTROL_QE, 1, 17, 0 },
+	{ DBS_RX_CONTROL_UWE, 1, 12, 0 }, { DBS_RX_CONTROL_UWS, 4, 13, 5 },
+};
+
+static nthw_fpga_field_init_s dbs_rx_dr_ctrl_fields[] = {
+	{ DBS_RX_DR_CTRL_ADR, 7, 0, 0x0000 },
+	{ DBS_RX_DR_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_rx_dr_data_fields[] = {
+	{ DBS_RX_DR_DATA_GPA, 64, 0, 0x0000 }, { DBS_RX_DR_DATA_HDR, 1, 88, 0x0000 },
+	{ DBS_RX_DR_DATA_HID, 8, 64, 0x0000 }, { DBS_RX_DR_DATA_PCKED, 1, 87, 0x0000 },
+	{ DBS_RX_DR_DATA_QS, 15, 72, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_rx_idle_fields[] = {
+	{ DBS_RX_IDLE_BUSY, 1, 8, 0 },
+	{ DBS_RX_IDLE_IDLE, 1, 0, 0x0000 },
+	{ DBS_RX_IDLE_QUEUE, 7, 1, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_rx_init_fields[] = {
+	{ DBS_RX_INIT_BUSY, 1, 8, 0 },
+	{ DBS_RX_INIT_INIT, 1, 0, 0x0000 },
+	{ DBS_RX_INIT_QUEUE, 7, 1, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_rx_init_val_fields[] = {
+	{ DBS_RX_INIT_VAL_IDX, 16, 0, 0x0000 },
+	{ DBS_RX_INIT_VAL_PTR, 15, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_rx_ptr_fields[] = {
+	{ DBS_RX_PTR_PTR, 16, 0, 0x0000 },
+	{ DBS_RX_PTR_QUEUE, 7, 16, 0x0000 },
+	{ DBS_RX_PTR_VALID, 1, 23, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_rx_uw_ctrl_fields[] = {
+	{ DBS_RX_UW_CTRL_ADR, 7, 0, 0x0000 },
+	{ DBS_RX_UW_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_rx_uw_data_fields[] = {
+	{ DBS_RX_UW_DATA_GPA, 64, 0, 0x0000 }, { DBS_RX_UW_DATA_HID, 8, 64, 0x0000 },
+	{ DBS_RX_UW_DATA_INT, 1, 88, 0x0000 }, { DBS_RX_UW_DATA_ISTK, 1, 92, 0x0000 },
+	{ DBS_RX_UW_DATA_PCKED, 1, 87, 0x0000 }, { DBS_RX_UW_DATA_QS, 15, 72, 0x0000 },
+	{ DBS_RX_UW_DATA_VEC, 3, 89, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_am_ctrl_fields[] = {
+	{ DBS_TX_AM_CTRL_ADR, 7, 0, 0x0000 },
+	{ DBS_TX_AM_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_am_data_fields[] = {
+	{ DBS_TX_AM_DATA_ENABLE, 1, 72, 0x0000 }, { DBS_TX_AM_DATA_GPA, 64, 0, 0x0000 },
+	{ DBS_TX_AM_DATA_HID, 8, 64, 0x0000 }, { DBS_TX_AM_DATA_INT, 1, 74, 0x0000 },
+	{ DBS_TX_AM_DATA_PCKED, 1, 73, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_control_fields[] = {
+	{ DBS_TX_CONTROL_AME, 1, 7, 0 }, { DBS_TX_CONTROL_AMS, 4, 8, 5 },
+	{ DBS_TX_CONTROL_LQ, 7, 0, 0 }, { DBS_TX_CONTROL_QE, 1, 17, 0 },
+	{ DBS_TX_CONTROL_UWE, 1, 12, 0 }, { DBS_TX_CONTROL_UWS, 4, 13, 8 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_dr_ctrl_fields[] = {
+	{ DBS_TX_DR_CTRL_ADR, 7, 0, 0x0000 },
+	{ DBS_TX_DR_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_dr_data_fields[] = {
+	{ DBS_TX_DR_DATA_GPA, 64, 0, 0x0000 }, { DBS_TX_DR_DATA_HDR, 1, 88, 0x0000 },
+	{ DBS_TX_DR_DATA_HID, 8, 64, 0x0000 }, { DBS_TX_DR_DATA_PCKED, 1, 87, 0x0000 },
+	{ DBS_TX_DR_DATA_PORT, 1, 89, 0x0000 }, { DBS_TX_DR_DATA_QS, 15, 72, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_idle_fields[] = {
+	{ DBS_TX_IDLE_BUSY, 1, 8, 0 },
+	{ DBS_TX_IDLE_IDLE, 1, 0, 0x0000 },
+	{ DBS_TX_IDLE_QUEUE, 7, 1, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_init_fields[] = {
+	{ DBS_TX_INIT_BUSY, 1, 8, 0 },
+	{ DBS_TX_INIT_INIT, 1, 0, 0x0000 },
+	{ DBS_TX_INIT_QUEUE, 7, 1, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_init_val_fields[] = {
+	{ DBS_TX_INIT_VAL_IDX, 16, 0, 0x0000 },
+	{ DBS_TX_INIT_VAL_PTR, 15, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_ptr_fields[] = {
+	{ DBS_TX_PTR_PTR, 16, 0, 0x0000 },
+	{ DBS_TX_PTR_QUEUE, 7, 16, 0x0000 },
+	{ DBS_TX_PTR_VALID, 1, 23, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_qos_ctrl_fields[] = {
+	{ DBS_TX_QOS_CTRL_ADR, 1, 0, 0x0000 },
+	{ DBS_TX_QOS_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_qos_data_fields[] = {
+	{ DBS_TX_QOS_DATA_BS, 27, 17, 0x0000 },
+	{ DBS_TX_QOS_DATA_EN, 1, 0, 0x0000 },
+	{ DBS_TX_QOS_DATA_IR, 16, 1, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_qos_rate_fields[] = {
+	{ DBS_TX_QOS_RATE_DIV, 19, 16, 2 },
+	{ DBS_TX_QOS_RATE_MUL, 16, 0, 1 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_qp_ctrl_fields[] = {
+	{ DBS_TX_QP_CTRL_ADR, 7, 0, 0x0000 },
+	{ DBS_TX_QP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_qp_data_fields[] = {
+	{ DBS_TX_QP_DATA_VPORT, 1, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_uw_ctrl_fields[] = {
+	{ DBS_TX_UW_CTRL_ADR, 7, 0, 0x0000 },
+	{ DBS_TX_UW_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s dbs_tx_uw_data_fields[] = {
+	{ DBS_TX_UW_DATA_GPA, 64, 0, 0x0000 }, { DBS_TX_UW_DATA_HID, 8, 64, 0x0000 },
+	{ DBS_TX_UW_DATA_INO, 1, 93, 0x0000 }, { DBS_TX_UW_DATA_INT, 1, 88, 0x0000 },
+	{ DBS_TX_UW_DATA_ISTK, 1, 92, 0x0000 }, { DBS_TX_UW_DATA_PCKED, 1, 87, 0x0000 },
+	{ DBS_TX_UW_DATA_QS, 15, 72, 0x0000 }, { DBS_TX_UW_DATA_VEC, 3, 89, 0x0000 },
+};
+
+static nthw_fpga_register_init_s dbs_registers[] = {
+	{ DBS_RX_AM_CTRL, 10, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, dbs_rx_am_ctrl_fields },
+	{ DBS_RX_AM_DATA, 11, 75, NTHW_FPGA_REG_TYPE_WO, 0, 5, dbs_rx_am_data_fields },
+	{ DBS_RX_CONTROL, 0, 18, NTHW_FPGA_REG_TYPE_RW, 43008, 6, dbs_rx_control_fields },
+	{ DBS_RX_DR_CTRL, 18, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, dbs_rx_dr_ctrl_fields },
+	{ DBS_RX_DR_DATA, 19, 89, NTHW_FPGA_REG_TYPE_WO, 0, 5, dbs_rx_dr_data_fields },
+	{ DBS_RX_IDLE, 8, 9, NTHW_FPGA_REG_TYPE_MIXED, 0, 3, dbs_rx_idle_fields },
+	{ DBS_RX_INIT, 2, 9, NTHW_FPGA_REG_TYPE_MIXED, 0, 3, dbs_rx_init_fields },
+	{ DBS_RX_INIT_VAL, 3, 31, NTHW_FPGA_REG_TYPE_WO, 0, 2, dbs_rx_init_val_fields },
+	{ DBS_RX_PTR, 4, 24, NTHW_FPGA_REG_TYPE_MIXED, 0, 3, dbs_rx_ptr_fields },
+	{ DBS_RX_UW_CTRL, 14, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, dbs_rx_uw_ctrl_fields },
+	{ DBS_RX_UW_DATA, 15, 93, NTHW_FPGA_REG_TYPE_WO, 0, 7, dbs_rx_uw_data_fields },
+	{ DBS_TX_AM_CTRL, 12, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, dbs_tx_am_ctrl_fields },
+	{ DBS_TX_AM_DATA, 13, 75, NTHW_FPGA_REG_TYPE_WO, 0, 5, dbs_tx_am_data_fields },
+	{ DBS_TX_CONTROL, 1, 18, NTHW_FPGA_REG_TYPE_RW, 66816, 6, dbs_tx_control_fields },
+	{ DBS_TX_DR_CTRL, 20, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, dbs_tx_dr_ctrl_fields },
+	{ DBS_TX_DR_DATA, 21, 90, NTHW_FPGA_REG_TYPE_WO, 0, 6, dbs_tx_dr_data_fields },
+	{ DBS_TX_IDLE, 9, 9, NTHW_FPGA_REG_TYPE_MIXED, 0, 3, dbs_tx_idle_fields },
+	{ DBS_TX_INIT, 5, 9, NTHW_FPGA_REG_TYPE_MIXED, 0, 3, dbs_tx_init_fields },
+	{ DBS_TX_INIT_VAL, 6, 31, NTHW_FPGA_REG_TYPE_WO, 0, 2, dbs_tx_init_val_fields },
+	{ DBS_TX_PTR, 7, 24, NTHW_FPGA_REG_TYPE_MIXED, 0, 3, dbs_tx_ptr_fields },
+	{ DBS_TX_QOS_CTRL, 24, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, dbs_tx_qos_ctrl_fields },
+	{ DBS_TX_QOS_DATA, 25, 44, NTHW_FPGA_REG_TYPE_WO, 0, 3, dbs_tx_qos_data_fields },
+	{ DBS_TX_QOS_RATE, 26, 35, NTHW_FPGA_REG_TYPE_RW, 131073, 2, dbs_tx_qos_rate_fields },
+	{ DBS_TX_QP_CTRL, 22, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, dbs_tx_qp_ctrl_fields },
+	{ DBS_TX_QP_DATA, 23, 1, NTHW_FPGA_REG_TYPE_WO, 0, 1, dbs_tx_qp_data_fields },
+	{ DBS_TX_UW_CTRL, 16, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, dbs_tx_uw_ctrl_fields },
+	{ DBS_TX_UW_DATA, 17, 94, NTHW_FPGA_REG_TYPE_WO, 0, 8, dbs_tx_uw_data_fields },
+};
+
+static nthw_fpga_field_init_s flm_buf_ctrl_fields[] = {
+	{ FLM_BUF_CTRL_INF_AVAIL, 16, 16, 0x0000 },
+	{ FLM_BUF_CTRL_LRN_FREE, 16, 0, 0x0000 },
+	{ FLM_BUF_CTRL_STA_AVAIL, 16, 32, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_control_fields[] = {
+	{ FLM_CONTROL_CALIB_RECALIBRATE, 4, 28, 0 },
+	{ FLM_CONTROL_CRCRD, 1, 12, 0x0000 },
+	{ FLM_CONTROL_CRCWR, 1, 11, 0x0000 },
+	{ FLM_CONTROL_EAB, 5, 18, 0 },
+	{ FLM_CONTROL_ENABLE, 1, 0, 0 },
+	{ FLM_CONTROL_INIT, 1, 1, 0x0000 },
+	{ FLM_CONTROL_LDS, 1, 2, 0x0000 },
+	{ FLM_CONTROL_LFS, 1, 3, 0x0000 },
+	{ FLM_CONTROL_LIS, 1, 4, 0x0000 },
+	{ FLM_CONTROL_PDS, 1, 9, 0x0000 },
+	{ FLM_CONTROL_PIS, 1, 10, 0x0000 },
+	{ FLM_CONTROL_RBL, 4, 13, 0 },
+	{ FLM_CONTROL_RDS, 1, 7, 0x0000 },
+	{ FLM_CONTROL_RIS, 1, 8, 0x0000 },
+	{ FLM_CONTROL_SPLIT_SDRAM_USAGE, 5, 23, 16 },
+	{ FLM_CONTROL_UDS, 1, 5, 0x0000 },
+	{ FLM_CONTROL_UIS, 1, 6, 0x0000 },
+	{ FLM_CONTROL_WPD, 1, 17, 0 },
+};
+
+static nthw_fpga_field_init_s flm_inf_data_fields[] = {
+	{ FLM_INF_DATA_BYTES, 64, 0, 0x0000 }, { FLM_INF_DATA_CAUSE, 3, 224, 0x0000 },
+	{ FLM_INF_DATA_EOR, 1, 287, 0x0000 }, { FLM_INF_DATA_ID, 32, 192, 0x0000 },
+	{ FLM_INF_DATA_PACKETS, 64, 64, 0x0000 }, { FLM_INF_DATA_TS, 64, 128, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_load_aps_fields[] = {
+	{ FLM_LOAD_APS_APS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_load_bin_fields[] = {
+	{ FLM_LOAD_BIN_BIN, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_load_lps_fields[] = {
+	{ FLM_LOAD_LPS_LPS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_lrn_data_fields[] = {
+	{ FLM_LRN_DATA_ADJ, 32, 480, 0x0000 }, { FLM_LRN_DATA_COLOR, 32, 448, 0x0000 },
+	{ FLM_LRN_DATA_DSCP, 6, 698, 0x0000 }, { FLM_LRN_DATA_ENT, 1, 693, 0x0000 },
+	{ FLM_LRN_DATA_EOR, 1, 767, 0x0000 }, { FLM_LRN_DATA_FILL, 16, 544, 0x0000 },
+	{ FLM_LRN_DATA_FT, 4, 560, 0x0000 }, { FLM_LRN_DATA_FT_MBR, 4, 564, 0x0000 },
+	{ FLM_LRN_DATA_FT_MISS, 4, 568, 0x0000 }, { FLM_LRN_DATA_ID, 32, 512, 0x0000 },
+	{ FLM_LRN_DATA_KID, 8, 328, 0x0000 }, { FLM_LRN_DATA_MBR_ID1, 28, 572, 0x0000 },
+	{ FLM_LRN_DATA_MBR_ID2, 28, 600, 0x0000 }, { FLM_LRN_DATA_MBR_ID3, 28, 628, 0x0000 },
+	{ FLM_LRN_DATA_MBR_ID4, 28, 656, 0x0000 }, { FLM_LRN_DATA_NAT_EN, 1, 711, 0x0000 },
+	{ FLM_LRN_DATA_NAT_IP, 32, 336, 0x0000 }, { FLM_LRN_DATA_NAT_PORT, 16, 400, 0x0000 },
+	{ FLM_LRN_DATA_NOFI, 1, 716, 0x0000 }, { FLM_LRN_DATA_OP, 4, 694, 0x0000 },
+	{ FLM_LRN_DATA_PRIO, 2, 691, 0x0000 }, { FLM_LRN_DATA_PROT, 8, 320, 0x0000 },
+	{ FLM_LRN_DATA_QFI, 6, 704, 0x0000 }, { FLM_LRN_DATA_QW0, 128, 192, 0x0000 },
+	{ FLM_LRN_DATA_QW4, 128, 64, 0x0000 }, { FLM_LRN_DATA_RATE, 16, 416, 0x0000 },
+	{ FLM_LRN_DATA_RQI, 1, 710, 0x0000 }, { FLM_LRN_DATA_SCRUB_PROF, 4, 712, 0x0000 },
+	{ FLM_LRN_DATA_SIZE, 16, 432, 0x0000 }, { FLM_LRN_DATA_STAT_PROF, 4, 687, 0x0000 },
+	{ FLM_LRN_DATA_SW8, 32, 32, 0x0000 }, { FLM_LRN_DATA_SW9, 32, 0, 0x0000 },
+	{ FLM_LRN_DATA_TEID, 32, 368, 0x0000 }, { FLM_LRN_DATA_VOL_IDX, 3, 684, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_prio_fields[] = {
+	{ FLM_PRIO_FT0, 4, 4, 1 }, { FLM_PRIO_FT1, 4, 12, 1 }, { FLM_PRIO_FT2, 4, 20, 1 },
+	{ FLM_PRIO_FT3, 4, 28, 1 }, { FLM_PRIO_LIMIT0, 4, 0, 0 }, { FLM_PRIO_LIMIT1, 4, 8, 0 },
+	{ FLM_PRIO_LIMIT2, 4, 16, 0 }, { FLM_PRIO_LIMIT3, 4, 24, 0 },
+};
+
+static nthw_fpga_field_init_s flm_pst_ctrl_fields[] = {
+	{ FLM_PST_CTRL_ADR, 4, 0, 0x0000 },
+	{ FLM_PST_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_pst_data_fields[] = {
+	{ FLM_PST_DATA_BP, 5, 0, 0x0000 },
+	{ FLM_PST_DATA_PP, 5, 5, 0x0000 },
+	{ FLM_PST_DATA_TP, 5, 10, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_rcp_ctrl_fields[] = {
+	{ FLM_RCP_CTRL_ADR, 5, 0, 0x0000 },
+	{ FLM_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_rcp_data_fields[] = {
+	{ FLM_RCP_DATA_AUTO_IPV4_MASK, 1, 402, 0x0000 },
+	{ FLM_RCP_DATA_BYT_DYN, 5, 387, 0x0000 },
+	{ FLM_RCP_DATA_BYT_OFS, 8, 392, 0x0000 },
+	{ FLM_RCP_DATA_IPN, 1, 386, 0x0000 },
+	{ FLM_RCP_DATA_KID, 8, 377, 0x0000 },
+	{ FLM_RCP_DATA_LOOKUP, 1, 0, 0x0000 },
+	{ FLM_RCP_DATA_MASK, 320, 57, 0x0000 },
+	{ FLM_RCP_DATA_OPN, 1, 385, 0x0000 },
+	{ FLM_RCP_DATA_QW0_DYN, 5, 1, 0x0000 },
+	{ FLM_RCP_DATA_QW0_OFS, 8, 6, 0x0000 },
+	{ FLM_RCP_DATA_QW0_SEL, 2, 14, 0x0000 },
+	{ FLM_RCP_DATA_QW4_DYN, 5, 16, 0x0000 },
+	{ FLM_RCP_DATA_QW4_OFS, 8, 21, 0x0000 },
+	{ FLM_RCP_DATA_SW8_DYN, 5, 29, 0x0000 },
+	{ FLM_RCP_DATA_SW8_OFS, 8, 34, 0x0000 },
+	{ FLM_RCP_DATA_SW8_SEL, 2, 42, 0x0000 },
+	{ FLM_RCP_DATA_SW9_DYN, 5, 44, 0x0000 },
+	{ FLM_RCP_DATA_SW9_OFS, 8, 49, 0x0000 },
+	{ FLM_RCP_DATA_TXPLM, 2, 400, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_scan_fields[] = {
+	{ FLM_SCAN_I, 16, 0, 0 },
+};
+
+static nthw_fpga_field_init_s flm_scrub_ctrl_fields[] = {
+	{ FLM_SCRUB_CTRL_ADR, 4, 0, 0x0000 },
+	{ FLM_SCRUB_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_scrub_data_fields[] = {
+	{ FLM_SCRUB_DATA_DEL, 1, 12, 0 },
+	{ FLM_SCRUB_DATA_INF, 1, 13, 0 },
+	{ FLM_SCRUB_DATA_R, 4, 8, 0 },
+	{ FLM_SCRUB_DATA_T, 8, 0, 0 },
+};
+
+static nthw_fpga_field_init_s flm_status_fields[] = {
+	{ FLM_STATUS_CACHE_BUFFER_CRITICAL, 1, 14, 0x0000 },
+	{ FLM_STATUS_CALIB_FAIL, 4, 4, 0 },
+	{ FLM_STATUS_CALIB_SUCCESS, 4, 0, 0 },
+	{ FLM_STATUS_CRCERR, 1, 12, 0x0000 },
+	{ FLM_STATUS_CRITICAL, 1, 10, 0x0000 },
+	{ FLM_STATUS_EFT_BP, 1, 13, 0x0000 },
+	{ FLM_STATUS_IDLE, 1, 9, 0x0000 },
+	{ FLM_STATUS_INITDONE, 1, 8, 0x0000 },
+	{ FLM_STATUS_PANIC, 1, 11, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_aul_done_fields[] = {
+	{ FLM_STAT_AUL_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_aul_fail_fields[] = {
+	{ FLM_STAT_AUL_FAIL_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_aul_ignore_fields[] = {
+	{ FLM_STAT_AUL_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_csh_hit_fields[] = {
+	{ FLM_STAT_CSH_HIT_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_csh_miss_fields[] = {
+	{ FLM_STAT_CSH_MISS_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_csh_unh_fields[] = {
+	{ FLM_STAT_CSH_UNH_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_cuc_move_fields[] = {
+	{ FLM_STAT_CUC_MOVE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_cuc_start_fields[] = {
+	{ FLM_STAT_CUC_START_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_flows_fields[] = {
+	{ FLM_STAT_FLOWS_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_inf_done_fields[] = {
+	{ FLM_STAT_INF_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_inf_skip_fields[] = {
+	{ FLM_STAT_INF_SKIP_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_lrn_done_fields[] = {
+	{ FLM_STAT_LRN_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_lrn_fail_fields[] = {
+	{ FLM_STAT_LRN_FAIL_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_lrn_ignore_fields[] = {
+	{ FLM_STAT_LRN_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_pck_dis_fields[] = {
+	{ FLM_STAT_PCK_DIS_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_pck_hit_fields[] = {
+	{ FLM_STAT_PCK_HIT_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_pck_miss_fields[] = {
+	{ FLM_STAT_PCK_MISS_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_pck_unh_fields[] = {
+	{ FLM_STAT_PCK_UNH_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_prb_done_fields[] = {
+	{ FLM_STAT_PRB_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_prb_ignore_fields[] = {
+	{ FLM_STAT_PRB_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_rel_done_fields[] = {
+	{ FLM_STAT_REL_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_rel_ignore_fields[] = {
+	{ FLM_STAT_REL_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_sta_done_fields[] = {
+	{ FLM_STAT_STA_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_tul_done_fields[] = {
+	{ FLM_STAT_TUL_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_unl_done_fields[] = {
+	{ FLM_STAT_UNL_DONE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_stat_unl_ignore_fields[] = {
+	{ FLM_STAT_UNL_IGNORE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s flm_sta_data_fields[] = {
+	{ FLM_STA_DATA_EOR, 1, 95, 0x0000 }, { FLM_STA_DATA_ID, 32, 0, 0x0000 },
+	{ FLM_STA_DATA_LDS, 1, 32, 0x0000 }, { FLM_STA_DATA_LFS, 1, 33, 0x0000 },
+	{ FLM_STA_DATA_LIS, 1, 34, 0x0000 }, { FLM_STA_DATA_PDS, 1, 39, 0x0000 },
+	{ FLM_STA_DATA_PIS, 1, 40, 0x0000 }, { FLM_STA_DATA_RDS, 1, 37, 0x0000 },
+	{ FLM_STA_DATA_RIS, 1, 38, 0x0000 }, { FLM_STA_DATA_UDS, 1, 35, 0x0000 },
+	{ FLM_STA_DATA_UIS, 1, 36, 0x0000 },
+};
+
+static nthw_fpga_register_init_s flm_registers[] = {
+	{ FLM_BUF_CTRL, 14, 48, NTHW_FPGA_REG_TYPE_RW, 0, 3, flm_buf_ctrl_fields },
+	{ FLM_CONTROL, 0, 32, NTHW_FPGA_REG_TYPE_MIXED, 134217728, 18, flm_control_fields },
+	{ FLM_INF_DATA, 16, 288, NTHW_FPGA_REG_TYPE_RO, 0, 6, flm_inf_data_fields },
+	{ FLM_LOAD_APS, 5, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_load_aps_fields },
+	{ FLM_LOAD_BIN, 3, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, flm_load_bin_fields },
+	{ FLM_LOAD_LPS, 4, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_load_lps_fields },
+	{ FLM_LRN_DATA, 15, 768, NTHW_FPGA_REG_TYPE_WO, 0, 34, flm_lrn_data_fields },
+	{ FLM_PRIO, 6, 32, NTHW_FPGA_REG_TYPE_WO, 269488144, 8, flm_prio_fields },
+	{ FLM_PST_CTRL, 12, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, flm_pst_ctrl_fields },
+	{ FLM_PST_DATA, 13, 15, NTHW_FPGA_REG_TYPE_WO, 0, 3, flm_pst_data_fields },
+	{ FLM_RCP_CTRL, 8, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, flm_rcp_ctrl_fields },
+	{ FLM_RCP_DATA, 9, 403, NTHW_FPGA_REG_TYPE_WO, 0, 19, flm_rcp_data_fields },
+	{ FLM_SCAN, 2, 16, NTHW_FPGA_REG_TYPE_WO, 0, 1, flm_scan_fields },
+	{ FLM_SCRUB_CTRL, 10, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, flm_scrub_ctrl_fields },
+	{ FLM_SCRUB_DATA, 11, 14, NTHW_FPGA_REG_TYPE_WO, 0, 4, flm_scrub_data_fields },
+	{ FLM_STATUS, 1, 19, NTHW_FPGA_REG_TYPE_MIXED, 0, 9, flm_status_fields },
+	{ FLM_STAT_AUL_DONE, 41, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_aul_done_fields },
+	{ FLM_STAT_AUL_FAIL, 43, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_aul_fail_fields },
+	{ FLM_STAT_AUL_IGNORE, 42, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_aul_ignore_fields },
+	{ FLM_STAT_CSH_HIT, 52, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_csh_hit_fields },
+	{ FLM_STAT_CSH_MISS, 53, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_csh_miss_fields },
+	{ FLM_STAT_CSH_UNH, 54, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_csh_unh_fields },
+	{ FLM_STAT_CUC_MOVE, 56, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_cuc_move_fields },
+	{ FLM_STAT_CUC_START, 55, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_cuc_start_fields },
+	{ FLM_STAT_FLOWS, 18, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_flows_fields },
+	{ FLM_STAT_INF_DONE, 46, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_inf_done_fields },
+	{ FLM_STAT_INF_SKIP, 47, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_inf_skip_fields },
+	{ FLM_STAT_LRN_DONE, 32, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_lrn_done_fields },
+	{ FLM_STAT_LRN_FAIL, 34, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_lrn_fail_fields },
+	{ FLM_STAT_LRN_IGNORE, 33, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_lrn_ignore_fields },
+	{ FLM_STAT_PCK_DIS, 51, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_pck_dis_fields },
+	{ FLM_STAT_PCK_HIT, 48, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_pck_hit_fields },
+	{ FLM_STAT_PCK_MISS, 49, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_pck_miss_fields },
+	{ FLM_STAT_PCK_UNH, 50, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_pck_unh_fields },
+	{ FLM_STAT_PRB_DONE, 39, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_prb_done_fields },
+	{ FLM_STAT_PRB_IGNORE, 40, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_prb_ignore_fields },
+	{ FLM_STAT_REL_DONE, 37, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_rel_done_fields },
+	{ FLM_STAT_REL_IGNORE, 38, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_rel_ignore_fields },
+	{ FLM_STAT_STA_DONE, 45, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_sta_done_fields },
+	{ FLM_STAT_TUL_DONE, 44, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_tul_done_fields },
+	{ FLM_STAT_UNL_DONE, 35, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_unl_done_fields },
+	{ FLM_STAT_UNL_IGNORE, 36, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, flm_stat_unl_ignore_fields },
+	{ FLM_STA_DATA, 17, 96, NTHW_FPGA_REG_TYPE_RO, 0, 11, flm_sta_data_fields },
+};
+
+static nthw_fpga_field_init_s gfg_burstsize0_fields[] = {
+	{ GFG_BURSTSIZE0_VAL, 24, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gfg_burstsize1_fields[] = {
+	{ GFG_BURSTSIZE1_VAL, 24, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gfg_ctrl0_fields[] = {
+	{ GFG_CTRL0_ENABLE, 1, 0, 0 },
+	{ GFG_CTRL0_MODE, 3, 1, 0 },
+	{ GFG_CTRL0_PRBS_EN, 1, 4, 0 },
+	{ GFG_CTRL0_SIZE, 14, 16, 64 },
+};
+
+static nthw_fpga_field_init_s gfg_ctrl1_fields[] = {
+	{ GFG_CTRL1_ENABLE, 1, 0, 0 },
+	{ GFG_CTRL1_MODE, 3, 1, 0 },
+	{ GFG_CTRL1_PRBS_EN, 1, 4, 0 },
+	{ GFG_CTRL1_SIZE, 14, 16, 64 },
+};
+
+static nthw_fpga_field_init_s gfg_run0_fields[] = {
+	{ GFG_RUN0_RUN, 1, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gfg_run1_fields[] = {
+	{ GFG_RUN1_RUN, 1, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gfg_sizemask0_fields[] = {
+	{ GFG_SIZEMASK0_VAL, 14, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gfg_sizemask1_fields[] = {
+	{ GFG_SIZEMASK1_VAL, 14, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gfg_streamid0_fields[] = {
+	{ GFG_STREAMID0_VAL, 8, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gfg_streamid1_fields[] = {
+	{ GFG_STREAMID1_VAL, 8, 0, 1 },
+};
+
+static nthw_fpga_register_init_s gfg_registers[] = {
+	{ GFG_BURSTSIZE0, 3, 24, NTHW_FPGA_REG_TYPE_WO, 0, 1, gfg_burstsize0_fields },
+	{ GFG_BURSTSIZE1, 8, 24, NTHW_FPGA_REG_TYPE_WO, 0, 1, gfg_burstsize1_fields },
+	{ GFG_CTRL0, 0, 30, NTHW_FPGA_REG_TYPE_WO, 4194304, 4, gfg_ctrl0_fields },
+	{ GFG_CTRL1, 5, 30, NTHW_FPGA_REG_TYPE_WO, 4194304, 4, gfg_ctrl1_fields },
+	{ GFG_RUN0, 1, 1, NTHW_FPGA_REG_TYPE_WO, 0, 1, gfg_run0_fields },
+	{ GFG_RUN1, 6, 1, NTHW_FPGA_REG_TYPE_WO, 0, 1, gfg_run1_fields },
+	{ GFG_SIZEMASK0, 4, 14, NTHW_FPGA_REG_TYPE_WO, 0, 1, gfg_sizemask0_fields },
+	{ GFG_SIZEMASK1, 9, 14, NTHW_FPGA_REG_TYPE_WO, 0, 1, gfg_sizemask1_fields },
+	{ GFG_STREAMID0, 2, 8, NTHW_FPGA_REG_TYPE_WO, 0, 1, gfg_streamid0_fields },
+	{ GFG_STREAMID1, 7, 8, NTHW_FPGA_REG_TYPE_WO, 1, 1, gfg_streamid1_fields },
+};
+
+static nthw_fpga_field_init_s gmf_ctrl_fields[] = {
+	{ GMF_CTRL_ENABLE, 1, 0, 0 },
+	{ GMF_CTRL_FCS_ALWAYS, 1, 1, 0 },
+	{ GMF_CTRL_IFG_AUTO_ADJUST_ENABLE, 1, 7, 0 },
+	{ GMF_CTRL_IFG_ENABLE, 1, 2, 0 },
+	{ GMF_CTRL_IFG_TX_NOW_ALWAYS, 1, 3, 0 },
+	{ GMF_CTRL_IFG_TX_NOW_ON_TS_ENABLE, 1, 5, 0 },
+	{ GMF_CTRL_IFG_TX_ON_TS_ADJUST_ON_SET_CLOCK, 1, 6, 0 },
+	{ GMF_CTRL_IFG_TX_ON_TS_ALWAYS, 1, 4, 0 },
+	{ GMF_CTRL_TS_INJECT_ALWAYS, 1, 8, 0 },
+	{ GMF_CTRL_TS_INJECT_DUAL_STEP, 1, 9, 0 },
+};
+
+static nthw_fpga_field_init_s gmf_debug_lane_marker_fields[] = {
+	{ GMF_DEBUG_LANE_MARKER_COMPENSATION, 16, 0, 16384 },
+};
+
+static nthw_fpga_field_init_s gmf_ifg_max_adjust_slack_fields[] = {
+	{ GMF_IFG_MAX_ADJUST_SLACK_SLACK, 64, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gmf_ifg_set_clock_delta_fields[] = {
+	{ GMF_IFG_SET_CLOCK_DELTA_DELTA, 64, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gmf_ifg_set_clock_delta_adjust_fields[] = {
+	{ GMF_IFG_SET_CLOCK_DELTA_ADJUST_DELTA, 64, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gmf_ifg_tx_now_on_ts_fields[] = {
+	{ GMF_IFG_TX_NOW_ON_TS_TS, 64, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gmf_speed_fields[] = {
+	{ GMF_SPEED_IFG_SPEED, 64, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gmf_stat_data_buffer_fields[] = {
+	{ GMF_STAT_DATA_BUFFER_USED, 15, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s gmf_stat_max_delayed_pkt_fields[] = {
+	{ GMF_STAT_MAX_DELAYED_PKT_NS, 64, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gmf_stat_next_pkt_fields[] = {
+	{ GMF_STAT_NEXT_PKT_NS, 64, 0, 0 },
+};
+
+static nthw_fpga_field_init_s gmf_stat_sticky_fields[] = {
+	{ GMF_STAT_STICKY_DATA_UNDERFLOWED, 1, 0, 0 },
+	{ GMF_STAT_STICKY_IFG_ADJUSTED, 1, 1, 0 },
+};
+
+static nthw_fpga_field_init_s gmf_ts_inject_fields[] = {
+	{ GMF_TS_INJECT_OFFSET, 14, 0, 0 },
+	{ GMF_TS_INJECT_POS, 2, 14, 0 },
+};
+
+static nthw_fpga_register_init_s gmf_registers[] = {
+	{ GMF_CTRL, 0, 10, NTHW_FPGA_REG_TYPE_WO, 0, 10, gmf_ctrl_fields },
+	{
+		GMF_DEBUG_LANE_MARKER, 7, 16, NTHW_FPGA_REG_TYPE_WO, 16384, 1,
+		gmf_debug_lane_marker_fields
+	},
+	{
+		GMF_IFG_MAX_ADJUST_SLACK, 4, 64, NTHW_FPGA_REG_TYPE_WO, 0, 1,
+		gmf_ifg_max_adjust_slack_fields
+	},
+	{
+		GMF_IFG_SET_CLOCK_DELTA, 2, 64, NTHW_FPGA_REG_TYPE_WO, 0, 1,
+		gmf_ifg_set_clock_delta_fields
+	},
+	{
+		GMF_IFG_SET_CLOCK_DELTA_ADJUST, 3, 64, NTHW_FPGA_REG_TYPE_WO, 0, 1,
+		gmf_ifg_set_clock_delta_adjust_fields
+	},
+	{ GMF_IFG_TX_NOW_ON_TS, 5, 64, NTHW_FPGA_REG_TYPE_WO, 0, 1, gmf_ifg_tx_now_on_ts_fields },
+	{ GMF_SPEED, 1, 64, NTHW_FPGA_REG_TYPE_WO, 0, 1, gmf_speed_fields },
+	{ GMF_STAT_DATA_BUFFER, 9, 15, NTHW_FPGA_REG_TYPE_RO, 0, 1, gmf_stat_data_buffer_fields },
+	{
+		GMF_STAT_MAX_DELAYED_PKT, 11, 64, NTHW_FPGA_REG_TYPE_RC1, 0, 1,
+		gmf_stat_max_delayed_pkt_fields
+	},
+	{ GMF_STAT_NEXT_PKT, 10, 64, NTHW_FPGA_REG_TYPE_RO, 0, 1, gmf_stat_next_pkt_fields },
+	{ GMF_STAT_STICKY, 8, 2, NTHW_FPGA_REG_TYPE_RC1, 0, 2, gmf_stat_sticky_fields },
+	{ GMF_TS_INJECT, 6, 16, NTHW_FPGA_REG_TYPE_WO, 0, 2, gmf_ts_inject_fields },
+};
+
+static nthw_fpga_field_init_s hfu_rcp_ctrl_fields[] = {
+	{ HFU_RCP_CTRL_ADR, 6, 0, 0x0000 },
+	{ HFU_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s hfu_rcp_data_fields[] = {
+	{ HFU_RCP_DATA_LEN_A_ADD_DYN, 5, 15, 0x0000 },
+	{ HFU_RCP_DATA_LEN_A_ADD_OFS, 8, 20, 0x0000 },
+	{ HFU_RCP_DATA_LEN_A_OL4LEN, 1, 1, 0x0000 },
+	{ HFU_RCP_DATA_LEN_A_POS_DYN, 5, 2, 0x0000 },
+	{ HFU_RCP_DATA_LEN_A_POS_OFS, 8, 7, 0x0000 },
+	{ HFU_RCP_DATA_LEN_A_SUB_DYN, 5, 28, 0x0000 },
+	{ HFU_RCP_DATA_LEN_A_WR, 1, 0, 0x0000 },
+	{ HFU_RCP_DATA_LEN_B_ADD_DYN, 5, 47, 0x0000 },
+	{ HFU_RCP_DATA_LEN_B_ADD_OFS, 8, 52, 0x0000 },
+	{ HFU_RCP_DATA_LEN_B_POS_DYN, 5, 34, 0x0000 },
+	{ HFU_RCP_DATA_LEN_B_POS_OFS, 8, 39, 0x0000 },
+	{ HFU_RCP_DATA_LEN_B_SUB_DYN, 5, 60, 0x0000 },
+	{ HFU_RCP_DATA_LEN_B_WR, 1, 33, 0x0000 },
+	{ HFU_RCP_DATA_LEN_C_ADD_DYN, 5, 79, 0x0000 },
+	{ HFU_RCP_DATA_LEN_C_ADD_OFS, 8, 84, 0x0000 },
+	{ HFU_RCP_DATA_LEN_C_POS_DYN, 5, 66, 0x0000 },
+	{ HFU_RCP_DATA_LEN_C_POS_OFS, 8, 71, 0x0000 },
+	{ HFU_RCP_DATA_LEN_C_SUB_DYN, 5, 92, 0x0000 },
+	{ HFU_RCP_DATA_LEN_C_WR, 1, 65, 0x0000 },
+	{ HFU_RCP_DATA_TTL_POS_DYN, 5, 98, 0x0000 },
+	{ HFU_RCP_DATA_TTL_POS_OFS, 8, 103, 0x0000 },
+	{ HFU_RCP_DATA_TTL_WR, 1, 97, 0x0000 },
+};
+
+static nthw_fpga_register_init_s hfu_registers[] = {
+	{ HFU_RCP_CTRL, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, hfu_rcp_ctrl_fields },
+	{ HFU_RCP_DATA, 1, 111, NTHW_FPGA_REG_TYPE_WO, 0, 22, hfu_rcp_data_fields },
+};
+
+static nthw_fpga_field_init_s hif_build_time_fields[] = {
+	{ HIF_BUILD_TIME_TIME, 32, 0, 1726786851 },
+};
+
+static nthw_fpga_field_init_s hif_config_fields[] = {
+	{ HIF_CONFIG_EXT_TAG, 1, 6, 0x0000 },
+	{ HIF_CONFIG_MAX_READ, 3, 3, 0x0000 },
+	{ HIF_CONFIG_MAX_TLP, 3, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s hif_control_fields[] = {
+	{ HIF_CONTROL_BLESSED, 8, 4, 0 },
+	{ HIF_CONTROL_FSR, 1, 12, 1 },
+	{ HIF_CONTROL_WRAW, 4, 0, 1 },
+};
+
+static nthw_fpga_field_init_s hif_prod_id_ex_fields[] = {
+	{ HIF_PROD_ID_EX_LAYOUT, 1, 31, 0 },
+	{ HIF_PROD_ID_EX_LAYOUT_VERSION, 8, 0, 1 },
+	{ HIF_PROD_ID_EX_RESERVED, 23, 8, 0 },
+};
+
+static nthw_fpga_field_init_s hif_prod_id_lsb_fields[] = {
+	{ HIF_PROD_ID_LSB_GROUP_ID, 16, 16, 9574 },
+	{ HIF_PROD_ID_LSB_REV_ID, 8, 0, 49 },
+	{ HIF_PROD_ID_LSB_VER_ID, 8, 8, 55 },
+};
+
+static nthw_fpga_field_init_s hif_prod_id_msb_fields[] = {
+	{ HIF_PROD_ID_MSB_BUILD_NO, 10, 12, 0 },
+	{ HIF_PROD_ID_MSB_TYPE_ID, 12, 0, 200 },
+};
+
+static nthw_fpga_field_init_s hif_sample_time_fields[] = {
+	{ HIF_SAMPLE_TIME_SAMPLE_TIME, 1, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s hif_status_fields[] = {
+	{ HIF_STATUS_RD_ERR, 1, 9, 0 },
+	{ HIF_STATUS_TAGS_IN_USE, 8, 0, 0 },
+	{ HIF_STATUS_WR_ERR, 1, 8, 0 },
+};
+
+static nthw_fpga_field_init_s hif_stat_ctrl_fields[] = {
+	{ HIF_STAT_CTRL_STAT_ENA, 1, 1, 0 },
+	{ HIF_STAT_CTRL_STAT_REQ, 1, 0, 0 },
+};
+
+static nthw_fpga_field_init_s hif_stat_refclk_fields[] = {
+	{ HIF_STAT_REFCLK_REFCLK250, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s hif_stat_rx_fields[] = {
+	{ HIF_STAT_RX_COUNTER, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s hif_stat_tx_fields[] = {
+	{ HIF_STAT_TX_COUNTER, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s hif_test0_fields[] = {
+	{ HIF_TEST0_DATA, 32, 0, 287454020 },
+};
+
+static nthw_fpga_field_init_s hif_test1_fields[] = {
+	{ HIF_TEST1_DATA, 32, 0, 2864434397 },
+};
+
+static nthw_fpga_field_init_s hif_uuid0_fields[] = {
+	{ HIF_UUID0_UUID0, 32, 0, 3012419783 },
+};
+
+static nthw_fpga_field_init_s hif_uuid1_fields[] = {
+	{ HIF_UUID1_UUID1, 32, 0, 2520748366 },
+};
+
+static nthw_fpga_field_init_s hif_uuid2_fields[] = {
+	{ HIF_UUID2_UUID2, 32, 0, 2554609223 },
+};
+
+static nthw_fpga_field_init_s hif_uuid3_fields[] = {
+	{ HIF_UUID3_UUID3, 32, 0, 3614884744 },
+};
+
+static nthw_fpga_register_init_s hif_registers[] = {
+	{ HIF_BUILD_TIME, 16, 32, NTHW_FPGA_REG_TYPE_RO, 1726786851, 1, hif_build_time_fields },
+	{ HIF_CONFIG, 24, 7, NTHW_FPGA_REG_TYPE_RW, 0, 3, hif_config_fields },
+	{ HIF_CONTROL, 40, 13, NTHW_FPGA_REG_TYPE_MIXED, 4097, 3, hif_control_fields },
+	{ HIF_PROD_ID_EX, 112, 32, NTHW_FPGA_REG_TYPE_RO, 1, 3, hif_prod_id_ex_fields },
+	{ HIF_PROD_ID_LSB, 0, 32, NTHW_FPGA_REG_TYPE_RO, 627455793, 3, hif_prod_id_lsb_fields },
+	{ HIF_PROD_ID_MSB, 8, 22, NTHW_FPGA_REG_TYPE_RO, 200, 2, hif_prod_id_msb_fields },
+	{ HIF_SAMPLE_TIME, 96, 1, NTHW_FPGA_REG_TYPE_WO, 0, 1, hif_sample_time_fields },
+	{ HIF_STATUS, 32, 10, NTHW_FPGA_REG_TYPE_MIXED, 0, 3, hif_status_fields },
+	{ HIF_STAT_CTRL, 64, 2, NTHW_FPGA_REG_TYPE_WO, 0, 2, hif_stat_ctrl_fields },
+	{ HIF_STAT_REFCLK, 72, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, hif_stat_refclk_fields },
+	{ HIF_STAT_RX, 88, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, hif_stat_rx_fields },
+	{ HIF_STAT_TX, 80, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, hif_stat_tx_fields },
+	{ HIF_TEST0, 48, 32, NTHW_FPGA_REG_TYPE_RW, 287454020, 1, hif_test0_fields },
+	{ HIF_TEST1, 56, 32, NTHW_FPGA_REG_TYPE_RW, 2864434397, 1, hif_test1_fields },
+	{ HIF_UUID0, 128, 32, NTHW_FPGA_REG_TYPE_RO, 3012419783, 1, hif_uuid0_fields },
+	{ HIF_UUID1, 144, 32, NTHW_FPGA_REG_TYPE_RO, 2520748366, 1, hif_uuid1_fields },
+	{ HIF_UUID2, 160, 32, NTHW_FPGA_REG_TYPE_RO, 2554609223, 1, hif_uuid2_fields },
+	{ HIF_UUID3, 176, 32, NTHW_FPGA_REG_TYPE_RO, 3614884744, 1, hif_uuid3_fields },
+};
+
+static nthw_fpga_field_init_s hsh_rcp_ctrl_fields[] = {
+	{ HSH_RCP_CTRL_ADR, 4, 0, 0x0000 },
+	{ HSH_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s hsh_rcp_data_fields[] = {
+	{ HSH_RCP_DATA_AUTO_IPV4_MASK, 1, 742, 0x0000 },
+	{ HSH_RCP_DATA_HSH_TYPE, 5, 416, 0x0000 },
+	{ HSH_RCP_DATA_HSH_VALID, 1, 415, 0x0000 },
+	{ HSH_RCP_DATA_K, 320, 422, 0x0000 },
+	{ HSH_RCP_DATA_LOAD_DIST_TYPE, 2, 0, 0x0000 },
+	{ HSH_RCP_DATA_MAC_PORT_MASK, 2, 2, 0x0000 },
+	{ HSH_RCP_DATA_P_MASK, 1, 61, 0x0000 },
+	{ HSH_RCP_DATA_QW0_OFS, 8, 11, 0x0000 },
+	{ HSH_RCP_DATA_QW0_PE, 5, 6, 0x0000 },
+	{ HSH_RCP_DATA_QW4_OFS, 8, 24, 0x0000 },
+	{ HSH_RCP_DATA_QW4_PE, 5, 19, 0x0000 },
+	{ HSH_RCP_DATA_SEED, 32, 382, 0x0000 },
+	{ HSH_RCP_DATA_SORT, 2, 4, 0x0000 },
+	{ HSH_RCP_DATA_TNL_P, 1, 414, 0x0000 },
+	{ HSH_RCP_DATA_TOEPLITZ, 1, 421, 0x0000 },
+	{ HSH_RCP_DATA_W8_OFS, 8, 37, 0x0000 },
+	{ HSH_RCP_DATA_W8_PE, 5, 32, 0x0000 },
+	{ HSH_RCP_DATA_W8_SORT, 1, 45, 0x0000 },
+	{ HSH_RCP_DATA_W9_OFS, 8, 51, 0x0000 },
+	{ HSH_RCP_DATA_W9_P, 1, 60, 0x0000 },
+	{ HSH_RCP_DATA_W9_PE, 5, 46, 0x0000 },
+	{ HSH_RCP_DATA_W9_SORT, 1, 59, 0x0000 },
+	{ HSH_RCP_DATA_WORD_MASK, 320, 62, 0x0000 },
+};
+
+static nthw_fpga_register_init_s hsh_registers[] = {
+	{ HSH_RCP_CTRL, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, hsh_rcp_ctrl_fields },
+	{ HSH_RCP_DATA, 1, 743, NTHW_FPGA_REG_TYPE_WO, 0, 23, hsh_rcp_data_fields },
+};
+
+static nthw_fpga_field_init_s i2cm_cmd_status_fields[] = {
+	{ I2CM_CMD_STATUS_CMD_STATUS, 8, 0, 0 },
+};
+
+static nthw_fpga_field_init_s i2cm_ctrl_fields[] = {
+	{ I2CM_CTRL_EN, 1, 7, 0 },
+	{ I2CM_CTRL_IEN, 1, 6, 0 },
+};
+
+static nthw_fpga_field_init_s i2cm_data_fields[] = {
+	{ I2CM_DATA_DATA, 8, 0, 0 },
+};
+
+static nthw_fpga_field_init_s i2cm_io_exp_fields[] = {
+	{ I2CM_IO_EXP_INT_B, 1, 1, 0 },
+	{ I2CM_IO_EXP_RST, 1, 0, 0 },
+};
+
+static nthw_fpga_field_init_s i2cm_prer_high_fields[] = {
+	{ I2CM_PRER_HIGH_PRER_HIGH, 8, 0, 255 },
+};
+
+static nthw_fpga_field_init_s i2cm_prer_low_fields[] = {
+	{ I2CM_PRER_LOW_PRER_LOW, 8, 0, 255 },
+};
+
+static nthw_fpga_field_init_s i2cm_select_fields[] = {
+	{ I2CM_SELECT_SELECT, 2, 0, 0 },
+};
+
+static nthw_fpga_register_init_s i2cm_registers[] = {
+	{ I2CM_CMD_STATUS, 4, 8, NTHW_FPGA_REG_TYPE_RW, 0, 1, i2cm_cmd_status_fields },
+	{ I2CM_CTRL, 2, 8, NTHW_FPGA_REG_TYPE_RW, 0, 2, i2cm_ctrl_fields },
+	{ I2CM_DATA, 3, 8, NTHW_FPGA_REG_TYPE_RW, 0, 1, i2cm_data_fields },
+	{ I2CM_IO_EXP, 6, 2, NTHW_FPGA_REG_TYPE_MIXED, 0, 2, i2cm_io_exp_fields },
+	{ I2CM_PRER_HIGH, 1, 8, NTHW_FPGA_REG_TYPE_RW, 255, 1, i2cm_prer_high_fields },
+	{ I2CM_PRER_LOW, 0, 8, NTHW_FPGA_REG_TYPE_RW, 255, 1, i2cm_prer_low_fields },
+	{ I2CM_SELECT, 5, 2, NTHW_FPGA_REG_TYPE_RW, 0, 1, i2cm_select_fields },
+};
+
+static nthw_fpga_field_init_s ifr_counters_ctrl_fields[] = {
+	{ IFR_COUNTERS_CTRL_ADR, 4, 0, 0x0000 },
+	{ IFR_COUNTERS_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s ifr_counters_data_fields[] = {
+	{ IFR_COUNTERS_DATA_DROP, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s ifr_df_buf_ctrl_fields[] = {
+	{ IFR_DF_BUF_CTRL_AVAILABLE, 11, 0, 0x0000 },
+	{ IFR_DF_BUF_CTRL_MTU_PROFILE, 16, 11, 0x0000 },
+};
+
+static nthw_fpga_field_init_s ifr_df_buf_data_fields[] = {
+	{ IFR_DF_BUF_DATA_FIFO_DAT, 128, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s ifr_rcp_ctrl_fields[] = {
+	{ IFR_RCP_CTRL_ADR, 4, 0, 0x0000 },
+	{ IFR_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s ifr_rcp_data_fields[] = {
+	{ IFR_RCP_DATA_IPV4_DF_DROP, 1, 17, 0x0000 }, { IFR_RCP_DATA_IPV4_EN, 1, 0, 0x0000 },
+	{ IFR_RCP_DATA_IPV6_DROP, 1, 16, 0x0000 }, { IFR_RCP_DATA_IPV6_EN, 1, 1, 0x0000 },
+	{ IFR_RCP_DATA_MTU, 14, 2, 0x0000 },
+};
+
+static nthw_fpga_register_init_s ifr_registers[] = {
+	{ IFR_COUNTERS_CTRL, 4, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, ifr_counters_ctrl_fields },
+	{ IFR_COUNTERS_DATA, 5, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, ifr_counters_data_fields },
+	{ IFR_DF_BUF_CTRL, 2, 27, NTHW_FPGA_REG_TYPE_RO, 0, 2, ifr_df_buf_ctrl_fields },
+	{ IFR_DF_BUF_DATA, 3, 128, NTHW_FPGA_REG_TYPE_RO, 0, 1, ifr_df_buf_data_fields },
+	{ IFR_RCP_CTRL, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, ifr_rcp_ctrl_fields },
+	{ IFR_RCP_DATA, 1, 18, NTHW_FPGA_REG_TYPE_WO, 0, 5, ifr_rcp_data_fields },
+};
+
+static nthw_fpga_field_init_s igam_base_fields[] = {
+	{ IGAM_BASE_BUSY, 1, 30, 0x0000 },
+	{ IGAM_BASE_CMD, 1, 31, 0x0000 },
+	{ IGAM_BASE_PTR, 30, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s igam_ctrl_fields[] = {
+	{ IGAM_CTRL_FORCE_RST, 1, 0, 0 },
+	{ IGAM_CTRL_FORWARD_RST, 1, 1, 1 },
+};
+
+static nthw_fpga_field_init_s igam_data_fields[] = {
+	{ IGAM_DATA_DATA, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_register_init_s igam_registers[] = {
+	{ IGAM_BASE, 0, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3, igam_base_fields },
+	{ IGAM_CTRL, 2, 2, NTHW_FPGA_REG_TYPE_RW, 2, 2, igam_ctrl_fields },
+	{ IGAM_DATA, 1, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1, igam_data_fields },
+};
+
+static nthw_fpga_field_init_s ins_rcp_ctrl_fields[] = {
+	{ INS_RCP_CTRL_ADR, 4, 0, 0x0000 },
+	{ INS_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s ins_rcp_data_fields[] = {
+	{ INS_RCP_DATA_DYN, 5, 0, 0x0000 },
+	{ INS_RCP_DATA_LEN, 8, 15, 0x0000 },
+	{ INS_RCP_DATA_OFS, 10, 5, 0x0000 },
+};
+
+static nthw_fpga_register_init_s ins_registers[] = {
+	{ INS_RCP_CTRL, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, ins_rcp_ctrl_fields },
+	{ INS_RCP_DATA, 1, 23, NTHW_FPGA_REG_TYPE_WO, 0, 3, ins_rcp_data_fields },
+};
+
+static nthw_fpga_field_init_s km_cam_ctrl_fields[] = {
+	{ KM_CAM_CTRL_ADR, 13, 0, 0x0000 },
+	{ KM_CAM_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s km_cam_data_fields[] = {
+	{ KM_CAM_DATA_FT0, 4, 192, 0x0000 }, { KM_CAM_DATA_FT1, 4, 196, 0x0000 },
+	{ KM_CAM_DATA_FT2, 4, 200, 0x0000 }, { KM_CAM_DATA_FT3, 4, 204, 0x0000 },
+	{ KM_CAM_DATA_FT4, 4, 208, 0x0000 }, { KM_CAM_DATA_FT5, 4, 212, 0x0000 },
+	{ KM_CAM_DATA_W0, 32, 0, 0x0000 }, { KM_CAM_DATA_W1, 32, 32, 0x0000 },
+	{ KM_CAM_DATA_W2, 32, 64, 0x0000 }, { KM_CAM_DATA_W3, 32, 96, 0x0000 },
+	{ KM_CAM_DATA_W4, 32, 128, 0x0000 }, { KM_CAM_DATA_W5, 32, 160, 0x0000 },
+};
+
+static nthw_fpga_field_init_s km_rcp_ctrl_fields[] = {
+	{ KM_RCP_CTRL_ADR, 5, 0, 0x0000 },
+	{ KM_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s km_rcp_data_fields[] = {
+	{ KM_RCP_DATA_BANK_A, 12, 694, 0x0000 }, { KM_RCP_DATA_BANK_B, 12, 706, 0x0000 },
+	{ KM_RCP_DATA_DUAL, 1, 651, 0x0000 }, { KM_RCP_DATA_DW0_B_DYN, 5, 729, 0x0000 },
+	{ KM_RCP_DATA_DW0_B_OFS, 8, 734, 0x0000 }, { KM_RCP_DATA_DW10_DYN, 5, 55, 0x0000 },
+	{ KM_RCP_DATA_DW10_OFS, 8, 60, 0x0000 }, { KM_RCP_DATA_DW10_SEL_A, 2, 68, 0x0000 },
+	{ KM_RCP_DATA_DW10_SEL_B, 2, 70, 0x0000 }, { KM_RCP_DATA_DW2_B_DYN, 5, 742, 0x0000 },
+	{ KM_RCP_DATA_DW2_B_OFS, 8, 747, 0x0000 }, { KM_RCP_DATA_DW8_DYN, 5, 36, 0x0000 },
+	{ KM_RCP_DATA_DW8_OFS, 8, 41, 0x0000 }, { KM_RCP_DATA_DW8_SEL_A, 3, 49, 0x0000 },
+	{ KM_RCP_DATA_DW8_SEL_B, 3, 52, 0x0000 }, { KM_RCP_DATA_EL_A, 4, 653, 0x0000 },
+	{ KM_RCP_DATA_EL_B, 3, 657, 0x0000 }, { KM_RCP_DATA_FTM_A, 16, 662, 0x0000 },
+	{ KM_RCP_DATA_FTM_B, 16, 678, 0x0000 }, { KM_RCP_DATA_INFO_A, 1, 660, 0x0000 },
+	{ KM_RCP_DATA_INFO_B, 1, 661, 0x0000 }, { KM_RCP_DATA_KEYWAY_A, 1, 725, 0x0000 },
+	{ KM_RCP_DATA_KEYWAY_B, 1, 726, 0x0000 }, { KM_RCP_DATA_KL_A, 4, 718, 0x0000 },
+	{ KM_RCP_DATA_KL_B, 3, 722, 0x0000 }, { KM_RCP_DATA_MASK_A, 384, 75, 0x0000 },
+	{ KM_RCP_DATA_MASK_B, 192, 459, 0x0000 }, { KM_RCP_DATA_PAIRED, 1, 652, 0x0000 },
+	{ KM_RCP_DATA_QW0_DYN, 5, 0, 0x0000 }, { KM_RCP_DATA_QW0_OFS, 8, 5, 0x0000 },
+	{ KM_RCP_DATA_QW0_SEL_A, 3, 13, 0x0000 }, { KM_RCP_DATA_QW0_SEL_B, 3, 16, 0x0000 },
+	{ KM_RCP_DATA_QW4_DYN, 5, 19, 0x0000 }, { KM_RCP_DATA_QW4_OFS, 8, 24, 0x0000 },
+	{ KM_RCP_DATA_QW4_SEL_A, 2, 32, 0x0000 }, { KM_RCP_DATA_QW4_SEL_B, 2, 34, 0x0000 },
+	{ KM_RCP_DATA_SW4_B_DYN, 5, 755, 0x0000 }, { KM_RCP_DATA_SW4_B_OFS, 8, 760, 0x0000 },
+	{ KM_RCP_DATA_SW5_B_DYN, 5, 768, 0x0000 }, { KM_RCP_DATA_SW5_B_OFS, 8, 773, 0x0000 },
+	{ KM_RCP_DATA_SWX_CCH, 1, 72, 0x0000 }, { KM_RCP_DATA_SWX_SEL_A, 1, 73, 0x0000 },
+	{ KM_RCP_DATA_SWX_SEL_B, 1, 74, 0x0000 }, { KM_RCP_DATA_SYNERGY_MODE, 2, 727, 0x0000 },
+};
+
+static nthw_fpga_field_init_s km_status_fields[] = {
+	{ KM_STATUS_TCQ_RDY, 1, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s km_tcam_ctrl_fields[] = {
+	{ KM_TCAM_CTRL_ADR, 14, 0, 0x0000 },
+	{ KM_TCAM_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s km_tcam_data_fields[] = {
+	{ KM_TCAM_DATA_T, 72, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s km_tci_ctrl_fields[] = {
+	{ KM_TCI_CTRL_ADR, 10, 0, 0x0000 },
+	{ KM_TCI_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s km_tci_data_fields[] = {
+	{ KM_TCI_DATA_COLOR, 32, 0, 0x0000 },
+	{ KM_TCI_DATA_FT, 4, 32, 0x0000 },
+};
+
+static nthw_fpga_field_init_s km_tcq_ctrl_fields[] = {
+	{ KM_TCQ_CTRL_ADR, 7, 0, 0x0000 },
+	{ KM_TCQ_CTRL_CNT, 5, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s km_tcq_data_fields[] = {
+	{ KM_TCQ_DATA_BANK_MASK, 12, 0, 0x0000 },
+	{ KM_TCQ_DATA_QUAL, 3, 12, 0x0000 },
+};
+
+static nthw_fpga_register_init_s km_registers[] = {
+	{ KM_CAM_CTRL, 2, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, km_cam_ctrl_fields },
+	{ KM_CAM_DATA, 3, 216, NTHW_FPGA_REG_TYPE_WO, 0, 12, km_cam_data_fields },
+	{ KM_RCP_CTRL, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, km_rcp_ctrl_fields },
+	{ KM_RCP_DATA, 1, 781, NTHW_FPGA_REG_TYPE_WO, 0, 44, km_rcp_data_fields },
+	{ KM_STATUS, 10, 1, NTHW_FPGA_REG_TYPE_RO, 0, 1, km_status_fields },
+	{ KM_TCAM_CTRL, 4, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, km_tcam_ctrl_fields },
+	{ KM_TCAM_DATA, 5, 72, NTHW_FPGA_REG_TYPE_WO, 0, 1, km_tcam_data_fields },
+	{ KM_TCI_CTRL, 6, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, km_tci_ctrl_fields },
+	{ KM_TCI_DATA, 7, 36, NTHW_FPGA_REG_TYPE_WO, 0, 2, km_tci_data_fields },
+	{ KM_TCQ_CTRL, 8, 21, NTHW_FPGA_REG_TYPE_WO, 0, 2, km_tcq_ctrl_fields },
+	{ KM_TCQ_DATA, 9, 15, NTHW_FPGA_REG_TYPE_WO, 0, 2, km_tcq_data_fields },
+};
+
+static nthw_fpga_field_init_s pci_rd_tg_tg_ctrl_fields[] = {
+	{ PCI_RD_TG_TG_CTRL_TG_RD_RDY, 1, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pci_rd_tg_tg_rdaddr_fields[] = {
+	{ PCI_RD_TG_TG_RDADDR_RAM_ADDR, 9, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pci_rd_tg_tg_rddata0_fields[] = {
+	{ PCI_RD_TG_TG_RDDATA0_PHYS_ADDR_LOW, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pci_rd_tg_tg_rddata1_fields[] = {
+	{ PCI_RD_TG_TG_RDDATA1_PHYS_ADDR_HIGH, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pci_rd_tg_tg_rddata2_fields[] = {
+	{ PCI_RD_TG_TG_RDDATA2_REQ_HID, 6, 22, 0 },
+	{ PCI_RD_TG_TG_RDDATA2_REQ_SIZE, 22, 0, 0 },
+	{ PCI_RD_TG_TG_RDDATA2_WAIT, 1, 30, 0 },
+	{ PCI_RD_TG_TG_RDDATA2_WRAP, 1, 31, 0 },
+};
+
+static nthw_fpga_field_init_s pci_rd_tg_tg_rd_run_fields[] = {
+	{ PCI_RD_TG_TG_RD_RUN_RD_ITERATION, 16, 0, 0 },
+};
+
+static nthw_fpga_register_init_s pci_rd_tg_registers[] = {
+	{ PCI_RD_TG_TG_CTRL, 5, 1, NTHW_FPGA_REG_TYPE_RO, 0, 1, pci_rd_tg_tg_ctrl_fields },
+	{ PCI_RD_TG_TG_RDADDR, 3, 9, NTHW_FPGA_REG_TYPE_WO, 0, 1, pci_rd_tg_tg_rdaddr_fields },
+	{ PCI_RD_TG_TG_RDDATA0, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, pci_rd_tg_tg_rddata0_fields },
+	{ PCI_RD_TG_TG_RDDATA1, 1, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, pci_rd_tg_tg_rddata1_fields },
+	{ PCI_RD_TG_TG_RDDATA2, 2, 32, NTHW_FPGA_REG_TYPE_WO, 0, 4, pci_rd_tg_tg_rddata2_fields },
+	{ PCI_RD_TG_TG_RD_RUN, 4, 16, NTHW_FPGA_REG_TYPE_WO, 0, 1, pci_rd_tg_tg_rd_run_fields },
+};
+
+static nthw_fpga_field_init_s pci_ta_control_fields[] = {
+	{ PCI_TA_CONTROL_ENABLE, 1, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pci_ta_length_error_fields[] = {
+	{ PCI_TA_LENGTH_ERROR_AMOUNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s pci_ta_packet_bad_fields[] = {
+	{ PCI_TA_PACKET_BAD_AMOUNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s pci_ta_packet_good_fields[] = {
+	{ PCI_TA_PACKET_GOOD_AMOUNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s pci_ta_payload_error_fields[] = {
+	{ PCI_TA_PAYLOAD_ERROR_AMOUNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_register_init_s pci_ta_registers[] = {
+	{ PCI_TA_CONTROL, 0, 1, NTHW_FPGA_REG_TYPE_WO, 0, 1, pci_ta_control_fields },
+	{ PCI_TA_LENGTH_ERROR, 3, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, pci_ta_length_error_fields },
+	{ PCI_TA_PACKET_BAD, 2, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, pci_ta_packet_bad_fields },
+	{ PCI_TA_PACKET_GOOD, 1, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, pci_ta_packet_good_fields },
+	{ PCI_TA_PAYLOAD_ERROR, 4, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, pci_ta_payload_error_fields },
+};
+
+static nthw_fpga_field_init_s pci_wr_tg_tg_ctrl_fields[] = {
+	{ PCI_WR_TG_TG_CTRL_TG_WR_RDY, 1, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pci_wr_tg_tg_seq_fields[] = {
+	{ PCI_WR_TG_TG_SEQ_SEQUENCE, 16, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pci_wr_tg_tg_wraddr_fields[] = {
+	{ PCI_WR_TG_TG_WRADDR_RAM_ADDR, 9, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pci_wr_tg_tg_wrdata0_fields[] = {
+	{ PCI_WR_TG_TG_WRDATA0_PHYS_ADDR_LOW, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pci_wr_tg_tg_wrdata1_fields[] = {
+	{ PCI_WR_TG_TG_WRDATA1_PHYS_ADDR_HIGH, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pci_wr_tg_tg_wrdata2_fields[] = {
+	{ PCI_WR_TG_TG_WRDATA2_INC_MODE, 1, 29, 0 }, { PCI_WR_TG_TG_WRDATA2_REQ_HID, 6, 22, 0 },
+	{ PCI_WR_TG_TG_WRDATA2_REQ_SIZE, 22, 0, 0 }, { PCI_WR_TG_TG_WRDATA2_WAIT, 1, 30, 0 },
+	{ PCI_WR_TG_TG_WRDATA2_WRAP, 1, 31, 0 },
+};
+
+static nthw_fpga_field_init_s pci_wr_tg_tg_wr_run_fields[] = {
+	{ PCI_WR_TG_TG_WR_RUN_WR_ITERATION, 16, 0, 0 },
+};
+
+static nthw_fpga_register_init_s pci_wr_tg_registers[] = {
+	{ PCI_WR_TG_TG_CTRL, 5, 1, NTHW_FPGA_REG_TYPE_RO, 0, 1, pci_wr_tg_tg_ctrl_fields },
+	{ PCI_WR_TG_TG_SEQ, 6, 16, NTHW_FPGA_REG_TYPE_RW, 0, 1, pci_wr_tg_tg_seq_fields },
+	{ PCI_WR_TG_TG_WRADDR, 3, 9, NTHW_FPGA_REG_TYPE_WO, 0, 1, pci_wr_tg_tg_wraddr_fields },
+	{ PCI_WR_TG_TG_WRDATA0, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, pci_wr_tg_tg_wrdata0_fields },
+	{ PCI_WR_TG_TG_WRDATA1, 1, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, pci_wr_tg_tg_wrdata1_fields },
+	{ PCI_WR_TG_TG_WRDATA2, 2, 32, NTHW_FPGA_REG_TYPE_WO, 0, 5, pci_wr_tg_tg_wrdata2_fields },
+	{ PCI_WR_TG_TG_WR_RUN, 4, 16, NTHW_FPGA_REG_TYPE_WO, 0, 1, pci_wr_tg_tg_wr_run_fields },
+};
+
+static nthw_fpga_field_init_s pcm_nt400dxx_ctrl_fields[] = {
+	{ PCM_NT400DXX_CTRL_TS_PLL_RECAL, 1, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pcm_nt400dxx_latch_fields[] = {
+	{ PCM_NT400DXX_LATCH_TS_PLL_LOCKED, 1, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s pcm_nt400dxx_stat_fields[] = {
+	{ PCM_NT400DXX_STAT_TS_PLL_LOCKED, 1, 0, 0x0000 },
+};
+
+static nthw_fpga_register_init_s pcm_nt400dxx_registers[] = {
+	{ PCM_NT400DXX_CTRL, 0, 1, NTHW_FPGA_REG_TYPE_RW, 0, 1, pcm_nt400dxx_ctrl_fields },
+	{ PCM_NT400DXX_LATCH, 2, 1, NTHW_FPGA_REG_TYPE_RW, 0, 1, pcm_nt400dxx_latch_fields },
+	{ PCM_NT400DXX_STAT, 1, 1, NTHW_FPGA_REG_TYPE_RO, 0, 1, pcm_nt400dxx_stat_fields },
+};
+
+static nthw_fpga_field_init_s pdb_config_fields[] = {
+	{ PDB_CONFIG_PORT_OFS, 6, 3, 0 },
+	{ PDB_CONFIG_TS_FORMAT, 3, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pdb_rcp_ctrl_fields[] = {
+	{ PDB_RCP_CTRL_ADR, 4, 0, 0x0000 },
+	{ PDB_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s pdb_rcp_data_fields[] = {
+	{ PDB_RCP_DATA_ALIGN, 1, 17, 0x0000 },
+	{ PDB_RCP_DATA_CRC_OVERWRITE, 1, 16, 0x0000 },
+	{ PDB_RCP_DATA_DESCRIPTOR, 4, 0, 0x0000 },
+	{ PDB_RCP_DATA_DESC_LEN, 5, 4, 0 },
+	{ PDB_RCP_DATA_DUPLICATE_BIT, 5, 61, 0x0000 },
+	{ PDB_RCP_DATA_DUPLICATE_EN, 1, 60, 0x0000 },
+	{ PDB_RCP_DATA_IP_PROT_TNL, 1, 57, 0x0000 },
+	{ PDB_RCP_DATA_OFS0_DYN, 5, 18, 0x0000 },
+	{ PDB_RCP_DATA_OFS0_REL, 8, 23, 0x0000 },
+	{ PDB_RCP_DATA_OFS1_DYN, 5, 31, 0x0000 },
+	{ PDB_RCP_DATA_OFS1_REL, 8, 36, 0x0000 },
+	{ PDB_RCP_DATA_OFS2_DYN, 5, 44, 0x0000 },
+	{ PDB_RCP_DATA_OFS2_REL, 8, 49, 0x0000 },
+	{ PDB_RCP_DATA_PCAP_KEEP_FCS, 1, 66, 0x0000 },
+	{ PDB_RCP_DATA_PPC_HSH, 2, 58, 0x0000 },
+	{ PDB_RCP_DATA_TX_IGNORE, 1, 14, 0x0000 },
+	{ PDB_RCP_DATA_TX_NOW, 1, 15, 0x0000 },
+	{ PDB_RCP_DATA_TX_PORT, 5, 9, 0x0000 },
+};
+
+static nthw_fpga_register_init_s pdb_registers[] = {
+	{ PDB_CONFIG, 2, 10, NTHW_FPGA_REG_TYPE_WO, 0, 2, pdb_config_fields },
+	{ PDB_RCP_CTRL, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, pdb_rcp_ctrl_fields },
+	{ PDB_RCP_DATA, 1, 67, NTHW_FPGA_REG_TYPE_WO, 0, 18, pdb_rcp_data_fields },
+};
+
+static nthw_fpga_field_init_s pdi_cr_fields[] = {
+	{ PDI_CR_EN, 1, 0, 0 }, { PDI_CR_PARITY, 1, 4, 0 }, { PDI_CR_RST, 1, 1, 0 },
+	{ PDI_CR_RXRST, 1, 2, 0 }, { PDI_CR_STOP, 1, 5, 0 }, { PDI_CR_TXRST, 1, 3, 0 },
+};
+
+static nthw_fpga_field_init_s pdi_drr_fields[] = {
+	{ PDI_DRR_DRR, 8, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pdi_dtr_fields[] = {
+	{ PDI_DTR_DTR, 8, 0, 0 },
+};
+
+static nthw_fpga_field_init_s pdi_pre_fields[] = {
+	{ PDI_PRE_PRE, 7, 0, 3 },
+};
+
+static nthw_fpga_field_init_s pdi_sr_fields[] = {
+	{ PDI_SR_DISABLE_BUSY, 1, 2, 0 }, { PDI_SR_DONE, 1, 0, 0 },
+	{ PDI_SR_ENABLE_BUSY, 1, 1, 0 }, { PDI_SR_FRAME_ERR, 1, 5, 0 },
+	{ PDI_SR_OVERRUN_ERR, 1, 7, 0 }, { PDI_SR_PARITY_ERR, 1, 6, 0 },
+	{ PDI_SR_RXLVL, 7, 8, 0 }, { PDI_SR_RX_BUSY, 1, 4, 0 },
+	{ PDI_SR_TXLVL, 7, 15, 0 }, { PDI_SR_TX_BUSY, 1, 3, 0 },
+};
+
+static nthw_fpga_field_init_s pdi_srr_fields[] = {
+	{ PDI_SRR_RST, 4, 0, 0 },
+};
+
+static nthw_fpga_register_init_s pdi_registers[] = {
+	{ PDI_CR, 1, 6, NTHW_FPGA_REG_TYPE_WO, 0, 6, pdi_cr_fields },
+	{ PDI_DRR, 4, 8, NTHW_FPGA_REG_TYPE_RO, 0, 1, pdi_drr_fields },
+	{ PDI_DTR, 3, 8, NTHW_FPGA_REG_TYPE_WO, 0, 1, pdi_dtr_fields },
+	{ PDI_PRE, 5, 7, NTHW_FPGA_REG_TYPE_WO, 3, 1, pdi_pre_fields },
+	{ PDI_SR, 2, 22, NTHW_FPGA_REG_TYPE_RO, 0, 10, pdi_sr_fields },
+	{ PDI_SRR, 0, 4, NTHW_FPGA_REG_TYPE_WO, 0, 1, pdi_srr_fields },
+};
+
+static nthw_fpga_field_init_s phy_tile_dr_cfg_fields[] = {
+	{ PHY_TILE_DR_CFG_DYN_RST, 1, 0, 0 },
+	{ PHY_TILE_DR_CFG_FEATURES, 7, 9, 0x0000 },
+	{ PHY_TILE_DR_CFG_SCRATCH, 8, 1, 0x0000 },
+	{ PHY_TILE_DR_CFG_TX_FLUSH_LEVEL, 6, 16, 23 },
+};
+
+static nthw_fpga_field_init_s phy_tile_dr_cfg_status_fields[] = {
+	{ PHY_TILE_DR_CFG_STATUS_CURR_PROFILE_ID, 15, 0, 0x0000 },
+	{ PHY_TILE_DR_CFG_STATUS_ERROR, 1, 16, 0x0000 },
+	{ PHY_TILE_DR_CFG_STATUS_IN_PROGRESS, 1, 15, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_dyn_reconfig_base_fields[] = {
+	{ PHY_TILE_DYN_RECONFIG_BASE_BUSY, 1, 30, 0x0000 },
+	{ PHY_TILE_DYN_RECONFIG_BASE_CMD, 1, 31, 0x0000 },
+	{ PHY_TILE_DYN_RECONFIG_BASE_PTR, 30, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_dyn_reconfig_data_fields[] = {
+	{ PHY_TILE_DYN_RECONFIG_DATA_DATA, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_link_summary_0_fields[] = {
+	{ PHY_TILE_LINK_SUMMARY_0_LH_RECEIVED_LOCAL_FAULT, 1, 14, 0 },
+	{ PHY_TILE_LINK_SUMMARY_0_LH_REMOTE_FAULT, 1, 15, 0 },
+	{ PHY_TILE_LINK_SUMMARY_0_LH_RX_HIGH_BIT_ERROR_RATE, 1, 13, 0 },
+	{ PHY_TILE_LINK_SUMMARY_0_LINK_DOWN_CNT, 8, 2, 0 },
+	{ PHY_TILE_LINK_SUMMARY_0_LL_PHY_LINK_STATE, 1, 1, 1 },
+	{ PHY_TILE_LINK_SUMMARY_0_LL_RX_AM_LOCK, 1, 11, 1 },
+	{ PHY_TILE_LINK_SUMMARY_0_LL_RX_BLOCK_LOCK, 1, 10, 1 },
+	{ PHY_TILE_LINK_SUMMARY_0_NT_PHY_LINK_STATE, 1, 0, 0 },
+};
+
+static nthw_fpga_field_init_s phy_tile_link_summary_1_fields[] = {
+	{ PHY_TILE_LINK_SUMMARY_1_LH_RECEIVED_LOCAL_FAULT, 1, 14, 0 },
+	{ PHY_TILE_LINK_SUMMARY_1_LH_REMOTE_FAULT, 1, 15, 0 },
+	{ PHY_TILE_LINK_SUMMARY_1_LH_RX_HIGH_BIT_ERROR_RATE, 1, 13, 0 },
+	{ PHY_TILE_LINK_SUMMARY_1_LINK_DOWN_CNT, 8, 2, 0 },
+	{ PHY_TILE_LINK_SUMMARY_1_LL_PHY_LINK_STATE, 1, 1, 1 },
+	{ PHY_TILE_LINK_SUMMARY_1_LL_RX_AM_LOCK, 1, 11, 1 },
+	{ PHY_TILE_LINK_SUMMARY_1_LL_RX_BLOCK_LOCK, 1, 10, 1 },
+	{ PHY_TILE_LINK_SUMMARY_1_NT_PHY_LINK_STATE, 1, 0, 0 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_0_eth_0_base_fields[] = {
+	{ PHY_TILE_PORT_0_ETH_0_BASE_BUSY, 1, 30, 0x0000 },
+	{ PHY_TILE_PORT_0_ETH_0_BASE_CMD, 1, 31, 0x0000 },
+	{ PHY_TILE_PORT_0_ETH_0_BASE_PTR, 30, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_0_eth_0_data_fields[] = {
+	{ PHY_TILE_PORT_0_ETH_0_DATA_DATA, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_0_xcvr_0_base_fields[] = {
+	{ PHY_TILE_PORT_0_XCVR_0_BASE_BUSY, 1, 30, 0x0000 },
+	{ PHY_TILE_PORT_0_XCVR_0_BASE_CMD, 1, 31, 0x0000 },
+	{ PHY_TILE_PORT_0_XCVR_0_BASE_PTR, 30, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_0_xcvr_0_data_fields[] = {
+	{ PHY_TILE_PORT_0_XCVR_0_DATA_DATA, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_0_xcvr_1_base_fields[] = {
+	{ PHY_TILE_PORT_0_XCVR_1_BASE_BUSY, 1, 30, 0x0000 },
+	{ PHY_TILE_PORT_0_XCVR_1_BASE_CMD, 1, 31, 0x0000 },
+	{ PHY_TILE_PORT_0_XCVR_1_BASE_PTR, 30, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_0_xcvr_1_data_fields[] = {
+	{ PHY_TILE_PORT_0_XCVR_1_DATA_DATA, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_0_xcvr_2_base_fields[] = {
+	{ PHY_TILE_PORT_0_XCVR_2_BASE_BUSY, 1, 30, 0x0000 },
+	{ PHY_TILE_PORT_0_XCVR_2_BASE_CMD, 1, 31, 0x0000 },
+	{ PHY_TILE_PORT_0_XCVR_2_BASE_PTR, 30, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_0_xcvr_2_data_fields[] = {
+	{ PHY_TILE_PORT_0_XCVR_2_DATA_DATA, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_0_xcvr_3_base_fields[] = {
+	{ PHY_TILE_PORT_0_XCVR_3_BASE_BUSY, 1, 30, 0x0000 },
+	{ PHY_TILE_PORT_0_XCVR_3_BASE_CMD, 1, 31, 0x0000 },
+	{ PHY_TILE_PORT_0_XCVR_3_BASE_PTR, 30, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_0_xcvr_3_data_fields[] = {
+	{ PHY_TILE_PORT_0_XCVR_3_DATA_DATA, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_1_eth_0_base_fields[] = {
+	{ PHY_TILE_PORT_1_ETH_0_BASE_BUSY, 1, 30, 0x0000 },
+	{ PHY_TILE_PORT_1_ETH_0_BASE_CMD, 1, 31, 0x0000 },
+	{ PHY_TILE_PORT_1_ETH_0_BASE_PTR, 30, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_1_eth_0_data_fields[] = {
+	{ PHY_TILE_PORT_1_ETH_0_DATA_DATA, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_1_xcvr_0_base_fields[] = {
+	{ PHY_TILE_PORT_1_XCVR_0_BASE_BUSY, 1, 30, 0x0000 },
+	{ PHY_TILE_PORT_1_XCVR_0_BASE_CMD, 1, 31, 0x0000 },
+	{ PHY_TILE_PORT_1_XCVR_0_BASE_PTR, 30, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_1_xcvr_0_data_fields[] = {
+	{ PHY_TILE_PORT_1_XCVR_0_DATA_DATA, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_1_xcvr_1_base_fields[] = {
+	{ PHY_TILE_PORT_1_XCVR_1_BASE_BUSY, 1, 30, 0x0000 },
+	{ PHY_TILE_PORT_1_XCVR_1_BASE_CMD, 1, 31, 0x0000 },
+	{ PHY_TILE_PORT_1_XCVR_1_BASE_PTR, 30, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_1_xcvr_1_data_fields[] = {
+	{ PHY_TILE_PORT_1_XCVR_1_DATA_DATA, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_1_xcvr_2_base_fields[] = {
+	{ PHY_TILE_PORT_1_XCVR_2_BASE_BUSY, 1, 30, 0x0000 },
+	{ PHY_TILE_PORT_1_XCVR_2_BASE_CMD, 1, 31, 0x0000 },
+	{ PHY_TILE_PORT_1_XCVR_2_BASE_PTR, 30, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_1_xcvr_2_data_fields[] = {
+	{ PHY_TILE_PORT_1_XCVR_2_DATA_DATA, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_1_xcvr_3_base_fields[] = {
+	{ PHY_TILE_PORT_1_XCVR_3_BASE_BUSY, 1, 30, 0x0000 },
+	{ PHY_TILE_PORT_1_XCVR_3_BASE_CMD, 1, 31, 0x0000 },
+	{ PHY_TILE_PORT_1_XCVR_3_BASE_PTR, 30, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_1_xcvr_3_data_fields[] = {
+	{ PHY_TILE_PORT_1_XCVR_3_DATA_DATA, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_comp_0_fields[] = {
+	{ PHY_TILE_PORT_COMP_0_RX_COMPENSATION, 16, 0, 0 },
+	{ PHY_TILE_PORT_COMP_0_TX_COMPENSATION, 16, 16, 0 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_comp_1_fields[] = {
+	{ PHY_TILE_PORT_COMP_1_RX_COMPENSATION, 16, 0, 0 },
+	{ PHY_TILE_PORT_COMP_1_TX_COMPENSATION, 16, 16, 0 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_config_0_fields[] = {
+	{ PHY_TILE_PORT_CONFIG_0_NT_AUTO_FORCE_LINK_DOWN, 1, 12, 0 },
+	{ PHY_TILE_PORT_CONFIG_0_NT_FORCE_LINK_DOWN, 1, 11, 0 },
+	{ PHY_TILE_PORT_CONFIG_0_NT_LINKUP_LATENCY, 8, 3, 10 },
+	{ PHY_TILE_PORT_CONFIG_0_RST, 1, 0, 1 },
+	{ PHY_TILE_PORT_CONFIG_0_RX_RST, 1, 1, 1 },
+	{ PHY_TILE_PORT_CONFIG_0_TX_RST, 1, 2, 1 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_config_1_fields[] = {
+	{ PHY_TILE_PORT_CONFIG_1_NT_AUTO_FORCE_LINK_DOWN, 1, 12, 0 },
+	{ PHY_TILE_PORT_CONFIG_1_NT_FORCE_LINK_DOWN, 1, 11, 0 },
+	{ PHY_TILE_PORT_CONFIG_1_NT_LINKUP_LATENCY, 8, 3, 10 },
+	{ PHY_TILE_PORT_CONFIG_1_RST, 1, 0, 1 },
+	{ PHY_TILE_PORT_CONFIG_1_RX_RST, 1, 1, 1 },
+	{ PHY_TILE_PORT_CONFIG_1_TX_RST, 1, 2, 1 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_status_0_fields[] = {
+	{ PHY_TILE_PORT_STATUS_0_RESET_ACK_N, 1, 0, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_0_RX_AM_LOCK, 1, 10, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_0_RX_HI_BER, 1, 7, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_0_RX_LOCAL_FAULT, 1, 9, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_0_RX_PCS_FULLY_ALIGNED, 1, 6, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_0_RX_REMOTE_FAULT, 1, 8, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_0_RX_RESET_ACK_N, 1, 2, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_0_SYS_PLL_LOCKED, 1, 5, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_0_TX_LANES_STABLE, 1, 3, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_0_TX_PLL_LOCKED, 1, 4, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_0_TX_RESET_ACK_N, 1, 1, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_port_status_1_fields[] = {
+	{ PHY_TILE_PORT_STATUS_1_RESET_ACK_N, 1, 0, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_1_RX_AM_LOCK, 1, 10, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_1_RX_HI_BER, 1, 7, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_1_RX_LOCAL_FAULT, 1, 9, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_1_RX_PCS_FULLY_ALIGNED, 1, 6, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_1_RX_REMOTE_FAULT, 1, 8, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_1_RX_RESET_ACK_N, 1, 2, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_1_SYS_PLL_LOCKED, 1, 5, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_1_TX_LANES_STABLE, 1, 3, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_1_TX_PLL_LOCKED, 1, 4, 0x0000 },
+	{ PHY_TILE_PORT_STATUS_1_TX_RESET_ACK_N, 1, 1, 0x0000 },
+};
+
+static nthw_fpga_field_init_s phy_tile_sys_pll_fields[] = {
+	{ PHY_TILE_SYS_PLL_DISABLE_REFCLK_MONITOR, 8, 13, 0 },
+	{ PHY_TILE_SYS_PLL_EN_REFCLK_FGT, 8, 5, 0 },
+	{ PHY_TILE_SYS_PLL_FORCE_RST, 1, 29, 0 },
+	{ PHY_TILE_SYS_PLL_FORWARD_RST, 1, 30, 1 },
+	{ PHY_TILE_SYS_PLL_GET_RDY, 1, 3, 0x0000 },
+	{ PHY_TILE_SYS_PLL_REFCLK_FGT_ENABLED, 8, 21, 0 },
+	{ PHY_TILE_SYS_PLL_SET_RDY, 3, 0, 0 },
+	{ PHY_TILE_SYS_PLL_SYSTEMPLL_LOCK, 1, 4, 0x0000 },
+};
+
+static nthw_fpga_register_init_s phy_tile_registers[] = {
+	{ PHY_TILE_DR_CFG, 32, 22, NTHW_FPGA_REG_TYPE_MIXED, 1507328, 4, phy_tile_dr_cfg_fields },
+	{
+		PHY_TILE_DR_CFG_STATUS, 31, 19, NTHW_FPGA_REG_TYPE_RO, 0, 3,
+		phy_tile_dr_cfg_status_fields
+	},
+	{
+		PHY_TILE_DYN_RECONFIG_BASE, 20, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3,
+		phy_tile_dyn_reconfig_base_fields
+	},
+	{
+		PHY_TILE_DYN_RECONFIG_DATA, 21, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1,
+		phy_tile_dyn_reconfig_data_fields
+	},
+	{
+		PHY_TILE_LINK_SUMMARY_0, 27, 16, NTHW_FPGA_REG_TYPE_RO, 7170, 8,
+		phy_tile_link_summary_0_fields
+	},
+	{
+		PHY_TILE_LINK_SUMMARY_1, 28, 16, NTHW_FPGA_REG_TYPE_RO, 7170, 8,
+		phy_tile_link_summary_1_fields
+	},
+	{
+		PHY_TILE_PORT_0_ETH_0_BASE, 8, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3,
+		phy_tile_port_0_eth_0_base_fields
+	},
+	{
+		PHY_TILE_PORT_0_ETH_0_DATA, 9, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1,
+		phy_tile_port_0_eth_0_data_fields
+	},
+	{
+		PHY_TILE_PORT_0_XCVR_0_BASE, 0, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3,
+		phy_tile_port_0_xcvr_0_base_fields
+	},
+	{
+		PHY_TILE_PORT_0_XCVR_0_DATA, 1, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1,
+		phy_tile_port_0_xcvr_0_data_fields
+	},
+	{
+		PHY_TILE_PORT_0_XCVR_1_BASE, 2, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3,
+		phy_tile_port_0_xcvr_1_base_fields
+	},
+	{
+		PHY_TILE_PORT_0_XCVR_1_DATA, 3, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1,
+		phy_tile_port_0_xcvr_1_data_fields
+	},
+	{
+		PHY_TILE_PORT_0_XCVR_2_BASE, 4, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3,
+		phy_tile_port_0_xcvr_2_base_fields
+	},
+	{
+		PHY_TILE_PORT_0_XCVR_2_DATA, 5, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1,
+		phy_tile_port_0_xcvr_2_data_fields
+	},
+	{
+		PHY_TILE_PORT_0_XCVR_3_BASE, 6, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3,
+		phy_tile_port_0_xcvr_3_base_fields
+	},
+	{
+		PHY_TILE_PORT_0_XCVR_3_DATA, 7, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1,
+		phy_tile_port_0_xcvr_3_data_fields
+	},
+	{
+		PHY_TILE_PORT_1_ETH_0_BASE, 18, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3,
+		phy_tile_port_1_eth_0_base_fields
+	},
+	{
+		PHY_TILE_PORT_1_ETH_0_DATA, 19, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1,
+		phy_tile_port_1_eth_0_data_fields
+	},
+	{
+		PHY_TILE_PORT_1_XCVR_0_BASE, 10, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3,
+		phy_tile_port_1_xcvr_0_base_fields
+	},
+	{
+		PHY_TILE_PORT_1_XCVR_0_DATA, 11, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1,
+		phy_tile_port_1_xcvr_0_data_fields
+	},
+	{
+		PHY_TILE_PORT_1_XCVR_1_BASE, 12, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3,
+		phy_tile_port_1_xcvr_1_base_fields
+	},
+	{
+		PHY_TILE_PORT_1_XCVR_1_DATA, 13, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1,
+		phy_tile_port_1_xcvr_1_data_fields
+	},
+	{
+		PHY_TILE_PORT_1_XCVR_2_BASE, 14, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3,
+		phy_tile_port_1_xcvr_2_base_fields
+	},
+	{
+		PHY_TILE_PORT_1_XCVR_2_DATA, 15, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1,
+		phy_tile_port_1_xcvr_2_data_fields
+	},
+	{
+		PHY_TILE_PORT_1_XCVR_3_BASE, 16, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3,
+		phy_tile_port_1_xcvr_3_base_fields
+	},
+	{
+		PHY_TILE_PORT_1_XCVR_3_DATA, 17, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1,
+		phy_tile_port_1_xcvr_3_data_fields
+	},
+	{ PHY_TILE_PORT_COMP_0, 35, 32, NTHW_FPGA_REG_TYPE_RW, 0, 2, phy_tile_port_comp_0_fields },
+	{ PHY_TILE_PORT_COMP_1, 36, 32, NTHW_FPGA_REG_TYPE_RW, 0, 2, phy_tile_port_comp_1_fields },
+	{
+		PHY_TILE_PORT_CONFIG_0, 33, 13, NTHW_FPGA_REG_TYPE_RW, 87, 6,
+		phy_tile_port_config_0_fields
+	},
+	{
+		PHY_TILE_PORT_CONFIG_1, 34, 13, NTHW_FPGA_REG_TYPE_RW, 87, 6,
+		phy_tile_port_config_1_fields
+	},
+	{
+		PHY_TILE_PORT_STATUS_0, 29, 16, NTHW_FPGA_REG_TYPE_RO, 0, 11,
+		phy_tile_port_status_0_fields
+	},
+	{
+		PHY_TILE_PORT_STATUS_1, 30, 16, NTHW_FPGA_REG_TYPE_RO, 0, 11,
+		phy_tile_port_status_1_fields
+	},
+	{
+		PHY_TILE_SYS_PLL, 26, 31, NTHW_FPGA_REG_TYPE_MIXED, 1073741824, 8,
+		phy_tile_sys_pll_fields
+	},
+};
+
+static nthw_fpga_field_init_s prm_nt400dxx_rst_fields[] = {
+	{ PRM_NT400DXX_RST_PERIPH, 1, 0, 0 },
+	{ PRM_NT400DXX_RST_PLATFORM, 1, 1, 1 },
+};
+
+static nthw_fpga_register_init_s prm_nt400dxx_registers[] = {
+	{ PRM_NT400DXX_RST, 0, 2, NTHW_FPGA_REG_TYPE_RW, 2, 2, prm_nt400dxx_rst_fields },
+};
+
+static nthw_fpga_field_init_s qsl_qen_ctrl_fields[] = {
+	{ QSL_QEN_CTRL_ADR, 5, 0, 0x0000 },
+	{ QSL_QEN_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s qsl_qen_data_fields[] = {
+	{ QSL_QEN_DATA_EN, 4, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s qsl_qst_ctrl_fields[] = {
+	{ QSL_QST_CTRL_ADR, 12, 0, 0x0000 },
+	{ QSL_QST_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s qsl_qst_data_fields[] = {
+	{ QSL_QST_DATA_LRE, 1, 9, 0x0000 }, { QSL_QST_DATA_QEN, 1, 7, 0x0000 },
+	{ QSL_QST_DATA_QUEUE, 7, 0, 0x0000 }, { QSL_QST_DATA_TCI, 16, 10, 0x0000 },
+	{ QSL_QST_DATA_TX_PORT, 1, 8, 0x0000 }, { QSL_QST_DATA_VEN, 1, 26, 0x0000 },
+};
+
+static nthw_fpga_field_init_s qsl_rcp_ctrl_fields[] = {
+	{ QSL_RCP_CTRL_ADR, 5, 0, 0x0000 },
+	{ QSL_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s qsl_rcp_data_fields[] = {
+	{ QSL_RCP_DATA_DISCARD, 1, 0, 0x0000 }, { QSL_RCP_DATA_DROP, 2, 1, 0x0000 },
+	{ QSL_RCP_DATA_LR, 2, 51, 0x0000 }, { QSL_RCP_DATA_TBL_HI, 12, 15, 0x0000 },
+	{ QSL_RCP_DATA_TBL_IDX, 12, 27, 0x0000 }, { QSL_RCP_DATA_TBL_LO, 12, 3, 0x0000 },
+	{ QSL_RCP_DATA_TBL_MSK, 12, 39, 0x0000 }, { QSL_RCP_DATA_TSA, 1, 53, 0x0000 },
+	{ QSL_RCP_DATA_VLI, 2, 54, 0x0000 },
+};
+
+static nthw_fpga_field_init_s qsl_unmq_ctrl_fields[] = {
+	{ QSL_UNMQ_CTRL_ADR, 1, 0, 0x0000 },
+	{ QSL_UNMQ_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s qsl_unmq_data_fields[] = {
+	{ QSL_UNMQ_DATA_DEST_QUEUE, 7, 0, 0x0000 },
+	{ QSL_UNMQ_DATA_EN, 1, 7, 0x0000 },
+};
+
+static nthw_fpga_register_init_s qsl_registers[] = {
+	{ QSL_QEN_CTRL, 4, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, qsl_qen_ctrl_fields },
+	{ QSL_QEN_DATA, 5, 4, NTHW_FPGA_REG_TYPE_WO, 0, 1, qsl_qen_data_fields },
+	{ QSL_QST_CTRL, 2, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, qsl_qst_ctrl_fields },
+	{ QSL_QST_DATA, 3, 27, NTHW_FPGA_REG_TYPE_WO, 0, 6, qsl_qst_data_fields },
+	{ QSL_RCP_CTRL, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, qsl_rcp_ctrl_fields },
+	{ QSL_RCP_DATA, 1, 56, NTHW_FPGA_REG_TYPE_WO, 0, 9, qsl_rcp_data_fields },
+	{ QSL_UNMQ_CTRL, 6, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, qsl_unmq_ctrl_fields },
+	{ QSL_UNMQ_DATA, 7, 8, NTHW_FPGA_REG_TYPE_WO, 0, 2, qsl_unmq_data_fields },
+};
+
+static nthw_fpga_field_init_s rac_dbg_ctrl_fields[] = {
+	{ RAC_DBG_CTRL_C, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s rac_dbg_data_fields[] = {
+	{ RAC_DBG_DATA_D, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s rac_rab_buf_free_fields[] = {
+	{ RAC_RAB_BUF_FREE_IB_FREE, 9, 0, 511 }, { RAC_RAB_BUF_FREE_IB_OVF, 1, 12, 0 },
+	{ RAC_RAB_BUF_FREE_OB_FREE, 9, 16, 511 }, { RAC_RAB_BUF_FREE_OB_OVF, 1, 28, 0 },
+	{ RAC_RAB_BUF_FREE_TIMEOUT, 1, 31, 0 },
+};
+
+static nthw_fpga_field_init_s rac_rab_buf_used_fields[] = {
+	{ RAC_RAB_BUF_USED_FLUSH, 1, 31, 0 },
+	{ RAC_RAB_BUF_USED_IB_USED, 9, 0, 0 },
+	{ RAC_RAB_BUF_USED_OB_USED, 9, 16, 0 },
+};
+
+static nthw_fpga_field_init_s rac_rab_dma_ib_hi_fields[] = {
+	{ RAC_RAB_DMA_IB_HI_PHYADDR, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s rac_rab_dma_ib_lo_fields[] = {
+	{ RAC_RAB_DMA_IB_LO_PHYADDR, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s rac_rab_dma_ib_rd_fields[] = {
+	{ RAC_RAB_DMA_IB_RD_PTR, 16, 0, 0 },
+};
+
+static nthw_fpga_field_init_s rac_rab_dma_ib_wr_fields[] = {
+	{ RAC_RAB_DMA_IB_WR_PTR, 16, 0, 0 },
+};
+
+static nthw_fpga_field_init_s rac_rab_dma_ob_hi_fields[] = {
+	{ RAC_RAB_DMA_OB_HI_PHYADDR, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s rac_rab_dma_ob_lo_fields[] = {
+	{ RAC_RAB_DMA_OB_LO_PHYADDR, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s rac_rab_dma_ob_wr_fields[] = {
+	{ RAC_RAB_DMA_OB_WR_PTR, 16, 0, 0 },
+};
+
+static nthw_fpga_field_init_s rac_rab_ib_data_fields[] = {
+	{ RAC_RAB_IB_DATA_D, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s rac_rab_init_fields[] = {
+	{ RAC_RAB_INIT_RAB, 3, 0, 7 },
+};
+
+static nthw_fpga_field_init_s rac_rab_ob_data_fields[] = {
+	{ RAC_RAB_OB_DATA_D, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_register_init_s rac_registers[] = {
+	{ RAC_DBG_CTRL, 4200, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1, rac_dbg_ctrl_fields },
+	{ RAC_DBG_DATA, 4208, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1, rac_dbg_data_fields },
+	{
+		RAC_RAB_BUF_FREE, 4176, 32, NTHW_FPGA_REG_TYPE_MIXED, 33489407, 5,
+		rac_rab_buf_free_fields
+	},
+	{ RAC_RAB_BUF_USED, 4184, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3, rac_rab_buf_used_fields },
+	{ RAC_RAB_DMA_IB_HI, 4360, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, rac_rab_dma_ib_hi_fields },
+	{ RAC_RAB_DMA_IB_LO, 4352, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, rac_rab_dma_ib_lo_fields },
+	{ RAC_RAB_DMA_IB_RD, 4424, 16, NTHW_FPGA_REG_TYPE_RO, 0, 1, rac_rab_dma_ib_rd_fields },
+	{ RAC_RAB_DMA_IB_WR, 4416, 16, NTHW_FPGA_REG_TYPE_WO, 0, 1, rac_rab_dma_ib_wr_fields },
+	{ RAC_RAB_DMA_OB_HI, 4376, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, rac_rab_dma_ob_hi_fields },
+	{ RAC_RAB_DMA_OB_LO, 4368, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, rac_rab_dma_ob_lo_fields },
+	{ RAC_RAB_DMA_OB_WR, 4480, 16, NTHW_FPGA_REG_TYPE_RO, 0, 1, rac_rab_dma_ob_wr_fields },
+	{ RAC_RAB_IB_DATA, 4160, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, rac_rab_ib_data_fields },
+	{ RAC_RAB_INIT, 4192, 3, NTHW_FPGA_REG_TYPE_RW, 7, 1, rac_rab_init_fields },
+	{ RAC_RAB_OB_DATA, 4168, 32, NTHW_FPGA_REG_TYPE_RC1, 0, 1, rac_rab_ob_data_fields },
+};
+
+static nthw_fpga_field_init_s rfd_ctrl_fields[] = {
+	{ RFD_CTRL_CFP, 1, 2, 1 },
+	{ RFD_CTRL_ISL, 1, 0, 1 },
+	{ RFD_CTRL_PWMCW, 1, 1, 1 },
+};
+
+static nthw_fpga_field_init_s rfd_max_frame_size_fields[] = {
+	{ RFD_MAX_FRAME_SIZE_MAX, 14, 0, 9018 },
+};
+
+static nthw_fpga_field_init_s rfd_tnl_vlan_fields[] = {
+	{ RFD_TNL_VLAN_TPID0, 16, 0, 33024 },
+	{ RFD_TNL_VLAN_TPID1, 16, 16, 33024 },
+};
+
+static nthw_fpga_field_init_s rfd_vlan_fields[] = {
+	{ RFD_VLAN_TPID0, 16, 0, 33024 },
+	{ RFD_VLAN_TPID1, 16, 16, 33024 },
+};
+
+static nthw_fpga_field_init_s rfd_vxlan_fields[] = {
+	{ RFD_VXLAN_DP0, 16, 0, 4789 },
+	{ RFD_VXLAN_DP1, 16, 16, 4789 },
+};
+
+static nthw_fpga_register_init_s rfd_registers[] = {
+	{ RFD_CTRL, 0, 3, NTHW_FPGA_REG_TYPE_WO, 7, 3, rfd_ctrl_fields },
+	{ RFD_MAX_FRAME_SIZE, 1, 14, NTHW_FPGA_REG_TYPE_WO, 9018, 1, rfd_max_frame_size_fields },
+	{ RFD_TNL_VLAN, 3, 32, NTHW_FPGA_REG_TYPE_WO, 2164293888, 2, rfd_tnl_vlan_fields },
+	{ RFD_VLAN, 2, 32, NTHW_FPGA_REG_TYPE_WO, 2164293888, 2, rfd_vlan_fields },
+	{ RFD_VXLAN, 4, 32, NTHW_FPGA_REG_TYPE_WO, 313856693, 2, rfd_vxlan_fields },
+};
+
+static nthw_fpga_field_init_s rpf_control_fields[] = {
+	{ RPF_CONTROL_KEEP_ALIVE_EN, 1, 7, 0 },
+	{ RPF_CONTROL_PEN, 2, 0, 0 },
+	{ RPF_CONTROL_RPP_EN, 4, 2, 0 },
+	{ RPF_CONTROL_ST_TGL_EN, 1, 6, 0 },
+};
+
+static nthw_fpga_field_init_s rpf_ts_sort_prg_fields[] = {
+	{ RPF_TS_SORT_PRG_MATURING_DELAY, 19, 0, 524163 },
+	{ RPF_TS_SORT_PRG_TS_AT_EOF, 1, 19, 1 },
+};
+
+static nthw_fpga_register_init_s rpf_registers[] = {
+	{ RPF_CONTROL, 0, 8, NTHW_FPGA_REG_TYPE_RW, 0, 4, rpf_control_fields },
+	{ RPF_TS_SORT_PRG, 1, 20, NTHW_FPGA_REG_TYPE_RW, 1048451, 2, rpf_ts_sort_prg_fields },
+};
+
+static nthw_fpga_field_init_s rpl_ext_ctrl_fields[] = {
+	{ RPL_EXT_CTRL_ADR, 10, 0, 0x0000 },
+	{ RPL_EXT_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s rpl_ext_data_fields[] = {
+	{ RPL_EXT_DATA_RPL_PTR, 12, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s rpl_rcp_ctrl_fields[] = {
+	{ RPL_RCP_CTRL_ADR, 4, 0, 0x0000 },
+	{ RPL_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s rpl_rcp_data_fields[] = {
+	{ RPL_RCP_DATA_DYN, 5, 0, 0x0000 }, { RPL_RCP_DATA_ETH_TYPE_WR, 1, 36, 0x0000 },
+	{ RPL_RCP_DATA_EXT_PRIO, 1, 35, 0x0000 }, { RPL_RCP_DATA_LEN, 8, 15, 0x0000 },
+	{ RPL_RCP_DATA_OFS, 10, 5, 0x0000 }, { RPL_RCP_DATA_RPL_PTR, 12, 23, 0x0000 },
+};
+
+static nthw_fpga_field_init_s rpl_rpl_ctrl_fields[] = {
+	{ RPL_RPL_CTRL_ADR, 12, 0, 0x0000 },
+	{ RPL_RPL_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s rpl_rpl_data_fields[] = {
+	{ RPL_RPL_DATA_VALUE, 128, 0, 0x0000 },
+};
+
+static nthw_fpga_register_init_s rpl_registers[] = {
+	{ RPL_EXT_CTRL, 2, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, rpl_ext_ctrl_fields },
+	{ RPL_EXT_DATA, 3, 12, NTHW_FPGA_REG_TYPE_WO, 0, 1, rpl_ext_data_fields },
+	{ RPL_RCP_CTRL, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, rpl_rcp_ctrl_fields },
+	{ RPL_RCP_DATA, 1, 37, NTHW_FPGA_REG_TYPE_WO, 0, 6, rpl_rcp_data_fields },
+	{ RPL_RPL_CTRL, 4, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, rpl_rpl_ctrl_fields },
+	{ RPL_RPL_DATA, 5, 128, NTHW_FPGA_REG_TYPE_WO, 0, 1, rpl_rpl_data_fields },
+};
+
+static nthw_fpga_field_init_s rpp_lr_ifr_rcp_ctrl_fields[] = {
+	{ RPP_LR_IFR_RCP_CTRL_ADR, 4, 0, 0x0000 },
+	{ RPP_LR_IFR_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s rpp_lr_ifr_rcp_data_fields[] = {
+	{ RPP_LR_IFR_RCP_DATA_IPV4_DF_DROP, 1, 17, 0x0000 },
+	{ RPP_LR_IFR_RCP_DATA_IPV4_EN, 1, 0, 0x0000 },
+	{ RPP_LR_IFR_RCP_DATA_IPV6_DROP, 1, 16, 0x0000 },
+	{ RPP_LR_IFR_RCP_DATA_IPV6_EN, 1, 1, 0x0000 },
+	{ RPP_LR_IFR_RCP_DATA_MTU, 14, 2, 0x0000 },
+};
+
+static nthw_fpga_field_init_s rpp_lr_rcp_ctrl_fields[] = {
+	{ RPP_LR_RCP_CTRL_ADR, 4, 0, 0x0000 },
+	{ RPP_LR_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s rpp_lr_rcp_data_fields[] = {
+	{ RPP_LR_RCP_DATA_EXP, 14, 0, 0x0000 },
+};
+
+static nthw_fpga_register_init_s rpp_lr_registers[] = {
+	{ RPP_LR_IFR_RCP_CTRL, 2, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, rpp_lr_ifr_rcp_ctrl_fields },
+	{ RPP_LR_IFR_RCP_DATA, 3, 18, NTHW_FPGA_REG_TYPE_WO, 0, 5, rpp_lr_ifr_rcp_data_fields },
+	{ RPP_LR_RCP_CTRL, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, rpp_lr_rcp_ctrl_fields },
+	{ RPP_LR_RCP_DATA, 1, 14, NTHW_FPGA_REG_TYPE_WO, 0, 1, rpp_lr_rcp_data_fields },
+};
+
+static nthw_fpga_field_init_s rst9574_latch_fields[] = {
+	{ RST9574_LATCH_DDR4_CALIB_COMPLETE, 1, 0, 0x0000 },
+	{ RST9574_LATCH_PHY_FTILE_RDY, 1, 2, 0x0000 },
+	{ RST9574_LATCH_PHY_FTILE_RST_DONE, 1, 1, 0x0000 },
+};
+
+static nthw_fpga_field_init_s rst9574_rst_fields[] = {
+	{ RST9574_RST_DDR4, 1, 1, 1 },
+	{ RST9574_RST_PHY_FTILE, 1, 2, 1 },
+	{ RST9574_RST_SYS, 1, 0, 1 },
+};
+
+static nthw_fpga_field_init_s rst9574_stat_fields[] = {
+	{ RST9574_STAT_DDR4_CALIB_COMPLETE, 1, 0, 0x0000 },
+	{ RST9574_STAT_PHY_FTILE_RDY, 1, 2, 0x0000 },
+	{ RST9574_STAT_PHY_FTILE_RST_DONE, 1, 1, 0x0000 },
+};
+
+static nthw_fpga_register_init_s rst9574_registers[] = {
+	{ RST9574_LATCH, 2, 3, NTHW_FPGA_REG_TYPE_RW, 0, 3, rst9574_latch_fields },
+	{ RST9574_RST, 0, 3, NTHW_FPGA_REG_TYPE_RW, 7, 3, rst9574_rst_fields },
+	{ RST9574_STAT, 1, 3, NTHW_FPGA_REG_TYPE_RO, 0, 3, rst9574_stat_fields },
+};
+
+static nthw_fpga_field_init_s slc_rcp_ctrl_fields[] = {
+	{ SLC_RCP_CTRL_ADR, 6, 0, 0x0000 },
+	{ SLC_RCP_CTRL_CNT, 16, 16, 0x0000 },
+};
+
+static nthw_fpga_field_init_s slc_rcp_data_fields[] = {
+	{ SLC_RCP_DATA_HEAD_DYN, 5, 1, 0x0000 }, { SLC_RCP_DATA_HEAD_OFS, 8, 6, 0x0000 },
+	{ SLC_RCP_DATA_HEAD_SLC_EN, 1, 0, 0x0000 }, { SLC_RCP_DATA_PCAP, 1, 35, 0x0000 },
+	{ SLC_RCP_DATA_TAIL_DYN, 5, 15, 0x0000 }, { SLC_RCP_DATA_TAIL_OFS, 15, 20, 0x0000 },
+	{ SLC_RCP_DATA_TAIL_SLC_EN, 1, 14, 0x0000 },
+};
+
+static nthw_fpga_register_init_s slc_registers[] = {
+	{ SLC_RCP_CTRL, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, slc_rcp_ctrl_fields },
+	{ SLC_RCP_DATA, 1, 36, NTHW_FPGA_REG_TYPE_WO, 0, 7, slc_rcp_data_fields },
+};
+
+static nthw_fpga_field_init_s spim_cfg_fields[] = {
+	{ SPIM_CFG_PRE, 3, 0, 5 },
+};
+
+static nthw_fpga_field_init_s spim_cfg_clk_fields[] = {
+	{ SPIM_CFG_CLK_MODE, 2, 0, 0 },
+};
+
+static nthw_fpga_field_init_s spim_cr_fields[] = {
+	{ SPIM_CR_EN, 1, 1, 0 },
+	{ SPIM_CR_LOOP, 1, 0, 0 },
+	{ SPIM_CR_RXRST, 1, 3, 0 },
+	{ SPIM_CR_TXRST, 1, 2, 0 },
+};
+
+static nthw_fpga_field_init_s spim_drr_fields[] = {
+	{ SPIM_DRR_DRR, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s spim_dtr_fields[] = {
+	{ SPIM_DTR_DTR, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s spim_sr_fields[] = {
+	{ SPIM_SR_DONE, 1, 0, 0 }, { SPIM_SR_RXEMPTY, 1, 2, 1 }, { SPIM_SR_RXFULL, 1, 4, 0 },
+	{ SPIM_SR_RXLVL, 8, 16, 0 }, { SPIM_SR_TXEMPTY, 1, 1, 1 }, { SPIM_SR_TXFULL, 1, 3, 0 },
+	{ SPIM_SR_TXLVL, 8, 8, 0 },
+};
+
+static nthw_fpga_field_init_s spim_srr_fields[] = {
+	{ SPIM_SRR_RST, 4, 0, 0 },
+};
+
+static nthw_fpga_register_init_s spim_registers[] = {
+	{ SPIM_CFG, 5, 3, NTHW_FPGA_REG_TYPE_WO, 5, 1, spim_cfg_fields },
+	{ SPIM_CFG_CLK, 6, 2, NTHW_FPGA_REG_TYPE_WO, 0, 1, spim_cfg_clk_fields },
+	{ SPIM_CR, 1, 4, NTHW_FPGA_REG_TYPE_WO, 0, 4, spim_cr_fields },
+	{ SPIM_DRR, 4, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, spim_drr_fields },
+	{ SPIM_DTR, 3, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, spim_dtr_fields },
+	{ SPIM_SR, 2, 24, NTHW_FPGA_REG_TYPE_MIXED, 6, 7, spim_sr_fields },
+	{ SPIM_SRR, 0, 4, NTHW_FPGA_REG_TYPE_WO, 0, 1, spim_srr_fields },
+};
+
+static nthw_fpga_field_init_s spis_cr_fields[] = {
+	{ SPIS_CR_DEBUG, 1, 4, 0 }, { SPIS_CR_EN, 1, 1, 0 }, { SPIS_CR_LOOP, 1, 0, 0 },
+	{ SPIS_CR_RXRST, 1, 3, 0 }, { SPIS_CR_TXRST, 1, 2, 0 },
+};
+
+static nthw_fpga_field_init_s spis_drr_fields[] = {
+	{ SPIS_DRR_DRR, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s spis_dtr_fields[] = {
+	{ SPIS_DTR_DTR, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s spis_ram_ctrl_fields[] = {
+	{ SPIS_RAM_CTRL_ADR, 6, 0, 0 },
+	{ SPIS_RAM_CTRL_CNT, 6, 6, 0 },
+};
+
+static nthw_fpga_field_init_s spis_ram_data_fields[] = {
+	{ SPIS_RAM_DATA_DATA, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s spis_sr_fields[] = {
+	{ SPIS_SR_DONE, 1, 0, 0 }, { SPIS_SR_FRAME_ERR, 1, 24, 0 },
+	{ SPIS_SR_READ_ERR, 1, 25, 0 }, { SPIS_SR_RXEMPTY, 1, 2, 1 },
+	{ SPIS_SR_RXFULL, 1, 4, 0 }, { SPIS_SR_RXLVL, 8, 16, 0 },
+	{ SPIS_SR_TXEMPTY, 1, 1, 1 }, { SPIS_SR_TXFULL, 1, 3, 0 },
+	{ SPIS_SR_TXLVL, 8, 8, 0 }, { SPIS_SR_WRITE_ERR, 1, 26, 0 },
+};
+
+static nthw_fpga_field_init_s spis_srr_fields[] = {
+	{ SPIS_SRR_RST, 4, 0, 0 },
+};
+
+static nthw_fpga_register_init_s spis_registers[] = {
+	{ SPIS_CR, 1, 5, NTHW_FPGA_REG_TYPE_WO, 0, 5, spis_cr_fields },
+	{ SPIS_DRR, 4, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, spis_drr_fields },
+	{ SPIS_DTR, 3, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, spis_dtr_fields },
+	{ SPIS_RAM_CTRL, 5, 12, NTHW_FPGA_REG_TYPE_RW, 0, 2, spis_ram_ctrl_fields },
+	{ SPIS_RAM_DATA, 6, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1, spis_ram_data_fields },
+	{ SPIS_SR, 2, 27, NTHW_FPGA_REG_TYPE_RO, 6, 10, spis_sr_fields },
+	{ SPIS_SRR, 0, 4, NTHW_FPGA_REG_TYPE_WO, 0, 1, spis_srr_fields },
+};
+
+static nthw_fpga_field_init_s sta_byte_fields[] = {
+	{ STA_BYTE_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s sta_cfg_fields[] = {
+	{ STA_CFG_CNT_CLEAR, 1, 1, 0 },
+	{ STA_CFG_DMA_ENA, 1, 0, 0 },
+};
+
+static nthw_fpga_field_init_s sta_cv_err_fields[] = {
+	{ STA_CV_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s sta_fcs_err_fields[] = {
+	{ STA_FCS_ERR_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s sta_host_adr_lsb_fields[] = {
+	{ STA_HOST_ADR_LSB_LSB, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s sta_host_adr_msb_fields[] = {
+	{ STA_HOST_ADR_MSB_MSB, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s sta_load_bin_fields[] = {
+	{ STA_LOAD_BIN_BIN, 32, 0, 8388607 },
+};
+
+static nthw_fpga_field_init_s sta_load_bps_rx_0_fields[] = {
+	{ STA_LOAD_BPS_RX_0_BPS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s sta_load_bps_rx_1_fields[] = {
+	{ STA_LOAD_BPS_RX_1_BPS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s sta_load_bps_tx_0_fields[] = {
+	{ STA_LOAD_BPS_TX_0_BPS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s sta_load_bps_tx_1_fields[] = {
+	{ STA_LOAD_BPS_TX_1_BPS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s sta_load_pps_rx_0_fields[] = {
+	{ STA_LOAD_PPS_RX_0_PPS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s sta_load_pps_rx_1_fields[] = {
+	{ STA_LOAD_PPS_RX_1_PPS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s sta_load_pps_tx_0_fields[] = {
+	{ STA_LOAD_PPS_TX_0_PPS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s sta_load_pps_tx_1_fields[] = {
+	{ STA_LOAD_PPS_TX_1_PPS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s sta_pckt_fields[] = {
+	{ STA_PCKT_CNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s sta_status_fields[] = {
+	{ STA_STATUS_STAT_TOGGLE_MISSED, 1, 0, 0x0000 },
+};
+
+static nthw_fpga_register_init_s sta_registers[] = {
+	{ STA_BYTE, 4, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, sta_byte_fields },
+	{ STA_CFG, 0, 2, NTHW_FPGA_REG_TYPE_RW, 0, 2, sta_cfg_fields },
+	{ STA_CV_ERR, 5, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, sta_cv_err_fields },
+	{ STA_FCS_ERR, 6, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, sta_fcs_err_fields },
+	{ STA_HOST_ADR_LSB, 1, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, sta_host_adr_lsb_fields },
+	{ STA_HOST_ADR_MSB, 2, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, sta_host_adr_msb_fields },
+	{ STA_LOAD_BIN, 8, 32, NTHW_FPGA_REG_TYPE_WO, 8388607, 1, sta_load_bin_fields },
+	{ STA_LOAD_BPS_RX_0, 11, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, sta_load_bps_rx_0_fields },
+	{ STA_LOAD_BPS_RX_1, 13, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, sta_load_bps_rx_1_fields },
+	{ STA_LOAD_BPS_TX_0, 15, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, sta_load_bps_tx_0_fields },
+	{ STA_LOAD_BPS_TX_1, 17, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, sta_load_bps_tx_1_fields },
+	{ STA_LOAD_PPS_RX_0, 10, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, sta_load_pps_rx_0_fields },
+	{ STA_LOAD_PPS_RX_1, 12, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, sta_load_pps_rx_1_fields },
+	{ STA_LOAD_PPS_TX_0, 14, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, sta_load_pps_tx_0_fields },
+	{ STA_LOAD_PPS_TX_1, 16, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, sta_load_pps_tx_1_fields },
+	{ STA_PCKT, 3, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, sta_pckt_fields },
+	{ STA_STATUS, 7, 1, NTHW_FPGA_REG_TYPE_RC1, 0, 1, sta_status_fields },
+};
+
+static nthw_fpga_field_init_s tint_ctrl_fields[] = {
+	{ TINT_CTRL_INTERVAL, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tint_status_fields[] = {
+	{ TINT_STATUS_DELAYED, 8, 8, 0 },
+	{ TINT_STATUS_SKIPPED, 8, 0, 0 },
+};
+
+static nthw_fpga_register_init_s tint_registers[] = {
+	{ TINT_CTRL, 0, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, tint_ctrl_fields },
+	{ TINT_STATUS, 1, 16, NTHW_FPGA_REG_TYPE_RC1, 0, 2, tint_status_fields },
+};
+
+static nthw_fpga_field_init_s tsm_con0_config_fields[] = {
+	{ TSM_CON0_CONFIG_BLIND, 5, 8, 9 }, { TSM_CON0_CONFIG_DC_SRC, 3, 5, 0 },
+	{ TSM_CON0_CONFIG_PORT, 3, 0, 0 }, { TSM_CON0_CONFIG_PPSIN_2_5V, 1, 13, 0 },
+	{ TSM_CON0_CONFIG_SAMPLE_EDGE, 2, 3, 2 },
+};
+
+static nthw_fpga_field_init_s tsm_con0_interface_fields[] = {
+	{ TSM_CON0_INTERFACE_EX_TERM, 2, 0, 3 }, { TSM_CON0_INTERFACE_IN_REF_PWM, 8, 12, 128 },
+	{ TSM_CON0_INTERFACE_PWM_ENA, 1, 2, 0 }, { TSM_CON0_INTERFACE_RESERVED, 1, 3, 0 },
+	{ TSM_CON0_INTERFACE_VTERM_PWM, 8, 4, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_con0_sample_hi_fields[] = {
+	{ TSM_CON0_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con0_sample_lo_fields[] = {
+	{ TSM_CON0_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con1_config_fields[] = {
+	{ TSM_CON1_CONFIG_BLIND, 5, 8, 9 }, { TSM_CON1_CONFIG_DC_SRC, 3, 5, 0 },
+	{ TSM_CON1_CONFIG_PORT, 3, 0, 0 }, { TSM_CON1_CONFIG_PPSIN_2_5V, 1, 13, 0 },
+	{ TSM_CON1_CONFIG_SAMPLE_EDGE, 2, 3, 2 },
+};
+
+static nthw_fpga_field_init_s tsm_con1_sample_hi_fields[] = {
+	{ TSM_CON1_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con1_sample_lo_fields[] = {
+	{ TSM_CON1_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con2_config_fields[] = {
+	{ TSM_CON2_CONFIG_BLIND, 5, 8, 9 }, { TSM_CON2_CONFIG_DC_SRC, 3, 5, 0 },
+	{ TSM_CON2_CONFIG_PORT, 3, 0, 0 }, { TSM_CON2_CONFIG_PPSIN_2_5V, 1, 13, 0 },
+	{ TSM_CON2_CONFIG_SAMPLE_EDGE, 2, 3, 2 },
+};
+
+static nthw_fpga_field_init_s tsm_con2_sample_hi_fields[] = {
+	{ TSM_CON2_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con2_sample_lo_fields[] = {
+	{ TSM_CON2_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con3_config_fields[] = {
+	{ TSM_CON3_CONFIG_BLIND, 5, 5, 26 },
+	{ TSM_CON3_CONFIG_PORT, 3, 0, 1 },
+	{ TSM_CON3_CONFIG_SAMPLE_EDGE, 2, 3, 1 },
+};
+
+static nthw_fpga_field_init_s tsm_con3_sample_hi_fields[] = {
+	{ TSM_CON3_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con3_sample_lo_fields[] = {
+	{ TSM_CON3_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con4_config_fields[] = {
+	{ TSM_CON4_CONFIG_BLIND, 5, 5, 26 },
+	{ TSM_CON4_CONFIG_PORT, 3, 0, 1 },
+	{ TSM_CON4_CONFIG_SAMPLE_EDGE, 2, 3, 1 },
+};
+
+static nthw_fpga_field_init_s tsm_con4_sample_hi_fields[] = {
+	{ TSM_CON4_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con4_sample_lo_fields[] = {
+	{ TSM_CON4_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con5_config_fields[] = {
+	{ TSM_CON5_CONFIG_BLIND, 5, 5, 26 },
+	{ TSM_CON5_CONFIG_PORT, 3, 0, 1 },
+	{ TSM_CON5_CONFIG_SAMPLE_EDGE, 2, 3, 1 },
+};
+
+static nthw_fpga_field_init_s tsm_con5_sample_hi_fields[] = {
+	{ TSM_CON5_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con5_sample_lo_fields[] = {
+	{ TSM_CON5_SAMPLE_LO_TIME, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con6_config_fields[] = {
+	{ TSM_CON6_CONFIG_BLIND, 5, 5, 26 },
+	{ TSM_CON6_CONFIG_PORT, 3, 0, 1 },
+	{ TSM_CON6_CONFIG_SAMPLE_EDGE, 2, 3, 1 },
+};
+
+static nthw_fpga_field_init_s tsm_con6_sample_hi_fields[] = {
+	{ TSM_CON6_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con6_sample_lo_fields[] = {
+	{ TSM_CON6_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con7_host_sample_hi_fields[] = {
+	{ TSM_CON7_HOST_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_con7_host_sample_lo_fields[] = {
+	{ TSM_CON7_HOST_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_config_fields[] = {
+	{ TSM_CONFIG_NTTS_SRC, 2, 5, 0 }, { TSM_CONFIG_NTTS_SYNC, 1, 4, 0 },
+	{ TSM_CONFIG_TIMESET_EDGE, 2, 8, 1 }, { TSM_CONFIG_TIMESET_SRC, 3, 10, 0 },
+	{ TSM_CONFIG_TIMESET_UP, 1, 7, 0 }, { TSM_CONFIG_TS_FORMAT, 4, 0, 1 },
+};
+
+static nthw_fpga_field_init_s tsm_int_config_fields[] = {
+	{ TSM_INT_CONFIG_AUTO_DISABLE, 1, 0, 0 },
+	{ TSM_INT_CONFIG_MASK, 19, 1, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_int_stat_fields[] = {
+	{ TSM_INT_STAT_CAUSE, 19, 1, 0 },
+	{ TSM_INT_STAT_ENABLE, 1, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_led_fields[] = {
+	{ TSM_LED_LED0_BG_COLOR, 2, 3, 0 }, { TSM_LED_LED0_COLOR, 2, 1, 0 },
+	{ TSM_LED_LED0_MODE, 1, 0, 0 }, { TSM_LED_LED0_SRC, 4, 5, 0 },
+	{ TSM_LED_LED1_BG_COLOR, 2, 12, 0 }, { TSM_LED_LED1_COLOR, 2, 10, 0 },
+	{ TSM_LED_LED1_MODE, 1, 9, 0 }, { TSM_LED_LED1_SRC, 4, 14, 1 },
+	{ TSM_LED_LED2_BG_COLOR, 2, 21, 0 }, { TSM_LED_LED2_COLOR, 2, 19, 0 },
+	{ TSM_LED_LED2_MODE, 1, 18, 0 }, { TSM_LED_LED2_SRC, 4, 23, 2 },
+};
+
+static nthw_fpga_field_init_s tsm_ntts_config_fields[] = {
+	{ TSM_NTTS_CONFIG_AUTO_HARDSET, 1, 5, 1 },
+	{ TSM_NTTS_CONFIG_EXT_CLK_ADJ, 1, 6, 0 },
+	{ TSM_NTTS_CONFIG_HIGH_SAMPLE, 1, 4, 0 },
+	{ TSM_NTTS_CONFIG_TS_SRC_FORMAT, 4, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_ntts_ext_stat_fields[] = {
+	{ TSM_NTTS_EXT_STAT_MASTER_ID, 8, 16, 0x0000 },
+	{ TSM_NTTS_EXT_STAT_MASTER_REV, 8, 24, 0x0000 },
+	{ TSM_NTTS_EXT_STAT_MASTER_STAT, 16, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_ntts_limit_hi_fields[] = {
+	{ TSM_NTTS_LIMIT_HI_SEC, 16, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_ntts_limit_lo_fields[] = {
+	{ TSM_NTTS_LIMIT_LO_NS, 32, 0, 100000 },
+};
+
+static nthw_fpga_field_init_s tsm_ntts_offset_fields[] = {
+	{ TSM_NTTS_OFFSET_NS, 30, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_ntts_sample_hi_fields[] = {
+	{ TSM_NTTS_SAMPLE_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_ntts_sample_lo_fields[] = {
+	{ TSM_NTTS_SAMPLE_LO_NS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_ntts_stat_fields[] = {
+	{ TSM_NTTS_STAT_NTTS_VALID, 1, 0, 0 },
+	{ TSM_NTTS_STAT_SIGNAL_LOST, 8, 1, 0 },
+	{ TSM_NTTS_STAT_SYNC_LOST, 8, 9, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_ntts_ts_t0_hi_fields[] = {
+	{ TSM_NTTS_TS_T0_HI_TIME, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_ntts_ts_t0_lo_fields[] = {
+	{ TSM_NTTS_TS_T0_LO_TIME, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_ntts_ts_t0_offset_fields[] = {
+	{ TSM_NTTS_TS_T0_OFFSET_COUNT, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_pb_ctrl_fields[] = {
+	{ TSM_PB_CTRL_INSTMEM_WR, 1, 1, 0 },
+	{ TSM_PB_CTRL_RST, 1, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_pb_instmem_fields[] = {
+	{ TSM_PB_INSTMEM_MEM_ADDR, 14, 0, 0 },
+	{ TSM_PB_INSTMEM_MEM_DATA, 18, 14, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_pi_ctrl_i_fields[] = {
+	{ TSM_PI_CTRL_I_VAL, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_pi_ctrl_ki_fields[] = {
+	{ TSM_PI_CTRL_KI_GAIN, 24, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_pi_ctrl_kp_fields[] = {
+	{ TSM_PI_CTRL_KP_GAIN, 24, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_pi_ctrl_shl_fields[] = {
+	{ TSM_PI_CTRL_SHL_VAL, 4, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_stat_fields[] = {
+	{ TSM_STAT_HARD_SYNC, 8, 8, 0 }, { TSM_STAT_LINK_CON0, 1, 0, 0 },
+	{ TSM_STAT_LINK_CON1, 1, 1, 0 }, { TSM_STAT_LINK_CON2, 1, 2, 0 },
+	{ TSM_STAT_LINK_CON3, 1, 3, 0 }, { TSM_STAT_LINK_CON4, 1, 4, 0 },
+	{ TSM_STAT_LINK_CON5, 1, 5, 0 }, { TSM_STAT_NTTS_INSYNC, 1, 6, 0 },
+	{ TSM_STAT_PTP_MI_PRESENT, 1, 7, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_timer_ctrl_fields[] = {
+	{ TSM_TIMER_CTRL_TIMER_EN_T0, 1, 0, 0 },
+	{ TSM_TIMER_CTRL_TIMER_EN_T1, 1, 1, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_timer_t0_fields[] = {
+	{ TSM_TIMER_T0_MAX_COUNT, 30, 0, 50000 },
+};
+
+static nthw_fpga_field_init_s tsm_timer_t1_fields[] = {
+	{ TSM_TIMER_T1_MAX_COUNT, 30, 0, 50000 },
+};
+
+static nthw_fpga_field_init_s tsm_time_hardset_hi_fields[] = {
+	{ TSM_TIME_HARDSET_HI_TIME, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_time_hardset_lo_fields[] = {
+	{ TSM_TIME_HARDSET_LO_TIME, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_time_hi_fields[] = {
+	{ TSM_TIME_HI_SEC, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_time_lo_fields[] = {
+	{ TSM_TIME_LO_NS, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_time_rate_adj_fields[] = {
+	{ TSM_TIME_RATE_ADJ_FRACTION, 29, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_ts_hi_fields[] = {
+	{ TSM_TS_HI_TIME, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_ts_lo_fields[] = {
+	{ TSM_TS_LO_TIME, 32, 0, 0x0000 },
+};
+
+static nthw_fpga_field_init_s tsm_ts_offset_fields[] = {
+	{ TSM_TS_OFFSET_NS, 30, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_ts_stat_fields[] = {
+	{ TSM_TS_STAT_OVERRUN, 1, 16, 0 },
+	{ TSM_TS_STAT_SAMPLES, 16, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_ts_stat_hi_offset_fields[] = {
+	{ TSM_TS_STAT_HI_OFFSET_NS, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_ts_stat_lo_offset_fields[] = {
+	{ TSM_TS_STAT_LO_OFFSET_NS, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_ts_stat_tar_hi_fields[] = {
+	{ TSM_TS_STAT_TAR_HI_SEC, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_ts_stat_tar_lo_fields[] = {
+	{ TSM_TS_STAT_TAR_LO_NS, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_ts_stat_x_fields[] = {
+	{ TSM_TS_STAT_X_NS, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_ts_stat_x2_hi_fields[] = {
+	{ TSM_TS_STAT_X2_HI_NS, 16, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_ts_stat_x2_lo_fields[] = {
+	{ TSM_TS_STAT_X2_LO_NS, 32, 0, 0 },
+};
+
+static nthw_fpga_field_init_s tsm_utc_offset_fields[] = {
+	{ TSM_UTC_OFFSET_SEC, 8, 0, 0 },
+};
+
+static nthw_fpga_register_init_s tsm_registers[] = {
+	{ TSM_CON0_CONFIG, 24, 14, NTHW_FPGA_REG_TYPE_RW, 2320, 5, tsm_con0_config_fields },
+	{
+		TSM_CON0_INTERFACE, 25, 20, NTHW_FPGA_REG_TYPE_RW, 524291, 5,
+		tsm_con0_interface_fields
+	},
+	{ TSM_CON0_SAMPLE_HI, 27, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con0_sample_hi_fields },
+	{ TSM_CON0_SAMPLE_LO, 26, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con0_sample_lo_fields },
+	{ TSM_CON1_CONFIG, 28, 14, NTHW_FPGA_REG_TYPE_RW, 2320, 5, tsm_con1_config_fields },
+	{ TSM_CON1_SAMPLE_HI, 30, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con1_sample_hi_fields },
+	{ TSM_CON1_SAMPLE_LO, 29, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con1_sample_lo_fields },
+	{ TSM_CON2_CONFIG, 31, 14, NTHW_FPGA_REG_TYPE_RW, 2320, 5, tsm_con2_config_fields },
+	{ TSM_CON2_SAMPLE_HI, 33, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con2_sample_hi_fields },
+	{ TSM_CON2_SAMPLE_LO, 32, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con2_sample_lo_fields },
+	{ TSM_CON3_CONFIG, 34, 10, NTHW_FPGA_REG_TYPE_RW, 841, 3, tsm_con3_config_fields },
+	{ TSM_CON3_SAMPLE_HI, 36, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con3_sample_hi_fields },
+	{ TSM_CON3_SAMPLE_LO, 35, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con3_sample_lo_fields },
+	{ TSM_CON4_CONFIG, 37, 10, NTHW_FPGA_REG_TYPE_RW, 841, 3, tsm_con4_config_fields },
+	{ TSM_CON4_SAMPLE_HI, 39, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con4_sample_hi_fields },
+	{ TSM_CON4_SAMPLE_LO, 38, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con4_sample_lo_fields },
+	{ TSM_CON5_CONFIG, 40, 10, NTHW_FPGA_REG_TYPE_RW, 841, 3, tsm_con5_config_fields },
+	{ TSM_CON5_SAMPLE_HI, 42, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con5_sample_hi_fields },
+	{ TSM_CON5_SAMPLE_LO, 41, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con5_sample_lo_fields },
+	{ TSM_CON6_CONFIG, 43, 10, NTHW_FPGA_REG_TYPE_RW, 841, 3, tsm_con6_config_fields },
+	{ TSM_CON6_SAMPLE_HI, 45, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con6_sample_hi_fields },
+	{ TSM_CON6_SAMPLE_LO, 44, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_con6_sample_lo_fields },
+	{
+		TSM_CON7_HOST_SAMPLE_HI, 47, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1,
+		tsm_con7_host_sample_hi_fields
+	},
+	{
+		TSM_CON7_HOST_SAMPLE_LO, 46, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1,
+		tsm_con7_host_sample_lo_fields
+	},
+	{ TSM_CONFIG, 0, 13, NTHW_FPGA_REG_TYPE_RW, 257, 6, tsm_config_fields },
+	{ TSM_INT_CONFIG, 2, 20, NTHW_FPGA_REG_TYPE_RW, 0, 2, tsm_int_config_fields },
+	{ TSM_INT_STAT, 3, 20, NTHW_FPGA_REG_TYPE_MIXED, 0, 2, tsm_int_stat_fields },
+	{ TSM_LED, 4, 27, NTHW_FPGA_REG_TYPE_RW, 16793600, 12, tsm_led_fields },
+	{ TSM_NTTS_CONFIG, 13, 7, NTHW_FPGA_REG_TYPE_RW, 32, 4, tsm_ntts_config_fields },
+	{ TSM_NTTS_EXT_STAT, 15, 32, NTHW_FPGA_REG_TYPE_MIXED, 0, 3, tsm_ntts_ext_stat_fields },
+	{ TSM_NTTS_LIMIT_HI, 23, 16, NTHW_FPGA_REG_TYPE_RW, 0, 1, tsm_ntts_limit_hi_fields },
+	{ TSM_NTTS_LIMIT_LO, 22, 32, NTHW_FPGA_REG_TYPE_RW, 100000, 1, tsm_ntts_limit_lo_fields },
+	{ TSM_NTTS_OFFSET, 21, 30, NTHW_FPGA_REG_TYPE_RW, 0, 1, tsm_ntts_offset_fields },
+	{ TSM_NTTS_SAMPLE_HI, 19, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_ntts_sample_hi_fields },
+	{ TSM_NTTS_SAMPLE_LO, 18, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_ntts_sample_lo_fields },
+	{ TSM_NTTS_STAT, 14, 17, NTHW_FPGA_REG_TYPE_RO, 0, 3, tsm_ntts_stat_fields },
+	{ TSM_NTTS_TS_T0_HI, 17, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_ntts_ts_t0_hi_fields },
+	{ TSM_NTTS_TS_T0_LO, 16, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_ntts_ts_t0_lo_fields },
+	{
+		TSM_NTTS_TS_T0_OFFSET, 20, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1,
+		tsm_ntts_ts_t0_offset_fields
+	},
+	{ TSM_PB_CTRL, 63, 2, NTHW_FPGA_REG_TYPE_WO, 0, 2, tsm_pb_ctrl_fields },
+	{ TSM_PB_INSTMEM, 64, 32, NTHW_FPGA_REG_TYPE_WO, 0, 2, tsm_pb_instmem_fields },
+	{ TSM_PI_CTRL_I, 54, 32, NTHW_FPGA_REG_TYPE_WO, 0, 1, tsm_pi_ctrl_i_fields },
+	{ TSM_PI_CTRL_KI, 52, 24, NTHW_FPGA_REG_TYPE_RW, 0, 1, tsm_pi_ctrl_ki_fields },
+	{ TSM_PI_CTRL_KP, 51, 24, NTHW_FPGA_REG_TYPE_RW, 0, 1, tsm_pi_ctrl_kp_fields },
+	{ TSM_PI_CTRL_SHL, 53, 4, NTHW_FPGA_REG_TYPE_WO, 0, 1, tsm_pi_ctrl_shl_fields },
+	{ TSM_STAT, 1, 16, NTHW_FPGA_REG_TYPE_RO, 0, 9, tsm_stat_fields },
+	{ TSM_TIMER_CTRL, 48, 2, NTHW_FPGA_REG_TYPE_RW, 0, 2, tsm_timer_ctrl_fields },
+	{ TSM_TIMER_T0, 49, 30, NTHW_FPGA_REG_TYPE_RW, 50000, 1, tsm_timer_t0_fields },
+	{ TSM_TIMER_T1, 50, 30, NTHW_FPGA_REG_TYPE_RW, 50000, 1, tsm_timer_t1_fields },
+	{ TSM_TIME_HARDSET_HI, 12, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_time_hardset_hi_fields },
+	{ TSM_TIME_HARDSET_LO, 11, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_time_hardset_lo_fields },
+	{ TSM_TIME_HI, 9, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1, tsm_time_hi_fields },
+	{ TSM_TIME_LO, 8, 32, NTHW_FPGA_REG_TYPE_RW, 0, 1, tsm_time_lo_fields },
+	{ TSM_TIME_RATE_ADJ, 10, 29, NTHW_FPGA_REG_TYPE_RW, 0, 1, tsm_time_rate_adj_fields },
+	{ TSM_TS_HI, 6, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_ts_hi_fields },
+	{ TSM_TS_LO, 5, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_ts_lo_fields },
+	{ TSM_TS_OFFSET, 7, 30, NTHW_FPGA_REG_TYPE_RW, 0, 1, tsm_ts_offset_fields },
+	{ TSM_TS_STAT, 55, 17, NTHW_FPGA_REG_TYPE_RO, 0, 2, tsm_ts_stat_fields },
+	{
+		TSM_TS_STAT_HI_OFFSET, 62, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1,
+		tsm_ts_stat_hi_offset_fields
+	},
+	{
+		TSM_TS_STAT_LO_OFFSET, 61, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1,
+		tsm_ts_stat_lo_offset_fields
+	},
+	{ TSM_TS_STAT_TAR_HI, 57, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_ts_stat_tar_hi_fields },
+	{ TSM_TS_STAT_TAR_LO, 56, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_ts_stat_tar_lo_fields },
+	{ TSM_TS_STAT_X, 58, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_ts_stat_x_fields },
+	{ TSM_TS_STAT_X2_HI, 60, 16, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_ts_stat_x2_hi_fields },
+	{ TSM_TS_STAT_X2_LO, 59, 32, NTHW_FPGA_REG_TYPE_RO, 0, 1, tsm_ts_stat_x2_lo_fields },
+	{ TSM_UTC_OFFSET, 65, 8, NTHW_FPGA_REG_TYPE_RW, 0, 1, tsm_utc_offset_fields },
+};
+
+static nthw_fpga_module_init_s fpga_modules[] = {
+	{ MOD_CAT, 0, MOD_CAT, 0, 21, NTHW_FPGA_BUS_TYPE_RAB1, 768, 34, cat_registers },
+	{ MOD_CSU, 0, MOD_CSU, 0, 0, NTHW_FPGA_BUS_TYPE_RAB1, 9728, 2, csu_registers },
+	{ MOD_DBS, 0, MOD_DBS, 0, 11, NTHW_FPGA_BUS_TYPE_RAB2, 1568, 27, dbs_registers },
+	{ MOD_FLM, 0, MOD_FLM, 0, 25, NTHW_FPGA_BUS_TYPE_RAB1, 1280, 43, flm_registers },
+	{ MOD_GFG, 0, MOD_GFG, 1, 1, NTHW_FPGA_BUS_TYPE_RAB2, 5120, 10, gfg_registers },
+	{ MOD_GMF, 0, MOD_GMF, 2, 5, NTHW_FPGA_BUS_TYPE_RAB2, 5632, 12, gmf_registers },
+	{ MOD_GMF, 1, MOD_GMF, 2, 5, NTHW_FPGA_BUS_TYPE_RAB2, 6144, 12, gmf_registers },
+	{ MOD_HFU, 0, MOD_HFU, 0, 2, NTHW_FPGA_BUS_TYPE_RAB1, 9472, 2, hfu_registers },
+	{ MOD_HIF, 0, MOD_HIF, 0, 0, NTHW_FPGA_BUS_TYPE_PCI, 0, 18, hif_registers },
+	{ MOD_HSH, 0, MOD_HSH, 0, 5, NTHW_FPGA_BUS_TYPE_RAB1, 1536, 2, hsh_registers },
+	{ MOD_I2CM, 0, MOD_I2CM, 0, 1, NTHW_FPGA_BUS_TYPE_RAB0, 640, 7, i2cm_registers },
+	{ MOD_IFR, 0, MOD_IFR, 0, 7, NTHW_FPGA_BUS_TYPE_RAB1, 9984, 6, ifr_registers },
+	{ MOD_IGAM, 0, MOD_IGAM, 0, 1, NTHW_FPGA_BUS_TYPE_RAB0, 1040, 3, igam_registers },
+	{ MOD_KM, 0, MOD_KM, 0, 7, NTHW_FPGA_BUS_TYPE_RAB1, 1024, 11, km_registers },
+	{
+		MOD_PCI_RD_TG, 0, MOD_PCI_RD_TG, 0, 1, NTHW_FPGA_BUS_TYPE_RAB0, 1312, 6,
+		pci_rd_tg_registers
+	},
+	{ MOD_PCI_TA, 0, MOD_PCI_TA, 0, 0, NTHW_FPGA_BUS_TYPE_RAB0, 1328, 5, pci_ta_registers },
+	{
+		MOD_PCI_WR_TG, 0, MOD_PCI_WR_TG, 0, 1, NTHW_FPGA_BUS_TYPE_RAB0, 1296, 7,
+		pci_wr_tg_registers
+	},
+	{
+		MOD_PCM_NT400DXX, 0, MOD_PCM_NT400DXX, 0, 3, NTHW_FPGA_BUS_TYPE_RAB0, 1024, 3,
+		pcm_nt400dxx_registers
+	},
+	{ MOD_PDB, 0, MOD_PDB, 0, 9, NTHW_FPGA_BUS_TYPE_RAB1, 2560, 3, pdb_registers },
+	{ MOD_PDI, 0, MOD_PDI, 1, 1, NTHW_FPGA_BUS_TYPE_RAB0, 64, 6, pdi_registers },
+	{
+		MOD_PHY_TILE, 0, MOD_PHY_TILE, 0, 10, NTHW_FPGA_BUS_TYPE_RAB2, 7168, 33,
+		phy_tile_registers
+	},
+	{
+		MOD_PRM_NT400DXX, 0, MOD_PRM_NT400DXX, 0, 0, NTHW_FPGA_BUS_TYPE_RAB0, 1032, 1,
+		prm_nt400dxx_registers
+	},
+	{ MOD_QSL, 0, MOD_QSL, 0, 7, NTHW_FPGA_BUS_TYPE_RAB1, 1792, 8, qsl_registers },
+	{ MOD_RAC, 0, MOD_RAC, 3, 0, NTHW_FPGA_BUS_TYPE_PCI, 8192, 14, rac_registers },
+	{ MOD_RFD, 0, MOD_RFD, 0, 4, NTHW_FPGA_BUS_TYPE_RAB1, 256, 5, rfd_registers },
+	{ MOD_RPF, 0, MOD_RPF, 0, 2, NTHW_FPGA_BUS_TYPE_RAB2, 4096, 2, rpf_registers },
+	{ MOD_RPP_LR, 0, MOD_RPP_LR, 0, 2, NTHW_FPGA_BUS_TYPE_RAB1, 2304, 4, rpp_lr_registers },
+	{ MOD_RST9574, 0, MOD_RST9574, 0, 2, NTHW_FPGA_BUS_TYPE_RAB2, 0, 3, rst9574_registers },
+	{ MOD_SLC_LR, 0, MOD_SLC, 0, 2, NTHW_FPGA_BUS_TYPE_RAB1, 2048, 2, slc_registers },
+	{ MOD_SPIM, 0, MOD_SPIM, 1, 1, NTHW_FPGA_BUS_TYPE_RAB0, 80, 7, spim_registers },
+	{ MOD_SPIS, 0, MOD_SPIS, 1, 0, NTHW_FPGA_BUS_TYPE_RAB0, 256, 7, spis_registers },
+	{ MOD_STA, 0, MOD_STA, 0, 9, NTHW_FPGA_BUS_TYPE_RAB2, 1536, 17, sta_registers },
+	{ MOD_TINT, 0, MOD_TINT, 0, 0, NTHW_FPGA_BUS_TYPE_RAB2, 1024, 2, tint_registers },
+	{ MOD_TSM, 0, MOD_TSM, 0, 8, NTHW_FPGA_BUS_TYPE_RAB2, 512, 66, tsm_registers },
+	{ MOD_TX_CPY, 0, MOD_CPY, 0, 4, NTHW_FPGA_BUS_TYPE_RAB1, 9216, 26, cpy_registers },
+	{ MOD_TX_INS, 0, MOD_INS, 0, 2, NTHW_FPGA_BUS_TYPE_RAB1, 8704, 2, ins_registers },
+	{ MOD_TX_RPL, 0, MOD_RPL, 0, 4, NTHW_FPGA_BUS_TYPE_RAB1, 8960, 6, rpl_registers },
+};
+
+static nthw_fpga_prod_param_s product_parameters[] = {
+	{ NT_BUILD_NUMBER, 0 },
+	{ NT_BUILD_TIME, 1726786851 },
+	{ NT_CATEGORIES, 64 },
+	{ NT_CAT_DCT_PRESENT, 0 },
+	{ NT_CAT_END_OFS_SUPPORT, 0 },
+	{ NT_CAT_FUNCS, 64 },
+	{ NT_CAT_KCC_BANKS, 3 },
+	{ NT_CAT_KCC_PRESENT, 0 },
+	{ NT_CAT_KCC_SIZE, 1536 },
+	{ NT_CAT_KM_IF_CNT, 2 },
+	{ NT_CAT_KM_IF_M0, 0 },
+	{ NT_CAT_KM_IF_M1, 1 },
+	{ NT_CAT_N_CMP, 8 },
+	{ NT_CAT_N_EXT, 4 },
+	{ NT_CAT_N_LEN, 8 },
+	{ NT_CB_DEBUG, 0 },
+	{ NT_COR_CATEGORIES, 16 },
+	{ NT_COR_PRESENT, 0 },
+	{ NT_CSU_PRESENT, 1 },
+	{ NT_DBS_PRESENT, 1 },
+	{ NT_DBS_RX_QUEUES, 128 },
+	{ NT_DBS_TX_PORTS, 2 },
+	{ NT_DBS_TX_QUEUES, 128 },
+	{ NT_DDP_PRESENT, 0 },
+	{ NT_DDP_TBL_DEPTH, 1024 },
+	{ NT_EMI_SPLIT_STEPS, 16 },
+	{ NT_EOF_TIMESTAMP_ONLY, 1 },
+	{ NT_EPP_CATEGORIES, 32 },
+	{ NT_FLM_CACHE, 1 },
+	{ NT_FLM_CATEGORIES, 32 },
+	{ NT_FLM_ENTRY_SIZE, 64 },
+	{ NT_FLM_LOAD_APS_MAX, 360000000 },
+	{ NT_FLM_LOAD_LPS_MAX, 600000000 },
+	{ NT_FLM_PRESENT, 1 },
+	{ NT_FLM_PRIOS, 4 },
+	{ NT_FLM_PST_PROFILES, 16 },
+	{ NT_FLM_SCRUB_PROFILES, 16 },
+	{ NT_FLM_SIZE_MB, 16384 },
+	{ NT_FLM_STATEFUL, 1 },
+	{ NT_FLM_VARIANT, 2 },
+	{ NT_GFG_PRESENT, 1 },
+	{ NT_GFG_TX_LIVE_RECONFIG_SUPPORT, 1 },
+	{ NT_GMF_FCS_PRESENT, 0 },
+	{ NT_GMF_IFG_SPEED_DIV, 34 },
+	{ NT_GMF_IFG_SPEED_DIV100G, 34 },
+	{ NT_GMF_IFG_SPEED_MUL, 16 },
+	{ NT_GMF_IFG_SPEED_MUL100G, 16 },
+	{ NT_GROUP_ID, 9574 },
+	{ NT_HFU_PRESENT, 1 },
+	{ NT_HIF_MSIX_BAR, 1 },
+	{ NT_HIF_MSIX_PBA_OFS, 8192 },
+	{ NT_HIF_MSIX_PRESENT, 1 },
+	{ NT_HIF_MSIX_TBL_OFS, 0 },
+	{ NT_HIF_MSIX_TBL_SIZE, 8 },
+	{ NT_HIF_PER_PS, 2222 },
+	{ NT_HIF_SRIOV_PRESENT, 1 },
+	{ NT_HIF_VF_OFFSET, 1 },
+	{ NT_HSH_CATEGORIES, 16 },
+	{ NT_HSH_TOEPLITZ, 1 },
+	{ NT_HST_CATEGORIES, 32 },
+	{ NT_HST_PRESENT, 0 },
+	{ NT_IOA_CATEGORIES, 1024 },
+	{ NT_IOA_PRESENT, 0 },
+	{ NT_IPF_PRESENT, 0 },
+	{ NT_KM_CAM_BANKS, 3 },
+	{ NT_KM_CAM_RECORDS, 2048 },
+	{ NT_KM_CAM_REC_WORDS, 6 },
+	{ NT_KM_CATEGORIES, 32 },
+	{ NT_KM_END_OFS_SUPPORT, 0 },
+	{ NT_KM_EXT_EXTRACTORS, 1 },
+	{ NT_KM_FLOW_TYPES, 16 },
+	{ NT_KM_PRESENT, 1 },
+	{ NT_KM_SWX_PRESENT, 0 },
+	{ NT_KM_SYNERGY_MATCH, 0 },
+	{ NT_KM_TCAM_BANKS, 12 },
+	{ NT_KM_TCAM_BANK_WIDTH, 72 },
+	{ NT_KM_TCAM_HIT_QUAL, 0 },
+	{ NT_KM_TCAM_KEYWAY, 1 },
+	{ NT_KM_WIDE, 0 },
+	{ NT_LR_PRESENT, 1 },
+	{ NT_MCU_PRESENT, 0 },
+	{ NT_MDG_DEBUG_FLOW_CONTROL, 0 },
+	{ NT_MDG_DEBUG_REG_READ_BACK, 0 },
+	{ NT_MSK_CATEGORIES, 32 },
+	{ NT_MSK_PRESENT, 0 },
+	{ NT_NFV_OVS_PRODUCT, 0 },
+	{ NT_NIMS, 2 },
+	{ NT_PCI_DEVICE_ID, 661 },
+	{ NT_PCI_TA_TG_PRESENT, 1 },
+	{ NT_PCI_VENDOR_ID, 6388 },
+	{ NT_PDB_CATEGORIES, 16 },
+	{ NT_PHY_ANEG_PRESENT, 0 },
+	{ NT_PHY_KRFEC_PRESENT, 0 },
+	{ NT_PHY_PORTS, 2 },
+	{ NT_PHY_PORTS_PER_QUAD, 1 },
+	{ NT_PHY_QUADS, 2 },
+	{ NT_PHY_RSFEC_PRESENT, 0 },
+	{ NT_QM_CELLS, 4194304 },
+	{ NT_QM_CELL_SIZE, 4096 },
+	{ NT_QM_PRESENT, 0 },
+	{ NT_QSL_CATEGORIES, 32 },
+	{ NT_QSL_COLOR_SEL_BW, 7 },
+	{ NT_QSL_QST_SIZE, 4096 },
+	{ NT_QUEUES, 128 },
+	{ NT_RAC_RAB_INTERFACES, 3 },
+	{ NT_RAC_RAB_OB_UPDATE, 0 },
+	{ NT_REVISION_ID, 49 },
+	{ NT_RMC_LAG_GROUPS, 1 },
+	{ NT_RMC_PRESENT, 0 },
+	{ NT_ROA_CATEGORIES, 1024 },
+	{ NT_ROA_PRESENT, 0 },
+	{ NT_RPF_MATURING_DEL_DEFAULT, -125 },
+	{ NT_RPF_PRESENT, 1 },
+	{ NT_RPP_PER_PS, 1666 },
+	{ NT_RTX_PRESENT, 0 },
+	{ NT_RX_HOST_BUFFERS, 128 },
+	{ NT_RX_PORTS, 2 },
+	{ NT_RX_PORT_REPLICATE, 0 },
+	{ NT_SLB_PRESENT, 0 },
+	{ NT_SLC_LR_PRESENT, 1 },
+	{ NT_SLC_PRESENT, 0 },
+	{ NT_STA_COLORS, 64 },
+	{ NT_STA_LOAD_AVG_RX, 1 },
+	{ NT_STA_LOAD_AVG_TX, 1 },
+	{ NT_STA_RX_PORTS, 2 },
+	{ NT_TBH_DEBUG_DLN, 1 },
+	{ NT_TBH_PRESENT, 0 },
+	{ NT_TFD_PRESENT, 1 },
+	{ NT_TPE_CATEGORIES, 16 },
+	{ NT_TSM_OST_ONLY, 1 },
+	{ NT_TS_APPEND, 0 },
+	{ NT_TS_INJECT_PRESENT, 0 },
+	{ NT_TX_CPY_PACKET_READERS, 0 },
+	{ NT_TX_CPY_PRESENT, 1 },
+	{ NT_TX_CPY_SIDEBAND_READERS, 7 },
+	{ NT_TX_CPY_VARIANT, 0 },
+	{ NT_TX_CPY_WRITERS, 6 },
+	{ NT_TX_HOST_BUFFERS, 128 },
+	{ NT_TX_INS_OFS_ZERO, 1 },
+	{ NT_TX_INS_PRESENT, 1 },
+	{ NT_TX_MTU_PROFILE_IFR, 16 },
+	{ NT_TX_ON_TIMESTAMP, 1 },
+	{ NT_TX_PORTS, 2 },
+	{ NT_TX_PORT_REPLICATE, 1 },
+	{ NT_TX_RPL_DEPTH, 4096 },
+	{ NT_TX_RPL_EXT_CATEGORIES, 1024 },
+	{ NT_TX_RPL_OFS_ZERO, 1 },
+	{ NT_TX_RPL_PRESENT, 1 },
+	{ NT_TYPE_ID, 200 },
+	{ NT_USE_TRIPLE_SPEED, 0 },
+	{ NT_VERSION_ID, 55 },
+	{ NT_VLI_PRESENT, 0 },
+	{ 0, -1 },	/* END */
+};
+
+nthw_fpga_prod_init_s nthw_fpga_9574_055_049_0000 = {
+	200, 9574, 55, 49, 0, 0, 1726786851, 152, product_parameters, 37, fpga_modules,
+};
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.c b/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.c
index c8a310c415..634095646c 100644
--- a/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.c
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.c
@@ -5,4 +5,7 @@
 
 
 #include "nthw_fpga_instances.h"
-nthw_fpga_prod_init_s *nthw_fpga_instances[] = { &nthw_fpga_9563_055_049_0000, NULL };
+nthw_fpga_prod_init_s *nthw_fpga_instances[] = {
+	 &nthw_fpga_9563_055_049_0000,
+	&nthw_fpga_9574_055_049_0000,
+	NULL  };
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h
index 3e5983f763..ad0e700bfd 100644
--- a/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_instances.h
@@ -7,3 +7,4 @@
 #include "fpga_model.h"
 extern nthw_fpga_prod_init_s *nthw_fpga_instances[];
 extern nthw_fpga_prod_init_s nthw_fpga_9563_055_049_0000;
+extern nthw_fpga_prod_init_s nthw_fpga_9574_055_049_0000;
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_mod_defs.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_mod_defs.h
index e6ed9e714b..e2a98a737a 100644
--- a/drivers/net/ntnic/nthw/supported/nthw_fpga_mod_defs.h
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_mod_defs.h
@@ -27,6 +27,7 @@
 #define MOD_HSH (0x501484bfUL)
 #define MOD_I2CM (0x93bc7780UL)
 #define MOD_IFR (0x9b01f1e6UL)
+#define MOD_IGAM (0xf3b0bfb9UL)
 #define MOD_IIC (0x7629cddbUL)
 #define MOD_INS (0x24df4b78UL)
 #define MOD_KM (0xcfbd9dbeUL)
@@ -35,19 +36,29 @@
 #define MOD_MAC_TX (0x351d1316UL)
 #define MOD_PCIE3 (0xfbc48c18UL)
 #define MOD_PCI_RD_TG (0x9ad9eed2UL)
+#define MOD_PCI_TA (0xfb431997UL)
 #define MOD_PCI_WR_TG (0x274b69e1UL)
+#define MOD_PCM_NT400DXX (0x93b709a3UL)
 #define MOD_PDB (0xa7771bffUL)
+#define MOD_PDI (0x30a5c277UL)
+#define MOD_PHY_TILE (0x4e0aef6eUL)
+#define MOD_PRM_NT400DXX (0xfccf12a8UL)
 #define MOD_QSL (0x448ed859UL)
 #define MOD_RAC (0xae830b42UL)
+#define MOD_RFD (0x7fa60826UL)
 #define MOD_RMC (0x236444eUL)
 #define MOD_RPL (0x6de535c3UL)
 #define MOD_RPF (0x8d30dcddUL)
 #define MOD_RPP_LR (0xba7f945cUL)
 #define MOD_RST9563 (0x385d6d1dUL)
+#define MOD_RST9574 (0xbf22c9ffUL)
 #define MOD_SDC (0xd2369530UL)
 #define MOD_SLC (0x1aef1f38UL)
 #define MOD_SLC_LR (0x969fc50bUL)
+#define MOD_SPIM (0x1da437bfUL)
+#define MOD_SPIS (0xe7ab0adcUL)
 #define MOD_STA (0x76fae64dUL)
+#define MOD_TINT (0xb8aea9feUL)
 #define MOD_TSM (0x35422a24UL)
 #define MOD_TX_CPY (0x60acf217UL)
 #define MOD_TX_INS (0x59afa100UL)
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_mod_str_map.c b/drivers/net/ntnic/nthw/supported/nthw_fpga_mod_str_map.c
index 459cc724c2..a0afa22579 100644
--- a/drivers/net/ntnic/nthw/supported/nthw_fpga_mod_str_map.c
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_mod_str_map.c
@@ -19,6 +19,7 @@ const struct nthw_fpga_mod_str_s sa_nthw_fpga_mod_str_map[] = {
 	{ MOD_HSH, "HSH" },
 	{ MOD_I2CM, "I2CM" },
 	{ MOD_IFR, "IFR" },
+	{ MOD_IGAM, "IGAM" },
 	{ MOD_IIC, "IIC" },
 	{ MOD_INS, "INS" },
 	{ MOD_KM, "KM" },
@@ -27,20 +28,30 @@ const struct nthw_fpga_mod_str_s sa_nthw_fpga_mod_str_map[] = {
 	{ MOD_MAC_RX, "MAC_RX" },
 	{ MOD_MAC_TX, "MAC_TX" },
 	{ MOD_PCI_RD_TG, "PCI_RD_TG" },
+	{ MOD_PCI_TA, "PCI_TA" },
 	{ MOD_PCI_WR_TG, "PCI_WR_TG" },
 	{ MOD_PCIE3, "PCIE3" },
+	{ MOD_PCM_NT400DXX, "PCM_NT400DXX" },
 	{ MOD_PDB, "PDB" },
+	{ MOD_PDI, "PDI" },
+	{ MOD_PHY_TILE, "PHY_TILE" },
+	{ MOD_PRM_NT400DXX, "PRM_NT400DXX" },
 	{ MOD_QSL, "QSL" },
 	{ MOD_RAC, "RAC" },
+	{ MOD_RFD, "RFD" },
 	{ MOD_RMC, "RMC" },
 	{ MOD_RPF, "RPF" },
 	{ MOD_RPL, "RPL" },
 	{ MOD_RPP_LR, "RPP_LR" },
 	{ MOD_RST9563, "RST9563" },
+	{ MOD_RST9574, "RST9574" },
 	{ MOD_SDC, "SDC" },
 	{ MOD_SLC_LR, "SLC_LR" },
 	{ MOD_SLC, "SLC" },
+	{ MOD_SPIM, "SPIM" },
+	{ MOD_SPIS, "SPIS" },
 	{ MOD_STA, "STA" },
+	{ MOD_TINT, "TINT" },
 	{ MOD_TSM, "TSM" },
 	{ MOD_TX_CPY, "TX_CPY" },
 	{ MOD_TX_INS, "TX_INS" },
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs.h
index 4d299c6aa8..5b824ef3e5 100644
--- a/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs.h
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs.h
@@ -26,6 +26,7 @@
 #include "nthw_fpga_reg_defs_hsh.h"
 #include "nthw_fpga_reg_defs_i2cm.h"
 #include "nthw_fpga_reg_defs_ifr.h"
+#include "nthw_fpga_reg_defs_igam.h"
 #include "nthw_fpga_reg_defs_iic.h"
 #include "nthw_fpga_reg_defs_ins.h"
 #include "nthw_fpga_reg_defs_km.h"
@@ -34,20 +35,30 @@
 #include "nthw_fpga_reg_defs_mac_tx.h"
 #include "nthw_fpga_reg_defs_pcie3.h"
 #include "nthw_fpga_reg_defs_pci_rd_tg.h"
+#include "nthw_fpga_reg_defs_pci_ta.h"
 #include "nthw_fpga_reg_defs_pci_wr_tg.h"
+#include "nthw_fpga_reg_defs_pcm_nt400dxx.h"
 #include "nthw_fpga_reg_defs_pdb.h"
+#include "nthw_fpga_reg_defs_pdi.h"
+#include "nthw_fpga_reg_defs_phy_tile.h"
+#include "nthw_fpga_reg_defs_prm_nt400dxx.h"
 #include "nthw_fpga_reg_defs_qsl.h"
 #include "nthw_fpga_reg_defs_rac.h"
+#include "nthw_fpga_reg_defs_rfd.h"
 #include "nthw_fpga_reg_defs_rmc.h"
 #include "nthw_fpga_reg_defs_rpf.h"
 #include "nthw_fpga_reg_defs_rpl.h"
 #include "nthw_fpga_reg_defs_rpp_lr.h"
 #include "nthw_fpga_reg_defs_rst9563.h"
+#include "nthw_fpga_reg_defs_rst9574.h"
 #include "nthw_fpga_reg_defs_sdc.h"
 #include "nthw_fpga_reg_defs_tsm.h"
 #include "nthw_fpga_reg_defs_slc.h"
 #include "nthw_fpga_reg_defs_slc_lr.h"
+#include "nthw_fpga_reg_defs_spim.h"
+#include "nthw_fpga_reg_defs_spis.h"
 #include "nthw_fpga_reg_defs_sta.h"
+#include "nthw_fpga_reg_defs_tint.h"
 #include "nthw_fpga_reg_defs_tx_cpy.h"
 #include "nthw_fpga_reg_defs_tx_ins.h"
 #include "nthw_fpga_reg_defs_tx_rpl.h"
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_igam.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_igam.h
new file mode 100644
index 0000000000..dd247ef0dd
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_igam.h
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+/*
+ * nthw_fpga_reg_defs_igam.h
+ *
+ * Auto-generated file - do *NOT* edit
+ *
+ */
+
+#ifndef _NTHW_FPGA_REG_DEFS_IGAM_
+#define _NTHW_FPGA_REG_DEFS_IGAM_
+
+/* IGAM */
+#define NTHW_MOD_IGAM (0xf3b0bfb9UL)
+#define IGAM_BASE (0xcdbfd276UL)
+#define IGAM_BASE_BUSY (0x2a018901UL)
+#define IGAM_BASE_CMD (0x61c2922dUL)
+#define IGAM_BASE_PTR (0x1076934dUL)
+#define IGAM_CTRL (0xf295d6dUL)
+#define IGAM_CTRL_FORCE_RST (0xf40df899UL)
+#define IGAM_CTRL_FORWARD_RST (0xbe779fc1UL)
+#define IGAM_DATA (0xa0f8df74UL)
+#define IGAM_DATA_DATA (0x6544d6f2UL)
+
+#endif	/* _NTHW_FPGA_REG_DEFS_IGAM_ */
+
+/*
+ * Auto-generated file - do *NOT* edit
+ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pci_ta.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pci_ta.h
new file mode 100644
index 0000000000..d9a0b4f381
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pci_ta.h
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+/*
+ * nthw_fpga_reg_defs_pci_ta.h
+ *
+ * Auto-generated file - do *NOT* edit
+ *
+ */
+
+#ifndef _NTHW_FPGA_REG_DEFS_PCI_TA_
+#define _NTHW_FPGA_REG_DEFS_PCI_TA_
+
+/* PCI_TA */
+#define NTHW_MOD_PCI_TA (0xfb431997UL)
+#define PCI_TA_CONTROL (0xa707df59UL)
+#define PCI_TA_CONTROL_ENABLE (0x87cdcc9aUL)
+#define PCI_TA_LENGTH_ERROR (0x8648b862UL)
+#define PCI_TA_LENGTH_ERROR_AMOUNT (0x8774bd63UL)
+#define PCI_TA_PACKET_BAD (0xaaa256d4UL)
+#define PCI_TA_PACKET_BAD_AMOUNT (0x601f72f3UL)
+#define PCI_TA_PACKET_GOOD (0xfc13da6cUL)
+#define PCI_TA_PACKET_GOOD_AMOUNT (0xd936d64dUL)
+#define PCI_TA_PAYLOAD_ERROR (0x69d7a09bUL)
+#define PCI_TA_PAYLOAD_ERROR_AMOUNT (0x445da330UL)
+
+#endif	/* _NTHW_FPGA_REG_DEFS_PCI_TA_ */
+
+/*
+ * Auto-generated file - do *NOT* edit
+ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pcm_nt400dxx.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pcm_nt400dxx.h
new file mode 100644
index 0000000000..fadb8c17e8
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pcm_nt400dxx.h
@@ -0,0 +1,29 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+/*
+ * nthw_fpga_reg_defs_pcm_nt400dxx.h
+ *
+ * Auto-generated file - do *NOT* edit
+ *
+ */
+
+#ifndef _NTHW_FPGA_REG_DEFS_PCM_NT400DXX_
+#define _NTHW_FPGA_REG_DEFS_PCM_NT400DXX_
+
+/* PCM_NT400DXX */
+#define NTHW_MOD_PCM_NT400DXX (0x93b709a3UL)
+#define PCM_NT400DXX_CTRL (0x7dd2be2aUL)
+#define PCM_NT400DXX_CTRL_TS_PLL_RECAL (0xe876b916UL)
+#define PCM_NT400DXX_LATCH (0x17416d46UL)
+#define PCM_NT400DXX_LATCH_TS_PLL_LOCKED (0xe38e12c5UL)
+#define PCM_NT400DXX_STAT (0x5f483071UL)
+#define PCM_NT400DXX_STAT_TS_PLL_LOCKED (0x92116985UL)
+
+#endif	/* _NTHW_FPGA_REG_DEFS_PCM_NT400DXX_ */
+
+/*
+ * Auto-generated file - do *NOT* edit
+ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pdi.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pdi.h
new file mode 100644
index 0000000000..67177ca288
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pdi.h
@@ -0,0 +1,49 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+/*
+ * nthw_fpga_reg_defs_pdi.h
+ *
+ * Auto-generated file - do *NOT* edit
+ *
+ */
+
+#ifndef _NTHW_FPGA_REG_DEFS_PDI_
+#define _NTHW_FPGA_REG_DEFS_PDI_
+
+/* PDI */
+#define NTHW_MOD_PDI (0x30a5c277UL)
+#define PDI_CR (0x9d6d02a8UL)
+#define PDI_CR_EN (0x7a6160dUL)
+#define PDI_CR_PARITY (0xaed85250UL)
+#define PDI_CR_RST (0x26b77922UL)
+#define PDI_CR_RXRST (0xe1aedb39UL)
+#define PDI_CR_STOP (0x78eaf29eUL)
+#define PDI_CR_TXRST (0x6eee2e99UL)
+#define PDI_DRR (0x8ab88f08UL)
+#define PDI_DRR_DRR (0x157e17dfUL)
+#define PDI_DTR (0xdce2288eUL)
+#define PDI_DTR_DTR (0x957d5344UL)
+#define PDI_PRE (0x12440163UL)
+#define PDI_PRE_PRE (0xccd36afbUL)
+#define PDI_SR (0xd7af10f9UL)
+#define PDI_SR_DISABLE_BUSY (0xd8936666UL)
+#define PDI_SR_DONE (0xb64f984dUL)
+#define PDI_SR_ENABLE_BUSY (0xee39b4e3UL)
+#define PDI_SR_FRAME_ERR (0x7c7b177dUL)
+#define PDI_SR_OVERRUN_ERR (0x4093d29dUL)
+#define PDI_SR_PARITY_ERR (0xa12e1293UL)
+#define PDI_SR_RXLVL (0xe5b6087bUL)
+#define PDI_SR_RX_BUSY (0xeb248de4UL)
+#define PDI_SR_TXLVL (0x6af6fddbUL)
+#define PDI_SR_TX_BUSY (0x88f4b8deUL)
+#define PDI_SRR (0x93d13afdUL)
+#define PDI_SRR_RST (0x5fd4fe29UL)
+
+#endif	/* _NTHW_FPGA_REG_DEFS_PDI_ */
+
+/*
+ * Auto-generated file - do *NOT* edit
+ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_phy_tile.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_phy_tile.h
new file mode 100644
index 0000000000..99ef0e21fc
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_phy_tile.h
@@ -0,0 +1,213 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+/*
+ * nthw_fpga_reg_defs_phy_tile.h
+ *
+ * Auto-generated file - do *NOT* edit
+ *
+ */
+
+#ifndef _NTHW_FPGA_REG_DEFS_PHY_TILE_
+#define _NTHW_FPGA_REG_DEFS_PHY_TILE_
+
+/* PHY_TILE */
+#define NTHW_MOD_PHY_TILE (0x4e0aef6eUL)
+#define PHY_TILE_DR_CFG (0x763df0f3UL)
+#define PHY_TILE_DR_CFG_DYN_RST (0x2ff2174cUL)
+#define PHY_TILE_DR_CFG_FEATURES (0xf43413f2UL)
+#define PHY_TILE_DR_CFG_SCRATCH (0x605efc72UL)
+#define PHY_TILE_DR_CFG_TX_FLUSH_LEVEL (0x528b497bUL)
+#define PHY_TILE_DR_CFG_STATUS (0x252aff33UL)
+#define PHY_TILE_DR_CFG_STATUS_CURR_PROFILE_ID (0x98db7e13UL)
+#define PHY_TILE_DR_CFG_STATUS_ERROR (0x594c35e7UL)
+#define PHY_TILE_DR_CFG_STATUS_IN_PROGRESS (0x62cdc29fUL)
+#define PHY_TILE_DYN_RECONFIG_BASE (0xda7abd93UL)
+#define PHY_TILE_DYN_RECONFIG_BASE_BUSY (0x3b97f6c6UL)
+#define PHY_TILE_DYN_RECONFIG_BASE_CMD (0xf6b609f6UL)
+#define PHY_TILE_DYN_RECONFIG_BASE_PTR (0x87020896UL)
+#define PHY_TILE_DYN_RECONFIG_DATA (0xb73db091UL)
+#define PHY_TILE_DYN_RECONFIG_DATA_DATA (0x74d2a935UL)
+#define PHY_TILE_LINK_SUMMARY_0 (0x2e6c2bb2UL)
+#define PHY_TILE_LINK_SUMMARY_0_LH_RECEIVED_LOCAL_FAULT (0x658fa4f2UL)
+#define PHY_TILE_LINK_SUMMARY_0_LH_REMOTE_FAULT (0x12c794faUL)
+#define PHY_TILE_LINK_SUMMARY_0_LH_RX_HIGH_BIT_ERROR_RATE (0x99e0ad8bUL)
+#define PHY_TILE_LINK_SUMMARY_0_LINK_DOWN_CNT (0x7c6a63a9UL)
+#define PHY_TILE_LINK_SUMMARY_0_LL_PHY_LINK_STATE (0x694563dcUL)
+#define PHY_TILE_LINK_SUMMARY_0_LL_RX_AM_LOCK (0xc958731bUL)
+#define PHY_TILE_LINK_SUMMARY_0_LL_RX_BLOCK_LOCK (0x1ae5c634UL)
+#define PHY_TILE_LINK_SUMMARY_0_NT_PHY_LINK_STATE (0x284d52caUL)
+#define PHY_TILE_LINK_SUMMARY_1 (0x596b1b24UL)
+#define PHY_TILE_LINK_SUMMARY_1_LH_RECEIVED_LOCAL_FAULT (0xc00434fcUL)
+#define PHY_TILE_LINK_SUMMARY_1_LH_REMOTE_FAULT (0x95615fb9UL)
+#define PHY_TILE_LINK_SUMMARY_1_LH_RX_HIGH_BIT_ERROR_RATE (0xf76cb6caUL)
+#define PHY_TILE_LINK_SUMMARY_1_LINK_DOWN_CNT (0xc591b841UL)
+#define PHY_TILE_LINK_SUMMARY_1_LL_PHY_LINK_STATE (0xbea7e384UL)
+#define PHY_TILE_LINK_SUMMARY_1_LL_RX_AM_LOCK (0x70a3a8f3UL)
+#define PHY_TILE_LINK_SUMMARY_1_LL_RX_BLOCK_LOCK (0xf5b770d5UL)
+#define PHY_TILE_LINK_SUMMARY_1_NT_PHY_LINK_STATE (0xffafd292UL)
+#define PHY_TILE_PORT_0_ETH_0_BASE (0x337c4712UL)
+#define PHY_TILE_PORT_0_ETH_0_BASE_BUSY (0xd5fbad30UL)
+#define PHY_TILE_PORT_0_ETH_0_BASE_CMD (0x948cd3f4UL)
+#define PHY_TILE_PORT_0_ETH_0_BASE_PTR (0xe538d294UL)
+#define PHY_TILE_PORT_0_ETH_0_DATA (0x5e3b4a10UL)
+#define PHY_TILE_PORT_0_ETH_0_DATA_DATA (0x9abef2c3UL)
+#define PHY_TILE_PORT_0_XCVR_0_BASE (0x758a7765UL)
+#define PHY_TILE_PORT_0_XCVR_0_BASE_BUSY (0x79488eafUL)
+#define PHY_TILE_PORT_0_XCVR_0_BASE_CMD (0x9b560cdfUL)
+#define PHY_TILE_PORT_0_XCVR_0_BASE_PTR (0xeae20dbfUL)
+#define PHY_TILE_PORT_0_XCVR_0_DATA (0x18cd7a67UL)
+#define PHY_TILE_PORT_0_XCVR_0_DATA_DATA (0x360dd15cUL)
+#define PHY_TILE_PORT_0_XCVR_1_BASE (0xbed6a4c0UL)
+#define PHY_TILE_PORT_0_XCVR_1_BASE_BUSY (0xb8c6516fUL)
+#define PHY_TILE_PORT_0_XCVR_1_BASE_CMD (0x749467e1UL)
+#define PHY_TILE_PORT_0_XCVR_1_BASE_PTR (0x5206681UL)
+#define PHY_TILE_PORT_0_XCVR_1_DATA (0xd391a9c2UL)
+#define PHY_TILE_PORT_0_XCVR_1_DATA_DATA (0xf7830e9cUL)
+#define PHY_TILE_PORT_0_XCVR_2_BASE (0x3842d66eUL)
+#define PHY_TILE_PORT_0_XCVR_2_BASE_BUSY (0x2124376eUL)
+#define PHY_TILE_PORT_0_XCVR_2_BASE_CMD (0x9fa3dce2UL)
+#define PHY_TILE_PORT_0_XCVR_2_BASE_PTR (0xee17dd82UL)
+#define PHY_TILE_PORT_0_XCVR_2_DATA (0x5505db6cUL)
+#define PHY_TILE_PORT_0_XCVR_2_DATA_DATA (0x6e61689dUL)
+#define PHY_TILE_PORT_0_XCVR_3_BASE (0xf31e05cbUL)
+#define PHY_TILE_PORT_0_XCVR_3_BASE_BUSY (0xe0aae8aeUL)
+#define PHY_TILE_PORT_0_XCVR_3_BASE_CMD (0x7061b7dcUL)
+#define PHY_TILE_PORT_0_XCVR_3_BASE_PTR (0x1d5b6bcUL)
+#define PHY_TILE_PORT_0_XCVR_3_DATA (0x9e5908c9UL)
+#define PHY_TILE_PORT_0_XCVR_3_DATA_DATA (0xafefb75dUL)
+#define PHY_TILE_PORT_1_ETH_0_BASE (0xa8d90b7dUL)
+#define PHY_TILE_PORT_1_ETH_0_BASE_BUSY (0x525d6673UL)
+#define PHY_TILE_PORT_1_ETH_0_BASE_CMD (0x3ae44265UL)
+#define PHY_TILE_PORT_1_ETH_0_BASE_PTR (0x4b504305UL)
+#define PHY_TILE_PORT_1_ETH_0_DATA (0xc59e067fUL)
+#define PHY_TILE_PORT_1_ETH_0_DATA_DATA (0x1d183980UL)
+#define PHY_TILE_PORT_1_XCVR_0_BASE (0xa81caee0UL)
+#define PHY_TILE_PORT_1_XCVR_0_BASE_BUSY (0x961a384eUL)
+#define PHY_TILE_PORT_1_XCVR_0_BASE_CMD (0x1cf0c79cUL)
+#define PHY_TILE_PORT_1_XCVR_0_BASE_PTR (0x6d44c6fcUL)
+#define PHY_TILE_PORT_1_XCVR_0_DATA (0xc55ba3e2UL)
+#define PHY_TILE_PORT_1_XCVR_0_DATA_DATA (0xd95f67bdUL)
+#define PHY_TILE_PORT_1_XCVR_1_BASE (0x63407d45UL)
+#define PHY_TILE_PORT_1_XCVR_1_BASE_BUSY (0x5794e78eUL)
+#define PHY_TILE_PORT_1_XCVR_1_BASE_CMD (0xf332aca2UL)
+#define PHY_TILE_PORT_1_XCVR_1_BASE_PTR (0x8286adc2UL)
+#define PHY_TILE_PORT_1_XCVR_1_DATA (0xe077047UL)
+#define PHY_TILE_PORT_1_XCVR_1_DATA_DATA (0x18d1b87dUL)
+#define PHY_TILE_PORT_1_XCVR_2_BASE (0xe5d40febUL)
+#define PHY_TILE_PORT_1_XCVR_2_BASE_BUSY (0xce76818fUL)
+#define PHY_TILE_PORT_1_XCVR_2_BASE_CMD (0x180517a1UL)
+#define PHY_TILE_PORT_1_XCVR_2_BASE_PTR (0x69b116c1UL)
+#define PHY_TILE_PORT_1_XCVR_2_DATA (0x889302e9UL)
+#define PHY_TILE_PORT_1_XCVR_2_DATA_DATA (0x8133de7cUL)
+#define PHY_TILE_PORT_1_XCVR_3_BASE (0x2e88dc4eUL)
+#define PHY_TILE_PORT_1_XCVR_3_BASE_BUSY (0xff85e4fUL)
+#define PHY_TILE_PORT_1_XCVR_3_BASE_CMD (0xf7c77c9fUL)
+#define PHY_TILE_PORT_1_XCVR_3_BASE_PTR (0x86737dffUL)
+#define PHY_TILE_PORT_1_XCVR_3_DATA (0x43cfd14cUL)
+#define PHY_TILE_PORT_1_XCVR_3_DATA_DATA (0x40bd01bcUL)
+#define PHY_TILE_PORT_COMP_0 (0xfc048a04UL)
+#define PHY_TILE_PORT_COMP_0_RX_COMPENSATION (0xffba9733UL)
+#define PHY_TILE_PORT_COMP_0_TX_COMPENSATION (0xdd4043c1UL)
+#define PHY_TILE_PORT_COMP_1 (0x8b03ba92UL)
+#define PHY_TILE_PORT_COMP_1_RX_COMPENSATION (0x781c5c70UL)
+#define PHY_TILE_PORT_COMP_1_TX_COMPENSATION (0x5ae68882UL)
+#define PHY_TILE_PORT_CONFIG (0x24e3ab60UL)
+#define PHY_TILE_PORT_CONFIG_DYN_RESET (0x72b5f859UL)
+#define PHY_TILE_PORT_CONFIG_NT_FORCE_LINK_DOWN_0 (0x7e66781UL)
+#define PHY_TILE_PORT_CONFIG_NT_FORCE_LINK_DOWN_1 (0x70e15717UL)
+#define PHY_TILE_PORT_CONFIG_NT_LINKUP_LATENCY_0 (0x33fd94c2UL)
+#define PHY_TILE_PORT_CONFIG_NT_LINKUP_LATENCY_1 (0x44faa454UL)
+#define PHY_TILE_PORT_CONFIG_RESET_0 (0xf0e1e1c4UL)
+#define PHY_TILE_PORT_CONFIG_RESET_1 (0x87e6d152UL)
+#define PHY_TILE_PORT_CONFIG_RX_RESET_0 (0x70027edeUL)
+#define PHY_TILE_PORT_CONFIG_RX_RESET_1 (0x7054e48UL)
+#define PHY_TILE_PORT_CONFIG_TX_RESET_0 (0x7d1c0e99UL)
+#define PHY_TILE_PORT_CONFIG_TX_RESET_1 (0xa1b3e0fUL)
+#define PHY_TILE_PORT_CONFIG_0 (0x7eda56ecUL)
+#define PHY_TILE_PORT_CONFIG_0_NT_AUTO_FORCE_LINK_DOWN (0x1e02d057UL)
+#define PHY_TILE_PORT_CONFIG_0_NT_FORCE_LINK_DOWN (0xf21d946dUL)
+#define PHY_TILE_PORT_CONFIG_0_NT_LINKUP_LATENCY (0x833ea2b3UL)
+#define PHY_TILE_PORT_CONFIG_0_RST (0xcbf3bb99UL)
+#define PHY_TILE_PORT_CONFIG_0_RX_RST (0x1c7f59c7UL)
+#define PHY_TILE_PORT_CONFIG_0_TX_RST (0xca26badaUL)
+#define PHY_TILE_PORT_CONFIG_1 (0x9dd667aUL)
+#define PHY_TILE_PORT_CONFIG_1_NT_AUTO_FORCE_LINK_DOWN (0xbb894059UL)
+#define PHY_TILE_PORT_CONFIG_1_NT_FORCE_LINK_DOWN (0x977aaf2bUL)
+#define PHY_TILE_PORT_CONFIG_1_NT_LINKUP_LATENCY (0x54dc22ebUL)
+#define PHY_TILE_PORT_CONFIG_1_RST (0xf6939229UL)
+#define PHY_TILE_PORT_CONFIG_1_RX_RST (0xd0d55959UL)
+#define PHY_TILE_PORT_CONFIG_1_TX_RST (0x68cba44UL)
+#define PHY_TILE_PORT_STATUS (0x8b69e100UL)
+#define PHY_TILE_PORT_STATUS_RESET_ACK_N_0 (0x812f344UL)
+#define PHY_TILE_PORT_STATUS_RESET_ACK_N_1 (0x7f15c3d2UL)
+#define PHY_TILE_PORT_STATUS_RX_AM_LOCK_0 (0x18c38950UL)
+#define PHY_TILE_PORT_STATUS_RX_AM_LOCK_1 (0x6fc4b9c6UL)
+#define PHY_TILE_PORT_STATUS_RX_BLOCK_LOCK_0 (0x72b847a5UL)
+#define PHY_TILE_PORT_STATUS_RX_BLOCK_LOCK_1 (0x5bf7733UL)
+#define PHY_TILE_PORT_STATUS_RX_CDR_LOCK_0 (0x8557733cUL)
+#define PHY_TILE_PORT_STATUS_RX_CDR_LOCK_1 (0xf25043aaUL)
+#define PHY_TILE_PORT_STATUS_RX_HI_BER_0 (0xae6e5427UL)
+#define PHY_TILE_PORT_STATUS_RX_HI_BER_1 (0xd96964b1UL)
+#define PHY_TILE_PORT_STATUS_RX_LOCAL_FAULT_0 (0xb7de3d5eUL)
+#define PHY_TILE_PORT_STATUS_RX_LOCAL_FAULT_1 (0xc0d90dc8UL)
+#define PHY_TILE_PORT_STATUS_RX_PCS_FULLY_ALIGNED_0 (0x690e7dbcUL)
+#define PHY_TILE_PORT_STATUS_RX_PCS_FULLY_ALIGNED_1 (0x1e094d2aUL)
+#define PHY_TILE_PORT_STATUS_RX_PCS_READY_0 (0x4bb3d53cUL)
+#define PHY_TILE_PORT_STATUS_RX_PCS_READY_1 (0x3cb4e5aaUL)
+#define PHY_TILE_PORT_STATUS_RX_PTP_OFFSET_DATA_VALID_0 (0x4a8305e7UL)
+#define PHY_TILE_PORT_STATUS_RX_PTP_OFFSET_DATA_VALID_1 (0x3d843571UL)
+#define PHY_TILE_PORT_STATUS_RX_PTP_READY_0 (0xb74c7368UL)
+#define PHY_TILE_PORT_STATUS_RX_PTP_READY_1 (0xc04b43feUL)
+#define PHY_TILE_PORT_STATUS_RX_REMOTE_FAULT_0 (0x7160c5c7UL)
+#define PHY_TILE_PORT_STATUS_RX_REMOTE_FAULT_1 (0x667f551UL)
+#define PHY_TILE_PORT_STATUS_SYSTEMPLL_LOCK (0x3d44b5b8UL)
+#define PHY_TILE_PORT_STATUS_SYS_PLL_LOCKED_0 (0x9a284858UL)
+#define PHY_TILE_PORT_STATUS_SYS_PLL_LOCKED_1 (0xed2f78ceUL)
+#define PHY_TILE_PORT_STATUS_TX_LANES_STABLE_0 (0x9d0d322aUL)
+#define PHY_TILE_PORT_STATUS_TX_LANES_STABLE_1 (0xea0a02bcUL)
+#define PHY_TILE_PORT_STATUS_TX_PLL_LOCKED_0 (0x56587371UL)
+#define PHY_TILE_PORT_STATUS_TX_PLL_LOCKED_1 (0x215f43e7UL)
+#define PHY_TILE_PORT_STATUS_0 (0x8d2e3a4fUL)
+#define PHY_TILE_PORT_STATUS_0_RESET_ACK_N (0xa0728651UL)
+#define PHY_TILE_PORT_STATUS_0_RX_AM_LOCK (0x84cbe16dUL)
+#define PHY_TILE_PORT_STATUS_0_RX_HI_BER (0x3284d104UL)
+#define PHY_TILE_PORT_STATUS_0_RX_LOCAL_FAULT (0x581a604cUL)
+#define PHY_TILE_PORT_STATUS_0_RX_PCS_FULLY_ALIGNED (0x8a9f2523UL)
+#define PHY_TILE_PORT_STATUS_0_RX_REMOTE_FAULT (0xa42546cfUL)
+#define PHY_TILE_PORT_STATUS_0_RX_RESET_ACK_N (0x5d1fa363UL)
+#define PHY_TILE_PORT_STATUS_0_SYS_PLL_LOCKED (0x1624ce5aUL)
+#define PHY_TILE_PORT_STATUS_0_TX_LANES_STABLE (0x7a66b5c7UL)
+#define PHY_TILE_PORT_STATUS_0_TX_PLL_LOCKED (0x29cd220bUL)
+#define PHY_TILE_PORT_STATUS_0_TX_RESET_ACK_N (0xa5dde8d5UL)
+#define PHY_TILE_PORT_STATUS_1 (0xfa290ad9UL)
+#define PHY_TILE_PORT_STATUS_1_RESET_ACK_N (0x7de45fd4UL)
+#define PHY_TILE_PORT_STATUS_1_RX_AM_LOCK (0x1f6ead02UL)
+#define PHY_TILE_PORT_STATUS_1_RX_HI_BER (0xf30a0ec4UL)
+#define PHY_TILE_PORT_STATUS_1_RX_LOCAL_FAULT (0xf672f1ddUL)
+#define PHY_TILE_PORT_STATUS_1_RX_PCS_FULLY_ALIGNED (0x9db741e3UL)
+#define PHY_TILE_PORT_STATUS_1_RX_REMOTE_FAULT (0x23838d8cUL)
+#define PHY_TILE_PORT_STATUS_1_RX_RESET_ACK_N (0xf37732f2UL)
+#define PHY_TILE_PORT_STATUS_1_SYS_PLL_LOCKED (0xb84c5fcbUL)
+#define PHY_TILE_PORT_STATUS_1_TX_LANES_STABLE (0xfdc07e84UL)
+#define PHY_TILE_PORT_STATUS_1_TX_PLL_LOCKED (0x9036f9e3UL)
+#define PHY_TILE_PORT_STATUS_1_TX_RESET_ACK_N (0xbb57944UL)
+#define PHY_TILE_SCRATCH (0xcd637527UL)
+#define PHY_TILE_SCRATCH_DATA (0x1934d873UL)
+#define PHY_TILE_SYS_PLL (0x65742dccUL)
+#define PHY_TILE_SYS_PLL_DISABLE_REFCLK_MONITOR (0xf740e941UL)
+#define PHY_TILE_SYS_PLL_EN_REFCLK_FGT (0x8f5bac3aUL)
+#define PHY_TILE_SYS_PLL_FORCE_RST (0xa3d1af1fUL)
+#define PHY_TILE_SYS_PLL_FORWARD_RST (0x26a13387UL)
+#define PHY_TILE_SYS_PLL_GET_RDY (0xa2822d9bUL)
+#define PHY_TILE_SYS_PLL_REFCLK_FGT_ENABLED (0x57072ab1UL)
+#define PHY_TILE_SYS_PLL_SET_RDY (0x31139546UL)
+#define PHY_TILE_SYS_PLL_SYSTEMPLL_LOCK (0x467d08f6UL)
+
+#endif	/* _NTHW_FPGA_REG_DEFS_PHY_TILE_ */
+
+/*
+ * Auto-generated file - do *NOT* edit
+ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_prm_nt400dxx.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_prm_nt400dxx.h
new file mode 100644
index 0000000000..7855c9cab5
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_prm_nt400dxx.h
@@ -0,0 +1,26 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+/*
+ * nthw_fpga_reg_defs_prm_nt400dxx.h
+ *
+ * Auto-generated file - do *NOT* edit
+ *
+ */
+
+#ifndef _NTHW_FPGA_REG_DEFS_PRM_NT400DXX_
+#define _NTHW_FPGA_REG_DEFS_PRM_NT400DXX_
+
+/* PRM_NT400DXX */
+#define NTHW_MOD_PRM_NT400DXX (0xfccf12a8UL)
+#define PRM_NT400DXX_RST (0x9c1555f7UL)
+#define PRM_NT400DXX_RST_PERIPH (0xe08c7c1cUL)
+#define PRM_NT400DXX_RST_PLATFORM (0x866ae8d1UL)
+
+#endif	/* _NTHW_FPGA_REG_DEFS_PRM_NT400DXX_ */
+
+/*
+ * Auto-generated file - do *NOT* edit
+ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_rfd.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_rfd.h
new file mode 100644
index 0000000000..18b67f4032
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_rfd.h
@@ -0,0 +1,38 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+/*
+ * nthw_fpga_reg_defs_rfd.h
+ *
+ * Auto-generated file - do *NOT* edit
+ *
+ */
+
+#ifndef _NTHW_FPGA_REG_DEFS_RFD_
+#define _NTHW_FPGA_REG_DEFS_RFD_
+
+/* RFD */
+#define NTHW_MOD_RFD (0x7fa60826UL)
+#define RFD_CTRL (0x5347930aUL)
+#define RFD_CTRL_CFP (0x38fb2beUL)
+#define RFD_CTRL_ISL (0x2dac8d33UL)
+#define RFD_CTRL_PWMCW (0xebb075fcUL)
+#define RFD_MAX_FRAME_SIZE (0x8369a9a2UL)
+#define RFD_MAX_FRAME_SIZE_MAX (0x647c0b15UL)
+#define RFD_TNL_VLAN (0xb85aa35fUL)
+#define RFD_TNL_VLAN_TPID0 (0xe2dfb0a4UL)
+#define RFD_TNL_VLAN_TPID1 (0x95d88032UL)
+#define RFD_VLAN (0xa954e6d1UL)
+#define RFD_VLAN_TPID0 (0xab4dac41UL)
+#define RFD_VLAN_TPID1 (0xdc4a9cd7UL)
+#define RFD_VXLAN (0xe2207aeaUL)
+#define RFD_VXLAN_DP0 (0xb17ca4d9UL)
+#define RFD_VXLAN_DP1 (0xc67b944fUL)
+
+#endif	/* _NTHW_FPGA_REG_DEFS_RFD_ */
+
+/*
+ * Auto-generated file - do *NOT* edit
+ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_rst9574.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_rst9574.h
new file mode 100644
index 0000000000..90aeaec3a4
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_rst9574.h
@@ -0,0 +1,35 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+/*
+ * nthw_fpga_reg_defs_rst9574.h
+ *
+ * Auto-generated file - do *NOT* edit
+ *
+ */
+
+#ifndef _NTHW_FPGA_REG_DEFS_RST9574_
+#define _NTHW_FPGA_REG_DEFS_RST9574_
+
+/* RST9574 */
+#define NTHW_MOD_RST9574 (0xbf22c9ffUL)
+#define RST9574_LATCH (0x3ed1e303UL)
+#define RST9574_LATCH_DDR4_CALIB_COMPLETE (0x3b59afedUL)
+#define RST9574_LATCH_PHY_FTILE_RDY (0x4e701f0fUL)
+#define RST9574_LATCH_PHY_FTILE_RST_DONE (0xd55b1659UL)
+#define RST9574_RST (0x4f1625b6UL)
+#define RST9574_RST_DDR4 (0x152e69ddUL)
+#define RST9574_RST_PHY_FTILE (0x8455e296UL)
+#define RST9574_RST_SYS (0x6a2c0d30UL)
+#define RST9574_STAT (0x160fed08UL)
+#define RST9574_STAT_DDR4_CALIB_COMPLETE (0x768d8717UL)
+#define RST9574_STAT_PHY_FTILE_RDY (0x727ca032UL)
+#define RST9574_STAT_PHY_FTILE_RST_DONE (0xb312b439UL)
+
+#endif	/* _NTHW_FPGA_REG_DEFS_RST9574_ */
+
+/*
+ * Auto-generated file - do *NOT* edit
+ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_spim.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_spim.h
new file mode 100644
index 0000000000..5adeaea1ec
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_spim.h
@@ -0,0 +1,76 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+/*
+ * nthw_fpga_reg_defs_spim.h
+ *
+ * Auto-generated file - do *NOT* edit
+ *
+ */
+
+#ifndef _NTHW_FPGA_REG_DEFS_SPIM_
+#define _NTHW_FPGA_REG_DEFS_SPIM_
+
+/* SPIM */
+#define NTHW_MOD_SPIM (0x1da437bfUL)
+#define SPIM_CFG (0x90b6b0d5UL)
+#define SPIM_CFG_PRE (0x156a8ea9UL)
+#define SPIM_CFG_CLK (0xeb7046a1UL)
+#define SPIM_CFG_CLK_MODE (0x228be0cbUL)
+#define SPIM_CMD (0xea4b38a4UL)
+#define SPIM_CMD_ADDR (0x95fe56baUL)
+#define SPIM_CMD_CMD (0x9c30279bUL)
+#define SPIM_CMD_DATA (0x6a9737ecUL)
+#define SPIM_CONF0 (0x84d4acb5UL)
+#define SPIM_CONF0_BYTE_PACE (0xc9a95016UL)
+#define SPIM_CONF0_MIRROR_EN (0xa710688UL)
+#define SPIM_CONF0_MSB_FIRST (0x5f60c96aUL)
+#define SPIM_CONF0_PRESCAL_CLK (0xadb38a7UL)
+#define SPIM_CONF0_RESTART (0x1fda85dcUL)
+#define SPIM_CONF0_RST (0x64e3b3bUL)
+#define SPIM_CONF0_SYNC_MON_EN (0x591a639eUL)
+#define SPIM_CONF1 (0xf3d39c23UL)
+#define SPIM_CONF1_MIRROR_PACE (0x370f3f34UL)
+#define SPIM_CONF1_MIRROR_SCAN (0x83daffbeUL)
+#define SPIM_CONF1_SYNCTIMEOUT (0x1b5d30cdUL)
+#define SPIM_CONF2 (0x6adacd99UL)
+#define SPIM_CONF2_MIRROR_PRESC (0x3a8c10e2UL)
+#define SPIM_CONF2_OPCODE_RD (0x3eb6084fUL)
+#define SPIM_CONF2_OPCODE_WR (0xb715495bUL)
+#define SPIM_CONF3 (0x1dddfd0fUL)
+#define SPIM_CONF3_MIRROR_RDADR (0xc00ba60fUL)
+#define SPIM_CONF3_MIRROR_WRADR (0x7d99213cUL)
+#define SPIM_CR (0x1c1de013UL)
+#define SPIM_CR_EN (0xf2e0e72fUL)
+#define SPIM_CR_LOOP (0xdeb882aUL)
+#define SPIM_CR_RXRST (0x487f7d1bUL)
+#define SPIM_CR_TXRST (0xc73f88bbUL)
+#define SPIM_DRR (0xd68a95eeUL)
+#define SPIM_DRR_DRR (0x78766633UL)
+#define SPIM_DTR (0x80d03268UL)
+#define SPIM_DTR_DTR (0xf87522a8UL)
+#define SPIM_REPLY (0x6ed04defUL)
+#define SPIM_REPLY_RDDATA (0x40db3b24UL)
+#define SPIM_SR (0x56dff242UL)
+#define SPIM_SR_DONE (0xdb47e9a1UL)
+#define SPIM_SR_RXEMPTY (0x489aaf91UL)
+#define SPIM_SR_RXFULL (0xd26832f5UL)
+#define SPIM_SR_RXLVL (0x4c67ae59UL)
+#define SPIM_SR_TXEMPTY (0x2b4a9aabUL)
+#define SPIM_SR_TXFULL (0x431d1e8UL)
+#define SPIM_SR_TXLVL (0xc3275bf9UL)
+#define SPIM_SRR (0xcfe3201bUL)
+#define SPIM_SRR_RST (0x32dc8fc5UL)
+#define SPIM_STATUS (0xd04220ceUL)
+#define SPIM_STATUS_CMDPENDING (0x74ed833fUL)
+#define SPIM_STATUS_RESERVED (0xa50278bUL)
+#define SPIM_STATUS_RESYNCDETECT (0x5b268881UL)
+#define SPIM_STATUS_RESYNCING (0x5ec3f11UL)
+
+#endif	/* _NTHW_FPGA_REG_DEFS_SPIM_ */
+
+/*
+ * Auto-generated file - do *NOT* edit
+ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_spis.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_spis.h
new file mode 100644
index 0000000000..11785d74b7
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_spis.h
@@ -0,0 +1,51 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+/*
+ * nthw_fpga_reg_defs_spis.h
+ *
+ * Auto-generated file - do *NOT* edit
+ *
+ */
+
+#ifndef _NTHW_FPGA_REG_DEFS_SPIS_
+#define _NTHW_FPGA_REG_DEFS_SPIS_
+
+/* SPIS */
+#define NTHW_MOD_SPIS (0xe7ab0adcUL)
+#define SPIS_CR (0xacdbc0bfUL)
+#define SPIS_CR_DEBUG (0xf2096408UL)
+#define SPIS_CR_EN (0xc50100bcUL)
+#define SPIS_CR_LOOP (0x69e911c9UL)
+#define SPIS_CR_RXRST (0x7118cc40UL)
+#define SPIS_CR_TXRST (0xfe5839e0UL)
+#define SPIS_DRR (0x95abc0dUL)
+#define SPIS_DRR_DRR (0x1c74ffd0UL)
+#define SPIS_DTR (0x5f001b8bUL)
+#define SPIS_DTR_DTR (0x9c77bb4bUL)
+#define SPIS_RAM_CTRL (0x682dc7d8UL)
+#define SPIS_RAM_CTRL_ADR (0x15c2f809UL)
+#define SPIS_RAM_CTRL_CNT (0x5ca61d8UL)
+#define SPIS_RAM_DATA (0xc7fc45c1UL)
+#define SPIS_RAM_DATA_DATA (0x422b05eaUL)
+#define SPIS_SR (0xe619d2eeUL)
+#define SPIS_SR_DONE (0xbf457042UL)
+#define SPIS_SR_FRAME_ERR (0x31b5d7e4UL)
+#define SPIS_SR_READ_ERR (0xa83d91f1UL)
+#define SPIS_SR_RXEMPTY (0xadb39173UL)
+#define SPIS_SR_RXFULL (0x2ee8dd38UL)
+#define SPIS_SR_RXLVL (0x75001f02UL)
+#define SPIS_SR_TXEMPTY (0xce63a449UL)
+#define SPIS_SR_TXFULL (0xf8b13e25UL)
+#define SPIS_SR_TXLVL (0xfa40eaa2UL)
+#define SPIS_SR_WRITE_ERR (0x9d389ce2UL)
+#define SPIS_SRR (0x103309f8UL)
+#define SPIS_SRR_RST (0x56de1626UL)
+
+#endif	/* _NTHW_FPGA_REG_DEFS_SPIS_ */
+
+/*
+ * Auto-generated file - do *NOT* edit
+ */
diff --git a/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_tint.h b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_tint.h
new file mode 100644
index 0000000000..acfc07a1b6
--- /dev/null
+++ b/drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_tint.h
@@ -0,0 +1,28 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+/*
+ * nthw_fpga_reg_defs_tint.h
+ *
+ * Auto-generated file - do *NOT* edit
+ *
+ */
+
+#ifndef _NTHW_FPGA_REG_DEFS_TINT_
+#define _NTHW_FPGA_REG_DEFS_TINT_
+
+/* TINT */
+#define NTHW_MOD_TINT (0xb8aea9feUL)
+#define TINT_CTRL (0x95bdc9c3UL)
+#define TINT_CTRL_INTERVAL (0xfe472b70UL)
+#define TINT_STATUS (0x2557d8a6UL)
+#define TINT_STATUS_DELAYED (0xabd2ff4cUL)
+#define TINT_STATUS_SKIPPED (0x1c35b879UL)
+
+#endif	/* _NTHW_FPGA_REG_DEFS_TINT_ */
+
+/*
+ * Auto-generated file - do *NOT* edit
+ */
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 16/32] net/ntnic: add setup for fpga reset
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (14 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 15/32] net/ntnic: add FPGA modules and registers Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 17/32] net/ntnic: add default reset setting for NT400D13 Serhii Iliushyk
                   ` (16 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen

Initialize FPGA reset module and register fields.

Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
 .../core/nt400dxx/reset/nthw_fpga_rst9574.c   | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
index 9ab26583df..bd38d6b8c8 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
@@ -14,6 +14,60 @@ static int nthw_fpga_rst9574_setup(nthw_fpga_t *p_fpga, struct nthw_fpga_rst_nt4
 	assert(p_fpga);
 	assert(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;
+
+	p->n_fpga_product_id = n_fpga_product_id;
+	p->n_fpga_version = n_fpga_version;
+	p->n_fpga_revision = n_fpga_revision;
+
+	NT_LOG(DBG, NTHW, "%s: %s: FPGA reset setup: FPGA %04d-%02d-%02d", p_adapter_id_str,
+		__func__, n_fpga_product_id, n_fpga_version, n_fpga_revision);
+
+	p_mod_rst = nthw_fpga_query_module(p_fpga, MOD_RST9574, 0);
+
+	if (p_mod_rst == NULL) {
+		NT_LOG(ERR, NTHW, "%s: RST %d: no such instance", p_adapter_id_str, 0);
+		return -1;
+	}
+
+	p_mod_rst = nthw_fpga_query_module(p_fpga, MOD_RST9574, 0);
+
+	if (p_mod_rst == NULL) {
+		NT_LOG(ERR, NTHW, "%s: RST %d: no such instance", p_adapter_id_str, 0);
+		return -1;
+	}
+
+	/* RST register field pointers */
+	p_curr_reg = nthw_module_get_register(p_mod_rst, RST9574_RST);
+	p->p_fld_rst_sys = nthw_register_get_field(p_curr_reg, RST9574_RST_SYS);
+	p->p_fld_rst_ddr4 = nthw_register_get_field(p_curr_reg, RST9574_RST_DDR4);
+	p->p_fld_rst_phy_ftile = nthw_register_get_field(p_curr_reg, RST9574_RST_PHY_FTILE);
+	nthw_register_update(p_curr_reg);
+
+	p_curr_reg = nthw_module_get_register(p_mod_rst, RST9574_STAT);
+	p->p_fld_stat_ddr4_calib_complete =
+		nthw_register_get_field(p_curr_reg, RST9574_STAT_DDR4_CALIB_COMPLETE);
+	p->p_fld_stat_phy_ftile_rst_done =
+		nthw_register_get_field(p_curr_reg, RST9574_STAT_PHY_FTILE_RST_DONE);
+	p->p_fld_stat_phy_ftile_rdy =
+		nthw_register_get_field(p_curr_reg, RST9574_STAT_PHY_FTILE_RDY);
+	nthw_register_update(p_curr_reg);
+
+	p_curr_reg = nthw_module_get_register(p_mod_rst, RST9574_LATCH);
+	p->p_fld_latch_ddr4_calib_complete =
+		nthw_register_get_field(p_curr_reg, RST9574_LATCH_DDR4_CALIB_COMPLETE);
+	p->p_fld_latch_phy_ftile_rst_done =
+		nthw_register_get_field(p_curr_reg, RST9574_LATCH_PHY_FTILE_RST_DONE);
+	p->p_fld_latch_phy_ftile_rdy =
+		nthw_register_get_field(p_curr_reg, RST9574_LATCH_PHY_FTILE_RDY);
+	nthw_register_update(p_curr_reg);
+
 	return 0;
 };
 
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 17/32] net/ntnic: add default reset setting for NT400D13
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (15 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 16/32] net/ntnic: add setup for fpga reset Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 18/32] net/ntnic: add DDR calibration to reset stage Serhii Iliushyk
                   ` (15 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen

Add DDR4 reset and calibration completion handling.

Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
 .../core/nt400dxx/reset/nthw_fpga_rst9574.c   | 29 ++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
index bd38d6b8c8..757ec1b4c6 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
@@ -71,14 +71,41 @@ static int nthw_fpga_rst9574_setup(nthw_fpga_t *p_fpga, struct nthw_fpga_rst_nt4
 	return 0;
 };
 
+static void nthw_fpga_rst9574_set_default_rst_values(struct nthw_fpga_rst_nt400dxx *const p)
+{
+	nthw_field_update_register(p->p_fld_rst_sys);
+	nthw_field_set_all(p->p_fld_rst_sys);
+	nthw_field_set_val32(p->p_fld_rst_ddr4, 1);
+	nthw_field_set_val_flush32(p->p_fld_rst_phy_ftile, 1);
+}
+
+static int nthw_fpga_rst9574_product_reset(struct fpga_info_s *p_fpga_info,
+	struct nthw_fpga_rst_nt400dxx *p_rst)
+{
+	assert(p_fpga_info);
+	assert(p_rst);
 
+	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+
+	/* (0) Reset all domains / modules except peripherals: */
+	NT_LOG(DBG, NTHW, "%s: %s: RST defaults", p_adapter_id_str, __func__);
+	nthw_fpga_rst9574_set_default_rst_values(p_rst);
+
+	/*
+	 * Wait a while before waiting for deasserting ddr4 reset
+	 */
+	nt_os_wait_usec(2000);
+
+
+	return 0;
+}
 
 static int nthw_fpga_rst9574_init(struct fpga_info_s *p_fpga_info,
 	struct nthw_fpga_rst_nt400dxx *p_rst)
 {
 	assert(p_fpga_info);
 	assert(p_rst);
-	int res = -1;
+	int res = nthw_fpga_rst9574_product_reset(p_fpga_info, p_rst);
 
 	return res;
 }
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 18/32] net/ntnic: add DDR calibration to reset stage
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (16 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 17/32] net/ntnic: add default reset setting for NT400D13 Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 19/32] net/ntnic: add PHY ftile reset Serhii Iliushyk
                   ` (14 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen

Add DDR4 reset and calibration functions for FPGA.

Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
 .../core/nt400dxx/reset/nthw_fpga_rst9574.c   | 95 +++++++++++++++++++
 1 file changed, 95 insertions(+)

diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
index 757ec1b4c6..27d60d1448 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
@@ -79,6 +79,72 @@ static void nthw_fpga_rst9574_set_default_rst_values(struct nthw_fpga_rst_nt400d
 	nthw_field_set_val_flush32(p->p_fld_rst_phy_ftile, 1);
 }
 
+static void nthw_fpga_rst9574_ddr4_rst(struct nthw_fpga_rst_nt400dxx *const p, uint32_t val)
+{
+	nthw_field_update_register(p->p_fld_rst_ddr4);
+	nthw_field_set_val_flush32(p->p_fld_rst_ddr4, val);
+}
+
+static bool nthw_fpga_rst9574_get_ddr4_calib_complete_stat(struct nthw_fpga_rst_nt400dxx *const p)
+{
+	return nthw_field_get_updated(p->p_fld_stat_ddr4_calib_complete) != 0;
+}
+
+static bool nthw_fpga_rst9574_get_ddr4_calib_complete_latch(struct nthw_fpga_rst_nt400dxx *const p)
+{
+	return nthw_field_get_updated(p->p_fld_latch_ddr4_calib_complete) != 0;
+}
+
+static void nthw_fpga_rst9574_set_ddr4_calib_complete_latch(struct nthw_fpga_rst_nt400dxx *const p,
+	uint32_t val)
+{
+	nthw_field_update_register(p->p_fld_latch_ddr4_calib_complete);
+	nthw_field_set_val_flush32(p->p_fld_latch_ddr4_calib_complete, val);
+}
+
+static int nthw_fpga_rst9574_wait_ddr4_calibration_complete(struct fpga_info_s *p_fpga_info,
+	struct nthw_fpga_rst_nt400dxx *p_rst)
+{
+	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+	uint32_t complete;
+	uint32_t retrycount;
+	uint32_t timeout;
+
+	/* 3: wait until DDR4 CALIB COMPLETE */
+	NT_LOG(DBG, NTHW, "%s: %s: DDR4 CALIB COMPLETE wait complete", p_adapter_id_str, __func__);
+	/*
+	 * 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
+	 */
+	retrycount = 1;
+	timeout = 50000;/* initial timeout must be set to 5 sec. */
+
+	do {
+		complete = nthw_fpga_rst9574_get_ddr4_calib_complete_stat(p_rst);
+
+		if (!complete)
+			nt_os_wait_usec(100);
+
+		timeout--;
+
+		if (timeout == 0) {
+			if (retrycount == 0) {
+				NT_LOG(ERR, NTHW,
+					"%s: %s: Timeout waiting for DDR4 CALIB COMPLETE to be complete",
+					p_adapter_id_str, __func__);
+				return -1;
+			}
+
+			nthw_fpga_rst9574_ddr4_rst(p_rst, 1);	/* Reset DDR4 */
+			nthw_fpga_rst9574_ddr4_rst(p_rst, 0);
+			retrycount--;
+			timeout = 90000;/* Increase timeout for second attempt to 8 sec. */
+		}
+	} while (!complete);
+
+	return 0;
+}
+
 static int nthw_fpga_rst9574_product_reset(struct fpga_info_s *p_fpga_info,
 	struct nthw_fpga_rst_nt400dxx *p_rst)
 {
@@ -86,6 +152,7 @@ static int nthw_fpga_rst9574_product_reset(struct fpga_info_s *p_fpga_info,
 	assert(p_rst);
 
 	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+	int res = -1;
 
 	/* (0) Reset all domains / modules except peripherals: */
 	NT_LOG(DBG, NTHW, "%s: %s: RST defaults", p_adapter_id_str, __func__);
@@ -96,6 +163,34 @@ static int nthw_fpga_rst9574_product_reset(struct fpga_info_s *p_fpga_info,
 	 */
 	nt_os_wait_usec(2000);
 
+	/* (1) De-assert DDR4 reset: */
+	NT_LOG(DBG, NTHW, "%s: %s: De-asserting DDR4 reset", p_adapter_id_str, __func__);
+	nthw_fpga_rst9574_ddr4_rst(p_rst, 0);
+
+	/*
+	 * Wait a while before waiting for calibration complete, since calibration complete
+	 * is true while ddr4 is in reset
+	 */
+	nt_os_wait_usec(2000);
+
+	/* (2) Wait until DDR4 calibration complete */
+	res = nthw_fpga_rst9574_wait_ddr4_calibration_complete(p_fpga_info, p_rst);
+
+	if (res)
+		return res;
+
+	/* (3) Set DDR4 calib complete latched bits: */
+	nthw_fpga_rst9574_set_ddr4_calib_complete_latch(p_rst, 1);
+
+	/* Wait for phy to settle.*/
+	nt_os_wait_usec(20000);
+
+	/* (4) Ensure all latched status bits are still set: */
+	if (!nthw_fpga_rst9574_get_ddr4_calib_complete_latch(p_rst)) {
+		NT_LOG(ERR, NTHW, "%s: %s: DDR4 calibration complete has toggled",
+			p_adapter_id_str, __func__);
+	}
+
 
 	return 0;
 }
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 19/32] net/ntnic: add PHY ftile reset
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (17 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 18/32] net/ntnic: add DDR calibration to reset stage Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 20/32] net/ntnic: add clock init Serhii Iliushyk
                   ` (13 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen

Add reset functions and reset procedure for module PHY FTILE

Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
 .../ntnic/nthw/core/include/nthw_phy_tile.h   |  12 ++
 .../core/nt400dxx/reset/nthw_fpga_rst9574.c   | 161 ++++++++++++++++++
 drivers/net/ntnic/nthw/core/nthw_phy_tile.c   |  38 +++++
 3 files changed, 211 insertions(+)

diff --git a/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
index f84aef44a9..68d8455b8d 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
@@ -8,6 +8,10 @@
 
 #include "nthw_fpga_model.h"
 
+enum mac_pcs_mode_e {
+	MAC_PCS_MODE_2X100
+};
+
 struct nt_phy_tile {
 	nthw_fpga_t *mp_fpga;
 
@@ -16,6 +20,8 @@ struct nt_phy_tile {
 	int mn_fpga_version;
 	int mn_fpga_revision;
 
+	enum mac_pcs_mode_e mac_pcs_mode;
+
 	nthw_register_t *mp_reg_port_xcvr_base[2][4];
 	nthw_field_t *mp_fld_port_xcvr_base_ptr[2][4];
 	nthw_field_t *mp_fld_port_xcvr_base_busy[2][4];
@@ -39,6 +45,8 @@ struct nt_phy_tile {
 
 	nthw_field_t *mp_fld_port_status_rx_hi_ber[2];
 	nthw_field_t *mp_fld_port_status_rx_am_lock[2];
+	nthw_field_t *mp_fld_port_status_reset_ackn[2];
+	nthw_field_t *mp_fld_port_status_tx_lanes_stable[2];
 	nthw_field_t *mp_fld_port_status_tx_reset_ackn[2];
 	nthw_field_t *mp_fld_port_status_rx_reset_ackn[2];
 
@@ -93,5 +101,9 @@ uint32_t nthw_phy_tile_read_xcvr(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t la
 	uint32_t address);
 void nthw_phy_tile_write_xcvr(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane, uint32_t address,
 	uint32_t data);
+uint32_t nthw_phy_tile_get_port_status_reset_ack(nthw_phy_tile_t *p, uint8_t intf_no);
+uint32_t nthw_phy_tile_get_port_status_tx_lanes_stable(nthw_phy_tile_t *p, uint8_t intf_no);
+uint8_t nthw_phy_tile_get_no_intfs(nthw_phy_tile_t *p);
+void nthw_phy_tile_set_port_config_rst(nthw_phy_tile_t *p, uint8_t intf_no, uint32_t value);
 
 #endif	/* __NTHW_PHY_TILE_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
index 27d60d1448..b1bbe28709 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
@@ -79,17 +79,44 @@ static void nthw_fpga_rst9574_set_default_rst_values(struct nthw_fpga_rst_nt400d
 	nthw_field_set_val_flush32(p->p_fld_rst_phy_ftile, 1);
 }
 
+static void nthw_fpga_rst9574_sys_rst(struct nthw_fpga_rst_nt400dxx *const p, uint32_t val)
+{
+	nthw_field_update_register(p->p_fld_rst_sys);
+	nthw_field_set_val_flush32(p->p_fld_rst_sys, val);
+}
+
 static void nthw_fpga_rst9574_ddr4_rst(struct nthw_fpga_rst_nt400dxx *const p, uint32_t val)
 {
 	nthw_field_update_register(p->p_fld_rst_ddr4);
 	nthw_field_set_val_flush32(p->p_fld_rst_ddr4, val);
 }
 
+static void nthw_fpga_rst9574_phy_ftile_rst(struct nthw_fpga_rst_nt400dxx *const p, uint32_t val)
+{
+	nthw_field_update_register(p->p_fld_rst_phy_ftile);
+	nthw_field_set_val_flush32(p->p_fld_rst_phy_ftile, val);
+}
+
+static bool nthw_fpga_rst9574_get_phy_ftile_rst(struct nthw_fpga_rst_nt400dxx *const p)
+{
+	return nthw_field_get_updated(p->p_fld_rst_phy_ftile) != 0;
+}
+
 static bool nthw_fpga_rst9574_get_ddr4_calib_complete_stat(struct nthw_fpga_rst_nt400dxx *const p)
 {
 	return nthw_field_get_updated(p->p_fld_stat_ddr4_calib_complete) != 0;
 }
 
+static bool nthw_fpga_rst9574_get_phy_ftile_rst_done_stat(struct nthw_fpga_rst_nt400dxx *const p)
+{
+	return nthw_field_get_updated(p->p_fld_stat_phy_ftile_rst_done) != 0;
+}
+
+static bool nthw_fpga_rst9574_get_phy_ftile_rdy_stat(struct nthw_fpga_rst_nt400dxx *const p)
+{
+	return nthw_field_get_updated(p->p_fld_stat_phy_ftile_rdy) != 0;
+}
+
 static bool nthw_fpga_rst9574_get_ddr4_calib_complete_latch(struct nthw_fpga_rst_nt400dxx *const p)
 {
 	return nthw_field_get_updated(p->p_fld_latch_ddr4_calib_complete) != 0;
@@ -145,6 +172,69 @@ static int nthw_fpga_rst9574_wait_ddr4_calibration_complete(struct fpga_info_s *
 	return 0;
 }
 
+static int nthw_fpga_rst9574_wait_phy_ftile_rdy(struct fpga_info_s *p_fpga_info,
+	struct nthw_fpga_rst_nt400dxx *p_rst)
+{
+	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+	uint32_t complete;
+	uint32_t timeout;
+
+	/* 5: wait until PHY_FTILE reset done */
+	NT_LOG(DBG, NTHW, "%s: %s: PHY FTILE ready", p_adapter_id_str, __func__);
+	timeout = 50000;/* initial timeout must be set to 5 sec. */
+
+	do {
+		complete = nthw_fpga_rst9574_get_phy_ftile_rdy_stat(p_rst);
+
+		if (!complete) {
+			nt_os_wait_usec(100);
+
+		} else {
+			NT_LOG(DBG, NTHW, "%s: PHY FTILE ready, margin to timeout %u",
+				p_adapter_id_str, timeout);
+		}
+
+		timeout--;
+
+		if (timeout == 0) {
+			NT_LOG(ERR, NTHW, "%s: %s: Timeout waiting for PHY FTILE ready",
+				p_adapter_id_str, __func__);
+			return -1;
+		}
+	} while (!complete);
+
+	return 0;
+}
+
+static int nthw_fpga_rst9574_wait_phy_ftile_rst_done(struct fpga_info_s *p_fpga_info,
+	struct nthw_fpga_rst_nt400dxx *p_rst)
+{
+	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+	uint32_t complete;
+	uint32_t timeout;
+
+	/* 5: wait until PHY_FTILE reset done */
+	NT_LOG(DBG, NTHW, "%s: %s: PHY FTILE RESET done", p_adapter_id_str, __func__);
+	timeout = 50000;/* initial timeout must be set to 5 sec. */
+
+	do {
+		complete = nthw_fpga_rst9574_get_phy_ftile_rst_done_stat(p_rst);
+
+		if (!complete)
+			nt_os_wait_usec(100);
+
+		timeout--;
+
+		if (timeout == 0) {
+			NT_LOG(ERR, NTHW, "%s: %s: Timeout waiting for PHY FTILE RESET to be done",
+				p_adapter_id_str, __func__);
+			return -1;
+		}
+	} while (!complete);
+
+	return 0;
+}
+
 static int nthw_fpga_rst9574_product_reset(struct fpga_info_s *p_fpga_info,
 	struct nthw_fpga_rst_nt400dxx *p_rst)
 {
@@ -191,6 +281,77 @@ static int nthw_fpga_rst9574_product_reset(struct fpga_info_s *p_fpga_info,
 			p_adapter_id_str, __func__);
 	}
 
+	int32_t tries = 0;
+	bool success = false;
+
+	do {
+		/* Only wait for ftile rst done if ftile is indeed in reset. */
+		if (nthw_fpga_rst9574_get_phy_ftile_rst(p_rst)) {
+			/* (5) Wait until PHY_FTILE reset done */
+			NT_LOG(DBG, NTHW, "%s: %s: Wait until PHY_FTILE reset done",
+				p_adapter_id_str, __func__);
+			res = nthw_fpga_rst9574_wait_phy_ftile_rst_done(p_fpga_info, p_rst);
+
+			if (res)
+				return res;
+		}
+
+		/* (6) De-assert PHY_FTILE reset: */
+		NT_LOG(DBG, NTHW, "%s: %s: De-asserting PHY_FTILE reset", p_adapter_id_str,
+			__func__);
+		nthw_fpga_rst9574_phy_ftile_rst(p_rst, 0);
+
+		nt_os_wait_usec(10000);
+		/* (7) Wait until PHY_FTILE ready */
+		if (nthw_fpga_rst9574_wait_phy_ftile_rdy(p_fpga_info, p_rst) != -1) {
+			success = true;
+			continue;
+		}
+
+		if (++tries >= 5) {
+			/* Give up */
+			NT_LOG(ERR, NTHW, "%s: %s: PHY_TILE not ready after %u attempts",
+				p_adapter_id_str, __func__, tries);
+			return res;
+		}
+
+		/* Try to recover with as little effort as possible */
+		nthw_phy_tile_t *p_phy_tile = p_fpga_info->mp_nthw_agx.p_phy_tile;
+
+		for (uint8_t i = 0; i < nthw_phy_tile_get_no_intfs(p_phy_tile); i++) {
+			/* Also consider TX_PLL_LOCKED == 0 */
+			if (!nthw_phy_tile_get_port_status_tx_lanes_stable(p_phy_tile, i)) {
+				success = false;
+				NT_LOG(WRN, NTHW,
+					"%s: %s: PHY_TILE Intf %u TX_LANES_STABLE == FALSE",
+					p_adapter_id_str, __func__, i);
+
+				/* Active low */
+				nthw_phy_tile_set_port_config_rst(p_phy_tile, i, 0);
+				int32_t count = 1000;
+
+				do {
+					nt_os_wait_usec(1000);
+				} while (!nthw_phy_tile_get_port_status_reset_ack(p_phy_tile, i) &&
+					(--count > 0));
+
+				if (count <= 0) {
+					NT_LOG(ERR, NTHW, "%s: %s: IntfNo %u: "
+					"Time-out waiting for PortStatusResetAck",
+					p_adapter_id_str, __func__, i);
+				}
+
+				/* Active low */
+				nthw_phy_tile_set_port_config_rst(p_phy_tile, i, 1);
+				nt_os_wait_usec(20000);
+			}
+		}
+
+	} while (!success);
+
+	/* (8) De-assert SYS reset: */
+	NT_LOG(DBG, NTHW, "%s: %s: De-asserting SYS reset", p_adapter_id_str, __func__);
+	nthw_fpga_rst9574_sys_rst(p_rst, 0);
 
 	return 0;
 }
diff --git a/drivers/net/ntnic/nthw/core/nthw_phy_tile.c b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
index b057e9e88c..a8c2d03be9 100644
--- a/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
+++ b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
@@ -44,6 +44,17 @@ static const uint32_t eth_soft_csr1 = 0x200;
 static const uint32_t eth_soft_csr2 = 0x204;
 static const uint32_t eth_soft_csr3 = 0x208;
 
+uint8_t nthw_phy_tile_get_no_intfs(nthw_phy_tile_t *p)
+{
+	switch (p->mac_pcs_mode) {
+	case MAC_PCS_MODE_2X100:
+		return 2;
+
+	default:
+		return 0;
+	}
+}
+
 static void nthw_phy_tile_set_reset(nthw_phy_tile_t *p, uint8_t intf_no, bool reset)
 {
 	/* Reset is active low */
@@ -543,3 +554,30 @@ bool nthw_phy_tile_configure_fec(nthw_phy_tile_t *p, uint8_t intf_no, bool enabl
 
 	return true;
 }
+
+uint32_t nthw_phy_tile_get_port_status_reset_ack(nthw_phy_tile_t *p, uint8_t intf_no)
+{
+	if (p->mp_fld_port_status_reset_ackn[intf_no]) {
+		return nthw_field_get_updated(p->mp_fld_port_status_reset_ackn[intf_no]) == 0
+			? 1
+			: 0;    /* Inverted */
+	}
+
+	return 1;
+}
+
+uint32_t nthw_phy_tile_get_port_status_tx_lanes_stable(nthw_phy_tile_t *p, uint8_t intf_no)
+{
+	if (p->mp_fld_port_status_tx_lanes_stable[intf_no])
+		return nthw_field_get_updated(p->mp_fld_port_status_tx_lanes_stable[intf_no]);
+
+	return 1;
+}
+
+void nthw_phy_tile_set_port_config_rst(nthw_phy_tile_t *p, uint8_t intf_no, uint32_t value)
+{
+	if (p->mp_fld_port_config_reset[intf_no]) {
+		nthw_field_get_updated(p->mp_fld_port_config_reset[intf_no]);
+		nthw_field_set_val_flush32(p->mp_fld_port_config_reset[intf_no], value);
+	}
+}
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 20/32] net/ntnic: add clock init
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (18 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 19/32] net/ntnic: add PHY ftile reset Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 21/32] net/ntnic: add nt400d13 pcm init Serhii Iliushyk
                   ` (12 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen

Add initialization for the clock subsystem

Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
 ...00D13_U62_Si5332-GM2-RevD-1_V5-Registers.h | 425 ++++++++++++++++++
 .../net/ntnic/nthw/core/include/nthw_i2cm.h   |   1 +
 .../nthw/core/include/nthw_pcm_nt400dxx.h     |  14 +
 .../nthw/core/include/nthw_si5332_si5156.h    |  36 ++
 .../nthw/core/nt400dxx/nthw_fpga_nt400dxx.c   | 115 ++++-
 drivers/net/ntnic/nthw/core/nthw_i2cm.c       |  57 +++
 .../net/ntnic/nthw/core/nthw_si5332_si5156.c  |  93 ++++
 drivers/net/ntnic/nthw/nthw_drv.h             |   7 +-
 8 files changed, 745 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/ntnic/nthw/core/include/NT400D13_U62_Si5332-GM2-RevD-1_V5-Registers.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h

diff --git a/drivers/net/ntnic/nthw/core/include/NT400D13_U62_Si5332-GM2-RevD-1_V5-Registers.h b/drivers/net/ntnic/nthw/core/include/NT400D13_U62_Si5332-GM2-RevD-1_V5-Registers.h
new file mode 100644
index 0000000000..f87828fcfe
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/include/NT400D13_U62_Si5332-GM2-RevD-1_V5-Registers.h
@@ -0,0 +1,425 @@
+/*
+ * Si5332-GM2 Rev D Configuration Register Export Header File
+ *
+ * This file represents a series of Skyworks Si5332-GM2 Rev D
+ * register writes that can be performed to load a single configuration
+ * on a device. It was created by a Skyworks ClockBuilder Pro
+ * export tool.
+ *
+ * Part:		                                       Si5332-GM2 Rev D
+ * Design ID:                                          1
+ * Includes Pre/Post Download Control Register Writes: Yes
+ * Created By:                                         ClockBuilder Pro v4.5 [2022-08-23]
+ * Timestamp:                                          2022-10-11 15:44:24 GMT+02:00
+ *
+ * A complete design report corresponding to this export is included at the end
+ * of this header file.
+ *
+ */
+
+#ifndef SI5332_GM2_REVD_REG_CONFIG_HEADER
+#define SI5332_GM2_REVD_REG_CONFIG_HEADER
+
+#define SI5332_GM2_REVD_REG_CONFIG_NUM_REGS 76
+
+typedef struct {
+	unsigned int address;	/* 8-bit register address */
+	unsigned char value;	/* 8-bit register data */
+
+} si5332_gm2_revd_register_t;
+
+si5332_gm2_revd_register_t const si5332_gm2_revd_registers[SI5332_GM2_REVD_REG_CONFIG_NUM_REGS] = {
+	/* Start configuration preamble */
+	/*    Set device in Ready mode */
+	{ 0x0006, 0x01 },
+	/* End configuration preamble */
+
+	/* Start configuration registers */
+	{ 0x0017, 0x31 },
+	{ 0x0018, 0x00 },
+	{ 0x0019, 0x00 },
+	{ 0x001A, 0x00 },
+	{ 0x001B, 0x00 },
+	{ 0x001C, 0x00 },
+	{ 0x0021, 0x6A },
+	{ 0x0024, 0x01 },
+	{ 0x0025, 0x00 },
+	{ 0x0026, 0x00 },
+	{ 0x0027, 0x50 },
+	{ 0x0028, 0x50 },
+	{ 0x0029, 0x00 },
+	{ 0x002A, 0x00 },
+	{ 0x002B, 0x10 },
+	{ 0x0036, 0x07 },
+	{ 0x0037, 0x80 },
+	{ 0x0038, 0x02 },
+	{ 0x0039, 0x80 },
+	{ 0x003A, 0x05 },
+	{ 0x003B, 0x35 },
+	{ 0x003C, 0x00 },
+	{ 0x0048, 0x00 },
+	{ 0x0054, 0x00 },
+	{ 0x0060, 0x00 },
+	{ 0x0067, 0x19 },
+	{ 0x0068, 0x00 },
+	{ 0x0069, 0x00 },
+	{ 0x006A, 0x00 },
+	{ 0x006B, 0x00 },
+	{ 0x006C, 0x01 },
+	{ 0x0073, 0x00 },
+	{ 0x0074, 0x00 },
+	{ 0x0075, 0x01 },
+	{ 0x007A, 0x07 },
+	{ 0x007B, 0x01 },
+	{ 0x007C, 0x00 },
+	{ 0x007D, 0x00 },
+	{ 0x007F, 0x07 },
+	{ 0x0080, 0x01 },
+	{ 0x0081, 0x00 },
+	{ 0x0082, 0x00 },
+	{ 0x0089, 0x07 },
+	{ 0x008A, 0x01 },
+	{ 0x008B, 0x00 },
+	{ 0x008C, 0x00 },
+	{ 0x008E, 0x07 },
+	{ 0x008F, 0x01 },
+	{ 0x0090, 0x00 },
+	{ 0x0091, 0x00 },
+	{ 0x0098, 0x07 },
+	{ 0x0099, 0x01 },
+	{ 0x009A, 0x00 },
+	{ 0x009B, 0x00 },
+	{ 0x009D, 0x07 },
+	{ 0x009E, 0x01 },
+	{ 0x009F, 0x00 },
+	{ 0x00A0, 0x00 },
+	{ 0x00A7, 0x07 },
+	{ 0x00A8, 0x01 },
+	{ 0x00A9, 0x00 },
+	{ 0x00AA, 0x00 },
+	{ 0x00AC, 0x07 },
+	{ 0x00AD, 0x01 },
+	{ 0x00AE, 0x00 },
+	{ 0x00AF, 0x00 },
+	{ 0x00B6, 0xDB },
+	{ 0x00B7, 0x06 },
+	{ 0x00B9, 0x06 },
+	{ 0x00BA, 0x5E },
+	{ 0x00BB, 0x00 },
+	{ 0x00BC, 0x00 },
+	{ 0x00BD, 0x00 },
+	{ 0x00BE, 0x20 },
+	/* End configuration registers */
+
+	/* Start configuration postamble */
+	/*    Set device in Active mode */
+	{ 0x0006, 0x02 },
+	/* End configuration postamble */
+};
+
+/*
+ * Design Report
+ *
+ * Overview
+ * ========
+ * Part:               Si5332EFL Rev D
+ * Project File:       P:\Hardware\NT
+ * Adapters\NT400D13\design\Clock_syn_design\Si5332-GM2-RevD-1-Project_V5.slabtimeproj Design ID: 1
+ * Created By:         ClockBuilder Pro v4.5 [2022-08-23]
+ * Timestamp:          2022-10-11 15:44:24 GMT+02:00
+ *
+ * Design Rule Check
+ * =================
+ * Errors:
+ * - No errors
+ *
+ * Warnings:
+ * - OUT1 [156.25 MHz] and OUT2 [166.625 MHz] may have coupling [1]
+ * - OUT5 [166.625 MHz] and OUT6 [156.25 MHz] may have coupling [1]
+ *
+ * Footnotes:
+ * [1] To avoid coupling in outputs, Skyworks recommends the following:
+ *
+ * - Avoid adjacent frequency values that are close. CBPro uses an output's integration bandwidth
+ *   (IBW) to determine whether two adjacent frequencies are too close. An IBW of 20 MHz is used
+ *   for frequencies 80 MHz and larger. Lower frequencies will use IBW of OUT/4. CBPro will flag
+ *   fundamental coupling and coupling up to the fourth harmonic, where coupling
+ *   frequency = Absolute(OUTa*x - OUTb*y) for all combinations of x and y 1 through 4. If any one
+ *   of these values is less than or equal to the IBW, the output is flagged as having possible
+ *   coupling.
+ * - Adjacent frequency values that are integer multiples of one another are okay and these
+ *   outputs should be grouped accordingly.
+ * - Unused outputs can be used to separate clock outputs that might otherwise interfere
+ *   with one another.
+ *
+ * Skyworks recommends you validate your design's jitter performance using an Evaluation Board.
+ * You can request a custom phase noise report for your design from CBPro's design dashboard.
+ *
+ * Device Grade
+ * ============
+ * Maximum Output Frequency: 166.625 MHz
+ * Frequency Synthesis Mode: Fractional
+ * Frequency Plan Grade:     F
+ * Minimum Base OPN:         Si5332F*
+ *
+ * Base       Output Clock         Supported Frequency Synthesis Modes
+ * OPN Grade  Frequency Range      (Typical Jitter)
+ * ---------  ------------------  --------------------------------------------
+ * Si5332E    5 MHz to 334 MHz    Integer (~230 fs) and fractional (~500 fs)
+ * Si5332F*   5 MHz to 200 MHz    "
+ * Si5332G    5 MHz to 334 MHz    Integer only (~230 fs)
+ * Si5332H    5 MHz to 200 MHz    "
+ * Si5332L*   5 MHz to 334 MHz    Integer (~230 fs) and fractional (~500 fs)
+ *
+ * * Based on your calculated frequency plan, a Si5332F grade device is
+ * sufficient for your design. For more in-system configuration flexibility
+ * (higher frequencies and/or to enable fractional synthesis), consider
+ * selecting device grade Si5332E when specifying an ordering part number (OPN)
+ * for your application. See the datasheet Ordering Guide for more information.
+ *
+ * Design
+ * ======
+ * Base I2C Address: 0x6A
+ *
+ * Universal Hardware Input Pins:
+ *    INPUT1 (P10): None
+ *    INPUT2 (P19): None
+ *    INPUT3 (P20): None
+ *    INPUT4 (P31): None
+ *    INPUT5 (P32): None
+ *    INPUT6 (P36): None
+ *    INPUT7 (P37): None
+ *
+ * Inputs:
+ *    XAXB: 50 MHz
+ *          Crystal Mode
+ *  CLKIN2: Unused
+ *  CLKIN3: Unused
+ *
+ * Outputs:
+ *    OUT0: 156.25 MHz LVDS Fast 1.8 V, Disabled-State: Stop Low
+ *          Power-up state: Enabled
+ *    OUT1: 156.25 MHz LVDS Fast 1.8 V, Disabled-State: Stop Low
+ *          Power-up state: Enabled
+ *    OUT2: 166.625 MHz LVDS Fast 1.8 V, Disabled-State: Stop Low
+ *          Power-up state: Enabled
+ *    OUT3: 166.625 MHz LVDS Fast 1.8 V, Disabled-State: Stop Low
+ *          Power-up state: Enabled
+ *    OUT4: 166.625 MHz LVDS Fast 1.8 V, Disabled-State: Stop Low
+ *          Power-up state: Enabled
+ *    OUT5: 166.625 MHz LVDS Fast 1.8 V, Disabled-State: Stop Low
+ *          Power-up state: Enabled
+ *    OUT6: 156.25 MHz LVDS Fast 1.8 V, Disabled-State: Stop Low
+ *          Power-up state: Enabled
+ *    OUT7: 156.25 MHz LVDS Fast 1.8 V, Disabled-State: Stop Low
+ *          Power-up state: Enabled
+ *
+ * Frequency Plan
+ * ==============
+ * Fpfd = 50 MHz
+ * Fvco = 2.5 GHz
+ *
+ * P divider = 1
+ * M = 50
+ * N dividers:
+ *    N0:
+ *       Value: 15.0037509377344336... [ 15 + 5/1333 ]
+ *       OUT2: 166.625 MHz, Error: 0 ppm
+ *       OUT3: 166.625 MHz, Error: 0 ppm
+ *       OUT4: 166.625 MHz, Error: 0 ppm
+ *       OUT5: 166.625 MHz, Error: 0 ppm
+ *    N1:
+ *       Unused
+ *
+ * O dividers:
+ *    O0:
+ *       Value: 16
+ *       OUT0: 156.25 MHz, Error: 0 ppm
+ *       OUT1: 156.25 MHz, Error: 0 ppm
+ *       OUT6: 156.25 MHz, Error: 0 ppm
+ *       OUT7: 156.25 MHz, Error: 0 ppm
+ *    O1:
+ *       Unused
+ *    O2:
+ *       Unused
+ *    O3:
+ *       Unused
+ *    O4:
+ *       Unused
+ *
+ * R dividers:
+ *    R0 = 1
+ *    R1 = 1
+ *    R2 = 1
+ *    R3 = 1
+ *    R4 = 1
+ *    R5 = 1
+ *    R6 = 1
+ *    R7 = 1
+ *
+ * Estimated Power
+ * ===============
+ * Total Power: 233 mW, On Chip Power: 220 mW, Tj: 31 °C
+ *
+ *                    Frequency    Format   Voltage   Current     Power
+ *                  -----------  --------  --------  --------  --------
+ * VDD                                        1.8 V   30.7 mA     55 mW
+ * VDD Dig                                    1.8 V    7.0 mA     13 mW
+ * VDD Xtal                                   1.8 V    2.3 mA      4 mW
+ * VDDO0
+ *            OUT0   156.25 MHz  LVDSFast     1.8 V   11.1 mA     20 mW
+ * VDDO1
+ *            OUT1   156.25 MHz  LVDSFast     1.8 V   11.1 mA     20 mW
+ * VDDO2
+ *            OUT2  166.625 MHz  LVDSFast     1.8 V   11.2 mA     20 mW
+ *            OUT3  166.625 MHz  LVDSFast     1.8 V   11.2 mA     20 mW
+ * VDDO3
+ *            OUT4  166.625 MHz  LVDSFast     1.8 V   11.2 mA     20 mW
+ *            OUT5  166.625 MHz  LVDSFast     1.8 V   11.2 mA     20 mW
+ * VDDO4
+ *            OUT6   156.25 MHz  LVDSFast     1.8 V   11.1 mA     20 mW
+ * VDDO5
+ *            OUT7   156.25 MHz  LVDSFast     1.8 V   11.1 mA     20 mW
+ *                                                   --------  --------
+ *                                            Total  129.4 mA    233 mW
+ *
+ * Note:
+ *
+ * -Tj is junction temperature. Tj must be less than 125 °C (on Si5332-GM2 Revision D) for device
+ *  to comply with datasheet specifications. Tj = Ta + Theta_JA*On_Chip_Power.
+ * -Overall power includes on-chip power dissipation and adds differential load power dissipation
+ *  to estimate total power requirements.
+ * -Above are estimates only: power and temperature should be measured on your PCB.
+ *
+ * Settings
+ * ========
+ *
+ * Location    Setting Name     Decimal Value      Hex Value
+ * ----------  ---------------  -----------------  -----------------
+ * 0x17[7:0]   DESIGN_ID0       49                 0x31
+ * 0x18[7:0]   DESIGN_ID1       0                  0x00
+ * 0x19[7:0]   DESIGN_ID2       0                  0x00
+ * 0x1A[7:0]   DESIGN_ID3       0                  0x00
+ * 0x1B[7:0]   DESIGN_ID4       0                  0x00
+ * 0x1C[7:0]   DESIGN_ID5       0                  0x00
+ * 0x21[6:0]   I2C_ADDR         106                0x6A
+ * 0x24[1:0]   IMUX_SEL         1                  0x1
+ * 0x25[1:0]   OMUX0_SEL0       0                  0x0
+ * 0x25[6:4]   OMUX0_SEL1       0                  0x0
+ * 0x26[1:0]   OMUX1_SEL0       0                  0x0
+ * 0x26[6:4]   OMUX1_SEL1       0                  0x0
+ * 0x27[1:0]   OMUX2_SEL0       0                  0x0
+ * 0x27[6:4]   OMUX2_SEL1       5                  0x5
+ * 0x28[1:0]   OMUX3_SEL0       0                  0x0
+ * 0x28[6:4]   OMUX3_SEL1       5                  0x5
+ * 0x29[1:0]   OMUX4_SEL0       0                  0x0
+ * 0x29[6:4]   OMUX4_SEL1       0                  0x0
+ * 0x2A[1:0]   OMUX5_SEL0       0                  0x0
+ * 0x2A[6:4]   OMUX5_SEL1       0                  0x0
+ * 0x2B[7:0]   HSDIV0A_DIV      16                 0x10
+ * 0x36[14:0]  ID0A_INTG        1920               0x0780
+ * 0x38[14:0]  ID0A_RES         640                0x0280
+ * 0x3A[14:0]  ID0A_DEN         1333               0x0535
+ * 0x3C[0]     ID0A_SS_ENA      0                  0x0
+ * 0x3C[2:1]   ID0A_SS_MODE     0                  0x0
+ * 0x48[0]     ID0B_SS_ENA      0                  0x0
+ * 0x48[2:1]   ID0B_SS_MODE     0                  0x0
+ * 0x54[0]     ID1A_SS_ENA      0                  0x0
+ * 0x54[2:1]   ID1A_SS_MODE     0                  0x0
+ * 0x60[0]     ID1B_SS_ENA      0                  0x0
+ * 0x60[2:1]   ID1B_SS_MODE     0                  0x0
+ * 0x67[14:0]  IDPA_INTG        6400               0x1900
+ * 0x69[14:0]  IDPA_RES         0                  0x0000
+ * 0x6B[14:0]  IDPA_DEN         1                  0x0001
+ * 0x73[1:0]   CLKIN_2_CLK_SEL  0                  0x0
+ * 0x74[1:0]   CLKIN_3_CLK_SEL  0                  0x0
+ * 0x75[4:0]   P_VAL            1                  0x01
+ * 0x7A[3:0]   OUT0_MODE        7                  0x7
+ * 0x7B[5:0]   OUT0_DIV         1                  0x01
+ * 0x7C[2:0]   OUT0_SKEW        0                  0x0
+ * 0x7D[0]     OUT0_STOP_HIGHZ  0                  0x0
+ * 0x7D[5:4]   OUT0_CMOS_INV    0                  0x0
+ * 0x7D[6]     OUT0_DIFF_INV    0                  0x0
+ * 0x7F[3:0]   OUT1_MODE        7                  0x7
+ * 0x80[5:0]   OUT1_DIV         1                  0x01
+ * 0x81[2:0]   OUT1_SKEW        0                  0x0
+ * 0x82[0]     OUT1_STOP_HIGHZ  0                  0x0
+ * 0x82[5:4]   OUT1_CMOS_INV    0                  0x0
+ * 0x82[6]     OUT1_DIFF_INV    0                  0x0
+ * 0x89[3:0]   OUT2_MODE        7                  0x7
+ * 0x8A[5:0]   OUT2_DIV         1                  0x01
+ * 0x8B[2:0]   OUT2_SKEW        0                  0x0
+ * 0x8C[0]     OUT2_STOP_HIGHZ  0                  0x0
+ * 0x8C[5:4]   OUT2_CMOS_INV    0                  0x0
+ * 0x8C[6]     OUT2_DIFF_INV    0                  0x0
+ * 0x8E[3:0]   OUT3_MODE        7                  0x7
+ * 0x8F[5:0]   OUT3_DIV         1                  0x01
+ * 0x90[2:0]   OUT3_SKEW        0                  0x0
+ * 0x91[0]     OUT3_STOP_HIGHZ  0                  0x0
+ * 0x91[5:4]   OUT3_CMOS_INV    0                  0x0
+ * 0x91[6]     OUT3_DIFF_INV    0                  0x0
+ * 0x98[3:0]   OUT4_MODE        7                  0x7
+ * 0x99[5:0]   OUT4_DIV         1                  0x01
+ * 0x9A[2:0]   OUT4_SKEW        0                  0x0
+ * 0x9B[0]     OUT4_STOP_HIGHZ  0                  0x0
+ * 0x9B[5:4]   OUT4_CMOS_INV    0                  0x0
+ * 0x9B[6]     OUT4_DIFF_INV    0                  0x0
+ * 0x9D[3:0]   OUT5_MODE        7                  0x7
+ * 0x9E[5:0]   OUT5_DIV         1                  0x01
+ * 0x9F[2:0]   OUT5_SKEW        0                  0x0
+ * 0xA0[0]     OUT5_STOP_HIGHZ  0                  0x0
+ * 0xA0[5:4]   OUT5_CMOS_INV    0                  0x0
+ * 0xA0[6]     OUT5_DIFF_INV    0                  0x0
+ * 0xA7[3:0]   OUT6_MODE        7                  0x7
+ * 0xA8[5:0]   OUT6_DIV         1                  0x01
+ * 0xA9[2:0]   OUT6_SKEW        0                  0x0
+ * 0xAA[0]     OUT6_STOP_HIGHZ  0                  0x0
+ * 0xAA[5:4]   OUT6_CMOS_INV    0                  0x0
+ * 0xAA[6]     OUT6_DIFF_INV    0                  0x0
+ * 0xAC[3:0]   OUT7_MODE        7                  0x7
+ * 0xAD[5:0]   OUT7_DIV         1                  0x01
+ * 0xAE[2:0]   OUT7_SKEW        0                  0x0
+ * 0xAF[0]     OUT7_STOP_HIGHZ  0                  0x0
+ * 0xAF[5:4]   OUT7_CMOS_INV    0                  0x0
+ * 0xAF[6]     OUT7_DIFF_INV    0                  0x0
+ * 0xB6[0]     OUT0_OE          1                  0x1
+ * 0xB6[1]     OUT1_OE          1                  0x1
+ * 0xB6[3]     OUT2_OE          1                  0x1
+ * 0xB6[4]     OUT3_OE          1                  0x1
+ * 0xB6[6]     OUT4_OE          1                  0x1
+ * 0xB6[7]     OUT5_OE          1                  0x1
+ * 0xB7[1]     OUT6_OE          1                  0x1
+ * 0xB7[2]     OUT7_OE          1                  0x1
+ * 0xB9[0]     XOSC_DIS         0                  0x0
+ * 0xB9[1]     IBUF0_DIS        1                  0x1
+ * 0xB9[2]     IBUF1_DIS        1                  0x1
+ * 0xB9[3]     IMUX_DIS         0                  0x0
+ * 0xB9[4]     PDIV_DIS         0                  0x0
+ * 0xB9[5]     PLL_DIS          0                  0x0
+ * 0xBA[5]     ID0_DIS          0                  0x0
+ * 0xBA[6]     ID1_DIS          1                  0x1
+ * 0xBA[0]     HSDIV0_DIS       0                  0x0
+ * 0xBA[1]     HSDIV1_DIS       1                  0x1
+ * 0xBA[2]     HSDIV2_DIS       1                  0x1
+ * 0xBA[3]     HSDIV3_DIS       1                  0x1
+ * 0xBA[4]     HSDIV4_DIS       1                  0x1
+ * 0xBB[0]     OMUX0_DIS        0                  0x0
+ * 0xBB[1]     OMUX1_DIS        0                  0x0
+ * 0xBB[2]     OMUX2_DIS        0                  0x0
+ * 0xBB[3]     OMUX3_DIS        0                  0x0
+ * 0xBB[4]     OMUX4_DIS        0                  0x0
+ * 0xBB[5]     OMUX5_DIS        0                  0x0
+ * 0xBC[0]     OUT0_DIS         0                  0x0
+ * 0xBC[1]     OUT1_DIS         0                  0x0
+ * 0xBC[3]     OUT2_DIS         0                  0x0
+ * 0xBC[4]     OUT3_DIS         0                  0x0
+ * 0xBC[6]     OUT4_DIS         0                  0x0
+ * 0xBC[7]     OUT5_DIS         0                  0x0
+ * 0xBD[1]     OUT6_DIS         0                  0x0
+ * 0xBD[2]     OUT7_DIS         0                  0x0
+ * 0xBE[7:0]   PLL_MODE         32                 0x20
+ *
+ *
+ */
+
+#endif
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_i2cm.h b/drivers/net/ntnic/nthw/core/include/nthw_i2cm.h
index eeb4dffe25..53aa3c018e 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_i2cm.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_i2cm.h
@@ -46,5 +46,6 @@ typedef struct nt_i2cm nthw_i2cm_t;
 
 int nthw_i2cm_read(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr, uint8_t *value);
 int nthw_i2cm_write(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr, uint8_t value);
+int nthw_i2cm_write16(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr, uint16_t value);
 
 #endif	/* __NTHW_II2CM_H__ */
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h b/drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h
new file mode 100644
index 0000000000..1e114886ca
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h
@@ -0,0 +1,14 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+#ifndef __NTHW_PCM_NT400DXX_H__
+#define __NTHW_PCM_NT400DXX_H__
+
+struct nthw_pcm_nt400_dxx {
+	int mn_module_minor_version;
+};
+
+typedef struct nthw_pcm_nt400_dxx nthw_pcm_nt400dxx_t;
+
+#endif  /* __NTHW_PCM_NT400DXX_H__ */
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h b/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
index 968d7eb74a..753717ba8a 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
@@ -21,4 +21,40 @@ typedef struct nthw_pca9849 nthw_pca9849_t;
 
 int nthw_pca9849_set_channel(nthw_pca9849_t *p, uint8_t channel);
 
+/*
+ * Si5332 clock synthesizer
+ */
+
+struct nthw_si5332 {
+	nthw_i2cm_t *mp_nt_i2cm;
+	uint8_t m_dev_address;
+	nthw_pca9849_t *mp_pca9849;
+	uint8_t m_mux_channel;
+};
+
+typedef struct nthw_si5332 nthw_si5332_t;
+
+nthw_si5332_t *nthw_si5332_new(void);
+int nthw_si5332_init(nthw_si5332_t *p, nthw_i2cm_t *p_nt_i2cm, uint8_t dev_address,
+	nthw_pca9849_t *pca9849, uint8_t mux_channel);
+bool nthw_si5332_clock_active(nthw_si5332_t *p);
+void nthw_si5332_write(nthw_si5332_t *p, uint8_t address, uint8_t value);
+
+/*
+ * Si5156 MEMS Super TCXO
+ */
+struct nthw_si5156 {
+	nthw_i2cm_t *mp_nt_i2cm;
+	uint8_t m_dev_address;
+	nthw_pca9849_t *mp_pca9849;
+	uint8_t m_mux_channel;
+};
+
+typedef struct nthw_si5156 nthw_si5156_t;
+
+nthw_si5156_t *nthw_si5156_new(void);
+int nthw_si5156_init(nthw_si5156_t *p, nthw_i2cm_t *p_nt_i2cm, uint8_t dev_address,
+	nthw_pca9849_t *pca9849, uint8_t mux_channel);
+int nthw_si5156_write16(nthw_si5156_t *p, uint8_t address, uint16_t value);
+
 #endif	/* __NTHW_SI5332_SI5156_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c
index 0a5add60e0..24118822c4 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c
@@ -2,10 +2,113 @@
  * SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2023 Napatech A/S
  */
-
+#include "ntlog.h"
 #include "nthw_fpga.h"
 #include "ntnic_mod_reg.h"
-#include "ntlog.h"
+#include "NT400D13_U62_Si5332-GM2-RevD-1_V5-Registers.h"
+
+static int nthw_fpga_nt400dxx_init_clock_synthesizers(struct fpga_info_s *p_fpga_info)
+{
+	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+	int res = -1;
+
+	/* Clock synthesizer on address 0x6a on channel 2 */
+	p_fpga_info->mp_nthw_agx.p_si5332 = nthw_si5332_new();
+	res = nthw_si5332_init(p_fpga_info->mp_nthw_agx.p_si5332,
+			p_fpga_info->mp_nthw_agx.p_i2cm,
+			0x6A,
+			p_fpga_info->mp_nthw_agx.p_pca9849,
+			2);
+
+	if (res) {
+		NT_LOG(ERR, NTHW, "%s: %s: Failed to initialize Si5332 clock - res=%d",
+			p_adapter_id_str, __func__, res);
+		return res;
+	}
+
+	p_fpga_info->mp_nthw_agx.p_si5156 = nthw_si5156_new();
+	res = nthw_si5156_init(p_fpga_info->mp_nthw_agx.p_si5156,
+			p_fpga_info->mp_nthw_agx.p_i2cm,
+			0x60,
+			p_fpga_info->mp_nthw_agx.p_pca9849,
+			2);
+
+	if (res) {
+		NT_LOG(ERR, NTHW, "%s: %s: Failed to initialize Si5156 clock - res=%d",
+			p_adapter_id_str, __func__, res);
+		return res;
+	}
+
+	if (nthw_si5332_clock_active(p_fpga_info->mp_nthw_agx.p_si5332)) {
+		NT_LOG(INF,
+			NTHW,
+			"%s: Fpga clock already active, skipping clock initialisation.",
+			p_adapter_id_str);
+
+	} else {
+		NT_LOG(INF, NTHW,
+			"%s: Fpga clock not active, performing full clock initialisation.",
+			p_adapter_id_str);
+
+		for (int i = 0; i < SI5332_GM2_REVD_REG_CONFIG_NUM_REGS; i++) {
+			nthw_si5332_write(p_fpga_info->mp_nthw_agx.p_si5332,
+				(uint8_t)si5332_gm2_revd_registers[i].address,
+				(uint8_t)si5332_gm2_revd_registers[i].value);
+		}
+	}
+
+	/*
+	 * TCXO capable PCM version if minor version >= 3
+	 * Unfortunately, the module version is not readily
+	 * available in the FPGA_400D1x class.
+	 */
+	bool tcxo_capable = p_fpga_info->mp_nthw_agx.p_pcm->mn_module_minor_version >= 3;
+
+	/*
+	 * This method of determining the presence of a TCXO
+	 *  will only work until non SI5156 equipped boards
+	 *  use the vacant I2C address for something else...
+	 *
+	 * There's no other way, there's no other way
+	 * All that you can do is watch them play
+	 * Clean-up when GA HW is readily available
+	 */
+	if (nthw_si5156_write16(p_fpga_info->mp_nthw_agx.p_si5156, 0x1, 0x0400) != 0) {
+		p_fpga_info->mp_nthw_agx.tcxo_capable = false;
+		p_fpga_info->mp_nthw_agx.tcxo_present = false;
+
+	} else {
+		p_fpga_info->mp_nthw_agx.tcxo_capable = tcxo_capable;
+		p_fpga_info->mp_nthw_agx.tcxo_present = true;
+	}
+
+	return 0;
+}
+
+static int nthw_fpga_nt400dxx_init_sub_systems(struct fpga_info_s *p_fpga_info)
+{
+	int res;
+	NT_LOG(INF, NTHW, "%s: Initializing NT4GA subsystems...", p_fpga_info->mp_adapter_id_str);
+
+	/* RAB subsystem */
+	NT_LOG(DBG, NTHW, "%s: Initializing RAB subsystem: flush", p_fpga_info->mp_adapter_id_str);
+	res = nthw_rac_rab_flush(p_fpga_info->mp_nthw_rac);
+
+	if (res)
+		return res;
+
+	/* clock synthesizer subsystem */
+	NT_LOG(DBG,
+		NTHW,
+		"%s: Initializing clock synthesizer subsystem",
+		p_fpga_info->mp_adapter_id_str);
+	res = nthw_fpga_nt400dxx_init_clock_synthesizers(p_fpga_info);
+
+	if (res)
+		return res;
+
+	return 0;
+}
 
 static int nthw_fpga_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 {
@@ -61,6 +164,14 @@ static int nthw_fpga_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 		return res;
 	}
 
+	res = nthw_fpga_nt400dxx_init_sub_systems(p_fpga_info);
+
+	if (res) {
+		NT_LOG(ERR, NTHW, "%s: %s: FPGA=%04d Failed to init subsystems res=%d",
+		p_adapter_id_str, __func__, p_fpga_info->n_fpga_prod_id, res);
+		return res;
+	}
+
 	res = rst_nt400dxx_ops->nthw_fpga_rst_nt400dxx_reset(p_fpga_info);
 
 	if (res) {
diff --git a/drivers/net/ntnic/nthw/core/nthw_i2cm.c b/drivers/net/ntnic/nthw/core/nthw_i2cm.c
index b5f8e299ff..f7500b2e93 100644
--- a/drivers/net/ntnic/nthw/core/nthw_i2cm.c
+++ b/drivers/net/ntnic/nthw/core/nthw_i2cm.c
@@ -73,6 +73,47 @@ static int nthw_i2cm_write_internal(nthw_i2cm_t *p, uint8_t value)
 	return 0;
 }
 
+static int nthw_i2cm_write16_internal(nthw_i2cm_t *p, uint16_t value)
+{
+	const uint8_t count = 1;
+
+	for (int8_t i = count; i >= 0; i--) {
+		uint8_t byte_value = (uint8_t)(value >> ((uint8_t)i * 8)) & 0xffU;
+
+		/* Write data to data register */
+		nthw_field_set_val_flush32(p->mp_fld_data_data, byte_value);
+
+		if (i == 0) {
+			nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status,
+				NT_I2C_CMD_WR | NT_I2C_CMD_IRQ_ACK);
+
+		} else {
+			nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status, NT_I2C_CMD_WR);
+		}
+
+		if (!nthw_i2cm_ready(p, true)) {
+			nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status,
+				NT_I2C_CMD_STOP | NT_I2C_CMD_IRQ_ACK);
+			NT_LOG(ERR, NTHW, "%s: Time-out writing data %u", __PRETTY_FUNCTION__,
+				value);
+			return 1;
+		}
+	}
+
+	/* Generate stop condition and clear interrupt */
+	nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status,
+		NT_I2C_CMD_STOP | NT_I2C_CMD_IRQ_ACK);
+
+	if (!nthw_i2cm_ready(p, true)) {
+		nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status,
+			NT_I2C_CMD_STOP | NT_I2C_CMD_IRQ_ACK);
+		NT_LOG(ERR, NTHW, "%s: Time-out sending stop condition", __PRETTY_FUNCTION__);
+		return 1;
+	}
+
+	return 0;
+}
+
 static int nthw_i2cm_write_reg_addr_internal(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr,
 	bool send_stop)
 {
@@ -190,3 +231,19 @@ int nthw_i2cm_write(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr, uint8_t
 
 	return 0;
 }
+
+int nthw_i2cm_write16(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr, uint16_t value)
+{
+	int status;
+	status = nthw_i2cm_write_reg_addr_internal(p, dev_addr, reg_addr, false);
+
+	if (status != 0)
+		return status;
+
+	status = nthw_i2cm_write16_internal(p, value);
+
+	if (status != 0)
+		return status;
+
+	return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c b/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
index b5560e2990..b4a7b57bcb 100644
--- a/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
+++ b/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
@@ -4,6 +4,7 @@
  */
 
 #include <pthread.h>
+#include "generic/rte_spinlock.h"
 #include "nt_util.h"
 #include "ntlog.h"
 
@@ -29,3 +30,95 @@ int nthw_pca9849_set_channel(nthw_pca9849_t *p, uint8_t channel)
 
 	return 0;
 }
+
+/*
+ * Si5332 clock synthesizer
+ */
+
+nthw_si5332_t *nthw_si5332_new(void)
+{
+	nthw_si5332_t *p = malloc(sizeof(nthw_si5332_t));
+
+	if (p)
+		memset(p, 0, sizeof(nthw_si5332_t));
+
+	return p;
+}
+
+int nthw_si5332_init(nthw_si5332_t *p, nthw_i2cm_t *p_nt_i2cm, uint8_t dev_address,
+	nthw_pca9849_t *pca9849, uint8_t mux_channel)
+{
+	p->mp_nt_i2cm = p_nt_i2cm;
+	p->m_dev_address = dev_address;
+	p->m_mux_channel = mux_channel;
+	p->mp_pca9849 = pca9849;
+	return 0;
+}
+
+bool nthw_si5332_clock_active(nthw_si5332_t *p)
+{
+	uint8_t ena1, ena2;
+
+	rte_spinlock_lock(&p->mp_nt_i2cm->i2cmmutex);
+	nthw_pca9849_set_channel(p->mp_pca9849, p->m_mux_channel);
+
+	nthw_i2cm_read(p->mp_nt_i2cm, p->m_dev_address, 0xB6, &ena1);
+	NT_LOG(DBG, NTHW, "Read %x from i2c dev 0x6A, reg 0xB6", ena1);
+
+	nthw_i2cm_read(p->mp_nt_i2cm, p->m_dev_address, 0xB7, &ena2);
+	NT_LOG(DBG, NTHW, "Read %x from i2c dev 0x6A, reg 0xB7", ena2);
+	rte_spinlock_unlock(&p->mp_nt_i2cm->i2cmmutex);
+
+	return ((ena1 & 0xDB) != 0) || ((ena2 & 0x06) != 0);
+}
+
+void nthw_si5332_write(nthw_si5332_t *p, uint8_t address, uint8_t value)
+{
+	rte_spinlock_lock(&p->mp_nt_i2cm->i2cmmutex);
+	nthw_pca9849_set_channel(p->mp_pca9849, p->m_mux_channel);
+	nthw_i2cm_write(p->mp_nt_i2cm, p->m_dev_address, address, value);
+	rte_spinlock_unlock(&p->mp_nt_i2cm->i2cmmutex);
+}
+
+/*
+ * Si5156 MEMS Super TCXO
+ */
+
+nthw_si5156_t *nthw_si5156_new(void)
+{
+	nthw_si5156_t *p = malloc(sizeof(nthw_si5156_t));
+
+	if (p)
+		memset(p, 0, sizeof(nthw_si5156_t));
+
+	return p;
+}
+
+int nthw_si5156_init(nthw_si5156_t *p, nthw_i2cm_t *p_nt_i2cm, uint8_t dev_address,
+	nthw_pca9849_t *pca9849, uint8_t mux_channel)
+{
+	p->mp_nt_i2cm = p_nt_i2cm;
+	p->m_dev_address = dev_address;
+	p->m_mux_channel = mux_channel;
+	p->mp_pca9849 = pca9849;
+	return 0;
+}
+
+int nthw_si5156_write16(nthw_si5156_t *p, uint8_t address, uint16_t value)
+{
+	int res = 0;
+	rte_spinlock_lock(&p->mp_nt_i2cm->i2cmmutex);
+	res = nthw_pca9849_set_channel(p->mp_pca9849, p->m_mux_channel);
+
+	if (res)
+		goto ERROR;
+
+	res = nthw_i2cm_write16(p->mp_nt_i2cm, p->m_dev_address, address, value);
+
+	if (res)
+		goto ERROR;
+
+ERROR:
+	rte_spinlock_unlock(&p->mp_nt_i2cm->i2cmmutex);
+	return res;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_drv.h b/drivers/net/ntnic/nthw/nthw_drv.h
index a3c54846f5..1d5b750db9 100644
--- a/drivers/net/ntnic/nthw/nthw_drv.h
+++ b/drivers/net/ntnic/nthw/nthw_drv.h
@@ -12,8 +12,8 @@
 #include "nthw_si5332_si5156.h"
 #include "nthw_pcal6416a.h"
 #include "nthw_pca9532.h"
-#include "nthw_phy_tile.h"
 #include "nthw_rpf.h"
+#include "nthw_pcm_nt400dxx.h"
 #include "nthw_phy_tile.h"
 
 /*
@@ -24,8 +24,13 @@ typedef struct nthw_agx_s {
 	nthw_pca9849_t *p_pca9849;
 	nthw_pcal6416a_t *p_io_nim;	/* PCAL6416A I/O expander for controlling TS */
 	nthw_pca9532_t *p_pca9532_led;
+	nthw_si5332_t *p_si5332;
+	nthw_si5156_t *p_si5156;
+	nthw_pcm_nt400dxx_t *p_pcm;
 	nthw_phy_tile_t *p_phy_tile;
 	nthw_rpf_t *p_rpf;
+	bool tcxo_present;
+	bool tcxo_capable;
 } nthw_agx_t;
 
 typedef enum nt_meta_port_type_e {
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 21/32] net/ntnic: add nt400d13 pcm init
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (19 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 20/32] net/ntnic: add clock init Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 22/32] net/ntnic: add HIF clock test Serhii Iliushyk
                   ` (11 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Initialize and create PCM for FPGA and HIF modules

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 drivers/net/ntnic/meson.build                 |  1 +
 .../nthw/core/include/nthw_pcm_nt400dxx.h     | 24 +++++++-
 .../nt400dxx/reset/nthw_fpga_rst_nt400dxx.c   | 18 ++++++
 .../net/ntnic/nthw/core/nthw_pcm_nt400dxx.c   | 56 +++++++++++++++++++
 drivers/net/ntnic/nthw/nthw_drv.h             |  1 +
 5 files changed, 99 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcm_nt400dxx.c

diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index aec7b52714..b9ac069bcc 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -61,6 +61,7 @@ sources = files(
         'nthw/core/nthw_pcie3.c',
         'nthw/core/nthw_pca9532.c',
         'nthw/core/nthw_pcal6416a.c',
+        'nthw/core/nthw_pcm_nt400dxx.c',
         'nthw/core/nthw_phy_tile.c',
         'nthw/core/nthw_si5332_si5156.c',
         'nthw/core/nthw_rpf.c',
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h b/drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h
index 1e114886ca..23865f466b 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h
@@ -5,10 +5,32 @@
 #ifndef __NTHW_PCM_NT400DXX_H__
 #define __NTHW_PCM_NT400DXX_H__
 
+#include "nthw_fpga_model.h"
+
 struct nthw_pcm_nt400_dxx {
+	nthw_fpga_t *mp_fpga;
+	nthw_module_t *mp_mod_pcm;
+	int mn_instance;
+
+	int mn_module_major_version;
 	int mn_module_minor_version;
+
+	nthw_register_t *mp_reg_ctrl;
+	nthw_field_t *mp_fld_ctrl_ts_pll_recal;	/* Dunite HW version 3 */
+	nthw_field_t *mp_fld_ctrl_ts_clksel;
+	nthw_field_t *mp_fld_ctrl_ts_pll_rst;
+
+	nthw_register_t *mp_reg_stat;
+	nthw_field_t *mp_fld_stat_ts_pll_locked;
+
+	nthw_register_t *mp_reg_latch;
+	nthw_field_t *mp_fld_latch_ts_pll_locked;
 };
 
 typedef struct nthw_pcm_nt400_dxx nthw_pcm_nt400dxx_t;
+typedef struct nthw_pcm_nt400_dxx nthw_pcm_nt400_dxx;
+
+nthw_pcm_nt400dxx_t *nthw_pcm_nt400dxx_new(void);
+int nthw_pcm_nt400dxx_init(nthw_pcm_nt400dxx_t *p, nthw_fpga_t *p_fpga, int n_instance);
 
-#endif  /* __NTHW_PCM_NT400DXX_H__ */
+#endif	/* __NTHW_PCM_NT400DXX_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
index e0e4bc0861..1d93474cff 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
@@ -13,6 +13,24 @@
 static int nthw_fpga_rst_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 {
 	assert(p_fpga_info);
+	int res = -1;
+	nthw_fpga_t *p_fpga = NULL;
+
+	p_fpga = p_fpga_info->mp_fpga;
+
+	nthw_hif_t *p_nthw_hif = nthw_hif_new();
+	res = nthw_hif_init(p_nthw_hif, p_fpga, 0);
+
+	if (res == 0)
+		NT_LOG(DBG, NTHW, "%s: Hif module found", p_fpga_info->mp_adapter_id_str);
+
+	/* Create PCM */
+	p_fpga_info->mp_nthw_agx.p_pcm = nthw_pcm_nt400dxx_new();
+	res = nthw_pcm_nt400dxx_init(p_fpga_info->mp_nthw_agx.p_pcm, p_fpga, 0);
+
+	if (res != 0)
+		return res;
+
 	return 0;
 }
 
diff --git a/drivers/net/ntnic/nthw/core/nthw_pcm_nt400dxx.c b/drivers/net/ntnic/nthw/core/nthw_pcm_nt400dxx.c
new file mode 100644
index 0000000000..f32a277e86
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_pcm_nt400dxx.c
@@ -0,0 +1,56 @@
+/*
+ * 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 "nthw_pcm_nt400dxx.h"
+
+nthw_pcm_nt400dxx_t *nthw_pcm_nt400dxx_new(void)
+{
+	nthw_pcm_nt400dxx_t *p = malloc(sizeof(nthw_pcm_nt400dxx_t));
+
+	if (p)
+		memset(p, 0, sizeof(nthw_pcm_nt400dxx_t));
+
+	return p;
+}
+
+int nthw_pcm_nt400dxx_init(nthw_pcm_nt400dxx_t *p, nthw_fpga_t *p_fpga, int n_instance)
+{
+	nthw_module_t *p_mod = nthw_fpga_query_module(p_fpga, MOD_PCM_NT400DXX, n_instance);
+
+	if (p == NULL)
+		return p_mod == NULL ? -1 : 0;
+
+	if (p_mod == NULL) {
+		NT_LOG(ERR, NTHW, "%s: PCM_NT400DXX %d: no such instance",
+			p->mp_fpga->p_fpga_info->mp_adapter_id_str, p->mn_instance);
+		return -1;
+	}
+
+	p->mp_mod_pcm = p_mod;
+
+	p->mp_fpga = p_fpga;
+	p->mn_instance = n_instance;
+
+	p->mn_module_major_version = nthw_module_get_major_version(p->mp_mod_pcm);
+	p->mn_module_minor_version = nthw_module_get_minor_version(p->mp_mod_pcm);
+
+	p->mp_reg_ctrl = nthw_module_get_register(p->mp_mod_pcm, PCM_NT400DXX_CTRL);
+	p->mp_fld_ctrl_ts_pll_recal =
+		nthw_register_query_field(p->mp_reg_ctrl, PCM_NT400DXX_CTRL_TS_PLL_RECAL);
+
+	p->mp_reg_stat = nthw_module_get_register(p->mp_mod_pcm, PCM_NT400DXX_STAT);
+	p->mp_fld_stat_ts_pll_locked =
+		nthw_register_get_field(p->mp_reg_stat, PCM_NT400DXX_STAT_TS_PLL_LOCKED);
+
+	p->mp_reg_latch = nthw_module_get_register(p->mp_mod_pcm, PCM_NT400DXX_LATCH);
+	p->mp_fld_latch_ts_pll_locked =
+		nthw_register_get_field(p->mp_reg_latch, PCM_NT400DXX_LATCH_TS_PLL_LOCKED);
+
+	return 0;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_drv.h b/drivers/net/ntnic/nthw/nthw_drv.h
index 1d5b750db9..955d0a37b0 100644
--- a/drivers/net/ntnic/nthw/nthw_drv.h
+++ b/drivers/net/ntnic/nthw/nthw_drv.h
@@ -15,6 +15,7 @@
 #include "nthw_rpf.h"
 #include "nthw_pcm_nt400dxx.h"
 #include "nthw_phy_tile.h"
+#include "nthw_pcm_nt400dxx.h"
 
 /*
  * Structs for controlling Agilex based NT400DXX adapter
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 22/32] net/ntnic: add HIF clock test
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (20 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 21/32] net/ntnic: add nt400d13 pcm init Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 23/32] net/ntnic: add nt400d13 PRM module init Serhii Iliushyk
                   ` (10 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Add HIF clock test with write/read verification.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../net/ntnic/nthw/core/include/nthw_hif.h    |  3 +
 .../nt400dxx/reset/nthw_fpga_rst_nt400dxx.c   | 20 +++++
 drivers/net/ntnic/nthw/core/nthw_hif.c        | 82 +++++++++++++++++++
 3 files changed, 105 insertions(+)

diff --git a/drivers/net/ntnic/nthw/core/include/nthw_hif.h b/drivers/net/ntnic/nthw/core/include/nthw_hif.h
index c8f4669f83..deb9ed04e8 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_hif.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_hif.h
@@ -148,4 +148,7 @@ int nthw_hif_get_stat_rate(nthw_hif_t *p, uint64_t *p_pci_rx_rate, uint64_t *p_p
 
 int nthw_hif_end_point_counters_sample(nthw_hif_t *p, struct nthw_hif_end_point_counters *epc);
 
+int nthw_hif_read_test_reg(nthw_hif_t *p, uint8_t test_reg, uint32_t *p_value);
+int nthw_hif_write_test_reg(nthw_hif_t *p, uint8_t test_reg, uint32_t value);
+
 #endif	/* __NTHW_HIF_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
index 1d93474cff..60e7714283 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
@@ -24,6 +24,26 @@ static int nthw_fpga_rst_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 	if (res == 0)
 		NT_LOG(DBG, NTHW, "%s: Hif module found", p_fpga_info->mp_adapter_id_str);
 
+	/* (A) Test HIF clock is running by performing simple write/read test of HIF registers */
+	const uint32_t test_pattern[2] = { 0x11223344, 0x55667788 };
+
+	for (uint8_t i = 0; i < 2; ++i) {
+		uint32_t test_data = 0;
+		nthw_hif_write_test_reg(p_nthw_hif, i, test_pattern[i]);
+		nthw_hif_read_test_reg(p_nthw_hif, i, &test_data);
+
+		if (test_data != test_pattern[i]) {
+			NT_LOG(ERR,
+				NTHW,
+				"%s: %s: Test sys 250 clock failed",
+				p_fpga_info->mp_adapter_id_str,
+				__func__);
+			return -1;
+		}
+	}
+
+	nthw_hif_delete(p_nthw_hif);
+
 	/* Create PCM */
 	p_fpga_info->mp_nthw_agx.p_pcm = nthw_pcm_nt400dxx_new();
 	res = nthw_pcm_nt400dxx_init(p_fpga_info->mp_nthw_agx.p_pcm, p_fpga, 0);
diff --git a/drivers/net/ntnic/nthw/core/nthw_hif.c b/drivers/net/ntnic/nthw/core/nthw_hif.c
index 9f699e4f94..92a2348bbb 100644
--- a/drivers/net/ntnic/nthw/core/nthw_hif.c
+++ b/drivers/net/ntnic/nthw/core/nthw_hif.c
@@ -298,3 +298,85 @@ int nthw_hif_end_point_counters_sample(nthw_hif_t *p, struct nthw_hif_end_point_
 
 	return 0;
 }
+
+int nthw_hif_read_test_reg(nthw_hif_t *p, uint8_t test_reg, uint32_t *p_value)
+{
+	uint32_t data;
+
+	switch (test_reg) {
+	case 0:
+		data = nthw_field_get_updated(p->mp_fld_pci_test0);
+		break;
+
+	case 1:
+		data = nthw_field_get_updated(p->mp_fld_pci_test1);
+		break;
+
+	case 2:
+		if (p->mp_fld_pci_test2)
+			data = nthw_field_get_updated(p->mp_fld_pci_test2);
+
+		else
+			return -1;
+
+		break;
+
+	case 3:
+		if (p->mp_fld_pci_test3)
+			data = nthw_field_get_updated(p->mp_fld_pci_test3);
+
+		else
+			return -1;
+
+		break;
+
+	default:
+		assert(false);
+		return -1;
+	}
+
+	if (p_value)
+		*p_value = data;
+
+	else
+		return -1;
+
+	return 0;
+}
+
+int nthw_hif_write_test_reg(nthw_hif_t *p, uint8_t test_reg, uint32_t value)
+{
+	switch (test_reg) {
+	case 0:
+		nthw_field_set_val_flush32(p->mp_fld_pci_test0, value);
+		break;
+
+	case 1:
+		nthw_field_set_val_flush32(p->mp_fld_pci_test1, value);
+		break;
+
+	case 2:
+		if (p->mp_fld_pci_test2)
+			nthw_field_set_val_flush32(p->mp_fld_pci_test2, value);
+
+		else
+			return -1;
+
+		break;
+
+	case 3:
+		if (p->mp_fld_pci_test3)
+			nthw_field_set_val_flush32(p->mp_fld_pci_test3, value);
+
+		else
+			return -1;
+
+		break;
+
+	default:
+		assert(false);
+		return -1;
+	}
+
+	return 0;
+}
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 23/32] net/ntnic: add nt400d13 PRM module init
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (21 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 22/32] net/ntnic: add HIF clock test Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 24/32] net/ntnic: add nt400d13 PRM module reset Serhii Iliushyk
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Initialize RAB0 and create PRM for FPGA.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 drivers/net/ntnic/meson.build                 |  1 +
 .../nthw/core/include/nthw_prm_nt400dxx.h     | 30 +++++++++++++
 .../nt400dxx/reset/nthw_fpga_rst_nt400dxx.c   | 11 +++++
 .../net/ntnic/nthw/core/nthw_prm_nt400dxx.c   | 43 +++++++++++++++++++
 drivers/net/ntnic/nthw/nthw_drv.h             |  2 +
 5 files changed, 87 insertions(+)
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_prm_nt400dxx.h
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_prm_nt400dxx.c

diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index b9ac069bcc..9885d4efbf 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -63,6 +63,7 @@ sources = files(
         'nthw/core/nthw_pcal6416a.c',
         'nthw/core/nthw_pcm_nt400dxx.c',
         'nthw/core/nthw_phy_tile.c',
+        'nthw/core/nthw_prm_nt400dxx.c',
         'nthw/core/nthw_si5332_si5156.c',
         'nthw/core/nthw_rpf.c',
         'nthw/core/nthw_rmc.c',
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_prm_nt400dxx.h b/drivers/net/ntnic/nthw/core/include/nthw_prm_nt400dxx.h
new file mode 100644
index 0000000000..09bfd79249
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/include/nthw_prm_nt400dxx.h
@@ -0,0 +1,30 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef NTHW_PRM_NT400DXX_H_
+#define NTHW_PRM_NT400DXX_H_
+
+#include <stdint.h>
+
+#include "nthw_fpga_model.h"
+
+struct nt_prm_nt400dxx {
+	nthw_fpga_t *mp_fpga;
+	nthw_module_t *mp_mod_prm;
+
+	int mn_instance;
+
+	nthw_register_t *mp_reg_rst;
+	nthw_field_t *mp_fld_rst_periph;
+	nthw_field_t *mp_fld_rst_platform;
+};
+
+typedef struct nt_prm_nt400dxx nthw_prm_nt400dxx_t;
+typedef struct nt_prm_nt400dxx nt_prm_nt400dxx;
+
+nthw_prm_nt400dxx_t *nthw_prm_nt400dxx_new(void);
+int nthw_prm_nt400dxx_init(nthw_prm_nt400dxx_t *p, nthw_fpga_t *p_fpga, int n_instance);
+
+#endif	/* NTHW_PRM_NT400DXX_H_ */
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
index 60e7714283..4d74db88de 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
@@ -44,6 +44,17 @@ static int nthw_fpga_rst_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 
 	nthw_hif_delete(p_nthw_hif);
 
+	/* (b) Init RAB0 */
+	nthw_rac_rab_init(p_fpga_info->mp_nthw_rac, 0x7);
+	nthw_rac_rab_init(p_fpga_info->mp_nthw_rac, 0x6);
+
+	/* Create PRM */
+	p_fpga_info->mp_nthw_agx.p_prm = nthw_prm_nt400dxx_new();
+	res = nthw_prm_nt400dxx_init(p_fpga_info->mp_nthw_agx.p_prm, p_fpga, 0);
+
+	if (res != 0)
+		return res;
+
 	/* Create PCM */
 	p_fpga_info->mp_nthw_agx.p_pcm = nthw_pcm_nt400dxx_new();
 	res = nthw_pcm_nt400dxx_init(p_fpga_info->mp_nthw_agx.p_pcm, p_fpga, 0);
diff --git a/drivers/net/ntnic/nthw/core/nthw_prm_nt400dxx.c b/drivers/net/ntnic/nthw/core/nthw_prm_nt400dxx.c
new file mode 100644
index 0000000000..b1910fdbd5
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_prm_nt400dxx.c
@@ -0,0 +1,43 @@
+/*
+ * 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_prm_nt400dxx.h"
+
+nthw_prm_nt400dxx_t *nthw_prm_nt400dxx_new(void)
+{
+	nthw_prm_nt400dxx_t *p = malloc(sizeof(nthw_prm_nt400dxx_t));
+
+	if (p)
+		memset(p, 0, sizeof(nthw_prm_nt400dxx_t));
+
+	return p;
+}
+
+int nthw_prm_nt400dxx_init(nthw_prm_nt400dxx_t *p, nthw_fpga_t *p_fpga, int n_instance)
+{
+	nthw_module_t *p_mod = nthw_fpga_query_module(p_fpga, MOD_PRM_NT400DXX, n_instance);
+
+	if (p == NULL)
+		return p_mod == NULL ? -1 : 0;
+
+	if (p_mod == NULL) {
+		NT_LOG(ERR, NTHW, "%s: PRM_NT400DXX %d: no such instance",
+			p->mp_fpga->p_fpga_info->mp_adapter_id_str, p->mn_instance);
+		return -1;
+	}
+
+	p->mp_mod_prm = p_mod;
+
+	p->mp_fpga = p_fpga;
+	p->mn_instance = n_instance;
+
+	p->mp_reg_rst = nthw_module_get_register(p->mp_mod_prm, PRM_NT400DXX_RST);
+	p->mp_fld_rst_periph = nthw_register_get_field(p->mp_reg_rst, PRM_NT400DXX_RST_PERIPH);
+	p->mp_fld_rst_platform = nthw_register_get_field(p->mp_reg_rst, PRM_NT400DXX_RST_PLATFORM);
+	return 0;
+}
diff --git a/drivers/net/ntnic/nthw/nthw_drv.h b/drivers/net/ntnic/nthw/nthw_drv.h
index 955d0a37b0..ecd3bb9cc4 100644
--- a/drivers/net/ntnic/nthw/nthw_drv.h
+++ b/drivers/net/ntnic/nthw/nthw_drv.h
@@ -15,6 +15,7 @@
 #include "nthw_rpf.h"
 #include "nthw_pcm_nt400dxx.h"
 #include "nthw_phy_tile.h"
+#include "nthw_prm_nt400dxx.h"
 #include "nthw_pcm_nt400dxx.h"
 
 /*
@@ -27,6 +28,7 @@ typedef struct nthw_agx_s {
 	nthw_pca9532_t *p_pca9532_led;
 	nthw_si5332_t *p_si5332;
 	nthw_si5156_t *p_si5156;
+	nthw_prm_nt400dxx_t *p_prm;
 	nthw_pcm_nt400dxx_t *p_pcm;
 	nthw_phy_tile_t *p_phy_tile;
 	nthw_rpf_t *p_rpf;
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 24/32] net/ntnic: add nt400d13 PRM module reset
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (22 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 23/32] net/ntnic: add nt400d13 PRM module init Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 25/32] net/ntnic: add SPI v3 support for FPGA Serhii Iliushyk
                   ` (8 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Reset platform and peripherals for PRM initialization.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../net/ntnic/nthw/core/include/nthw_prm_nt400dxx.h |  2 ++
 .../core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c    | 13 +++++++++++++
 drivers/net/ntnic/nthw/core/nthw_prm_nt400dxx.c     | 12 ++++++++++++
 3 files changed, 27 insertions(+)

diff --git a/drivers/net/ntnic/nthw/core/include/nthw_prm_nt400dxx.h b/drivers/net/ntnic/nthw/core/include/nthw_prm_nt400dxx.h
index 09bfd79249..53692145b7 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_prm_nt400dxx.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_prm_nt400dxx.h
@@ -26,5 +26,7 @@ typedef struct nt_prm_nt400dxx nt_prm_nt400dxx;
 
 nthw_prm_nt400dxx_t *nthw_prm_nt400dxx_new(void);
 int nthw_prm_nt400dxx_init(nthw_prm_nt400dxx_t *p, nthw_fpga_t *p_fpga, int n_instance);
+void nthw_prm_nt400dxx_periph_rst(nthw_prm_nt400dxx_t *p, uint32_t val);
+void nthw_prm_nt400dxx_platform_rst(nthw_prm_nt400dxx_t *p, uint32_t val);
 
 #endif	/* NTHW_PRM_NT400DXX_H_ */
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
index 4d74db88de..ff29101e61 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
@@ -52,6 +52,19 @@ static int nthw_fpga_rst_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 	p_fpga_info->mp_nthw_agx.p_prm = nthw_prm_nt400dxx_new();
 	res = nthw_prm_nt400dxx_init(p_fpga_info->mp_nthw_agx.p_prm, p_fpga, 0);
 
+	if (res != 0)
+		return res;
+
+	/* (b1) Reset platform. It is released later */
+	nthw_prm_nt400dxx_platform_rst(p_fpga_info->mp_nthw_agx.p_prm, 1);
+	nt_os_wait_usec(10000);
+
+	/* (C) Reset peripherals and release the reset */
+	nthw_prm_nt400dxx_periph_rst(p_fpga_info->mp_nthw_agx.p_prm, 1);
+	nt_os_wait_usec(10000);
+	nthw_prm_nt400dxx_periph_rst(p_fpga_info->mp_nthw_agx.p_prm, 0);
+	nt_os_wait_usec(10000);
+
 	if (res != 0)
 		return res;
 
diff --git a/drivers/net/ntnic/nthw/core/nthw_prm_nt400dxx.c b/drivers/net/ntnic/nthw/core/nthw_prm_nt400dxx.c
index b1910fdbd5..286bda43f8 100644
--- a/drivers/net/ntnic/nthw/core/nthw_prm_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nthw_prm_nt400dxx.c
@@ -41,3 +41,15 @@ int nthw_prm_nt400dxx_init(nthw_prm_nt400dxx_t *p, nthw_fpga_t *p_fpga, int n_in
 	p->mp_fld_rst_platform = nthw_register_get_field(p->mp_reg_rst, PRM_NT400DXX_RST_PLATFORM);
 	return 0;
 }
+
+void nthw_prm_nt400dxx_periph_rst(nthw_prm_nt400dxx_t *p, uint32_t val)
+{
+	nthw_field_update_register(p->mp_fld_rst_periph);
+	nthw_field_set_val_flush32(p->mp_fld_rst_periph, val);
+}
+
+void nthw_prm_nt400dxx_platform_rst(nthw_prm_nt400dxx_t *p, uint32_t val)
+{
+	nthw_field_update_register(p->mp_fld_rst_platform);
+	nthw_field_set_val_flush32(p->mp_fld_rst_platform, val);
+}
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 25/32] net/ntnic: add SPI v3 support for FPGA
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (23 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 24/32] net/ntnic: add nt400d13 PRM module reset Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 26/32] net/ntnic: add i2cm init Serhii Iliushyk
                   ` (7 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

- Implement nthw_spi_v3 module with initialization, transfer, and
utility functions.
- Add nthw_spim and nthw_spis modules for SPI primary and secondary
interfaces.
- Include SPI v3 header files and update meson build configuration.
- Implement AVR probe function to retrieve and log AVR information.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 drivers/net/ntnic/meson.build                 |   3 +
 .../net/ntnic/nthw/core/include/nthw_fpga.h   |   2 +
 .../net/ntnic/nthw/core/include/nthw_spi_v3.h | 107 +++++
 .../net/ntnic/nthw/core/include/nthw_spim.h   |  58 +++
 .../net/ntnic/nthw/core/include/nthw_spis.h   |  63 +++
 .../nt400dxx/reset/nthw_fpga_rst_nt400dxx.c   |   2 +
 drivers/net/ntnic/nthw/core/nthw_fpga.c       | 444 ++++++++++++++++++
 drivers/net/ntnic/nthw/core/nthw_spi_v3.c     | 358 ++++++++++++++
 drivers/net/ntnic/nthw/core/nthw_spim.c       | 113 +++++
 drivers/net/ntnic/nthw/core/nthw_spis.c       | 121 +++++
 10 files changed, 1271 insertions(+)
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_spi_v3.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_spim.h
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_spis.h
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_spi_v3.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_spim.c
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_spis.c

diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 9885d4efbf..7e326a3e1d 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -69,6 +69,9 @@ sources = files(
         'nthw/core/nthw_rmc.c',
         'nthw/core/nthw_sdc.c',
         'nthw/core/nthw_si5340.c',
+        'nthw/core/nthw_spim.c',
+        'nthw/core/nthw_spis.c',
+        'nthw/core/nthw_spi_v3.c',
         'nthw/stat/nthw_stat.c',
         'nthw/flow_api/flow_api.c',
         'nthw/flow_api/flow_group.c',
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_fpga.h b/drivers/net/ntnic/nthw/core/include/nthw_fpga.h
index 8b1d548a25..418aea8277 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_fpga.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_fpga.h
@@ -18,6 +18,8 @@ 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_avr_probe(nthw_fpga_t *p_fpga, const int n_instance_no);
+
 int nthw_fpga_iic_scan(nthw_fpga_t *p_fpga, const int n_instance_no_begin,
 	const int n_instance_no_end);
 
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_spi_v3.h b/drivers/net/ntnic/nthw/core/include/nthw_spi_v3.h
new file mode 100644
index 0000000000..66b1f7f45d
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/include/nthw_spi_v3.h
@@ -0,0 +1,107 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NT4GA_SPI_V3__
+#define __NT4GA_SPI_V3__
+
+#include "nthw_spis.h"
+#include "nthw_spim.h"
+
+/* Must include v1.x series. The first v1.0a only had 248 bytes of storage. v2.0x have 255 */
+#define MAX_AVR_CONTAINER_SIZE (248)
+
+enum avr_opcodes {
+	__AVR_OP_NOP = 0,	/* v2 NOP command */
+	/* version handlers */
+	AVR_OP_VERSION = 1,
+	AVR_OP_SPI_VERSION = 2,	/* v2.0+ command Get protocol version */
+	AVR_OP_SYSINFO = 3,
+	/* Ping handlers */
+	AVR_OP_PING = 4,
+	AVR_OP_PING_DELAY = 5,
+	/* i2c handlers */
+	AVR_OP_I2C_READ = 9,
+	AVR_OP_I2C_WRITE = 10,
+	AVR_OP_I2C_RANDOM_READ = 11,
+	/* VPD handlers */
+	AVR_OP_VPD_READ = 19,
+	AVR_OP_VPD_WRITE = 20,
+	/* SENSOR handlers */
+	AVR_OP_SENSOR_FETCH = 28,
+	/* The following command are only relevant to V3 */
+	AVR_OP_SENSOR_MON_CONTROL = 42,
+	AVR_OP_SENSOR_MON_SETUP = 43,
+	/* special version handler */
+	AVR_OP_SYSINFO_2 = 62,
+};
+
+#define GEN2_AVR_IDENT_SIZE (20)
+#define GEN2_AVR_VERSION_SIZE (50)
+
+#define GEN2_PN_SIZE (13)
+#define GEN2_PBA_SIZE (16)
+#define GEN2_SN_SIZE (10)
+#define GEN2_BNAME_SIZE (14)
+#define GEN2_PLATFORM_SIZE (72)
+#define GEN2_VPD_SIZE_TOTAL                                                                       \
+	(1 + GEN2_PN_SIZE + GEN2_PBA_SIZE + GEN2_SN_SIZE + GEN2_BNAME_SIZE + GEN2_PLATFORM_SIZE + \
+	 2)
+
+typedef struct vpd_eeprom_s {
+	uint8_t psu_hw_version;	/* Hw revision - MUST NEVER ne overwritten. */
+	/* Vital Product Data: P/N   (13bytes ascii 0-9) */
+	uint8_t vpd_pn[GEN2_PN_SIZE];
+	/* Vital Product Data: PBA   (16bytes ascii 0-9) */
+	uint8_t vpd_pba[GEN2_PBA_SIZE];
+	/* Vital Product Data: S/N   (10bytes ascii 0-9) */
+	uint8_t vpd_sn[GEN2_SN_SIZE];
+	/* Vital Product Data: Board Name (10bytes ascii) (e.g. "ntmainb1e2" or "ntfront20b1") */
+	uint8_t vpd_board_name[GEN2_BNAME_SIZE];
+	/*
+	 * Vital Product Data: Other (72bytes of MAC addresses or other stuff.. (gives up to 12 mac
+	 * addresses)
+	 */
+	uint8_t vpd_platform_section[GEN2_PLATFORM_SIZE];
+	/* CRC16 checksum of all of above. This field is not included in the checksum */
+	uint16_t crc16;
+} vpd_eeprom_t;
+
+typedef struct {
+	uint8_t psu_hw_revision;
+	char board_type[GEN2_BNAME_SIZE + 1];
+	char product_id[GEN2_PN_SIZE + 1];
+	char pba_id[GEN2_PBA_SIZE + 1];
+	char serial_number[GEN2_SN_SIZE + 1];
+	uint8_t product_family;
+	uint32_t feature_mask;
+	uint32_t invfeature_mask;
+	uint8_t no_of_macs;
+	uint8_t mac_address[6];
+	uint16_t custom_id;
+	uint8_t user_id[8];
+} board_info_t;
+
+struct tx_rx_buf {
+	uint16_t size;
+	void *p_buf;
+};
+
+struct nthw_spi_v3 {
+	int m_time_out;
+	int mn_instance_no;
+	nthw_spim_t *mp_spim_mod;
+	nthw_spis_t *mp_spis_mod;
+};
+
+typedef struct nthw_spi_v3 nthw_spi_v3_t;
+typedef struct nthw_spi_v3 nthw_spi_v3;
+
+nthw_spi_v3_t *nthw_spi_v3_new(void);
+int nthw_spi_v3_init(nthw_spi_v3_t *p, nthw_fpga_t *p_fpga, int n_instance_no);
+
+int nthw_spi_v3_transfer(nthw_spi_v3_t *p, uint16_t opcode, struct tx_rx_buf *tx_buf,
+	struct tx_rx_buf *rx_buf);
+
+#endif	/* __NT4GA_SPI_V3__ */
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_spim.h b/drivers/net/ntnic/nthw/core/include/nthw_spim.h
new file mode 100644
index 0000000000..70a49ab627
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/include/nthw_spim.h
@@ -0,0 +1,58 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_SPIM_H__
+#define __NTHW_SPIM_H__
+
+#include "nthw_fpga.h"
+
+struct nthw_spim {
+	nthw_fpga_t *mp_fpga;
+	nthw_module_t *mp_mod_spim;
+	int mn_instance;
+
+	nthw_register_t *mp_reg_srr;
+	nthw_field_t *mp_fld_srr_rst;
+
+	nthw_register_t *mp_reg_cr;
+	nthw_field_t *mp_fld_cr_loop;
+	nthw_field_t *mp_fld_cr_en;
+	nthw_field_t *mp_fld_cr_txrst;
+	nthw_field_t *mp_fld_cr_rxrst;
+
+	nthw_register_t *mp_reg_sr;
+	nthw_field_t *mp_fld_sr_done;
+	nthw_field_t *mp_fld_sr_txempty;
+	nthw_field_t *mp_fld_sr_rxempty;
+	nthw_field_t *mp_fld_sr_txfull;
+	nthw_field_t *mp_fld_sr_rxfull;
+	nthw_field_t *mp_fld_sr_txlvl;
+	nthw_field_t *mp_fld_sr_rxlvl;
+
+	nthw_register_t *mp_reg_dtr;
+	nthw_field_t *mp_fld_dtr_dtr;
+
+	nthw_register_t *mp_reg_drr;
+	nthw_field_t *mp_fld_drr_drr;
+
+	nthw_register_t *mp_reg_cfg;
+	nthw_field_t *mp_fld_cfg_pre;
+
+	nthw_register_t *mp_reg_cfg_clk;
+	nthw_field_t *mp_fld_cfg_clk_mode;
+};
+
+typedef struct nthw_spim nthw_spim_t;
+typedef struct nthw_spim nthw_spim;
+
+nthw_spim_t *nthw_spim_new(void);
+int nthw_spim_init(nthw_spim_t *p, nthw_fpga_t *p_fpga, int n_instance);
+
+uint32_t nthw_spim_reset(nthw_spim_t *p);
+uint32_t nthw_spim_enable(nthw_spim_t *p, bool b_enable);
+uint32_t nthw_spim_get_tx_fifo_empty(nthw_spim_t *p, bool *pb_empty);
+uint32_t nthw_spim_write_tx_fifo(nthw_spim_t *p, uint32_t n_data);
+
+#endif	/* __NTHW_SPIM_H__ */
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_spis.h b/drivers/net/ntnic/nthw/core/include/nthw_spis.h
new file mode 100644
index 0000000000..978f239dd0
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/include/nthw_spis.h
@@ -0,0 +1,63 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_SPIS_H__
+#define __NTHW_SPIS_H__
+
+#include "nthw_fpga.h"
+
+struct nthw_spis {
+	nthw_fpga_t *mp_fpga;
+	nthw_module_t *mp_mod_spis;
+	int mn_instance;
+
+	nthw_register_t *mp_reg_srr;
+	nthw_field_t *mp_fld_srr_rst;
+
+	nthw_register_t *mp_reg_cr;
+	nthw_field_t *mp_fld_cr_loop;
+	nthw_field_t *mp_fld_cr_en;
+	nthw_field_t *mp_fld_cr_txrst;
+	nthw_field_t *mp_fld_cr_rxrst;
+	nthw_field_t *mp_fld_cr_debug;
+
+	nthw_register_t *mp_reg_sr;
+	nthw_field_t *mp_fld_sr_done;
+	nthw_field_t *mp_fld_sr_txempty;
+	nthw_field_t *mp_fld_sr_rxempty;
+	nthw_field_t *mp_fld_sr_txfull;
+	nthw_field_t *mp_fld_sr_rxfull;
+	nthw_field_t *mp_fld_sr_txlvl;
+	nthw_field_t *mp_fld_sr_rxlvl;
+	nthw_field_t *mp_fld_sr_frame_err;
+	nthw_field_t *mp_fld_sr_read_err;
+	nthw_field_t *mp_fld_sr_write_err;
+
+	nthw_register_t *mp_reg_dtr;
+	nthw_field_t *mp_fld_dtr_dtr;
+
+	nthw_register_t *mp_reg_drr;
+	nthw_field_t *mp_fld_drr_drr;
+
+	nthw_register_t *mp_reg_ram_ctrl;
+	nthw_field_t *mp_fld_ram_ctrl_adr;
+	nthw_field_t *mp_fld_ram_ctrl_cnt;
+
+	nthw_register_t *mp_reg_ram_data;
+	nthw_field_t *mp_fld_ram_data_data;
+};
+
+typedef struct nthw_spis nthw_spis_t;
+typedef struct nthw_spis nthw_spis;
+
+nthw_spis_t *nthw_spis_new(void);
+int nthw_spis_init(nthw_spis_t *p, nthw_fpga_t *p_fpga, int n_instance);
+
+uint32_t nthw_spis_reset(nthw_spis_t *p);
+uint32_t nthw_spis_enable(nthw_spis_t *p, bool b_enable);
+uint32_t nthw_spis_get_rx_fifo_empty(nthw_spis_t *p, bool *pb_empty);
+uint32_t nthw_spis_read_rx_fifo(nthw_spis_t *p, uint32_t *p_data);
+
+#endif	/* __NTHW_SPIS_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
index ff29101e61..73feaa4ebd 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
@@ -65,6 +65,8 @@ static int nthw_fpga_rst_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 	nthw_prm_nt400dxx_periph_rst(p_fpga_info->mp_nthw_agx.p_prm, 0);
 	nt_os_wait_usec(10000);
 
+	res = nthw_fpga_avr_probe(p_fpga, 0);
+
 	if (res != 0)
 		return res;
 
diff --git a/drivers/net/ntnic/nthw/core/nthw_fpga.c b/drivers/net/ntnic/nthw/core/nthw_fpga.c
index e54a210c9f..3166a2ba51 100644
--- a/drivers/net/ntnic/nthw/core/nthw_fpga.c
+++ b/drivers/net/ntnic/nthw/core/nthw_fpga.c
@@ -14,6 +14,7 @@
 #include "nthw_fpga_mod_str_map.h"
 
 #include "nthw_tsm.h"
+#include "nthw_spi_v3.h"
 
 #include <arpa/inet.h>
 
@@ -151,6 +152,449 @@ int nthw_fpga_silabs_detect(nthw_fpga_t *p_fpga, const int n_instance_no, const
 	return res;
 }
 
+/*
+ * Calculate CRC-16-CCITT of passed data
+ * CRC-16-CCITT ^16 + ^12 + ^5 + 1 (0x1021) (X.25, HDLC, XMODEM, Bluetooth,
+ *   SD, many others; known as CRC-CCITT)
+ */
+static uint16_t crc16(uint8_t *buffer, size_t length)
+{
+	uint16_t seed = 0;
+
+	while (length--) {
+		seed = (uint16_t)(seed >> 8 | seed << 8);
+		seed = (uint16_t)(seed ^ *buffer++);
+		seed = (uint16_t)(seed ^ (seed & 0xff) >> 4);
+		seed = (uint16_t)(seed ^ seed << 8 << 4);
+		seed = (uint16_t)(seed ^ (seed & 0xff) << 4 << 1);
+	}
+
+	return seed;
+}
+
+int nthw_fpga_avr_probe(nthw_fpga_t *p_fpga, const int n_instance_no)
+{
+	struct fpga_info_s *p_fpga_info = p_fpga->p_fpga_info;
+	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+	nthw_spi_v3_t *p_avr_spi;
+	int res = -1;
+
+	p_avr_spi = nthw_spi_v3_new();
+
+	if (p_avr_spi) {
+		struct avr_vpd_info_s {
+			/* avr info */
+			uint32_t n_avr_spi_version;
+			uint8_t n_avr_fw_ver_major;
+			uint8_t n_avr_fw_ver_minor;
+			uint8_t n_avr_fw_ver_micro;
+			uint8_t a_avr_fw_ver_str[50];
+			uint8_t a_avr_fw_plat_id_str[20];
+
+			/* vpd_eeprom_t */
+			uint8_t psu_hw_version;
+			uint8_t vpd_pn[GEN2_PN_SIZE];
+			uint8_t vpd_pba[GEN2_PBA_SIZE];
+			uint8_t vpd_sn[GEN2_SN_SIZE];
+			uint8_t vpd_board_name[GEN2_BNAME_SIZE];
+			uint8_t vpd_platform_section[GEN2_PLATFORM_SIZE];
+
+			/* board_info_t aka vpd_platform_section: */
+			uint32_t product_family;/* uint8_t 1: capture, 2: Inline, 3: analysis */
+			uint32_t feature_mask;	/* Bit 0: OC192 capable */
+			uint32_t invfeature_mask;
+			uint8_t no_of_macs;
+			uint8_t mac_address[6];
+			uint16_t custom_id;
+			uint8_t user_id[8];
+			/*
+			 * Reserved NT operations to monitor the reprogram count of user_id with
+			 * vpduser
+			 */
+			uint16_t user_id_erase_write_count;
+
+			/*
+			 * AVR_OP_SYSINFO: struct version_sysinfo_request_container
+			 * Which version of the sysinfo container to retrieve. Set to zero to fetch
+			 * latest. Offset zero of latest always contain an uint8_t version info
+			 */
+			uint8_t sysinfo_container_version;
+
+			/* AVR_OP_SYSINFO: struct AvrLibcVersion */
+			/* The constant __AVR_LIBC_VERSION__ */
+			uint32_t sysinfo_avr_libc_version;
+
+			/* AVR_OP_SYSINFO: struct AvrLibcSignature */
+			uint8_t sysinfo_signature_0;	/* The constant SIGNATURE_0 */
+			uint8_t sysinfo_signature_1;	/* The constant SIGNATURE_1 */
+			uint8_t sysinfo_signature_2;	/* The constant SIGNATURE_2 */
+
+			/* AVR_OP_SYSINFO: struct AvrOs */
+			uint8_t sysinfo_spi_version;	/* SPI command layer version */
+			/*
+			 * Hardware revision. Locked to eeprom address zero. Is also available via
+			 * VPD read opcode (prior to v1.4b, this is required)
+			 */
+			uint8_t sysinfo_hw_revision;
+			/*
+			 * Number of ticks/second (Note: Be aware this may become zero if timer
+			 * module is rewritten to a tickles system!)
+			 */
+			uint8_t sysinfo_ticks_per_second;
+			uint32_t sysinfo_uptime;/* Uptime in seconds since last AVR reset */
+			uint8_t sysinfo_osccal;	/* OSCCAL value */
+
+			/*
+			 * Meta data concluded/calculated from req/reply
+			 */
+			bool b_feature_mask_valid;
+			bool b_crc16_valid;
+			uint16_t n_crc16_stored;
+			uint16_t n_crc16_calced;
+			uint64_t n_mac_val;
+		};
+
+		struct avr_vpd_info_s avr_vpd_info;
+		struct tx_rx_buf tx_buf;
+		struct tx_rx_buf rx_buf;
+		char rx_data[MAX_AVR_CONTAINER_SIZE];
+		uint32_t u32;
+
+		memset(&avr_vpd_info, 0, sizeof(avr_vpd_info));
+
+		nthw_spi_v3_init(p_avr_spi, p_fpga, n_instance_no);
+
+		/* AVR_OP_SPI_VERSION */
+		tx_buf.size = 0;
+		tx_buf.p_buf = NULL;
+		rx_buf.size = sizeof(u32);
+		rx_buf.p_buf = &u32;
+		u32 = 0;
+		res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SPI_VERSION, &tx_buf, &rx_buf);
+		avr_vpd_info.n_avr_spi_version = u32;
+		NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d", p_adapter_id_str, n_instance_no,
+			avr_vpd_info.n_avr_spi_version);
+
+		/* AVR_OP_VERSION */
+		tx_buf.size = 0;
+		tx_buf.p_buf = NULL;
+		rx_buf.size = sizeof(rx_data);
+		rx_buf.p_buf = &rx_data;
+		res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_VERSION, &tx_buf, &rx_buf);
+
+		avr_vpd_info.n_avr_fw_ver_major = rx_data[0];
+		avr_vpd_info.n_avr_fw_ver_minor = rx_data[1];
+		avr_vpd_info.n_avr_fw_ver_micro = rx_data[2];
+		NT_LOG(DBG, NTHW, "%s: AVR%d: FW_VER: %c.%c.%c", p_adapter_id_str, n_instance_no,
+			avr_vpd_info.n_avr_fw_ver_major, avr_vpd_info.n_avr_fw_ver_minor,
+			avr_vpd_info.n_avr_fw_ver_micro);
+
+		memcpy(avr_vpd_info.a_avr_fw_ver_str, &rx_data[0 + 3],
+			sizeof(avr_vpd_info.a_avr_fw_ver_str));
+		NT_LOG(DBG, NTHW, "%s: AVR%d: FW_VER_STR: '%.*s'", p_adapter_id_str,
+			n_instance_no, (int)sizeof(avr_vpd_info.a_avr_fw_ver_str),
+			avr_vpd_info.a_avr_fw_ver_str);
+
+		memcpy(avr_vpd_info.a_avr_fw_plat_id_str, &rx_data[0 + 3 + 50],
+			sizeof(avr_vpd_info.a_avr_fw_plat_id_str));
+		NT_LOG(DBG, NTHW, "%s: AVR%d: FW_HW_ID_STR: '%.*s'", p_adapter_id_str,
+			n_instance_no, (int)sizeof(avr_vpd_info.a_avr_fw_plat_id_str),
+			avr_vpd_info.a_avr_fw_plat_id_str);
+
+		snprintf(p_fpga_info->nthw_hw_info.hw_plat_id_str,
+			sizeof(p_fpga_info->nthw_hw_info.hw_plat_id_str), "%s",
+			(char *)avr_vpd_info.a_avr_fw_plat_id_str);
+		p_fpga_info->nthw_hw_info
+		.hw_plat_id_str[sizeof(p_fpga_info->nthw_hw_info.hw_plat_id_str) - 1] = 0;
+
+		/* AVR_OP_SYSINFO_2 */
+		tx_buf.size = 0;
+		tx_buf.p_buf = NULL;
+		rx_buf.size = sizeof(rx_data);
+		rx_buf.p_buf = &rx_data;
+		res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SYSINFO_2, &tx_buf, &rx_buf);
+
+		if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 && rx_buf.size >= 16) {
+			if (rx_buf.size != 16) {
+				NT_LOG(WRN, NTHW,
+					"%s: AVR%d: SYSINFO2: reply is larger than expected: %04X %04X",
+					p_adapter_id_str, n_instance_no, rx_buf.size, 16);
+
+			} else {
+				NT_LOG(DBG, NTHW, "%s: AVR%d: SYSINFO2: OK: res=%d sz=%d",
+					p_adapter_id_str, n_instance_no, res, rx_buf.size);
+			}
+
+			avr_vpd_info.sysinfo_container_version = rx_data[0];
+			NT_LOG(DBG, NTHW, "%s: AVR%d: SYSINFO_REQ_VER: %d", p_adapter_id_str,
+				n_instance_no, avr_vpd_info.sysinfo_container_version);
+
+			memcpy(&avr_vpd_info.sysinfo_avr_libc_version, &rx_data[0 + 1],
+				sizeof(avr_vpd_info.sysinfo_avr_libc_version));
+			NT_LOG(DBG, NTHW, "%s: AVR%d: LIBC_VER: %d", p_adapter_id_str,
+				n_instance_no, avr_vpd_info.sysinfo_avr_libc_version);
+
+			avr_vpd_info.sysinfo_signature_0 = rx_data[5];
+			avr_vpd_info.sysinfo_signature_1 = rx_data[6];
+			avr_vpd_info.sysinfo_signature_2 = rx_data[7];
+			NT_LOG(DBG, NTHW, "%s: AVR%d: SIGNATURE: %02x%02x%02x", p_adapter_id_str,
+				n_instance_no, avr_vpd_info.sysinfo_signature_0,
+				avr_vpd_info.sysinfo_signature_1, avr_vpd_info.sysinfo_signature_2);
+
+			avr_vpd_info.sysinfo_spi_version = rx_data[8];
+			NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d", p_adapter_id_str,
+				n_instance_no, avr_vpd_info.sysinfo_spi_version);
+
+			avr_vpd_info.sysinfo_hw_revision = rx_data[9];
+			NT_LOG(DBG, NTHW, "%s: AVR%d: HW_REV: %d", p_adapter_id_str,
+				n_instance_no, avr_vpd_info.sysinfo_hw_revision);
+
+			avr_vpd_info.sysinfo_ticks_per_second = rx_data[10];
+			NT_LOG(DBG, NTHW, "%s: AVR%d: TICKS_PER_SEC: %d", p_adapter_id_str,
+				n_instance_no, avr_vpd_info.sysinfo_ticks_per_second);
+
+			memcpy(&avr_vpd_info.sysinfo_uptime, &rx_data[11],
+				sizeof(avr_vpd_info.sysinfo_uptime));
+			NT_LOG(DBG, NTHW, "%s: AVR%d: UPTIME: %d", p_adapter_id_str,
+				n_instance_no, avr_vpd_info.sysinfo_uptime);
+
+			avr_vpd_info.sysinfo_osccal = rx_data[15];
+			NT_LOG(DBG, NTHW, "%s: AVR%d: OSCCAL: %d", p_adapter_id_str,
+				n_instance_no, avr_vpd_info.sysinfo_osccal);
+
+			{
+				bool b_spi_ver_match = (avr_vpd_info.n_avr_spi_version ==
+						avr_vpd_info.sysinfo_spi_version);
+				(void)b_spi_ver_match;
+				NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER_TST: %s (%d %d)",
+					p_adapter_id_str, n_instance_no,
+					(b_spi_ver_match ? "OK" : "MISMATCH"),
+					avr_vpd_info.n_avr_spi_version,
+					avr_vpd_info.sysinfo_spi_version);
+			}
+
+			/* SYSINFO2: if response: only populate hw_id not hw_id_emulated */
+			p_fpga_info->nthw_hw_info.hw_id = avr_vpd_info.sysinfo_hw_revision;
+
+		} else {
+			/* AVR_OP_SYSINFO */
+			tx_buf.size = 0;
+			tx_buf.p_buf = NULL;
+			rx_buf.size = sizeof(rx_data);
+			rx_buf.p_buf = &rx_data;
+			res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_SYSINFO, &tx_buf, &rx_buf);
+
+			if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 && rx_buf.size >= 16) {
+				if (rx_buf.size != 16) {
+					NT_LOG(WRN, NTHW,
+						"%s: AVR%d: SYSINFO: reply is larger than expected: %04X %04X",
+						p_adapter_id_str, n_instance_no, rx_buf.size, 16);
+
+				} else {
+					NT_LOG(DBG, NTHW, "%s: AVR%d: SYSINFO: OK: res=%d sz=%d",
+						p_adapter_id_str, n_instance_no, res, rx_buf.size);
+				}
+
+				avr_vpd_info.sysinfo_container_version = rx_data[0];
+				NT_LOG(DBG, NTHW, "%s: AVR%d: SYSINFO_REQ_VER: %d",
+					p_adapter_id_str, n_instance_no,
+					avr_vpd_info.sysinfo_container_version);
+
+				memcpy(&avr_vpd_info.sysinfo_avr_libc_version, &rx_data[0 + 1],
+					sizeof(avr_vpd_info.sysinfo_avr_libc_version));
+				NT_LOG(DBG, NTHW, "%s: AVR%d: LIBC_VER: %d", p_adapter_id_str,
+					n_instance_no, avr_vpd_info.sysinfo_avr_libc_version);
+
+				avr_vpd_info.sysinfo_signature_0 = rx_data[5];
+				avr_vpd_info.sysinfo_signature_1 = rx_data[6];
+				avr_vpd_info.sysinfo_signature_2 = rx_data[7];
+				NT_LOG(DBG, NTHW, "%s: AVR%d: SIGNATURE: %02x%02x%02x",
+					p_adapter_id_str, n_instance_no,
+					avr_vpd_info.sysinfo_signature_0,
+					avr_vpd_info.sysinfo_signature_1,
+					avr_vpd_info.sysinfo_signature_2);
+
+				avr_vpd_info.sysinfo_spi_version = rx_data[8];
+				NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER: %d", p_adapter_id_str,
+					n_instance_no, avr_vpd_info.sysinfo_spi_version);
+
+				avr_vpd_info.sysinfo_hw_revision = rx_data[9];
+				NT_LOG(DBG, NTHW, "%s: AVR%d: HW_REV: %d", p_adapter_id_str,
+					n_instance_no, avr_vpd_info.sysinfo_hw_revision);
+				NT_LOG(INF, NTHW, "%s: AVR%d: HW_REV: %d", p_adapter_id_str,
+					n_instance_no, avr_vpd_info.sysinfo_hw_revision);
+
+				avr_vpd_info.sysinfo_ticks_per_second = rx_data[10];
+				NT_LOG(DBG, NTHW, "%s: AVR%d: TICKS_PER_SEC: %d",
+					p_adapter_id_str, n_instance_no,
+					avr_vpd_info.sysinfo_ticks_per_second);
+
+				memcpy(&avr_vpd_info.sysinfo_uptime, &rx_data[11],
+					sizeof(avr_vpd_info.sysinfo_uptime));
+				NT_LOG(DBG, NTHW, "%s: AVR%d: UPTIME: %d", p_adapter_id_str,
+					n_instance_no, avr_vpd_info.sysinfo_uptime);
+
+				avr_vpd_info.sysinfo_osccal = rx_data[15];
+				NT_LOG(DBG, NTHW, "%s: AVR%d: OSCCAL: %d", p_adapter_id_str,
+					n_instance_no, avr_vpd_info.sysinfo_osccal);
+
+				{
+					bool b_spi_ver_match = (avr_vpd_info.n_avr_spi_version ==
+							avr_vpd_info.sysinfo_spi_version);
+					(void)b_spi_ver_match;
+					NT_LOG(DBG, NTHW, "%s: AVR%d: SPI_VER_TST: %s (%d %d)",
+						p_adapter_id_str, n_instance_no,
+						(b_spi_ver_match ? "OK" : "MISMATCH"),
+						avr_vpd_info.n_avr_spi_version,
+						avr_vpd_info.sysinfo_spi_version);
+				}
+
+				p_fpga_info->nthw_hw_info.hw_id = avr_vpd_info.sysinfo_hw_revision;
+				p_fpga_info->nthw_hw_info.hw_id_emulated =
+					avr_vpd_info.sysinfo_hw_revision;
+
+			} else {
+				NT_LOG(ERR, NTHW, "%s: AVR%d: SYSINFO: NA: res=%d sz=%d",
+					p_adapter_id_str, n_instance_no, res, rx_buf.size);
+			}
+		}
+
+		/* AVR_OP_VPD_READ */
+		tx_buf.size = 0;
+		tx_buf.p_buf = NULL;
+		rx_buf.size = sizeof(rx_data);
+		rx_buf.p_buf = &rx_data;
+		res = nthw_spi_v3_transfer(p_avr_spi, AVR_OP_VPD_READ, &tx_buf, &rx_buf);
+
+		if (res == 0 && avr_vpd_info.n_avr_spi_version >= 3 &&
+			rx_buf.size >= GEN2_VPD_SIZE_TOTAL) {
+			avr_vpd_info.n_crc16_calced = crc16(rx_buf.p_buf, rx_buf.size - 2);
+			memcpy(&avr_vpd_info.n_crc16_stored, &rx_data[rx_buf.size - 2],
+				sizeof(avr_vpd_info.n_crc16_stored));
+			NT_LOG(DBG, NTHW, "%s: AVR%d: VPD_CRC: %04X %04X", p_adapter_id_str,
+				n_instance_no, avr_vpd_info.n_crc16_stored,
+				avr_vpd_info.n_crc16_calced);
+
+			avr_vpd_info.b_crc16_valid =
+				(avr_vpd_info.n_crc16_stored == avr_vpd_info.n_crc16_calced);
+			NT_LOG(DBG, NTHW, "%s: AVR%d: CRC_TST: %s", p_adapter_id_str,
+				n_instance_no, (avr_vpd_info.b_crc16_valid ? "OK" : "ERROR"));
+
+			if (avr_vpd_info.b_crc16_valid) {
+				memcpy(&avr_vpd_info.psu_hw_version, &rx_data[0],
+					sizeof(avr_vpd_info.psu_hw_version));
+				NT_LOG(DBG, NTHW, "%s: AVR%d: PSU_HW_VER: %d", p_adapter_id_str,
+					n_instance_no, avr_vpd_info.psu_hw_version);
+
+				memcpy(&avr_vpd_info.vpd_pn, &rx_data[0 + 1],
+					sizeof(avr_vpd_info.vpd_pn));
+				NT_LOG(DBG, NTHW, "%s: AVR%d: PN: '%.*s'", p_adapter_id_str,
+					n_instance_no, GEN2_PN_SIZE, avr_vpd_info.vpd_pn);
+
+				memcpy(&avr_vpd_info.vpd_pba, &rx_data[0 + 1 + GEN2_PN_SIZE],
+					sizeof(avr_vpd_info.vpd_pba));
+				NT_LOG(DBG, NTHW, "%s: AVR%d: PBA: '%.*s'", p_adapter_id_str,
+					n_instance_no, GEN2_PBA_SIZE, avr_vpd_info.vpd_pba);
+
+				memcpy(&avr_vpd_info.vpd_sn,
+					&rx_data[0 + 1 + GEN2_PN_SIZE + GEN2_PBA_SIZE],
+					sizeof(avr_vpd_info.vpd_sn));
+				NT_LOG(DBG, NTHW, "%s: AVR%d: SN: '%.*s", p_adapter_id_str,
+					n_instance_no, GEN2_SN_SIZE, avr_vpd_info.vpd_sn);
+
+				memcpy(&avr_vpd_info.vpd_board_name,
+					&rx_data[0 + 1 + GEN2_PN_SIZE + GEN2_PBA_SIZE +
+						GEN2_SN_SIZE],
+					sizeof(avr_vpd_info.vpd_board_name));
+				NT_LOG(DBG, NTHW, "%s: AVR%d: BN: '%.*s'", p_adapter_id_str,
+					n_instance_no, GEN2_BNAME_SIZE,
+					avr_vpd_info.vpd_board_name);
+
+				union mac_u {
+					uint8_t a_u8[8];
+					uint16_t a_u16[4];
+					uint32_t a_u32[2];
+					uint64_t a_u64[1];
+				} mac;
+
+				/* vpd_platform_section */
+				uint8_t *p_vpd_board_info =
+					(uint8_t *)(&rx_data[1 + GEN2_PN_SIZE + GEN2_PBA_SIZE +
+					GEN2_SN_SIZE + GEN2_BNAME_SIZE]);
+				memcpy(&avr_vpd_info.product_family, &p_vpd_board_info[0],
+					sizeof(avr_vpd_info.product_family));
+				NT_LOG(DBG, NTHW, "%s: AVR%d: PROD_FAM: %d", p_adapter_id_str,
+					n_instance_no, avr_vpd_info.product_family);
+
+				memcpy(&avr_vpd_info.feature_mask, &p_vpd_board_info[0 + 4],
+					sizeof(avr_vpd_info.feature_mask));
+				NT_LOG(DBG, NTHW, "%s: AVR%d: FMSK_VAL: 0x%08X",
+					p_adapter_id_str, n_instance_no, avr_vpd_info.feature_mask);
+
+				memcpy(&avr_vpd_info.invfeature_mask, &p_vpd_board_info[0 + 4 + 4],
+					sizeof(avr_vpd_info.invfeature_mask));
+				NT_LOG(DBG, NTHW, "%s: AVR%d: FMSK_INV: 0x%08X",
+					p_adapter_id_str, n_instance_no,
+					avr_vpd_info.invfeature_mask);
+
+				avr_vpd_info.b_feature_mask_valid =
+					(avr_vpd_info.feature_mask ==
+						~avr_vpd_info.invfeature_mask);
+				NT_LOG(DBG, NTHW, "%s: AVR%d: FMSK_TST: %s", p_adapter_id_str,
+					n_instance_no,
+					(avr_vpd_info.b_feature_mask_valid ? "OK" : "ERROR"));
+
+				memcpy(&avr_vpd_info.no_of_macs, &p_vpd_board_info[0 + 4 + 4 + 4],
+					sizeof(avr_vpd_info.no_of_macs));
+				NT_LOG(DBG, NTHW, "%s: AVR%d: NUM_MACS: %d", p_adapter_id_str,
+					n_instance_no, avr_vpd_info.no_of_macs);
+
+				memcpy(&avr_vpd_info.mac_address,
+					&p_vpd_board_info[0 + 4 + 4 + 4 + 1],
+					sizeof(avr_vpd_info.mac_address));
+				NT_LOG(DBG, NTHW,
+					"%s: AVR%d: MAC_ADDR: %02x:%02x:%02x:%02x:%02x:%02x",
+					p_adapter_id_str, n_instance_no,
+					avr_vpd_info.mac_address[0], avr_vpd_info.mac_address[1],
+					avr_vpd_info.mac_address[2], avr_vpd_info.mac_address[3],
+					avr_vpd_info.mac_address[4], avr_vpd_info.mac_address[5]);
+
+				mac.a_u64[0] = 0;
+				memcpy(&mac.a_u8[2], &avr_vpd_info.mac_address,
+					sizeof(avr_vpd_info.mac_address));
+				{
+					const uint32_t u1 = ntohl(mac.a_u32[0]);
+
+					if (u1 != mac.a_u32[0]) {
+						const uint32_t u0 = ntohl(mac.a_u32[1]);
+						mac.a_u32[0] = u0;
+						mac.a_u32[1] = u1;
+					}
+				}
+
+				avr_vpd_info.n_mac_val = mac.a_u64[0];
+				NT_LOG(DBG, NTHW, "%s: AVR%d: MAC_U64: %012" PRIX64 "",
+					p_adapter_id_str, n_instance_no, avr_vpd_info.n_mac_val);
+			}
+
+			p_fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_count =
+				avr_vpd_info.no_of_macs;
+			p_fpga_info->nthw_hw_info.vpd_info.mn_mac_addr_value =
+				avr_vpd_info.n_mac_val;
+			memcpy(p_fpga_info->nthw_hw_info.vpd_info.ma_mac_addr_octets,
+				avr_vpd_info.mac_address,
+				ARRAY_SIZE(p_fpga_info->nthw_hw_info.vpd_info.ma_mac_addr_octets));
+
+		} else {
+			NT_LOG(ERR, NTHW, "%s:%u: res=%d", __func__, __LINE__, res);
+			NT_LOG(ERR, NTHW, "%s: AVR%d: SYSINFO2: NA: res=%d sz=%d",
+				p_adapter_id_str, n_instance_no, res, rx_buf.size);
+		}
+	}
+
+	return res;
+}
+
 /*
  * NT200A02, NT200A01-HWbuild2
  */
diff --git a/drivers/net/ntnic/nthw/core/nthw_spi_v3.c b/drivers/net/ntnic/nthw/core/nthw_spi_v3.c
new file mode 100644
index 0000000000..0b611462a0
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spi_v3.c
@@ -0,0 +1,358 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_fpga.h"
+
+#include "nthw_spi_v3.h"
+
+#include <arpa/inet.h>
+
+#undef SPI_V3_DEBUG_PRINT
+
+nthw_spi_v3_t *nthw_spi_v3_new(void)
+{
+	nthw_spi_v3_t *p = malloc(sizeof(nthw_spi_v3_t));
+
+	if (p)
+		memset(p, 0, sizeof(nthw_spi_v3_t));
+
+	return p;
+}
+
+static int nthw_spi_v3_set_timeout(nthw_spi_v3_t *p, int time_out)
+{
+	p->m_time_out = time_out;
+	return 0;
+}
+
+/*
+ * Wait until Tx data have been sent after they have been placed in the Tx FIFO.
+ */
+static int wait_for_tx_data_sent(nthw_spim_t *p_spim_mod, uint64_t time_out)
+{
+	int result;
+	bool empty;
+	uint64_t start_time;
+	uint64_t cur_time;
+	start_time = nt_os_get_time_monotonic_counter();
+
+	while (true) {
+		nt_os_wait_usec(1000);	/* Every 1ms */
+
+		result = nthw_spim_get_tx_fifo_empty(p_spim_mod, &empty);
+
+		if (result != 0) {
+			NT_LOG(WRN, NTHW, "nthw_spim_get_tx_fifo_empty failed");
+			return result;
+		}
+
+		if (empty)
+			break;
+
+		cur_time = nt_os_get_time_monotonic_counter();
+
+		if ((cur_time - start_time) > time_out) {
+			NT_LOG(WRN, NTHW, "%s: Timed out", __func__);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Wait until Rx data have been received.
+ */
+static int wait_for_rx_data_ready(nthw_spis_t *p_spis_mod, uint64_t time_out)
+{
+	int result;
+	bool empty;
+	uint64_t start_time;
+	uint64_t cur_time;
+	start_time = nt_os_get_time_monotonic_counter();
+
+	/* Wait for data to become ready in the Rx FIFO */
+	while (true) {
+		nt_os_wait_usec(10000);	/* Every 10ms */
+
+		result = nthw_spis_get_rx_fifo_empty(p_spis_mod, &empty);
+
+		if (result != 0) {
+			NT_LOG(WRN, NTHW, "nthw_spis_get_rx_empty failed");
+			return result;
+		}
+
+		if (!empty)
+			break;
+
+		cur_time = nt_os_get_time_monotonic_counter();
+
+		if ((cur_time - start_time) > time_out) {
+			NT_LOG(WRN, NTHW, "%s: Timed out", __func__);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+#ifdef SPI_V3_DEBUG_PRINT
+static void dump_hex(uint8_t *p_data, uint16_t count)
+{
+	int i;
+	int j = 0;
+	char tmp_str[128];
+
+	for (i = 0; i < count; i++) {
+		sprintf(&tmp_str[j * 3], "%02X ", *(p_data++));
+		j++;
+
+		if (j == 16 || i == count - 1) {
+			tmp_str[j * 3 - 1] = '\0';
+			NT_LOG(DBG, NTHW, "    %s", tmp_str);
+			j = 0;
+		}
+	}
+}
+
+#endif
+
+int nthw_spi_v3_init(nthw_spi_v3_t *p, nthw_fpga_t *p_fpga, int n_instance_no)
+{
+	const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str;
+	uint32_t result;
+
+	p->mn_instance_no = n_instance_no;
+
+	nthw_spi_v3_set_timeout(p, 1);
+
+	/* Initialize SPIM module */
+	p->mp_spim_mod = nthw_spim_new();
+
+	result = nthw_spim_init(p->mp_spim_mod, p_fpga, n_instance_no);
+
+	if (result != 0)
+		NT_LOG(ERR, NTHW, "%s: nthw_spis_init failed: %d", p_adapter_id_str, result);
+
+	/* Initialize SPIS module */
+	p->mp_spis_mod = nthw_spis_new();
+
+	result = nthw_spis_init(p->mp_spis_mod, p_fpga, n_instance_no);
+
+	if (result != 0)
+		NT_LOG(ERR, NTHW, "%s: nthw_spim_init failed: %d", p_adapter_id_str, result);
+
+	/* Reset SPIM and SPIS modules */
+	result = nthw_spim_reset(p->mp_spim_mod);
+
+	if (result != 0)
+		NT_LOG(ERR, NTHW, "%s: nthw_spim_reset failed: %d", p_adapter_id_str, result);
+
+	result = nthw_spis_reset(p->mp_spis_mod);
+
+	if (result != 0)
+		NT_LOG(ERR, NTHW, "%s: nthw_spis_reset failed: %d", p_adapter_id_str, result);
+
+	return result;
+}
+
+/*
+ * Send Tx data using the SPIM module and receive any data using the SPIS module.
+ * The data are sent and received being wrapped into a SPI v3 container.
+ */
+int nthw_spi_v3_transfer(nthw_spi_v3_t *p, uint16_t opcode, struct tx_rx_buf *tx_buf,
+	struct tx_rx_buf *rx_buf)
+{
+	const uint16_t max_payload_rx_size = rx_buf->size;
+	int result = 0;
+
+#pragma pack(push, 1)
+	union {
+		uint32_t raw;
+
+		struct {
+			uint16_t opcode;
+			uint16_t size;
+		};
+	} spi_tx_hdr;
+
+	union {
+		uint32_t raw;
+
+		struct {
+			uint16_t error_code;
+			uint16_t size;
+		};
+	} spi_rx_hdr;
+
+#pragma pack(pop)
+
+#ifdef SPI_V3_DEBUG_PRINT
+	NT_LOG_DBG(DBG, NTHW, "Started");
+#endif
+
+	/* Disable transmission from Tx FIFO */
+	result = nthw_spim_enable(p->mp_spim_mod, false);
+
+	if (result != 0) {
+		NT_LOG(WRN, NTHW, "nthw_spim_enable failed");
+		return result;
+	}
+
+	/* Enable SPIS module */
+	result = nthw_spis_enable(p->mp_spis_mod, true);
+
+	if (result != 0) {
+		NT_LOG(WRN, NTHW, "nthw_spis_enable failed");
+		return result;
+	}
+
+	/* Put data into Tx FIFO */
+	spi_tx_hdr.opcode = opcode;
+	spi_tx_hdr.size = tx_buf->size;
+
+#ifdef SPI_V3_DEBUG_PRINT
+	NT_LOG(DBG, NTHW, "Opcode=0x%04X tx_bufSize=0x%04X rx_bufSize=0x%04X", opcode,
+		tx_buf->size, rx_buf->size);
+
+#endif	/* SPI_V3_DEBUG_PRINT */
+
+	result = nthw_spim_write_tx_fifo(p->mp_spim_mod, htonl(spi_tx_hdr.raw));
+
+	if (result != 0) {
+		NT_LOG(WRN, NTHW, "nthw_spim_write_tx_fifo failed");
+		return result;
+	}
+
+	{
+		uint8_t *tx_data = (uint8_t *)tx_buf->p_buf;
+		uint16_t tx_size = tx_buf->size;
+		uint16_t count;
+		uint32_t value;
+
+		while (tx_size > 0) {
+			if (tx_size > 4) {
+				count = 4;
+
+			} else {
+				count = tx_size;
+				value = 0;
+			}
+
+			memcpy(&value, tx_data, count);
+
+			result = nthw_spim_write_tx_fifo(p->mp_spim_mod, htonl(value));
+
+			if (result != 0) {
+				NT_LOG(WRN, NTHW, "nthw_spim_write_tx_fifo failed");
+				return result;
+			}
+
+			tx_size = (uint16_t)(tx_size - count);
+			tx_data += count;
+		}
+	}
+
+	/* Enable Tx FIFO */
+	result = nthw_spim_enable(p->mp_spim_mod, true);
+
+	if (result != 0) {
+		NT_LOG(WRN, NTHW, "nthw_spim_enable failed");
+		return result;
+	}
+
+	result = wait_for_tx_data_sent(p->mp_spim_mod, p->m_time_out);
+
+	if (result != 0)
+		return result;
+
+#ifdef SPI_V3_DEBUG_PRINT
+	NT_LOG(DBG, NTHW, "%s: SPI header and payload data have been sent", __func__);
+#endif
+
+	{
+		/* Start receiving data */
+		uint16_t rx_size =
+			sizeof(spi_rx_hdr.raw);	/* The first data to read is the header */
+		uint8_t *rx_data = (uint8_t *)rx_buf->p_buf;
+		bool rx_hdr_read = false;
+
+		rx_buf->size = 0;
+
+		while (true) {
+			uint16_t count;
+			uint32_t value;
+
+			if (!rx_hdr_read) {	/* Read the header */
+				result = wait_for_rx_data_ready(p->mp_spis_mod, p->m_time_out);
+
+				if (result != 0)
+					return result;
+
+				result = nthw_spis_read_rx_fifo(p->mp_spis_mod, &spi_rx_hdr.raw);
+
+				if (result != 0) {
+					NT_LOG(WRN, NTHW, "nthw_spis_read_rx_fifo failed");
+					return result;
+				}
+
+				spi_rx_hdr.raw = ntohl(spi_rx_hdr.raw);
+				rx_size = spi_rx_hdr.size;
+				rx_hdr_read = true;	/* Next time read payload */
+
+#ifdef SPI_V3_DEBUG_PRINT
+				NT_LOG(DBG, NTHW,
+					"  spi_rx_hdr.error_code = 0x%04X, spi_rx_hdr.size = 0x%04X",
+					spi_rx_hdr.error_code, spi_rx_hdr.size);
+#endif
+
+				if (spi_rx_hdr.error_code != 0) {
+					result = -1;	/* NT_ERROR_AVR_OPCODE_RETURNED_ERROR; */
+					break;
+				}
+
+				if (rx_size > max_payload_rx_size) {
+					result = 1;	/* NT_ERROR_AVR_RX_BUFFER_TOO_SMALL; */
+					break;
+				}
+
+			} else {/* Read the payload */
+				count = (uint16_t)(rx_size < 4U ? rx_size : 4U);
+
+				if (count == 0)
+					break;
+
+				result = wait_for_rx_data_ready(p->mp_spis_mod, p->m_time_out);
+
+				if (result != 0)
+					return result;
+
+				result = nthw_spis_read_rx_fifo(p->mp_spis_mod, &value);
+
+				if (result != 0) {
+					NT_LOG(WRN, NTHW, "nthw_spis_read_rx_fifo failed");
+					return result;
+				}
+
+				value = ntohl(value);	/* Convert to host endian */
+				memcpy(rx_data, &value, count);
+				rx_buf->size = (uint16_t)(rx_buf->size + count);
+				rx_size = (uint16_t)(rx_size - count);
+				rx_data += count;
+			}
+		}
+	}
+
+#ifdef SPI_V3_DEBUG_PRINT
+	NT_LOG(DBG, NTHW, "  RxData: %d", rx_buf->size);
+	dump_hex(rx_buf->p_buf, rx_buf->size);
+	NT_LOG(DBG, NTHW, "%s:  Ended: %d", __func__, result);
+#endif
+
+	return result;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_spim.c b/drivers/net/ntnic/nthw/core/nthw_spim.c
new file mode 100644
index 0000000000..d30c11d0ff
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spim.c
@@ -0,0 +1,113 @@
+/*
+ * 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_spim.h"
+
+nthw_spim_t *nthw_spim_new(void)
+{
+	nthw_spim_t *p = malloc(sizeof(nthw_spim_t));
+
+	if (p)
+		memset(p, 0, sizeof(nthw_spim_t));
+
+	return p;
+}
+
+int nthw_spim_init(nthw_spim_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_SPIM, n_instance);
+
+	if (p == NULL)
+		return mod == NULL ? -1 : 0;
+
+	if (mod == NULL) {
+		NT_LOG(ERR, NTHW, "%s: SPIM %d: no such instance", p_adapter_id_str, n_instance);
+		return -1;
+	}
+
+	p->mp_fpga = p_fpga;
+	p->mn_instance = n_instance;
+	p->mp_mod_spim = mod;
+
+	/* SPIM is a primary communication channel - turn off debug by default */
+	nthw_module_set_debug_mode(p->mp_mod_spim, 0x00);
+
+	p->mp_reg_srr = nthw_module_get_register(p->mp_mod_spim, SPIM_SRR);
+	p->mp_fld_srr_rst = nthw_register_get_field(p->mp_reg_srr, SPIM_SRR_RST);
+
+	p->mp_reg_cr = nthw_module_get_register(p->mp_mod_spim, SPIM_CR);
+	p->mp_fld_cr_loop = nthw_register_get_field(p->mp_reg_cr, SPIM_CR_LOOP);
+	p->mp_fld_cr_en = nthw_register_get_field(p->mp_reg_cr, SPIM_CR_EN);
+	p->mp_fld_cr_txrst = nthw_register_get_field(p->mp_reg_cr, SPIM_CR_TXRST);
+	p->mp_fld_cr_rxrst = nthw_register_get_field(p->mp_reg_cr, SPIM_CR_RXRST);
+
+	p->mp_reg_sr = nthw_module_get_register(p->mp_mod_spim, SPIM_SR);
+	p->mp_fld_sr_done = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_DONE);
+	p->mp_fld_sr_txempty = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_TXEMPTY);
+	p->mp_fld_sr_rxempty = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_RXEMPTY);
+	p->mp_fld_sr_txfull = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_TXFULL);
+	p->mp_fld_sr_rxfull = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_RXFULL);
+	p->mp_fld_sr_txlvl = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_TXLVL);
+	p->mp_fld_sr_rxlvl = nthw_register_get_field(p->mp_reg_sr, SPIM_SR_RXLVL);
+
+	p->mp_reg_dtr = nthw_module_get_register(p->mp_mod_spim, SPIM_DTR);
+	p->mp_fld_dtr_dtr = nthw_register_get_field(p->mp_reg_dtr, SPIM_DTR_DTR);
+
+	p->mp_reg_drr = nthw_module_get_register(p->mp_mod_spim, SPIM_DRR);
+	p->mp_fld_drr_drr = nthw_register_get_field(p->mp_reg_drr, SPIM_DRR_DRR);
+
+	p->mp_reg_cfg = nthw_module_get_register(p->mp_mod_spim, SPIM_CFG);
+	p->mp_fld_cfg_pre = nthw_register_get_field(p->mp_reg_cfg, SPIM_CFG_PRE);
+
+	p->mp_reg_cfg_clk = nthw_module_query_register(p->mp_mod_spim, SPIM_CFG_CLK);
+	p->mp_fld_cfg_clk_mode = nthw_register_query_field(p->mp_reg_cfg, SPIM_CFG_CLK_MODE);
+
+	return 0;
+}
+
+uint32_t nthw_spim_reset(nthw_spim_t *p)
+{
+	nthw_register_update(p->mp_reg_srr);
+	nthw_field_set_val32(p->mp_fld_srr_rst, 0x0A);	/* 0x0A hardcoded value - see doc */
+	nthw_register_flush(p->mp_reg_srr, 1);
+
+	return 0;
+}
+
+uint32_t nthw_spim_enable(nthw_spim_t *p, bool b_enable)
+{
+	nthw_field_update_register(p->mp_fld_cr_en);
+
+	if (b_enable)
+		nthw_field_set_all(p->mp_fld_cr_en);
+
+	else
+		nthw_field_clr_all(p->mp_fld_cr_en);
+
+	nthw_field_flush_register(p->mp_fld_cr_en);
+
+	return 0;
+}
+
+uint32_t nthw_spim_write_tx_fifo(nthw_spim_t *p, uint32_t n_data)
+{
+	nthw_field_set_val_flush32(p->mp_fld_dtr_dtr, n_data);
+	return 0;
+}
+
+uint32_t nthw_spim_get_tx_fifo_empty(nthw_spim_t *p, bool *pb_empty)
+{
+	assert(pb_empty);
+
+	*pb_empty = nthw_field_get_updated(p->mp_fld_sr_txempty) ? true : false;
+
+	return 0;
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_spis.c b/drivers/net/ntnic/nthw/core/nthw_spis.c
new file mode 100644
index 0000000000..3c34dec936
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_spis.c
@@ -0,0 +1,121 @@
+/*
+ * 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_spis.h"
+
+nthw_spis_t *nthw_spis_new(void)
+{
+	nthw_spis_t *p = malloc(sizeof(nthw_spis_t));
+
+	if (p)
+		memset(p, 0, sizeof(nthw_spis_t));
+
+	return p;
+}
+
+int nthw_spis_init(nthw_spis_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_SPIS, n_instance);
+
+	if (p == NULL)
+		return mod == NULL ? -1 : 0;
+
+	if (mod == NULL) {
+		NT_LOG(ERR, NTHW, "%s: SPIS %d: no such instance", p_adapter_id_str, n_instance);
+		return -1;
+	}
+
+	p->mp_fpga = p_fpga;
+	p->mn_instance = n_instance;
+	p->mp_mod_spis = mod;
+
+	/* SPIS is a primary communication channel - turn off debug by default */
+	nthw_module_set_debug_mode(p->mp_mod_spis, 0x00);
+
+	p->mp_reg_srr = nthw_module_get_register(p->mp_mod_spis, SPIS_SRR);
+	p->mp_fld_srr_rst = nthw_register_get_field(p->mp_reg_srr, SPIS_SRR_RST);
+
+	p->mp_reg_cr = nthw_module_get_register(p->mp_mod_spis, SPIS_CR);
+	p->mp_fld_cr_loop = nthw_register_get_field(p->mp_reg_cr, SPIS_CR_LOOP);
+	p->mp_fld_cr_en = nthw_register_get_field(p->mp_reg_cr, SPIS_CR_EN);
+	p->mp_fld_cr_txrst = nthw_register_get_field(p->mp_reg_cr, SPIS_CR_TXRST);
+	p->mp_fld_cr_rxrst = nthw_register_get_field(p->mp_reg_cr, SPIS_CR_RXRST);
+	p->mp_fld_cr_debug = nthw_register_get_field(p->mp_reg_cr, SPIS_CR_DEBUG);
+
+	p->mp_reg_sr = nthw_module_get_register(p->mp_mod_spis, SPIS_SR);
+	p->mp_fld_sr_done = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_DONE);
+	p->mp_fld_sr_txempty = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_TXEMPTY);
+	p->mp_fld_sr_rxempty = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_RXEMPTY);
+	p->mp_fld_sr_txfull = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_TXFULL);
+	p->mp_fld_sr_rxfull = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_RXFULL);
+	p->mp_fld_sr_txlvl = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_TXLVL);
+	p->mp_fld_sr_rxlvl = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_RXLVL);
+	p->mp_fld_sr_frame_err = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_FRAME_ERR);
+	p->mp_fld_sr_read_err = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_READ_ERR);
+	p->mp_fld_sr_write_err = nthw_register_get_field(p->mp_reg_sr, SPIS_SR_WRITE_ERR);
+
+	p->mp_reg_dtr = nthw_module_get_register(p->mp_mod_spis, SPIS_DTR);
+	p->mp_fld_dtr_dtr = nthw_register_get_field(p->mp_reg_dtr, SPIS_DTR_DTR);
+
+	p->mp_reg_drr = nthw_module_get_register(p->mp_mod_spis, SPIS_DRR);
+	p->mp_fld_drr_drr = nthw_register_get_field(p->mp_reg_drr, SPIS_DRR_DRR);
+
+	p->mp_reg_ram_ctrl = nthw_module_get_register(p->mp_mod_spis, SPIS_RAM_CTRL);
+	p->mp_fld_ram_ctrl_adr = nthw_register_get_field(p->mp_reg_ram_ctrl, SPIS_RAM_CTRL_ADR);
+	p->mp_fld_ram_ctrl_cnt = nthw_register_get_field(p->mp_reg_ram_ctrl, SPIS_RAM_CTRL_CNT);
+
+	p->mp_reg_ram_data = nthw_module_get_register(p->mp_mod_spis, SPIS_RAM_DATA);
+	p->mp_fld_ram_data_data = nthw_register_get_field(p->mp_reg_ram_data, SPIS_RAM_DATA_DATA);
+
+	return 0;
+}
+
+uint32_t nthw_spis_reset(nthw_spis_t *p)
+{
+	nthw_register_update(p->mp_reg_srr);
+	nthw_field_set_val32(p->mp_fld_srr_rst, 0x0A);	/* 0x0A hardcoded value - see doc */
+	nthw_register_flush(p->mp_reg_srr, 1);
+
+	return 0;
+}
+
+uint32_t nthw_spis_enable(nthw_spis_t *p, bool b_enable)
+{
+	nthw_field_update_register(p->mp_fld_cr_en);
+
+	if (b_enable)
+		nthw_field_set_all(p->mp_fld_cr_en);
+
+	else
+		nthw_field_clr_all(p->mp_fld_cr_en);
+
+	nthw_field_flush_register(p->mp_fld_cr_en);
+
+	return 0;
+}
+
+uint32_t nthw_spis_get_rx_fifo_empty(nthw_spis_t *p, bool *pb_empty)
+{
+	assert(pb_empty);
+
+	*pb_empty = nthw_field_get_updated(p->mp_fld_sr_rxempty) ? true : false;
+
+	return 0;
+}
+
+uint32_t nthw_spis_read_rx_fifo(nthw_spis_t *p, uint32_t *p_data)
+{
+	assert(p_data);
+
+	*p_data = nthw_field_get_updated(p->mp_fld_drr_drr);
+
+	return 0;
+}
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 26/32] net/ntnic: add i2cm init
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (24 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 25/32] net/ntnic: add SPI v3 support for FPGA Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 27/32] net/ntnic: add pca init Serhii Iliushyk
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Create and initialize I2C for FPGA.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../net/ntnic/nthw/core/include/nthw_i2cm.h   |  2 +
 .../nt400dxx/reset/nthw_fpga_rst_nt400dxx.c   |  7 ++
 drivers/net/ntnic/nthw/core/nthw_i2cm.c       | 82 +++++++++++++++++++
 3 files changed, 91 insertions(+)

diff --git a/drivers/net/ntnic/nthw/core/include/nthw_i2cm.h b/drivers/net/ntnic/nthw/core/include/nthw_i2cm.h
index 53aa3c018e..1bf780d714 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_i2cm.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_i2cm.h
@@ -44,6 +44,8 @@ struct nt_i2cm {
 
 typedef struct nt_i2cm nthw_i2cm_t;
 
+nthw_i2cm_t *nthw_i2cm_new(void);
+int nthw_i2cm_init(nthw_i2cm_t *p, nthw_fpga_t *p_fpga, int n_i2c_instance);
 int nthw_i2cm_read(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr, uint8_t *value);
 int nthw_i2cm_write(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr, uint8_t value);
 int nthw_i2cm_write16(nthw_i2cm_t *p, uint8_t dev_addr, uint8_t reg_addr, uint16_t value);
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
index 73feaa4ebd..bfc66a97d1 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
@@ -67,6 +67,13 @@ static int nthw_fpga_rst_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 
 	res = nthw_fpga_avr_probe(p_fpga, 0);
 
+	if (res != 0)
+		return res;
+
+	/* Create I2C */
+	p_fpga_info->mp_nthw_agx.p_i2cm = nthw_i2cm_new();
+	res = nthw_i2cm_init(p_fpga_info->mp_nthw_agx.p_i2cm, p_fpga, 0);
+
 	if (res != 0)
 		return res;
 
diff --git a/drivers/net/ntnic/nthw/core/nthw_i2cm.c b/drivers/net/ntnic/nthw/core/nthw_i2cm.c
index f7500b2e93..353fb3f82a 100644
--- a/drivers/net/ntnic/nthw/core/nthw_i2cm.c
+++ b/drivers/net/ntnic/nthw/core/nthw_i2cm.c
@@ -27,6 +27,88 @@
 #define NUM_RETRIES 50U
 #define SLEEP_USECS 100U/* 0.1 ms */
 
+nthw_i2cm_t *nthw_i2cm_new(void)
+{
+	nthw_i2cm_t *p = malloc(sizeof(nthw_i2cm_t));
+
+	if (p)
+		memset(p, 0, sizeof(nthw_i2cm_t));
+
+	return p;
+}
+
+int nthw_i2cm_init(nthw_i2cm_t *p, nthw_fpga_t *p_fpga, int n_i2c_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_I2CM, n_i2c_instance);
+
+	if (p == NULL)
+		return mod == NULL ? -1 : 0;
+
+	if (mod == NULL) {
+		NT_LOG(ERR, NTHW, "%s: I2C %d: no such instance", p_adapter_id_str,
+			n_i2c_instance);
+		return -1;
+	}
+
+	p->mp_fpga = p_fpga;
+	p->mn_i2c_instance = n_i2c_instance;
+	p->m_mod_i2cm = mod;
+
+	p->mp_reg_prer_low = nthw_module_get_register(p->m_mod_i2cm, I2CM_PRER_LOW);
+	p->mp_fld_prer_low_prer_low =
+		nthw_register_get_field(p->mp_reg_prer_low, I2CM_PRER_LOW_PRER_LOW);
+
+	p->mp_reg_prer_high = nthw_module_get_register(p->m_mod_i2cm, I2CM_PRER_HIGH);
+	p->mp_fld_prer_high_prer_high =
+		nthw_register_get_field(p->mp_reg_prer_high, I2CM_PRER_HIGH_PRER_HIGH);
+
+	p->mp_reg_ctrl = nthw_module_get_register(p->m_mod_i2cm, I2CM_CTRL);
+	p->mp_fld_ctrl_ien = nthw_register_get_field(p->mp_reg_ctrl, I2CM_CTRL_IEN);
+	p->mp_fld_ctrl_en = nthw_register_get_field(p->mp_reg_ctrl, I2CM_CTRL_EN);
+
+	p->mp_reg_data = nthw_module_get_register(p->m_mod_i2cm, I2CM_DATA);
+	p->mp_fld_data_data = nthw_register_get_field(p->mp_reg_data, I2CM_DATA_DATA);
+
+	p->mp_reg_cmd_status = nthw_module_get_register(p->m_mod_i2cm, I2CM_CMD_STATUS);
+	p->mp_fld_cmd_status_cmd_status =
+		nthw_register_get_field(p->mp_reg_cmd_status, I2CM_CMD_STATUS_CMD_STATUS);
+
+	p->mp_reg_select = nthw_module_get_register(p->m_mod_i2cm, I2CM_SELECT);
+	p->mp_fld_select_select = nthw_register_get_field(p->mp_reg_select, I2CM_SELECT_SELECT);
+
+	p->mp_reg_io_exp = nthw_module_get_register(p->m_mod_i2cm, I2CM_IO_EXP);
+	p->mp_fld_io_exp_rst = nthw_register_get_field(p->mp_reg_io_exp, I2CM_IO_EXP_RST);
+	p->mp_fld_io_exp_int_b = nthw_register_get_field(p->mp_reg_io_exp, I2CM_IO_EXP_INT_B);
+
+	nthw_field_get_updated(p->mp_fld_io_exp_rst);
+	nthw_field_set_val_flush32(p->mp_fld_io_exp_rst, 1);
+	nthw_field_set_val_flush32(p->mp_fld_io_exp_rst, 0);
+
+	/* disable interrupt and core */
+	nthw_field_get_updated(p->mp_fld_ctrl_ien);
+	nthw_field_set_val_flush32(p->mp_fld_ctrl_ien, 0);
+	nthw_field_get_updated(p->mp_fld_ctrl_en);
+	nthw_field_set_val_flush32(p->mp_fld_ctrl_en, 0);
+
+	nthw_field_set_val_flush32(p->mp_fld_prer_high_prer_high, 0);
+	nthw_field_set_val_flush32(p->mp_fld_prer_low_prer_low, 225);
+
+	/* Enable interrupt and core */
+	nthw_field_set_val_flush32(p->mp_fld_ctrl_ien, 1);
+	nthw_field_set_val_flush32(p->mp_fld_ctrl_en, 1);
+
+	nthw_field_set_val_flush32(p->mp_fld_cmd_status_cmd_status,
+		NT_I2C_CMD_STOP | NT_I2C_CMD_NACK);
+
+	NT_LOG(INF, NTHW, "%s: %s  init done", p_adapter_id_str, __PRETTY_FUNCTION__);
+	nt_os_wait_usec(10000);
+
+	/* Initialize mutex */
+	rte_spinlock_init(&p->i2cmmutex);
+
+	return 0;
+}
 
 static bool nthw_i2cm_ready(nthw_i2cm_t *p, bool wait_for_ack)
 {
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 27/32] net/ntnic: add pca init
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (25 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 26/32] net/ntnic: add i2cm init Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 28/32] net/ntnic: add pcal init Serhii Iliushyk
                   ` (5 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Add initialization for I2C mux and LED driver.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../ntnic/nthw/core/include/nthw_pca9532.h    |  3 +++
 .../nthw/core/include/nthw_si5332_si5156.h    |  3 +++
 .../nt400dxx/reset/nthw_fpga_rst_nt400dxx.c   | 23 +++++++++++++++++++
 drivers/net/ntnic/nthw/core/nthw_pca9532.c    | 20 ++++++++++++++++
 .../net/ntnic/nthw/core/nthw_si5332_si5156.c  | 18 +++++++++++++++
 5 files changed, 67 insertions(+)

diff --git a/drivers/net/ntnic/nthw/core/include/nthw_pca9532.h b/drivers/net/ntnic/nthw/core/include/nthw_pca9532.h
index 24da937a18..7cc0008dcb 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_pca9532.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_pca9532.h
@@ -17,6 +17,9 @@ struct nthw_pca9532 {
 
 typedef struct nthw_pca9532 nthw_pca9532_t;
 
+nthw_pca9532_t *nthw_pca9532_new(void);
+int nthw_pca9532_init(nthw_pca9532_t *p, nthw_i2cm_t *p_nt_i2cm, uint8_t dev_address,
+	nthw_pca9849_t *pca9849, uint8_t mux_channel);
 void nthw_pca9532_set_led_on(nthw_pca9532_t *p, uint8_t led_pos, bool state_on);
 
 #endif	/* __NTHW_PCA9532_H__ */
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h b/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
index 753717ba8a..9eaf8872e3 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
@@ -19,6 +19,9 @@ struct nthw_pca9849 {
 
 typedef struct nthw_pca9849 nthw_pca9849_t;
 
+nthw_pca9849_t *nthw_pca9849_new(void);
+int nthw_pca9849_init(nthw_pca9849_t *p, nthw_i2cm_t *p_nt_i2cm, uint8_t dev_address);
+
 int nthw_pca9849_set_channel(nthw_pca9849_t *p, uint8_t channel);
 
 /*
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
index bfc66a97d1..6c5c1cd51e 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
@@ -77,6 +77,29 @@ static int nthw_fpga_rst_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 	if (res != 0)
 		return res;
 
+	/* Create pca9849 i2c mux */
+	p_fpga_info->mp_nthw_agx.p_pca9849 = nthw_pca9849_new();
+	res = nthw_pca9849_init(p_fpga_info->mp_nthw_agx.p_pca9849,
+			p_fpga_info->mp_nthw_agx.p_i2cm,
+			0x71);
+
+	if (res != 0)
+		return res;
+
+	/* Create LED driver */
+	p_fpga_info->mp_nthw_agx.p_pca9532_led = nthw_pca9532_new();
+	res = nthw_pca9532_init(p_fpga_info->mp_nthw_agx.p_pca9532_led,
+			p_fpga_info->mp_nthw_agx.p_i2cm,
+			0x60,
+			p_fpga_info->mp_nthw_agx.p_pca9849,
+			3);
+
+	if (res != 0)
+		return res;
+
+	for (uint8_t i = 0; i < 16; i++)
+		nthw_pca9532_set_led_on(p_fpga_info->mp_nthw_agx.p_pca9532_led, i, false);
+
 	/* Create PCM */
 	p_fpga_info->mp_nthw_agx.p_pcm = nthw_pcm_nt400dxx_new();
 	res = nthw_pcm_nt400dxx_init(p_fpga_info->mp_nthw_agx.p_pcm, p_fpga, 0);
diff --git a/drivers/net/ntnic/nthw/core/nthw_pca9532.c b/drivers/net/ntnic/nthw/core/nthw_pca9532.c
index fcf5463fcb..af14cd6d06 100644
--- a/drivers/net/ntnic/nthw/core/nthw_pca9532.c
+++ b/drivers/net/ntnic/nthw/core/nthw_pca9532.c
@@ -15,6 +15,26 @@
 
 static const uint8_t led_sel_reg[4] = { 6, 7, 8, 9 };
 
+nthw_pca9532_t *nthw_pca9532_new(void)
+{
+	nthw_pca9532_t *p = malloc(sizeof(nthw_pca9532_t));
+
+	if (p)
+		memset(p, 0, sizeof(nthw_pca9532_t));
+
+	return p;
+}
+
+int nthw_pca9532_init(nthw_pca9532_t *p, nthw_i2cm_t *p_nt_i2cm, uint8_t dev_address,
+	nthw_pca9849_t *pca9849, uint8_t mux_channel)
+{
+	p->mp_nt_i2cm = p_nt_i2cm;
+	p->m_dev_address = dev_address;
+	p->mp_ca9849 = pca9849;
+	p->m_mux_channel = mux_channel;
+	return 0;
+}
+
 void nthw_pca9532_set_led_on(nthw_pca9532_t *p, uint8_t led_pos, bool state_on)
 {
 	if (led_pos >= 16) {
diff --git a/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c b/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
index b4a7b57bcb..eb11ebc67a 100644
--- a/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
+++ b/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
@@ -13,6 +13,24 @@
 
 #include "nthw_si5332_si5156.h"
 
+nthw_pca9849_t *nthw_pca9849_new(void)
+{
+	nthw_pca9849_t *p = malloc(sizeof(nthw_pca9849_t));
+
+	if (p)
+		memset(p, 0, sizeof(nthw_pca9849_t));
+
+	return p;
+}
+
+int nthw_pca9849_init(nthw_pca9849_t *p, nthw_i2cm_t *p_nt_i2cm, uint8_t dev_address)
+{
+	p->mp_nt_i2cm = p_nt_i2cm;
+	p->m_dev_address = dev_address;
+	p->m_current_channel = 0;
+	return 0;
+}
+
 int nthw_pca9849_set_channel(nthw_pca9849_t *p, uint8_t channel)
 {
 	int res;
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 28/32] net/ntnic: add pcal init
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (26 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 27/32] net/ntnic: add pca init Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 29/32] net/ntnic: add reset PHY init Serhii Iliushyk
                   ` (4 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Add initialization for I/O expanders and configure TS settings.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../ntnic/nthw/core/include/nthw_pcal6416a.h  |  3 +
 .../nt400dxx/reset/nthw_fpga_rst_nt400dxx.c   | 69 +++++++++++++++++++
 drivers/net/ntnic/nthw/core/nthw_pcal6416a.c  | 23 +++++++
 drivers/net/ntnic/nthw/nthw_drv.h             |  1 +
 4 files changed, 96 insertions(+)

diff --git a/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h b/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
index a718b59a29..e3dadcc8e3 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
@@ -24,6 +24,9 @@ struct nthw_pcal6416a {
 
 typedef struct nthw_pcal6416a nthw_pcal6416a_t;
 
+nthw_pcal6416a_t *nthw_pcal6416a_new(void);
+int nthw_pcal6416a_init(nthw_pcal6416a_t *p, nthw_i2cm_t *p_nt_i2cm, uint8_t dev_address,
+	nthw_pca9849_t *pca9849, uint8_t mux_channel);
 void nthw_pcal6416a_write(nthw_pcal6416a_t *p, uint8_t pin, uint8_t value);
 void nthw_pcal6416a_read(nthw_pcal6416a_t *p, uint8_t pin, uint8_t *value);
 
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
index 6c5c1cd51e..c8fd37d0ff 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
@@ -86,6 +86,58 @@ static int nthw_fpga_rst_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 	if (res != 0)
 		return res;
 
+	/* Create PCAL6416A I/O expander for controlling Nim */
+	p_fpga_info->mp_nthw_agx.p_io_nim = nthw_pcal6416a_new();
+	res = nthw_pcal6416a_init(p_fpga_info->mp_nthw_agx.p_io_nim,
+			p_fpga_info->mp_nthw_agx.p_i2cm,
+			0x20,
+			p_fpga_info->mp_nthw_agx.p_pca9849,
+			3);
+
+	if (res != 0)
+		return res;
+
+	/* Create PCAL6416A I/O expander for controlling TS */
+	p_fpga_info->mp_nthw_agx.p_io_ts = nthw_pcal6416a_new();
+	res = nthw_pcal6416a_init(p_fpga_info->mp_nthw_agx.p_io_ts,
+			p_fpga_info->mp_nthw_agx.p_i2cm,
+			0x20,
+			p_fpga_info->mp_nthw_agx.p_pca9849,
+			2);
+
+	if (res != 0)
+		return res;
+
+	/*
+	 * disable pps out
+	 * TS_EXT1_OUT_EN : Low
+	 */
+	nthw_pcal6416a_write(p_fpga_info->mp_nthw_agx.p_io_ts, 0, 0);
+
+	/*
+	 * Enable DC termination
+	 * TS_EXT1_TERM_DC_E : High
+	 */
+	nthw_pcal6416a_write(p_fpga_info->mp_nthw_agx.p_io_ts, 3, 1);
+
+	/*
+	 * enable 50 ohm termination
+	 * TS_EXT1_TERM50_DIS : low
+	 */
+	nthw_pcal6416a_write(p_fpga_info->mp_nthw_agx.p_io_ts, 2, 0);
+
+	/*
+	 * Normal Threshold
+	 * TS_EXT1_LOW_THRESHOLD: Low
+	 */
+	nthw_pcal6416a_write(p_fpga_info->mp_nthw_agx.p_io_ts, 1, 0);
+
+	/*
+	 * Select FPGA I/O - we want to use TSM Bresenham for time adjustments against PPS time
+	 * reference TS_EXT_ZL30733_EnB: High
+	 */
+	nthw_pcal6416a_write(p_fpga_info->mp_nthw_agx.p_io_ts, 8, 1);
+
 	/* Create LED driver */
 	p_fpga_info->mp_nthw_agx.p_pca9532_led = nthw_pca9532_new();
 	res = nthw_pca9532_init(p_fpga_info->mp_nthw_agx.p_pca9532_led,
@@ -100,6 +152,23 @@ static int nthw_fpga_rst_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 	for (uint8_t i = 0; i < 16; i++)
 		nthw_pca9532_set_led_on(p_fpga_info->mp_nthw_agx.p_pca9532_led, i, false);
 
+	/* Enable power supply to NIMs */
+	nthw_pcal6416a_write(p_fpga_info->mp_nthw_agx.p_io_nim, 8, 1);
+	nt_os_wait_usec(100000);/* 100ms */
+
+	/* Check that power supply turned on. Warn if it didn't. */
+	uint8_t port_power_ok;
+	nthw_pcal6416a_read(p_fpga_info->mp_nthw_agx.p_io_nim, 9, &port_power_ok);
+
+	if (port_power_ok != 1) {
+		NT_LOG(ERR,
+			NTHW,
+			"Warning: Power supply for QSFP modules did not turn on - Fuse might be blown.");
+		return -1;
+	}
+
+	NT_LOG(INF, NTHW, "Status of power supply for QSFP modules %u", port_power_ok);
+
 	/* Create PCM */
 	p_fpga_info->mp_nthw_agx.p_pcm = nthw_pcm_nt400dxx_new();
 	res = nthw_pcm_nt400dxx_init(p_fpga_info->mp_nthw_agx.p_pcm, p_fpga, 0);
diff --git a/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c b/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
index dd803ac66d..2fca469497 100644
--- a/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
+++ b/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
@@ -20,6 +20,29 @@ static const uint8_t config_port[2] = { 0x06, 0x07 };
  * PCAL6416A I/O expander class
  */
 
+nthw_pcal6416a_t *nthw_pcal6416a_new(void)
+{
+	nthw_pcal6416a_t *p = malloc(sizeof(nthw_pcal6416a_t));
+
+	if (p) {
+		memset(p, 0, sizeof(nthw_pcal6416a_t));
+		p->m_config_data[0] = 0xFF;
+		p->m_config_data[1] = 0xFF;
+	}
+
+	return p;
+}
+
+int nthw_pcal6416a_init(nthw_pcal6416a_t *p, nthw_i2cm_t *p_nt_i2cm, uint8_t dev_address,
+	nthw_pca9849_t *pca9849, uint8_t mux_channel)
+{
+	p->mp_nt_i2cm = p_nt_i2cm;
+	p->m_dev_address = dev_address;
+	p->mp_ca9849 = pca9849;
+	p->m_mux_channel = mux_channel;
+	return 0;
+}
+
 void nthw_pcal6416a_write(nthw_pcal6416a_t *p, uint8_t pin, uint8_t value)
 {
 	uint8_t port;
diff --git a/drivers/net/ntnic/nthw/nthw_drv.h b/drivers/net/ntnic/nthw/nthw_drv.h
index ecd3bb9cc4..574dd663ea 100644
--- a/drivers/net/ntnic/nthw/nthw_drv.h
+++ b/drivers/net/ntnic/nthw/nthw_drv.h
@@ -24,6 +24,7 @@
 typedef struct nthw_agx_s {
 	nthw_i2cm_t *p_i2cm;
 	nthw_pca9849_t *p_pca9849;
+	nthw_pcal6416a_t *p_io_ts;	/* PCAL6416A I/O expander for controlling TS */
 	nthw_pcal6416a_t *p_io_nim;	/* PCAL6416A I/O expander for controlling TS */
 	nthw_pca9532_t *p_pca9532_led;
 	nthw_si5332_t *p_si5332;
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 29/32] net/ntnic: add reset PHY init
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (27 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 28/32] net/ntnic: add pcal init Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 30/32] net/ntnic: add igam module init Serhii Iliushyk
                   ` (3 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Add initialization and logging for Phy Tile module.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../ntnic/nthw/core/include/nthw_phy_tile.h   |  39 ++
 .../nt400dxx/reset/nthw_fpga_rst_nt400dxx.c   |  16 +
 drivers/net/ntnic/nthw/core/nthw_phy_tile.c   | 598 ++++++++++++++++++
 3 files changed, 653 insertions(+)

diff --git a/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
index 68d8455b8d..ba044a5091 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
@@ -9,12 +9,16 @@
 #include "nthw_fpga_model.h"
 
 enum mac_pcs_mode_e {
+	MAC_PCS_MODE_8x10_25,
+	MAC_PCS_MODE_2X40,
 	MAC_PCS_MODE_2X100
 };
 
 struct nt_phy_tile {
 	nthw_fpga_t *mp_fpga;
 
+	nthw_module_t *m_mod_phy_tile;
+
 	int mn_phy_tile_instance;
 
 	int mn_fpga_version;
@@ -27,6 +31,7 @@ struct nt_phy_tile {
 	nthw_field_t *mp_fld_port_xcvr_base_busy[2][4];
 	nthw_field_t *mp_fld_port_xcvr_base_cmd[2][4];
 
+	nthw_register_t *mp_reg_port_xcvr_data[2][4];
 	nthw_field_t *mp_fld_port_xcvr_data_data[2][4];
 
 	nthw_register_t *mp_reg_port_eth_base[2];
@@ -34,27 +39,44 @@ struct nt_phy_tile {
 	nthw_field_t *mp_fld_port_eth_base_busy[2];
 	nthw_field_t *mp_fld_port_eth_base_cmd[2];
 
+	nthw_register_t *mp_reg_port_eth_data[2];
 	nthw_field_t *mp_fld_port_eth_data_data[2];
 
 	nthw_register_t *mp_reg_link_summary[2];
 	nthw_field_t *mp_fld_link_summary_nt_phy_link_state[2];
 	nthw_field_t *mp_fld_link_summary_ll_nt_phy_link_state[2];
 	nthw_field_t *mp_fld_link_summary_link_down_cnt[2];
+	nthw_field_t *mp_fld_link_summary_ll_rx_block_lock[2];
+	nthw_field_t *mp_fld_link_summary_ll_rx_am_lock[2];
+	nthw_field_t *mp_fld_link_summary_lh_rx_high_bit_error_rate[2];
 	nthw_field_t *mp_fld_link_summary_lh_received_local_fault[2];
 	nthw_field_t *mp_fld_link_summary_lh_remote_fault[2];
 
+	nthw_register_t *mp_reg_port_status[2];
+	nthw_field_t *mp_fld_port_status_rx_pcs_fully_aligned[2];
 	nthw_field_t *mp_fld_port_status_rx_hi_ber[2];
+	nthw_field_t *mp_fld_port_status_rx_remote_fault[2];
+	nthw_field_t *mp_fld_port_status_rx_local_fault[2];
 	nthw_field_t *mp_fld_port_status_rx_am_lock[2];
 	nthw_field_t *mp_fld_port_status_reset_ackn[2];
 	nthw_field_t *mp_fld_port_status_tx_lanes_stable[2];
+	nthw_field_t *mp_fld_port_status_tx_pll_locked[2];
+	nthw_field_t *mp_fld_port_status_sys_pll_locked[2];
 	nthw_field_t *mp_fld_port_status_tx_reset_ackn[2];
 	nthw_field_t *mp_fld_port_status_rx_reset_ackn[2];
 
+	nthw_register_t *mp_reg_port_config[2];
+	nthw_field_t *mp_fld_port_config_dyn_reset;
 	nthw_field_t *mp_fld_port_config_reset[2];
 	nthw_field_t *mp_fld_port_config_rx_reset[2];
 	nthw_field_t *mp_fld_port_config_tx_reset[2];
+	nthw_field_t *mp_fld_port_config_nt_linkup_latency[2];
+	nthw_field_t *mp_fld_port_config_nt_force_linkdown[2];
+	nthw_field_t *mp_fld_port_config_nt_auto_force_linkdown[2];
 
+	nthw_register_t *mp_reg_port_comp[2];
 	nthw_field_t *mp_fld_port_comp_rx_compensation[2];
+	nthw_field_t *mp_fld_port_comp_tx_compensation[2];
 
 	nthw_register_t *mp_reg_dyn_reconfig_base;
 	nthw_field_t *mp_fld_dyn_reconfig_base_ptr;
@@ -64,17 +86,34 @@ struct nt_phy_tile {
 	nthw_register_t *mp_reg_dyn_reconfig_data;
 	nthw_field_t *mp_fld_dyn_reconfig_data_data;
 
+	nthw_register_t *mp_reg_scratch;
 	nthw_field_t *mp_fld_scratch_data;
 
+	nthw_register_t *mp_reg_dr_cfg;
+	nthw_field_t *mp_fld_reg_dr_cfg_features;
+	nthw_field_t *mp_fld_reg_dr_cfg_tx_flush_level;
+
 	nthw_register_t *mp_reg_dr_cfg_status;
 	nthw_field_t *mp_fld_dr_cfg_status_curr_profile_id;
 	nthw_field_t *mp_fld_dr_cfg_status_in_progress;
 	nthw_field_t *mp_fld_dr_cfg_status_error;
+
+	nthw_register_t *mp_reg_sys_pll;
+	nthw_field_t *mp_fld_sys_pll_set_rdy;
+	nthw_field_t *mp_fld_sys_pll_get_rdy;
+	nthw_field_t *mp_fld_sys_pll_system_pll_lock;
+	nthw_field_t *mp_fld_sys_pll_en_ref_clk_fgt;
+	nthw_field_t *mp_fld_sys_pll_disable_ref_clk_monitor;
+	nthw_field_t *mp_fld_sys_pll_ref_clk_fgt_enabled;
+	nthw_field_t *mp_fld_sys_pll_forward_rst;
+	nthw_field_t *mp_fld_sys_pll_force_rst;
 };
 
 typedef struct nt_phy_tile nthw_phy_tile_t;
 typedef struct nt_phy_tile nt_phy_tile;
 
+nthw_phy_tile_t *nthw_phy_tile_new(void);
+int nthw_phy_tile_init(nthw_phy_tile_t *p, nthw_fpga_t *p_fpga, int mn_phy_tile_instance);
 void nthw_phy_tile_set_tx_pol_inv(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane, bool invert);
 void nthw_phy_tile_set_rx_pol_inv(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane, bool invert);
 void nthw_phy_tile_set_host_loopback(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
index c8fd37d0ff..35cbaea81e 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
@@ -181,7 +181,23 @@ static int nthw_fpga_rst_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 
 static int nthw_fpga_rst_nt400dxx_reset(struct fpga_info_s *p_fpga_info)
 {
+	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
+	nthw_fpga_t *p_fpga = NULL;
+
+	p_fpga = p_fpga_info->mp_fpga;
+
 	assert(p_fpga_info);
+
+	NT_LOG(DBG, NTHW, "%s: %s: BEGIN", p_adapter_id_str, __PRETTY_FUNCTION__);
+
+	/* Create Phy Tile module */
+	p_fpga_info->mp_nthw_agx.p_phy_tile = nthw_phy_tile_new();
+
+	if (nthw_phy_tile_init(p_fpga_info->mp_nthw_agx.p_phy_tile, p_fpga, 0)) {
+		NT_LOG(ERR, NTHW, "%s: Failed to create Phy Tile Module", p_adapter_id_str);
+		return -1;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/net/ntnic/nthw/core/nthw_phy_tile.c b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
index a8c2d03be9..f78d8263f5 100644
--- a/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
+++ b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
@@ -44,6 +44,604 @@ static const uint32_t eth_soft_csr1 = 0x200;
 static const uint32_t eth_soft_csr2 = 0x204;
 static const uint32_t eth_soft_csr3 = 0x208;
 
+nthw_phy_tile_t *nthw_phy_tile_new(void)
+{
+	nthw_phy_tile_t *p = malloc(sizeof(nthw_phy_tile_t));
+
+	if (p)
+		memset(p, 0, sizeof(nthw_phy_tile_t));
+
+	return p;
+}
+
+int nthw_phy_tile_init(nthw_phy_tile_t *p, nthw_fpga_t *p_fpga, int mn_phy_tile_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_PHY_TILE, mn_phy_tile_instance);
+
+	if (p == NULL)
+		return mod == NULL ? -1 : 0;
+
+	if (mod == NULL) {
+		NT_LOG(ERR, NTHW, "%s: PHY_TILE %d: no such instance", p_adapter_id_str,
+			mn_phy_tile_instance);
+		return -1;
+	}
+
+	p->mp_fpga = p_fpga;
+	p->mn_phy_tile_instance = mn_phy_tile_instance;
+
+	p->m_mod_phy_tile = mod;
+
+	p->mn_fpga_revision = p_fpga->mn_fpga_revision;
+	p->mn_fpga_version = p_fpga->mn_fpga_version;
+
+	switch (p_fpga->mn_product_id) {
+	case 9569:
+	case 9574:
+		p->mac_pcs_mode = MAC_PCS_MODE_2X100;
+		break;
+
+	default:
+		NT_LOG_DBG(DBG, NTHW, "unknown product ID: %u", p_fpga->mn_product_id);
+		break;
+	}
+
+	/* Port 0 Base 0..3 */
+	p->mp_reg_port_xcvr_base[0][0] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_0_XCVR_0_BASE);
+	p->mp_fld_port_xcvr_base_ptr[0][0] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[0][0],
+			PHY_TILE_PORT_0_XCVR_0_BASE_PTR);
+	p->mp_fld_port_xcvr_base_busy[0][0] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[0][0],
+			PHY_TILE_PORT_0_XCVR_0_BASE_BUSY);
+	p->mp_fld_port_xcvr_base_cmd[0][0] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[0][0],
+			PHY_TILE_PORT_0_XCVR_0_BASE_CMD);
+
+	p->mp_reg_port_xcvr_base[0][1] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_0_XCVR_1_BASE);
+	p->mp_fld_port_xcvr_base_ptr[0][1] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[0][1],
+			PHY_TILE_PORT_0_XCVR_1_BASE_PTR);
+	p->mp_fld_port_xcvr_base_busy[0][1] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[0][1],
+			PHY_TILE_PORT_0_XCVR_1_BASE_BUSY);
+	p->mp_fld_port_xcvr_base_cmd[0][1] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[0][1],
+			PHY_TILE_PORT_0_XCVR_1_BASE_CMD);
+
+	p->mp_reg_port_xcvr_base[0][2] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_0_XCVR_2_BASE);
+	p->mp_fld_port_xcvr_base_ptr[0][2] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[0][2],
+			PHY_TILE_PORT_0_XCVR_2_BASE_PTR);
+	p->mp_fld_port_xcvr_base_busy[0][2] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[0][2],
+			PHY_TILE_PORT_0_XCVR_2_BASE_BUSY);
+	p->mp_fld_port_xcvr_base_cmd[0][2] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[0][2],
+			PHY_TILE_PORT_0_XCVR_2_BASE_CMD);
+
+	p->mp_reg_port_xcvr_base[0][3] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_0_XCVR_3_BASE);
+	p->mp_fld_port_xcvr_base_ptr[0][3] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[0][3],
+			PHY_TILE_PORT_0_XCVR_3_BASE_PTR);
+	p->mp_fld_port_xcvr_base_busy[0][3] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[0][3],
+			PHY_TILE_PORT_0_XCVR_3_BASE_BUSY);
+	p->mp_fld_port_xcvr_base_cmd[0][3] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[0][3],
+			PHY_TILE_PORT_0_XCVR_3_BASE_CMD);
+
+	/* Port 0 Data 0..3 */
+	p->mp_reg_port_xcvr_data[0][0] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_0_XCVR_0_DATA);
+	p->mp_fld_port_xcvr_data_data[0][0] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_data[0][0],
+			PHY_TILE_PORT_0_XCVR_0_DATA_DATA);
+
+	p->mp_reg_port_xcvr_data[0][1] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_0_XCVR_1_DATA);
+	p->mp_fld_port_xcvr_data_data[0][1] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_data[0][1],
+			PHY_TILE_PORT_0_XCVR_1_DATA_DATA);
+
+	p->mp_reg_port_xcvr_data[0][2] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_0_XCVR_2_DATA);
+	p->mp_fld_port_xcvr_data_data[0][2] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_data[0][2],
+			PHY_TILE_PORT_0_XCVR_2_DATA_DATA);
+
+	p->mp_reg_port_xcvr_data[0][3] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_0_XCVR_3_DATA);
+	p->mp_fld_port_xcvr_data_data[0][3] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_data[0][3],
+			PHY_TILE_PORT_0_XCVR_3_DATA_DATA);
+
+	/* Port 1 Base 0..3 */
+	p->mp_reg_port_xcvr_base[1][0] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_1_XCVR_0_BASE);
+	p->mp_fld_port_xcvr_base_ptr[1][0] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[1][0],
+			PHY_TILE_PORT_1_XCVR_0_BASE_PTR);
+	p->mp_fld_port_xcvr_base_busy[1][0] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[1][0],
+			PHY_TILE_PORT_1_XCVR_0_BASE_BUSY);
+	p->mp_fld_port_xcvr_base_cmd[1][0] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[1][0],
+			PHY_TILE_PORT_1_XCVR_0_BASE_CMD);
+
+	p->mp_reg_port_xcvr_base[1][1] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_1_XCVR_1_BASE);
+	p->mp_fld_port_xcvr_base_ptr[1][1] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[1][1],
+			PHY_TILE_PORT_1_XCVR_1_BASE_PTR);
+	p->mp_fld_port_xcvr_base_busy[1][1] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[1][1],
+			PHY_TILE_PORT_1_XCVR_1_BASE_BUSY);
+	p->mp_fld_port_xcvr_base_cmd[1][1] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[1][1],
+			PHY_TILE_PORT_1_XCVR_1_BASE_CMD);
+
+	p->mp_reg_port_xcvr_base[1][2] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_1_XCVR_2_BASE);
+	p->mp_fld_port_xcvr_base_ptr[1][2] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[1][2],
+			PHY_TILE_PORT_1_XCVR_2_BASE_PTR);
+	p->mp_fld_port_xcvr_base_busy[1][2] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[1][2],
+			PHY_TILE_PORT_1_XCVR_2_BASE_BUSY);
+	p->mp_fld_port_xcvr_base_cmd[1][2] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[1][2],
+			PHY_TILE_PORT_1_XCVR_2_BASE_CMD);
+
+	p->mp_reg_port_xcvr_base[1][3] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_1_XCVR_3_BASE);
+	p->mp_fld_port_xcvr_base_ptr[1][3] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[1][3],
+			PHY_TILE_PORT_1_XCVR_3_BASE_PTR);
+	p->mp_fld_port_xcvr_base_busy[1][3] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[1][3],
+			PHY_TILE_PORT_1_XCVR_3_BASE_BUSY);
+	p->mp_fld_port_xcvr_base_cmd[1][3] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_base[1][3],
+			PHY_TILE_PORT_1_XCVR_3_BASE_CMD);
+
+	/* Port 1 Data 0..3 */
+	p->mp_reg_port_xcvr_data[1][0] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_1_XCVR_0_DATA);
+	p->mp_fld_port_xcvr_data_data[1][0] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_data[1][0],
+			PHY_TILE_PORT_1_XCVR_0_DATA_DATA);
+
+	p->mp_reg_port_xcvr_data[1][1] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_1_XCVR_1_DATA);
+	p->mp_fld_port_xcvr_data_data[1][1] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_data[1][1],
+			PHY_TILE_PORT_1_XCVR_1_DATA_DATA);
+
+	p->mp_reg_port_xcvr_data[1][2] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_1_XCVR_2_DATA);
+	p->mp_fld_port_xcvr_data_data[1][2] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_data[1][2],
+			PHY_TILE_PORT_1_XCVR_2_DATA_DATA);
+
+	p->mp_reg_port_xcvr_data[1][3] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_1_XCVR_3_DATA);
+	p->mp_fld_port_xcvr_data_data[1][3] =
+		nthw_register_get_field(p->mp_reg_port_xcvr_data[1][3],
+			PHY_TILE_PORT_1_XCVR_3_DATA_DATA);
+
+	if (nthw_module_is_version_newer(p->m_mod_phy_tile, 0, 3)) {
+		if (p->mac_pcs_mode == MAC_PCS_MODE_2X100 ||
+			p->mac_pcs_mode == MAC_PCS_MODE_8x10_25) {
+			/* DYN_RECONFIG */
+			p->mp_reg_dyn_reconfig_base =
+				nthw_module_get_register(p->m_mod_phy_tile,
+					PHY_TILE_DYN_RECONFIG_BASE);
+			p->mp_fld_dyn_reconfig_base_ptr =
+				nthw_register_get_field(p->mp_reg_dyn_reconfig_base,
+					PHY_TILE_DYN_RECONFIG_BASE_PTR);
+			p->mp_fld_dyn_reconfig_base_busy =
+				nthw_register_get_field(p->mp_reg_dyn_reconfig_base,
+					PHY_TILE_DYN_RECONFIG_BASE_BUSY);
+			p->mp_fld_dyn_reconfig_base_cmd =
+				nthw_register_get_field(p->mp_reg_dyn_reconfig_base,
+					PHY_TILE_DYN_RECONFIG_BASE_CMD);
+
+			p->mp_reg_dyn_reconfig_data =
+				nthw_module_get_register(p->m_mod_phy_tile,
+					PHY_TILE_DYN_RECONFIG_DATA);
+			p->mp_fld_dyn_reconfig_data_data =
+				nthw_register_get_field(p->mp_reg_dyn_reconfig_data,
+					PHY_TILE_DYN_RECONFIG_DATA_DATA);
+		}
+
+		/* Port 0 Eth Base */
+		p->mp_reg_port_eth_base[0] =
+			nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_0_ETH_0_BASE);
+		p->mp_fld_port_eth_base_ptr[0] =
+			nthw_register_get_field(p->mp_reg_port_eth_base[0],
+				PHY_TILE_PORT_0_ETH_0_BASE_PTR);
+		p->mp_fld_port_eth_base_busy[0] =
+			nthw_register_get_field(p->mp_reg_port_eth_base[0],
+				PHY_TILE_PORT_0_ETH_0_BASE_BUSY);
+		p->mp_fld_port_eth_base_cmd[0] =
+			nthw_register_get_field(p->mp_reg_port_eth_base[0],
+				PHY_TILE_PORT_0_ETH_0_BASE_CMD);
+
+		/* Port 1 Eth Base */
+		p->mp_reg_port_eth_base[1] =
+			nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_1_ETH_0_BASE);
+		p->mp_fld_port_eth_base_ptr[1] =
+			nthw_register_get_field(p->mp_reg_port_eth_base[1],
+				PHY_TILE_PORT_1_ETH_0_BASE_PTR);
+		p->mp_fld_port_eth_base_busy[1] =
+			nthw_register_get_field(p->mp_reg_port_eth_base[1],
+				PHY_TILE_PORT_1_ETH_0_BASE_BUSY);
+		p->mp_fld_port_eth_base_cmd[1] =
+			nthw_register_get_field(p->mp_reg_port_eth_base[1],
+				PHY_TILE_PORT_1_ETH_0_BASE_CMD);
+
+		/* Port 0 Eth Data */
+		p->mp_reg_port_eth_data[0] =
+			nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_0_ETH_0_DATA);
+		p->mp_fld_port_eth_data_data[0] =
+			nthw_register_get_field(p->mp_reg_port_eth_data[0],
+				PHY_TILE_PORT_0_ETH_0_DATA_DATA);
+
+		/* Port 1 Eth Data 0..3 */
+		p->mp_reg_port_eth_data[1] =
+			nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_1_ETH_0_DATA);
+		p->mp_fld_port_eth_data_data[1] =
+			nthw_register_get_field(p->mp_reg_port_eth_data[1],
+				PHY_TILE_PORT_1_ETH_0_DATA_DATA);
+	}
+
+	p->mp_reg_link_summary[0] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_LINK_SUMMARY_0);
+	p->mp_fld_link_summary_nt_phy_link_state[0] =
+		nthw_register_get_field(p->mp_reg_link_summary[0],
+			PHY_TILE_LINK_SUMMARY_0_NT_PHY_LINK_STATE);
+	p->mp_fld_link_summary_ll_nt_phy_link_state[0] =
+		nthw_register_get_field(p->mp_reg_link_summary[0],
+			PHY_TILE_LINK_SUMMARY_0_LL_PHY_LINK_STATE);
+	p->mp_fld_link_summary_link_down_cnt[0] =
+		nthw_register_get_field(p->mp_reg_link_summary[0],
+			PHY_TILE_LINK_SUMMARY_0_LINK_DOWN_CNT);
+	p->mp_fld_link_summary_ll_rx_block_lock[0] =
+		nthw_register_get_field(p->mp_reg_link_summary[0],
+			PHY_TILE_LINK_SUMMARY_0_LL_RX_BLOCK_LOCK);
+	p->mp_fld_link_summary_ll_rx_am_lock[0] =
+		nthw_register_get_field(p->mp_reg_link_summary[0],
+			PHY_TILE_LINK_SUMMARY_0_LL_RX_AM_LOCK);
+	p->mp_fld_link_summary_lh_rx_high_bit_error_rate[0] =
+		nthw_register_get_field(p->mp_reg_link_summary[0],
+			PHY_TILE_LINK_SUMMARY_0_LH_RX_HIGH_BIT_ERROR_RATE);
+	p->mp_fld_link_summary_lh_received_local_fault[0] =
+		nthw_register_get_field(p->mp_reg_link_summary[0],
+			PHY_TILE_LINK_SUMMARY_0_LH_RECEIVED_LOCAL_FAULT);
+	p->mp_fld_link_summary_lh_remote_fault[0] =
+		nthw_register_get_field(p->mp_reg_link_summary[0],
+			PHY_TILE_LINK_SUMMARY_0_LH_REMOTE_FAULT);
+
+	p->mp_reg_link_summary[1] =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_LINK_SUMMARY_1);
+	p->mp_fld_link_summary_nt_phy_link_state[1] =
+		nthw_register_get_field(p->mp_reg_link_summary[1],
+			PHY_TILE_LINK_SUMMARY_1_NT_PHY_LINK_STATE);
+	p->mp_fld_link_summary_ll_nt_phy_link_state[1] =
+		nthw_register_get_field(p->mp_reg_link_summary[1],
+			PHY_TILE_LINK_SUMMARY_1_LL_PHY_LINK_STATE);
+	p->mp_fld_link_summary_link_down_cnt[1] =
+		nthw_register_get_field(p->mp_reg_link_summary[1],
+			PHY_TILE_LINK_SUMMARY_1_LINK_DOWN_CNT);
+	p->mp_fld_link_summary_ll_rx_block_lock[1] =
+		nthw_register_get_field(p->mp_reg_link_summary[1],
+			PHY_TILE_LINK_SUMMARY_1_LL_RX_BLOCK_LOCK);
+	p->mp_fld_link_summary_ll_rx_am_lock[1] =
+		nthw_register_get_field(p->mp_reg_link_summary[1],
+			PHY_TILE_LINK_SUMMARY_1_LL_RX_AM_LOCK);
+	p->mp_fld_link_summary_lh_rx_high_bit_error_rate[1] =
+		nthw_register_get_field(p->mp_reg_link_summary[1],
+			PHY_TILE_LINK_SUMMARY_1_LH_RX_HIGH_BIT_ERROR_RATE);
+	p->mp_fld_link_summary_lh_received_local_fault[1] =
+		nthw_register_get_field(p->mp_reg_link_summary[1],
+			PHY_TILE_LINK_SUMMARY_1_LH_RECEIVED_LOCAL_FAULT);
+	p->mp_fld_link_summary_lh_remote_fault[1] =
+		nthw_register_get_field(p->mp_reg_link_summary[1],
+			PHY_TILE_LINK_SUMMARY_1_LH_REMOTE_FAULT);
+
+	if (nthw_module_is_version_newer(p->m_mod_phy_tile, 0, 4)) {
+		p->mp_reg_port_status[0] =
+			nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_STATUS_0);
+		p->mp_fld_port_status_rx_pcs_fully_aligned[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_0_RX_PCS_FULLY_ALIGNED);
+		p->mp_fld_port_status_rx_hi_ber[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_0_RX_HI_BER);
+		p->mp_fld_port_status_rx_remote_fault[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_0_RX_REMOTE_FAULT);
+		p->mp_fld_port_status_rx_local_fault[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_0_RX_LOCAL_FAULT);
+		p->mp_fld_port_status_rx_am_lock[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_0_RX_AM_LOCK);
+		p->mp_fld_port_status_reset_ackn[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_0_RESET_ACK_N);
+		p->mp_fld_port_status_tx_lanes_stable[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_0_TX_LANES_STABLE);
+		p->mp_fld_port_status_tx_pll_locked[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_0_TX_PLL_LOCKED);
+		p->mp_fld_port_status_sys_pll_locked[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_0_SYS_PLL_LOCKED);
+		p->mp_fld_port_status_tx_reset_ackn[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_0_TX_RESET_ACK_N);
+		p->mp_fld_port_status_rx_reset_ackn[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_0_RX_RESET_ACK_N);
+
+		p->mp_reg_port_status[1] =
+			nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_STATUS_1);
+		p->mp_fld_port_status_rx_pcs_fully_aligned[1] =
+			nthw_register_get_field(p->mp_reg_port_status[1],
+				PHY_TILE_PORT_STATUS_1_RX_PCS_FULLY_ALIGNED);
+		p->mp_fld_port_status_rx_hi_ber[1] =
+			nthw_register_get_field(p->mp_reg_port_status[1],
+				PHY_TILE_PORT_STATUS_1_RX_HI_BER);
+		p->mp_fld_port_status_rx_remote_fault[1] =
+			nthw_register_get_field(p->mp_reg_port_status[1],
+				PHY_TILE_PORT_STATUS_1_RX_REMOTE_FAULT);
+		p->mp_fld_port_status_rx_local_fault[1] =
+			nthw_register_get_field(p->mp_reg_port_status[1],
+				PHY_TILE_PORT_STATUS_1_RX_LOCAL_FAULT);
+		p->mp_fld_port_status_rx_am_lock[1] =
+			nthw_register_get_field(p->mp_reg_port_status[1],
+				PHY_TILE_PORT_STATUS_1_RX_AM_LOCK);
+		p->mp_fld_port_status_reset_ackn[1] =
+			nthw_register_get_field(p->mp_reg_port_status[1],
+				PHY_TILE_PORT_STATUS_1_RESET_ACK_N);
+		p->mp_fld_port_status_tx_lanes_stable[1] =
+			nthw_register_get_field(p->mp_reg_port_status[1],
+				PHY_TILE_PORT_STATUS_1_TX_LANES_STABLE);
+		p->mp_fld_port_status_tx_pll_locked[1] =
+			nthw_register_get_field(p->mp_reg_port_status[1],
+				PHY_TILE_PORT_STATUS_1_TX_PLL_LOCKED);
+		p->mp_fld_port_status_sys_pll_locked[1] =
+			nthw_register_get_field(p->mp_reg_port_status[1],
+				PHY_TILE_PORT_STATUS_1_SYS_PLL_LOCKED);
+		p->mp_fld_port_status_tx_reset_ackn[1] =
+			nthw_register_get_field(p->mp_reg_port_status[1],
+				PHY_TILE_PORT_STATUS_1_TX_RESET_ACK_N);
+		p->mp_fld_port_status_rx_reset_ackn[1] =
+			nthw_register_get_field(p->mp_reg_port_status[1],
+				PHY_TILE_PORT_STATUS_1_RX_RESET_ACK_N);
+
+	} else {
+		p->mp_reg_port_status[0] =
+			nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_STATUS);
+		p->mp_fld_port_status_rx_pcs_fully_aligned[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_RX_PCS_FULLY_ALIGNED_0);
+		p->mp_fld_port_status_rx_hi_ber[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_RX_HI_BER_0);
+		p->mp_fld_port_status_rx_remote_fault[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_RX_REMOTE_FAULT_0);
+		p->mp_fld_port_status_rx_local_fault[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_RX_LOCAL_FAULT_0);
+		p->mp_fld_port_status_rx_am_lock[0] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_RX_AM_LOCK_0);
+
+		p->mp_fld_port_status_rx_pcs_fully_aligned[1] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_RX_PCS_FULLY_ALIGNED_1);
+		p->mp_fld_port_status_rx_hi_ber[1] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_RX_HI_BER_1);
+		p->mp_fld_port_status_rx_remote_fault[1] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_RX_REMOTE_FAULT_1);
+		p->mp_fld_port_status_rx_local_fault[1] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_RX_LOCAL_FAULT_1);
+		p->mp_fld_port_status_rx_am_lock[1] =
+			nthw_register_get_field(p->mp_reg_port_status[0],
+				PHY_TILE_PORT_STATUS_RX_AM_LOCK_1);
+
+		p->mp_fld_port_status_reset_ackn[0] = NULL;
+		p->mp_fld_port_status_tx_lanes_stable[0] = NULL;
+		p->mp_fld_port_status_tx_pll_locked[0] = NULL;
+		p->mp_fld_port_status_sys_pll_locked[0] = NULL;
+		p->mp_fld_port_status_tx_reset_ackn[0] = NULL;
+		p->mp_fld_port_status_rx_reset_ackn[0] = NULL;
+
+		p->mp_fld_port_status_reset_ackn[1] = NULL;
+		p->mp_fld_port_status_tx_lanes_stable[1] = NULL;
+		p->mp_fld_port_status_tx_pll_locked[1] = NULL;
+		p->mp_fld_port_status_sys_pll_locked[1] = NULL;
+		p->mp_fld_port_status_tx_reset_ackn[1] = NULL;
+		p->mp_fld_port_status_rx_reset_ackn[1] = NULL;
+	}
+
+	if (nthw_module_is_version_newer(p->m_mod_phy_tile, 0, 4)) {
+		p->mp_reg_port_config[0] =
+			nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_CONFIG_0);
+		p->mp_fld_port_config_reset[0] =
+			nthw_register_query_field(p->mp_reg_port_config[0],
+				PHY_TILE_PORT_CONFIG_0_RST);
+		p->mp_fld_port_config_rx_reset[0] =
+			nthw_register_query_field(p->mp_reg_port_config[0],
+				PHY_TILE_PORT_CONFIG_0_RX_RST);
+		p->mp_fld_port_config_tx_reset[0] =
+			nthw_register_query_field(p->mp_reg_port_config[0],
+				PHY_TILE_PORT_CONFIG_0_TX_RST);
+		p->mp_fld_port_config_nt_linkup_latency[0] =
+			nthw_register_query_field(p->mp_reg_port_config[0],
+				PHY_TILE_PORT_CONFIG_0_NT_LINKUP_LATENCY);
+		p->mp_fld_port_config_nt_force_linkdown[0] =
+			nthw_register_query_field(p->mp_reg_port_config[0],
+				PHY_TILE_PORT_CONFIG_0_NT_FORCE_LINK_DOWN);
+
+		if (nthw_module_is_version_newer(p->m_mod_phy_tile, 0, 10)) {
+			p->mp_fld_port_config_nt_auto_force_linkdown[0] =
+				nthw_register_query_field(p->mp_reg_port_config[0],
+					PHY_TILE_PORT_CONFIG_0_NT_AUTO_FORCE_LINK_DOWN);
+		}
+
+		p->mp_reg_port_config[1] =
+			nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_CONFIG_1);
+		p->mp_fld_port_config_reset[1] =
+			nthw_register_query_field(p->mp_reg_port_config[1],
+				PHY_TILE_PORT_CONFIG_1_RST);
+		p->mp_fld_port_config_rx_reset[1] =
+			nthw_register_query_field(p->mp_reg_port_config[1],
+				PHY_TILE_PORT_CONFIG_1_RX_RST);
+		p->mp_fld_port_config_tx_reset[1] =
+			nthw_register_query_field(p->mp_reg_port_config[1],
+				PHY_TILE_PORT_CONFIG_1_TX_RST);
+		p->mp_fld_port_config_nt_linkup_latency[1] =
+			nthw_register_query_field(p->mp_reg_port_config[1],
+				PHY_TILE_PORT_CONFIG_1_NT_LINKUP_LATENCY);
+		p->mp_fld_port_config_nt_force_linkdown[1] =
+			nthw_register_query_field(p->mp_reg_port_config[1],
+				PHY_TILE_PORT_CONFIG_1_NT_FORCE_LINK_DOWN);
+
+		if (nthw_module_is_version_newer(p->m_mod_phy_tile, 0, 10)) {
+			p->mp_fld_port_config_nt_auto_force_linkdown[1] =
+				nthw_register_query_field(p->mp_reg_port_config[1],
+					PHY_TILE_PORT_CONFIG_1_NT_AUTO_FORCE_LINK_DOWN);
+		}
+
+	} else {
+		p->mp_reg_port_config[0] =
+			nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_CONFIG);
+		p->mp_fld_port_config_dyn_reset =
+			nthw_register_query_field(p->mp_reg_port_config[0],
+				PHY_TILE_PORT_CONFIG_DYN_RESET);
+		p->mp_fld_port_config_reset[0] =
+			nthw_register_query_field(p->mp_reg_port_config[0],
+				PHY_TILE_PORT_CONFIG_RESET_0);
+		p->mp_fld_port_config_rx_reset[0] =
+			nthw_register_get_field(p->mp_reg_port_config[0],
+				PHY_TILE_PORT_CONFIG_RX_RESET_0);
+		p->mp_fld_port_config_tx_reset[0] =
+			nthw_register_get_field(p->mp_reg_port_config[0],
+				PHY_TILE_PORT_CONFIG_TX_RESET_0);
+		p->mp_fld_port_config_reset[1] =
+			nthw_register_query_field(p->mp_reg_port_config[0],
+				PHY_TILE_PORT_CONFIG_RESET_1);
+		p->mp_fld_port_config_rx_reset[1] =
+			nthw_register_get_field(p->mp_reg_port_config[0],
+				PHY_TILE_PORT_CONFIG_RX_RESET_1);
+		p->mp_fld_port_config_tx_reset[1] =
+			nthw_register_get_field(p->mp_reg_port_config[0],
+				PHY_TILE_PORT_CONFIG_TX_RESET_1);
+	}
+
+	p->mp_reg_port_comp[0] = nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_COMP_0);
+	p->mp_fld_port_comp_rx_compensation[0] =
+		nthw_register_get_field(p->mp_reg_port_comp[0],
+			PHY_TILE_PORT_COMP_0_RX_COMPENSATION);
+	p->mp_fld_port_comp_tx_compensation[0] =
+		nthw_register_get_field(p->mp_reg_port_comp[0],
+			PHY_TILE_PORT_COMP_0_TX_COMPENSATION);
+	p->mp_reg_port_comp[1] = nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_PORT_COMP_1);
+	p->mp_fld_port_comp_rx_compensation[1] =
+		nthw_register_get_field(p->mp_reg_port_comp[1],
+			PHY_TILE_PORT_COMP_1_RX_COMPENSATION);
+	p->mp_fld_port_comp_tx_compensation[1] =
+		nthw_register_get_field(p->mp_reg_port_comp[1],
+			PHY_TILE_PORT_COMP_1_TX_COMPENSATION);
+
+	p->mp_reg_scratch = nthw_module_query_register(p->m_mod_phy_tile, PHY_TILE_SCRATCH);
+
+	if (p->mp_reg_scratch) {
+		p->mp_fld_scratch_data =
+			nthw_register_query_field(p->mp_reg_scratch, PHY_TILE_SCRATCH_DATA);
+	}
+
+	if (nthw_module_is_version_newer(p->m_mod_phy_tile, 0, 4)) {
+		p->mp_reg_dr_cfg = nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_DR_CFG);
+		p->mp_fld_port_config_dyn_reset =
+			nthw_register_get_field(p->mp_reg_dr_cfg, PHY_TILE_DR_CFG_DYN_RST);
+
+		if (!p->mp_reg_scratch) {
+			p->mp_fld_scratch_data =
+				nthw_register_get_field(p->mp_reg_dr_cfg, PHY_TILE_DR_CFG_SCRATCH);
+		}
+
+		p->mp_fld_reg_dr_cfg_features =
+			nthw_register_get_field(p->mp_reg_dr_cfg, PHY_TILE_DR_CFG_FEATURES);
+
+		if (nthw_module_is_version_newer(p->m_mod_phy_tile, 0, 10)) {
+			p->mp_fld_reg_dr_cfg_tx_flush_level =
+				nthw_register_get_field(p->mp_reg_dr_cfg,
+					PHY_TILE_DR_CFG_TX_FLUSH_LEVEL);
+		}
+	}
+
+	p->mp_reg_dr_cfg_status =
+		nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_DR_CFG_STATUS);
+	p->mp_fld_dr_cfg_status_curr_profile_id =
+		nthw_register_get_field(p->mp_reg_dr_cfg_status,
+			PHY_TILE_DR_CFG_STATUS_CURR_PROFILE_ID);
+	p->mp_fld_dr_cfg_status_in_progress =
+		nthw_register_get_field(p->mp_reg_dr_cfg_status,
+			PHY_TILE_DR_CFG_STATUS_IN_PROGRESS);
+	p->mp_fld_dr_cfg_status_error =
+		nthw_register_get_field(p->mp_reg_dr_cfg_status, PHY_TILE_DR_CFG_STATUS_ERROR);
+
+	if (nthw_module_is_version_newer(p->m_mod_phy_tile, 0, 7)) {
+		p->mp_reg_sys_pll = nthw_module_get_register(p->m_mod_phy_tile, PHY_TILE_SYS_PLL);
+		p->mp_fld_sys_pll_set_rdy =
+			nthw_register_get_field(p->mp_reg_sys_pll, PHY_TILE_SYS_PLL_SET_RDY);
+		p->mp_fld_sys_pll_get_rdy =
+			nthw_register_get_field(p->mp_reg_sys_pll, PHY_TILE_SYS_PLL_GET_RDY);
+		p->mp_fld_sys_pll_system_pll_lock =
+			nthw_register_get_field(p->mp_reg_sys_pll,
+				PHY_TILE_SYS_PLL_SYSTEMPLL_LOCK);
+		p->mp_fld_sys_pll_en_ref_clk_fgt =
+			nthw_register_get_field(p->mp_reg_sys_pll, PHY_TILE_SYS_PLL_EN_REFCLK_FGT);
+		p->mp_fld_sys_pll_disable_ref_clk_monitor =
+			nthw_register_get_field(p->mp_reg_sys_pll,
+				PHY_TILE_SYS_PLL_DISABLE_REFCLK_MONITOR);
+		p->mp_fld_sys_pll_ref_clk_fgt_enabled =
+			nthw_register_get_field(p->mp_reg_sys_pll,
+				PHY_TILE_SYS_PLL_REFCLK_FGT_ENABLED);
+		p->mp_fld_sys_pll_forward_rst =
+			nthw_register_get_field(p->mp_reg_sys_pll, PHY_TILE_SYS_PLL_FORWARD_RST);
+		p->mp_fld_sys_pll_force_rst =
+			nthw_register_get_field(p->mp_reg_sys_pll, PHY_TILE_SYS_PLL_FORCE_RST);
+
+	} else {
+		p->mp_fld_sys_pll_set_rdy = NULL;
+		p->mp_fld_sys_pll_get_rdy = NULL;
+		p->mp_fld_sys_pll_system_pll_lock = NULL;
+		p->mp_fld_sys_pll_en_ref_clk_fgt = NULL;
+		p->mp_fld_sys_pll_disable_ref_clk_monitor = NULL;
+		p->mp_fld_sys_pll_ref_clk_fgt_enabled = NULL;
+		p->mp_fld_sys_pll_forward_rst = NULL;
+		p->mp_fld_sys_pll_force_rst = NULL;
+	}
+
+	return 0;
+}
+
 uint8_t nthw_phy_tile_get_no_intfs(nthw_phy_tile_t *p)
 {
 	switch (p->mac_pcs_mode) {
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 30/32] net/ntnic: add igam module init
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (28 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 29/32] net/ntnic: add reset PHY init Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 31/32] net/ntnic: init IGAM and config PLL for FPGA Serhii Iliushyk
                   ` (2 subsequent siblings)
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

Create and initialize IGAM module.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 drivers/net/ntnic/meson.build                 |  1 +
 .../net/ntnic/nthw/core/include/nthw_igam.h   | 37 +++++++++++
 .../nt400dxx/reset/nthw_fpga_rst_nt400dxx.c   |  4 ++
 drivers/net/ntnic/nthw/core/nthw_igam.c       | 62 +++++++++++++++++++
 4 files changed, 104 insertions(+)
 create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_igam.h
 create mode 100644 drivers/net/ntnic/nthw/core/nthw_igam.c

diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 7e326a3e1d..30a92130b5 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -56,6 +56,7 @@ sources = files(
         'nthw/core/nthw_gpio_phy.c',
         'nthw/core/nthw_hif.c',
         'nthw/core/nthw_i2cm.c',
+        'nthw/core/nthw_igam.c',
         'nthw/core/nthw_iic.c',
         'nthw/core/nthw_mac_pcs.c',
         'nthw/core/nthw_pcie3.c',
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_igam.h b/drivers/net/ntnic/nthw/core/include/nthw_igam.h
new file mode 100644
index 0000000000..e78637a331
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/include/nthw_igam.h
@@ -0,0 +1,37 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#ifndef __NTHW_IGAM_H__
+#define __NTHW_IGAM_H__
+
+#include "nthw_fpga_model.h"
+
+struct nt_igam {
+	nthw_fpga_t *mp_fpga;
+
+	nthw_module_t *mp_mod_igam;
+
+	int mn_igam_instance;
+
+	nthw_register_t *mp_reg_base;
+	nthw_field_t *mp_fld_base_ptr;
+	nthw_field_t *mp_fld_base_busy;
+	nthw_field_t *mp_fld_base_cmd;
+
+	nthw_register_t *mp_reg_data;
+	nthw_field_t *mp_fld_data_data;
+
+	/* CTRL From version 0.1 */
+	nthw_register_t *mp_reg_ctrl;
+	nthw_field_t *mp_fld_ctrl_forward_rst;
+};
+
+typedef struct nt_igam nthw_igam_t;
+typedef struct nt_igam nthw_igam;
+
+nthw_igam_t *nthw_igam_new(void);
+int nthw_igam_init(nthw_igam_t *p, nthw_fpga_t *p_fpga, int mn_igam_instance);
+
+#endif	/*  __NTHW_IGAM_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
index 35cbaea81e..95394b9c8f 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
@@ -9,6 +9,7 @@
 #include "nthw_fpga.h"
 #include "nthw_hif.h"
 #include "ntnic_mod_reg.h"
+#include "nthw_igam.h"
 
 static int nthw_fpga_rst_nt400dxx_init(struct fpga_info_s *p_fpga_info)
 {
@@ -198,6 +199,9 @@ static int nthw_fpga_rst_nt400dxx_reset(struct fpga_info_s *p_fpga_info)
 		return -1;
 	}
 
+	nthw_igam_t *p_igam = nthw_igam_new();
+	nthw_igam_init(p_igam, p_fpga, 0);
+
 	return 0;
 }
 
diff --git a/drivers/net/ntnic/nthw/core/nthw_igam.c b/drivers/net/ntnic/nthw/core/nthw_igam.c
new file mode 100644
index 0000000000..5dc7e36c7b
--- /dev/null
+++ b/drivers/net/ntnic/nthw/core/nthw_igam.c
@@ -0,0 +1,62 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Napatech A/S
+ */
+
+#include "nt_util.h"
+#include "ntlog.h"
+
+#include "nthw_drv.h"
+#include "nthw_register.h"
+
+#include "nthw_igam.h"
+
+nthw_igam_t *nthw_igam_new(void)
+{
+	nthw_igam_t *p = malloc(sizeof(nthw_igam_t));
+
+	if (p)
+		memset(p, 0, sizeof(nthw_igam_t));
+
+	return p;
+}
+
+int nthw_igam_init(nthw_igam_t *p, nthw_fpga_t *p_fpga, int mn_igam_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_IGAM, mn_igam_instance);
+
+	if (p == NULL)
+		return mod == NULL ? -1 : 0;
+
+	if (mod == NULL) {
+		NT_LOG(ERR, NTHW, "%s: IGAM %d: no such instance", p_adapter_id_str,
+			mn_igam_instance);
+		return -1;
+	}
+
+	p->mp_fpga = p_fpga;
+	p->mn_igam_instance = mn_igam_instance;
+
+	p->mp_mod_igam = mod;
+
+	p->mp_reg_base = nthw_module_get_register(p->mp_mod_igam, IGAM_BASE);
+	p->mp_fld_base_ptr = nthw_register_get_field(p->mp_reg_base, IGAM_BASE_PTR);
+	p->mp_fld_base_busy = nthw_register_get_field(p->mp_reg_base, IGAM_BASE_BUSY);
+	p->mp_fld_base_cmd = nthw_register_get_field(p->mp_reg_base, IGAM_BASE_CMD);
+
+	p->mp_reg_data = nthw_module_get_register(p->mp_mod_igam, IGAM_DATA);
+	p->mp_fld_data_data = nthw_register_get_field(p->mp_reg_data, IGAM_DATA_DATA);
+
+	p->mp_reg_ctrl = nthw_module_query_register(p->mp_mod_igam, IGAM_CTRL);
+
+	if (p->mp_reg_ctrl) {
+		p->mp_fld_ctrl_forward_rst =
+			nthw_register_get_field(p->mp_reg_ctrl, IGAM_CTRL_FORWARD_RST);
+
+	} else {
+		p->mp_fld_ctrl_forward_rst = NULL;
+	}
+
+	return 0;
+}
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 31/32] net/ntnic: init IGAM and config PLL for FPGA
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (29 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 30/32] net/ntnic: add igam module init Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:03 ` [PATCH v1 32/32] net/ntnic: revert untrusted loop bound Serhii Iliushyk
  2025-02-20 23:49 ` [PATCH v1 00/32] add new adapter NT400D13 Stephen Hemminger
  32 siblings, 0 replies; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen, Danylo Vodopianov

From: Danylo Vodopianov <dvo-plv@napatech.com>

- Initialize IGAM module and check for its presence.
- Enable system PLL using IGAM and check for PLL lock status.
- Reset and configure TS PLL and check for lock status.
- Force HIF soft reset and de-assert platform reset.
- Enable RAB1 and RAB2 and perform RAB initialization and flush.
- Check system PLL readiness using PHY_TILE and handle PLL lock status.

Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
 .../net/ntnic/nthw/core/include/nthw_hif.h    |   1 +
 .../net/ntnic/nthw/core/include/nthw_igam.h   |   3 +
 .../nthw/core/include/nthw_pcm_nt400dxx.h     |   4 +
 .../ntnic/nthw/core/include/nthw_phy_tile.h   |   8 +
 .../nt400dxx/reset/nthw_fpga_rst_nt400dxx.c   | 211 ++++++++++++++++++
 drivers/net/ntnic/nthw/core/nthw_hif.c        |  10 +
 drivers/net/ntnic/nthw/core/nthw_igam.c       |  31 +++
 .../net/ntnic/nthw/core/nthw_pcm_nt400dxx.c   |  24 ++
 drivers/net/ntnic/nthw/core/nthw_phy_tile.c   |  61 +++++
 drivers/net/ntnic/nthw/nthw_drv.h             |   2 +
 10 files changed, 355 insertions(+)

diff --git a/drivers/net/ntnic/nthw/core/include/nthw_hif.h b/drivers/net/ntnic/nthw/core/include/nthw_hif.h
index deb9ed04e8..7d5e1f1310 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_hif.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_hif.h
@@ -135,6 +135,7 @@ void nthw_hif_delete(nthw_hif_t *p);
 int nthw_hif_init(nthw_hif_t *p, nthw_fpga_t *p_fpga, int n_instance);
 
 int nthw_hif_trigger_sample_time(nthw_hif_t *p);
+int nthw_hif_force_soft_reset(nthw_hif_t *p);
 
 int nthw_hif_stat_req_enable(nthw_hif_t *p);
 int nthw_hif_stat_req_disable(nthw_hif_t *p);
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_igam.h b/drivers/net/ntnic/nthw/core/include/nthw_igam.h
index e78637a331..fed462cd34 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_igam.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_igam.h
@@ -33,5 +33,8 @@ typedef struct nt_igam nthw_igam;
 
 nthw_igam_t *nthw_igam_new(void);
 int nthw_igam_init(nthw_igam_t *p, nthw_fpga_t *p_fpga, int mn_igam_instance);
+uint32_t nthw_igam_read(nthw_igam_t *p, uint32_t address);
+void nthw_igam_write(nthw_igam_t *p, uint32_t address, uint32_t data);
+void nthw_igam_set_ctrl_forward_rst(nthw_igam_t *p, uint32_t value);
 
 #endif	/*  __NTHW_IGAM_H__ */
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h b/drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h
index 23865f466b..47d2670cf5 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h
@@ -32,5 +32,9 @@ typedef struct nthw_pcm_nt400_dxx nthw_pcm_nt400_dxx;
 
 nthw_pcm_nt400dxx_t *nthw_pcm_nt400dxx_new(void);
 int nthw_pcm_nt400dxx_init(nthw_pcm_nt400dxx_t *p, nthw_fpga_t *p_fpga, int n_instance);
+void nthw_pcm_nt400dxx_set_ts_pll_recal(nthw_pcm_nt400dxx_t *p, uint32_t val);
+bool nthw_pcm_nt400dxx_get_ts_pll_locked_stat(nthw_pcm_nt400dxx_t *p);
+bool nthw_pcm_nt400dxx_get_ts_pll_locked_latch(nthw_pcm_nt400dxx_t *p);
+void nthw_pcm_nt400dxx_set_ts_pll_locked_latch(nthw_pcm_nt400dxx_t *p, uint32_t val);
 
 #endif	/* __NTHW_PCM_NT400DXX_H__ */
diff --git a/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
index ba044a5091..c4ec100c23 100644
--- a/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
+++ b/drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
@@ -142,7 +142,15 @@ void nthw_phy_tile_write_xcvr(nthw_phy_tile_t *p, uint8_t intf_no, uint8_t lane,
 	uint32_t data);
 uint32_t nthw_phy_tile_get_port_status_reset_ack(nthw_phy_tile_t *p, uint8_t intf_no);
 uint32_t nthw_phy_tile_get_port_status_tx_lanes_stable(nthw_phy_tile_t *p, uint8_t intf_no);
+void nthw_phy_tile_set_sys_pll_set_rdy(nthw_phy_tile_t *p, uint32_t value);
+uint32_t nthw_phy_tile_get_sys_pll_get_rdy(nthw_phy_tile_t *p);
+uint32_t nthw_phy_tile_get_sys_pll_system_pll_lock(nthw_phy_tile_t *p);
+void nthw_phy_tile_set_sys_pll_en_ref_clk_fgt(nthw_phy_tile_t *p, uint32_t value);
+uint32_t nthw_phy_tile_get_sys_pll_ref_clk_fgt_enabled(nthw_phy_tile_t *p);
+void nthw_phy_tile_set_sys_pll_forward_rst(nthw_phy_tile_t *p, uint32_t value);
+void nthw_phy_tile_set_sys_pll_force_rst(nthw_phy_tile_t *p, uint32_t value);
 uint8_t nthw_phy_tile_get_no_intfs(nthw_phy_tile_t *p);
 void nthw_phy_tile_set_port_config_rst(nthw_phy_tile_t *p, uint8_t intf_no, uint32_t value);
+bool nthw_phy_tile_use_phy_tile_pll_check(nthw_phy_tile_t *p);
 
 #endif	/* __NTHW_PHY_TILE_H__ */
diff --git a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
index 95394b9c8f..b93b0a829a 100644
--- a/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
@@ -184,9 +184,13 @@ static int nthw_fpga_rst_nt400dxx_reset(struct fpga_info_s *p_fpga_info)
 {
 	const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
 	nthw_fpga_t *p_fpga = NULL;
+	int res = -1;
 
 	p_fpga = p_fpga_info->mp_fpga;
 
+	nthw_pcm_nt400dxx_t *p_pcm = p_fpga_info->mp_nthw_agx.p_pcm;
+	nthw_prm_nt400dxx_t *p_prm = p_fpga_info->mp_nthw_agx.p_prm;
+
 	assert(p_fpga_info);
 
 	NT_LOG(DBG, NTHW, "%s: %s: BEGIN", p_adapter_id_str, __PRETTY_FUNCTION__);
@@ -199,9 +203,216 @@ static int nthw_fpga_rst_nt400dxx_reset(struct fpga_info_s *p_fpga_info)
 		return -1;
 	}
 
+	nthw_phy_tile_t *p_phy_tile = p_fpga_info->mp_nthw_agx.p_phy_tile;
+
 	nthw_igam_t *p_igam = nthw_igam_new();
 	nthw_igam_init(p_igam, p_fpga, 0);
 
+	if (p_igam) {
+		if (!nthw_phy_tile_use_phy_tile_pll_check(p_fpga_info->mp_nthw_agx.p_phy_tile)) {
+			NT_LOG(DBG, NTHW, "%s: IGAM module present.", p_adapter_id_str);
+			uint32_t data;
+
+			p_fpga_info->mp_nthw_agx.p_igam = p_igam;
+
+			/*
+			 * (E) When the reference clock for the F-tile system PLL is started (and
+			 * stable) it must be enabled using the Intel Global Avalon Memory-Mapped
+			 * Mailbox (IGAM) module.
+			 */
+
+			nthw_igam_write(p_igam, 0xffff8, 0x90000000);
+
+			/* (F) Check that the system PLL is ready. */
+			for (int i = 1000; i >= 0; i--) {
+				nt_os_wait_usec(1000);
+				data = nthw_igam_read(p_igam, 0xffff4);
+
+				if (data == 0x80000000 || data == 0xA0000000) {
+					NT_LOG(INF,
+						NTHW,
+						"%s: All enabled system PLLs are locked. Response: %#08x",
+						p_adapter_id_str,
+						data);
+					break;
+				}
+
+				if (i == 0) {
+					NT_LOG(ERR,
+						NTHW,
+						"%s: Timeout waiting for all system PLLs to lock. Response: %#08x",
+						p_adapter_id_str,
+						data);
+					return -1;
+				}
+			}
+
+		} else {
+			nthw_igam_set_ctrl_forward_rst(p_igam,
+				0);	/* Ensure that the Avalon bus is not */
+			/* reset at every driver re-load. */
+			nt_os_wait_usec(1000000);
+			NT_LOG(DBG, NTHW, "%s: IGAM module not used.", p_adapter_id_str);
+		}
+
+	} else {
+		NT_LOG(DBG, NTHW, "%s: No IGAM module present.", p_adapter_id_str);
+	}
+
+	/*
+	 * (G) Reset TS PLL and select Time-of-Day clock (tod_fpga_clk). Source is either
+	 * from ZL clock device or SiTime tunable XO. NOTE that the PLL must be held in
+	 * RESET during clock switchover.
+	 */
+
+	if (p_fpga_info->mp_nthw_agx.tcxo_present && p_fpga_info->mp_nthw_agx.tcxo_capable) {
+		nthw_pcm_nt400dxx_set_ts_pll_recal(p_pcm, 1);
+		nt_os_wait_usec(1000);
+		nthw_pcm_nt400dxx_set_ts_pll_recal(p_pcm, 0);
+		nt_os_wait_usec(1000);
+	}
+
+	/* (I) Wait for TS PLL locked. */
+	for (int i = 1000; i >= 0; i--) {
+		nt_os_wait_usec(1000);
+
+		if (nthw_pcm_nt400dxx_get_ts_pll_locked_stat(p_pcm))
+			break;
+
+		if (i == 0) {
+			NT_LOG(ERR,
+				NTHW,
+				"%s: %s: Time out waiting for TS PLL locked",
+				p_adapter_id_str,
+				__func__);
+			return -1;
+		}
+	}
+
+	/* NT_RAB0_REG.PCM_NT400D1X.STAT.TS_PLL_LOCKED==1 */
+
+	/* (J) Set latched TS PLL locked. */
+	nthw_pcm_nt400dxx_set_ts_pll_locked_latch(p_pcm, 1);
+	/* NT_RAB0_REG.PCM_NT400D1X.LATCH.TS_PLL_LOCKED=1 */
+
+	/* (K) Ensure TS latched status bit is still set. */
+	if (!nthw_pcm_nt400dxx_get_ts_pll_locked_stat(p_pcm)) {
+		NT_LOG(ERR,
+			NTHW,
+			"%s: %s: TS latched status bit toggled",
+			p_adapter_id_str,
+			__func__);
+		return -1;
+	}
+
+	/* NT_RAB0_REG.PCM_NT400D1X.LATCH.TS_PLL_LOCKED==1 */
+
+	/*
+	 * At this point all system clocks and TS clocks are running.
+	 * Last thing to do before proceeding to product reset is to
+	 * de-assert the platform reset and enable the RAB buses.
+	 */
+
+	/* (K1) Force HIF soft reset. */
+	nthw_hif_t *p_nthw_hif = nthw_hif_new();
+	res = nthw_hif_init(p_nthw_hif, p_fpga, 0);
+
+	if (res == 0)
+		NT_LOG(DBG, NTHW, "%s: Hif module found", p_fpga_info->mp_adapter_id_str);
+
+	nt_os_wait_usec(1000);
+	nthw_hif_force_soft_reset(p_nthw_hif);
+	nt_os_wait_usec(1000);
+	nthw_hif_delete(p_nthw_hif);
+
+	/* (L) De-assert platform reset. */
+	nthw_prm_nt400dxx_platform_rst(p_prm, 0);
+
+	/*
+	 * (M) Enable RAB1 and RAB2.
+	 * NT_BAR_REG.RAC.RAB_INIT.RAB=0
+	 */
+	NT_LOG_DBGX(DBG, NTHW, "%s: RAB Init", p_adapter_id_str);
+	nthw_rac_rab_init(p_fpga_info->mp_nthw_rac, 0);
+	nthw_rac_rab_setup(p_fpga_info->mp_nthw_rac);
+
+	NT_LOG_DBGX(DBG, NTHW, "%s: RAB Flush", p_adapter_id_str);
+	nthw_rac_rab_flush(p_fpga_info->mp_nthw_rac);
+
+	/*
+	 * FPGAs with newer PHY_TILE versions must use PhyTile to check that system PLL is ready.
+	 * It has been added here after consultations with ORA since the test must be performed
+	 * after de-assertion of platform reset.
+	 */
+
+	if (nthw_phy_tile_use_phy_tile_pll_check(p_phy_tile)) {
+		/* Ensure that the Avalon bus is not reset at every driver re-load. */
+		nthw_phy_tile_set_sys_pll_forward_rst(p_phy_tile, 0);
+
+		nthw_phy_tile_set_sys_pll_set_rdy(p_phy_tile, 0x07);
+		NT_LOG_DBGX(DBG, NTHW, "%s: setSysPllSetRdy.", p_adapter_id_str);
+
+		/* (F) Check that the system PLL is ready. */
+		for (int i = 1000; i >= 0; i--) {
+			nt_os_wait_usec(1000);
+
+			if (nthw_phy_tile_get_sys_pll_get_rdy(p_phy_tile) &&
+				nthw_phy_tile_get_sys_pll_system_pll_lock(p_phy_tile)) {
+				break;
+			}
+
+			if (i == 500) {
+				nthw_phy_tile_set_sys_pll_force_rst(p_phy_tile, 1);
+				nt_os_wait_usec(1000);
+				nthw_phy_tile_set_sys_pll_force_rst(p_phy_tile, 0);
+				NT_LOG_DBGX(DBG,
+					NTHW,
+					"%s: setSysPllForceRst due to system PLL not ready.",
+					p_adapter_id_str);
+			}
+
+			if (i == 0) {
+				NT_LOG_DBGX(DBG,
+					NTHW,
+					"%s: Timeout waiting for all system PLLs to lock",
+					p_adapter_id_str);
+				return -1;
+			}
+		}
+
+		nt_os_wait_usec(100000);/* 100 ms */
+
+		uint32_t fgt_enable = 0x0d;	/* FGT 0, 2 & 3 */
+		nthw_phy_tile_set_sys_pll_en_ref_clk_fgt(p_phy_tile, fgt_enable);
+
+		for (int i = 1000; i >= 0; i--) {
+			nt_os_wait_usec(1000);
+
+			if (nthw_phy_tile_get_sys_pll_ref_clk_fgt_enabled(p_phy_tile) ==
+				fgt_enable) {
+				break;
+			}
+
+			if (i == 500) {
+				nthw_phy_tile_set_sys_pll_force_rst(p_phy_tile, 1);
+				nt_os_wait_usec(1000);
+				nthw_phy_tile_set_sys_pll_force_rst(p_phy_tile, 0);
+				NT_LOG_DBGX(DBG,
+					NTHW,
+					"%s: setSysPllForceRst due to FGTs not ready.",
+					p_adapter_id_str);
+			}
+
+			if (i == 0) {
+				NT_LOG_DBGX(DBG,
+					NTHW,
+					"%s: Timeout waiting for FGTs to lock",
+					p_adapter_id_str);
+				return -1;
+			}
+		}
+	}
+
 	return 0;
 }
 
diff --git a/drivers/net/ntnic/nthw/core/nthw_hif.c b/drivers/net/ntnic/nthw/core/nthw_hif.c
index 92a2348bbb..630262a7fc 100644
--- a/drivers/net/ntnic/nthw/core/nthw_hif.c
+++ b/drivers/net/ntnic/nthw/core/nthw_hif.c
@@ -202,6 +202,16 @@ int nthw_hif_init(nthw_hif_t *p, nthw_fpga_t *p_fpga, int n_instance)
 	return 0;
 }
 
+int nthw_hif_force_soft_reset(nthw_hif_t *p)
+{
+	if (p->mp_fld_ctrl_fsr) {
+		nthw_field_update_register(p->mp_fld_ctrl_fsr);
+		nthw_field_set_flush(p->mp_fld_ctrl_fsr);
+	}
+
+	return 0;
+}
+
 int nthw_hif_trigger_sample_time(nthw_hif_t *p)
 {
 	nthw_field_set_val_flush32(p->mp_fld_sample_time, 0xfee1dead);
diff --git a/drivers/net/ntnic/nthw/core/nthw_igam.c b/drivers/net/ntnic/nthw/core/nthw_igam.c
index 5dc7e36c7b..385282298a 100644
--- a/drivers/net/ntnic/nthw/core/nthw_igam.c
+++ b/drivers/net/ntnic/nthw/core/nthw_igam.c
@@ -60,3 +60,34 @@ int nthw_igam_init(nthw_igam_t *p, nthw_fpga_t *p_fpga, int mn_igam_instance)
 
 	return 0;
 }
+
+uint32_t nthw_igam_read(nthw_igam_t *p, uint32_t address)
+{
+	nthw_register_update(p->mp_reg_base);
+	nthw_field_set_val32(p->mp_fld_base_cmd, 0);
+	nthw_field_set_val_flush32(p->mp_fld_base_ptr, address);
+
+	while (nthw_field_get_updated(p->mp_fld_base_busy) == 1)
+		nt_os_wait_usec(100);
+
+	return nthw_field_get_updated(p->mp_fld_data_data);
+}
+
+void nthw_igam_write(nthw_igam_t *p, uint32_t address, uint32_t data)
+{
+	nthw_field_set_val_flush32(p->mp_fld_data_data, data);
+	nthw_register_update(p->mp_reg_base);
+	nthw_field_set_val32(p->mp_fld_base_ptr, address);
+	nthw_field_set_val_flush32(p->mp_fld_base_cmd, 1);
+
+	while (nthw_field_get_updated(p->mp_fld_base_busy) == 1)
+		nt_os_wait_usec(100);
+}
+
+void nthw_igam_set_ctrl_forward_rst(nthw_igam_t *p, uint32_t value)
+{
+	if (p->mp_fld_ctrl_forward_rst) {
+		nthw_field_get_updated(p->mp_fld_ctrl_forward_rst);
+		nthw_field_set_val_flush32(p->mp_fld_ctrl_forward_rst, value);
+	}
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_pcm_nt400dxx.c b/drivers/net/ntnic/nthw/core/nthw_pcm_nt400dxx.c
index f32a277e86..e7be634a83 100644
--- a/drivers/net/ntnic/nthw/core/nthw_pcm_nt400dxx.c
+++ b/drivers/net/ntnic/nthw/core/nthw_pcm_nt400dxx.c
@@ -54,3 +54,27 @@ int nthw_pcm_nt400dxx_init(nthw_pcm_nt400dxx_t *p, nthw_fpga_t *p_fpga, int n_in
 
 	return 0;
 }
+
+void nthw_pcm_nt400dxx_set_ts_pll_recal(nthw_pcm_nt400dxx_t *p, uint32_t val)
+{
+	if (p->mp_fld_ctrl_ts_pll_recal) {
+		nthw_field_update_register(p->mp_fld_ctrl_ts_pll_recal);
+		nthw_field_set_val_flush32(p->mp_fld_ctrl_ts_pll_recal, val);
+	}
+}
+
+bool nthw_pcm_nt400dxx_get_ts_pll_locked_stat(nthw_pcm_nt400dxx_t *p)
+{
+	return nthw_field_get_updated(p->mp_fld_stat_ts_pll_locked) != 0;
+}
+
+bool nthw_pcm_nt400dxx_get_ts_pll_locked_latch(nthw_pcm_nt400dxx_t *p)
+{
+	return nthw_field_get_updated(p->mp_fld_latch_ts_pll_locked) != 0;
+}
+
+void nthw_pcm_nt400dxx_set_ts_pll_locked_latch(nthw_pcm_nt400dxx_t *p, uint32_t val)
+{
+	nthw_field_update_register(p->mp_fld_latch_ts_pll_locked);
+	nthw_field_set_val_flush32(p->mp_fld_latch_ts_pll_locked, val);
+}
diff --git a/drivers/net/ntnic/nthw/core/nthw_phy_tile.c b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
index f78d8263f5..0dc2784034 100644
--- a/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
+++ b/drivers/net/ntnic/nthw/core/nthw_phy_tile.c
@@ -642,6 +642,11 @@ int nthw_phy_tile_init(nthw_phy_tile_t *p, nthw_fpga_t *p_fpga, int mn_phy_tile_
 	return 0;
 }
 
+bool nthw_phy_tile_use_phy_tile_pll_check(nthw_phy_tile_t *p)
+{
+	return nthw_module_is_version_newer(p->m_mod_phy_tile, 0, 8);
+}
+
 uint8_t nthw_phy_tile_get_no_intfs(nthw_phy_tile_t *p)
 {
 	switch (p->mac_pcs_mode) {
@@ -1172,6 +1177,62 @@ uint32_t nthw_phy_tile_get_port_status_tx_lanes_stable(nthw_phy_tile_t *p, uint8
 	return 1;
 }
 
+void nthw_phy_tile_set_sys_pll_set_rdy(nthw_phy_tile_t *p, uint32_t value)
+{
+	if (p->mp_fld_sys_pll_set_rdy) {
+		nthw_field_get_updated(p->mp_fld_sys_pll_set_rdy);
+		nthw_field_set_val_flush32(p->mp_fld_sys_pll_set_rdy, value);
+	}
+}
+
+uint32_t nthw_phy_tile_get_sys_pll_get_rdy(nthw_phy_tile_t *p)
+{
+	if (p->mp_fld_sys_pll_get_rdy)
+		return nthw_field_get_updated(p->mp_fld_sys_pll_get_rdy);
+
+	return 0;
+}
+
+uint32_t nthw_phy_tile_get_sys_pll_system_pll_lock(nthw_phy_tile_t *p)
+{
+	if (p->mp_fld_sys_pll_system_pll_lock)
+		return nthw_field_get_updated(p->mp_fld_sys_pll_system_pll_lock);
+
+	return 0;
+}
+
+void nthw_phy_tile_set_sys_pll_en_ref_clk_fgt(nthw_phy_tile_t *p, uint32_t value)
+{
+	if (p->mp_fld_sys_pll_en_ref_clk_fgt) {
+		nthw_field_get_updated(p->mp_fld_sys_pll_en_ref_clk_fgt);
+		nthw_field_set_val_flush32(p->mp_fld_sys_pll_en_ref_clk_fgt, value);
+	}
+}
+
+uint32_t nthw_phy_tile_get_sys_pll_ref_clk_fgt_enabled(nthw_phy_tile_t *p)
+{
+	if (p->mp_fld_sys_pll_ref_clk_fgt_enabled)
+		return nthw_field_get_updated(p->mp_fld_sys_pll_ref_clk_fgt_enabled);
+
+	return 0;
+}
+
+void nthw_phy_tile_set_sys_pll_forward_rst(nthw_phy_tile_t *p, uint32_t value)
+{
+	if (p->mp_fld_sys_pll_forward_rst) {
+		nthw_field_get_updated(p->mp_fld_sys_pll_forward_rst);
+		nthw_field_set_val_flush32(p->mp_fld_sys_pll_forward_rst, value);
+	}
+}
+
+void nthw_phy_tile_set_sys_pll_force_rst(nthw_phy_tile_t *p, uint32_t value)
+{
+	if (p->mp_fld_sys_pll_force_rst) {
+		nthw_field_get_updated(p->mp_fld_sys_pll_force_rst);
+		nthw_field_set_val_flush32(p->mp_fld_sys_pll_force_rst, value);
+	}
+}
+
 void nthw_phy_tile_set_port_config_rst(nthw_phy_tile_t *p, uint8_t intf_no, uint32_t value)
 {
 	if (p->mp_fld_port_config_reset[intf_no]) {
diff --git a/drivers/net/ntnic/nthw/nthw_drv.h b/drivers/net/ntnic/nthw/nthw_drv.h
index 574dd663ea..e1a00c5ea5 100644
--- a/drivers/net/ntnic/nthw/nthw_drv.h
+++ b/drivers/net/ntnic/nthw/nthw_drv.h
@@ -17,6 +17,7 @@
 #include "nthw_phy_tile.h"
 #include "nthw_prm_nt400dxx.h"
 #include "nthw_pcm_nt400dxx.h"
+#include "nthw_igam.h"
 
 /*
  * Structs for controlling Agilex based NT400DXX adapter
@@ -31,6 +32,7 @@ typedef struct nthw_agx_s {
 	nthw_si5156_t *p_si5156;
 	nthw_prm_nt400dxx_t *p_prm;
 	nthw_pcm_nt400dxx_t *p_pcm;
+	nthw_igam_t *p_igam;
 	nthw_phy_tile_t *p_phy_tile;
 	nthw_rpf_t *p_rpf;
 	bool tcxo_present;
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v1 32/32] net/ntnic: revert untrusted loop bound
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (30 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 31/32] net/ntnic: init IGAM and config PLL for FPGA Serhii Iliushyk
@ 2025-02-20 22:03 ` Serhii Iliushyk
  2025-02-20 22:31   ` Stephen Hemminger
  2025-02-20 23:49 ` [PATCH v1 00/32] add new adapter NT400D13 Stephen Hemminger
  32 siblings, 1 reply; 35+ messages in thread
From: Serhii Iliushyk @ 2025-02-20 22:03 UTC (permalink / raw)
  To: dev; +Cc: mko-plv, sil-plv, ckm, stephen

The changes for untrusted loop bound breaks VLAN processing

This reverts commit 36cd2cb0eea49813dd59ee1df2eb592e8ae5b6b4.

Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
 drivers/net/ntnic/ntnic_filter/ntnic_filter.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
index 70bff776be..43f45ebe34 100644
--- a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
+++ b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
@@ -53,7 +53,7 @@ int interpret_raw_data(uint8_t *data, uint8_t *preserve, int size, struct rte_fl
 		goto interpret_end;
 
 	/* VLAN */
-	if (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) ||
+	while (ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) ||
 		ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ) ||
 		ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ1)) {
 		if (size - pkti == 0)
-- 
2.45.0


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v1 32/32] net/ntnic: revert untrusted loop bound
  2025-02-20 22:03 ` [PATCH v1 32/32] net/ntnic: revert untrusted loop bound Serhii Iliushyk
@ 2025-02-20 22:31   ` Stephen Hemminger
  0 siblings, 0 replies; 35+ messages in thread
From: Stephen Hemminger @ 2025-02-20 22:31 UTC (permalink / raw)
  To: Serhii Iliushyk; +Cc: dev, mko-plv, ckm

On Thu, 20 Feb 2025 23:03:56 +0100
Serhii Iliushyk <sil-plv@napatech.com> wrote:

> The changes for untrusted loop bound breaks VLAN processing
> 
> This reverts commit 36cd2cb0eea49813dd59ee1df2eb592e8ae5b6b4.
> 
> Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>

This will bring back the Coverity bug and potential for VLAN "packet of doom" bugs.
Any loop iterating over VLAN's needs to limit depth

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v1 00/32] add new adapter NT400D13
  2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
                   ` (31 preceding siblings ...)
  2025-02-20 22:03 ` [PATCH v1 32/32] net/ntnic: revert untrusted loop bound Serhii Iliushyk
@ 2025-02-20 23:49 ` Stephen Hemminger
  32 siblings, 0 replies; 35+ messages in thread
From: Stephen Hemminger @ 2025-02-20 23:49 UTC (permalink / raw)
  To: Serhii Iliushyk; +Cc: dev, mko-plv, ckm

[-- Attachment #1: Type: text/plain, Size: 52726 bytes --]

Ok, scan of ntnic with PVS studio after this bundle.
Similar to Coverity it is a good automated tool for finding bugs.

MESSAGES
LocationCodeMessage
Fails/Info

nt4ga_adapter.c (129)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function.
Under certain conditions the pointer can be null.

nt4ga_adapter.c (150)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function.
Under certain conditions the pointer can be null.

nt4ga_stat.c (252)
V595 <https://pvs-studio.com/en/docs/warnings/v595/> The 'p_nt4ga_stat'
pointer was utilized before it was verified against nullptr. Check lines:
252, 259.

nt4ga_stat.c (47)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression
'p_nt4ga_stat' is always true.

ntnic_dbsconfig.c (595)
V595 <https://pvs-studio.com/en/docs/warnings/v595/> The 'txvq' pointer was
utilized before it was verified against nullptr. Check lines: 595, 597.

ntnic_dbsconfig.c (765)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression 'irq_vector
>= 0' is always false.

ntnic_dbsconfig.c (400)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
UNSIGNED integer type argument is expected.

hw_mod_backend.h (750)
V1071 <https://pvs-studio.com/en/docs/warnings/v1071/> Consider inspecting
the 'hw_mod_hsh_rcp_set' function. The return value is not always used.
Total calls: 15, discarded results: 1.

nt4ga_link_100g.c (259)
V781 <https://pvs-studio.com/en/docs/warnings/v781/> The value of the
'port' variable is checked after it was used. Perhaps there is a mistake in
program logic. Check lines: 259, 261.

nt4ga_link_100g.c (674)
V560 <https://pvs-studio.com/en/docs/warnings/v560/> A part of conditional
expression is always true: res == 0.

nt4ga_agx_link_100g.c (696)
V523 <https://pvs-studio.com/en/docs/warnings/v523/> The 'then' statement
is equivalent to the 'else' statement.

nt4ga_agx_link_100g.c (1012)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression 'res == 0'
is always true.

nt4ga_agx_link_100g.c (1021)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression 'res == 0'
is always true.

nt4ga_agx_link_100g.c (522)
V781 <https://pvs-studio.com/en/docs/warnings/v781/> The value of the
'port' variable is checked after it was used. Perhaps there is a mistake in
program logic. Check lines: 522, 524.

nt4ga_agx_link_100g.c (916)
V619 <https://pvs-studio.com/en/docs/warnings/v619/> The array 'nim_ctx' is
being utilized as a pointer to single object.

nt4ga_agx_link_100g.c (318)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'rte_log' function. The
UNSIGNED integer type argument is expected.

nt4ga_agx_link_100g.c (370)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the seventh actual argument of the 'rte_log' function.
The SIGNED integer type argument is expected.

nt4ga_agx_link_100g.c (370)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nt4ga_agx_link_100g.c (385)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'rte_log' function. The
UNSIGNED integer type argument is expected.

nt4ga_agx_link_100g.c (391)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'rte_log' function. The
UNSIGNED integer type argument is expected.

nt4ga_agx_link_100g.c (976)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
UNSIGNED integer type argument is expected.

nt4ga_agx_link_100g.c (984)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
UNSIGNED integer type argument is expected.

nt4ga_agx_link_100g.c (380)
V1051 <https://pvs-studio.com/en/docs/warnings/v1051/> Consider checking
for misprints. It's possible that the 'state->link_up' should be checked
here.

i2c_nim.c (126)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression 'multi_byte
== 1' is always true.

i2c_nim.c (881)
V519 <https://pvs-studio.com/en/docs/warnings/v519/> The variable is
assigned values twice successively. Perhaps this is a mistake. Check lines:
880, 881.

nthw_fpga_rst9563.c (62)
V519 <https://pvs-studio.com/en/docs/warnings/v519/> The
'p->mp_fld_rst_ptp' variable is assigned values twice successively. Perhaps
this is a mistake. Check lines: 61, 62.

nthw_fpga_rst9563.c (107)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression
'!p->mp_fld_stat_tsm_ref_mmcm_locked' is always true.

nthw_fpga_rst9563.c (129)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression
'!p->mp_fld_sticky_tsm_ref_mmcm_unlocked' is always true.

nthw_fpga_rst_nt200a0x.c (531)
V519 <https://pvs-studio.com/en/docs/warnings/v519/> The 'res' variable is
assigned values twice successively. Perhaps this is a mistake. Check lines:
530, 531.

nthw_fpga_rst_nt200a0x.c (62)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_fpga_rst_nt200a0x.c (72)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_fpga_nt400dxx.c (187)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression
'rst9574_ops' is always true.

nthw_fpga_rst_nt400dxx.c (185)
V595 <https://pvs-studio.com/en/docs/warnings/v595/> The 'p_fpga_info'
pointer was utilized before it was verified against nullptr. Check lines:
185, 194.

nthw_fpga_rst_nt400dxx.c (60)
V525 <https://pvs-studio.com/en/docs/warnings/v525/> The code contains the
collection of similar blocks. Check items 'nthw_prm_nt400dxx_platform_rst',
'nthw_prm_nt400dxx_periph_rst', 'nthw_prm_nt400dxx_periph_rst' in lines 60,
64, 66.

nthw_fpga_rst_nt400dxx.c (116)
V525 <https://pvs-studio.com/en/docs/warnings/v525/> The code contains the
collection of similar blocks. Check items '0', '1', '0', '0', '1' in lines
116, 122, 128, 134, 140.

nthw_fpga.c (623)
V595 <https://pvs-studio.com/en/docs/warnings/v595/> The 'p_fpga_info'
pointer was utilized before it was verified against nullptr. Check lines:
623, 639.

nthw_fpga.c (317)
V560 <https://pvs-studio.com/en/docs/warnings/v560/> A part of conditional
expression is always false: avr_vpd_info.n_avr_spi_version >= 3.

nthw_fpga.c (387)
V560 <https://pvs-studio.com/en/docs/warnings/v560/> A part of conditional
expression is always false: avr_vpd_info.n_avr_spi_version >= 3.

nthw_fpga.c (469)
V560 <https://pvs-studio.com/en/docs/warnings/v560/> A part of conditional
expression is always false: avr_vpd_info.n_avr_spi_version >= 3.

nthw_fpga.c (831)
V560 <https://pvs-studio.com/en/docs/warnings/v560/> A part of conditional
expression is always true: p_fpga_info.

nthw_fpga.c (831)
V571 <https://pvs-studio.com/en/docs/warnings/v571/> Recurring check. The
'p_fpga_info' condition was already verified in line 830.

nthw_fpga.c (524)
V1086 <https://pvs-studio.com/en/docs/warnings/v1086/> A call of the
'memcpy' function will lead to underflow of the buffer '&
p_vpd_board_info[0]'.

nthw_hif.c (27)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

nthw_hif.c (82)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the seventh actual argument of the 'rte_log' function.
The SIGNED integer type argument is expected.

nthw_iic.c (257)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

nthw_iic.c (242)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the seventh actual argument of the 'rte_log' function.
The SIGNED integer type argument is expected.

nthw_pcie3.c (28)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

nthw_pcm_nt400dxx.c (45)
V525 <https://pvs-studio.com/en/docs/warnings/v525/> The code contains the
collection of similar blocks. Check items 'nthw_register_query_field',
'nthw_register_get_field', 'nthw_register_get_field' in lines 45, 49, 53.

nthw_phy_tile.c (821)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression 'i == 0' is
always false.

nthw_phy_tile.c (800)
V1048 <https://pvs-studio.com/en/docs/warnings/v1048/> The 'xcvr_instance'
variable was assigned the same value.

nthw_phy_tile.c (86)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'rte_log' function. The
UNSIGNED integer type argument is expected.

nthw_rpf.c (26)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

nthw_sdc.c (26)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

nthw_sdc.c (135)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression
'pn_result_mask' is always true.

nthw_si5340.c (48)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

nthw_spi_v3.c (140)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_spi_v3.c (148)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_spi_v3.c (154)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_spi_v3.c (159)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_tsm.c (92)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression 'p_ts' is
always true.

nthw_tsm.c (111)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression 'p_time' is
always true.

flow_api.c (833)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression 'ndev' is
always true.

flow_api.c (999)
V1029 <https://pvs-studio.com/en/docs/warnings/v1029/> Numeric Truncation
Error. Return value of the 'strlen' function is written to the 16-bit
variable.

flow_api.c (1001)
V1029 <https://pvs-studio.com/en/docs/warnings/v1029/> Numeric Truncation
Error. Return value of the 'strlen' function is written to the 16-bit
variable.

flow_api.c (214)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the seventh actual argument of the 'rte_log' function.
The SIGNED integer type argument is expected.

flow_api.c (227)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the seventh actual argument of the 'rte_log' function.
The SIGNED integer type argument is expected.

flow_api.c (428)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

flow_group.c (35)
V522 <https://pvs-studio.com/en/docs/warnings/v522/> There might be
dereferencing of a potential null pointer 'group_handle'. Check lines: 35,
32.

flow_hsh_cfg.c (74)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the seventh actual argument of the 'rte_log' function.
The SIGNED integer type argument is expected.

flow_hsh_cfg.c (77)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the seventh actual argument of the 'rte_log' function.
The SIGNED integer type argument is expected.

flow_id_table.c (71)
V522 <https://pvs-studio.com/en/docs/warnings/v522/> There might be
dereferencing of a potential null pointer 'handle'. Check lines: 71, 69.

flow_km.c (583)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the seventh actual argument of the 'rte_log' function.
The SIGNED integer type argument is expected.

flow_km.c (614)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the seventh actual argument of the 'rte_log' function.
The SIGNED integer type argument is expected.

flow_km.c (791)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

flow_km.c (92)
V769 <https://pvs-studio.com/en/docs/warnings/v769/> The '(char *)
km->cam_dist' pointer in the expression could be nullptr. In such case,
resulting value of arithmetic operations on this pointer will be senseless
and it should not be used. Check lines: 92, 85.

hw_mod_flm.c (836)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression
'be->flm.ver < 18' is always false.

hw_mod_hsh.c (127)
V568 <https://pvs-studio.com/en/docs/warnings/v568/> It's odd that
'sizeof()' operator evaluates the size of a pointer to a class, but not the
size of the 'be->hsh.v5.rcp' class object.

hw_mod_hsh.c (130)
V1064 <https://pvs-studio.com/en/docs/warnings/v1064/> The 'buffer_size'
operand of integer division is less than the 'element_size' one. The result
will always be zero.

hw_mod_hsh.c (133)
V560 <https://pvs-studio.com/en/docs/warnings/v560/> A part of conditional
expression is always false: index < max_idx. Unsigned type value is never <
0.

hw_mod_hsh.c (133)
V560 <https://pvs-studio.com/en/docs/warnings/v560/> A part of conditional
expression is always false: word_off < max_idx. Unsigned type value is
never < 0.

hw_mod_pdb.c (137)
V568 <https://pvs-studio.com/en/docs/warnings/v568/> It's odd that
'sizeof()' operator evaluates the size of a pointer to a class, but not the
size of the 'be->pdb.v9.rcp' class object.

hw_mod_pdb.c (140)
V1064 <https://pvs-studio.com/en/docs/warnings/v1064/> The 'buffer_size'
operand of integer division is less than the 'element_size' one. The result
will always be zero.

hw_mod_pdb.c (143)
V560 <https://pvs-studio.com/en/docs/warnings/v560/> A part of conditional
expression is always false: * value < max_idx. Unsigned type value is never
< 0.

hw_mod_pdb.c (143)
V560 <https://pvs-studio.com/en/docs/warnings/v560/> A part of conditional
expression is always false: index < max_idx. Unsigned type value is never <
0.

flm_evt_queue.c (194)
V557 <https://pvs-studio.com/en/docs/warnings/v557/> Array overrun is
possible. The value of 'port' index could reach 127.

flm_evt_queue.c (202)
V557 <https://pvs-studio.com/en/docs/warnings/v557/> Array overrun is
possible. The value of 'port' index could reach 127.

flm_evt_queue.c (80)
V1037 <https://pvs-studio.com/en/docs/warnings/v1037/> Two or more
case-branches perform the same actions. Check lines: 80, 88

flm_evt_queue.c (84)
V1037 <https://pvs-studio.com/en/docs/warnings/v1037/> Two or more
case-branches perform the same actions. Check lines: 84, 92

flow_api_hw_db_inline.c (2461)
V1086 <https://pvs-studio.com/en/docs/warnings/v1086/> A call of the
'memset' function will lead to underflow of the buffer '&
db->flm[idx.id1].data'.

flow_api_hw_db_inline.c (426)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (428)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (428)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fourth actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (428)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (428)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (438)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (446)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (455)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (457)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the eighth actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (457)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (457)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fourth actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (457)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the seventh actual argument of the 'fprintf' function.
The SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (457)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (457)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (467)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (482)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (494)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (509)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (518)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (526)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (560)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (578)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (579)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'fprintf' function. The
integer argument of 32-bit size is expected.

flow_api_hw_db_inline.c (579)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fourth actual argument of the 'fprintf' function. The
integer argument of 32-bit size is expected.

flow_api_hw_db_inline.c (579)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'fprintf' function. The
integer argument of 32-bit size is expected.

flow_api_hw_db_inline.c (579)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
integer argument of 32-bit size is expected.

flow_api_hw_db_inline.c (581)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'fprintf' function. The
integer argument of 32-bit size is expected.

flow_api_hw_db_inline.c (581)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fourth actual argument of the 'fprintf' function. The
integer argument of 32-bit size is expected.

flow_api_hw_db_inline.c (581)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'fprintf' function. The
integer argument of 32-bit size is expected.

flow_api_hw_db_inline.c (581)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
integer argument of 32-bit size is expected.

flow_api_hw_db_inline.c (583)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fourth actual argument of the 'fprintf' function. The
integer argument of 32-bit size is expected.

flow_api_hw_db_inline.c (583)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
integer argument of 32-bit size is expected.

flow_api_hw_db_inline.c (596)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (604)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (610)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (618)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (619)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (620)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (621)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (627)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (628)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (629)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fourth actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (629)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (636)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the third actual argument of the 'fprintf' function. The
SIGNED integer type argument is expected.

flow_api_hw_db_inline.c (706)
V1037 <https://pvs-studio.com/en/docs/warnings/v1037/> Two or more
case-branches perform the same actions. Check lines: 706, 736, 742

flow_api_profile_inline.c (117)
V629 <https://pvs-studio.com/en/docs/warnings/v629/> Consider inspecting
the '1 << (shift - 1)' expression. Bit shifting of the 32-bit value with a
subsequent expansion to the 64-bit type.

flow_api_profile_inline.c (738)
V674 <https://pvs-studio.com/en/docs/warnings/v674/> The '0.01' literal of
the 'double' type is compared to a value of the 'int' type. Consider
inspecting the '0.01 > 0' expression.

flow_api_profile_inline.c (3469)
V522 <https://pvs-studio.com/en/docs/warnings/v522/> There might be
dereferencing of a potential null pointer 'fh'. Check lines: 3469, 3467.

flow_api_profile_inline.c (4925)
V522 <https://pvs-studio.com/en/docs/warnings/v522/> There might be
dereferencing of a potential null pointer 'template'. Check lines: 4925,
4923.

flow_api_profile_inline.c (4990)
V522 <https://pvs-studio.com/en/docs/warnings/v522/> There might be
dereferencing of a potential null pointer 'template'. Check lines: 4990,
4988.

flow_api_profile_inline.c (5262)
V522 <https://pvs-studio.com/en/docs/warnings/v522/> There might be
dereferencing of a potential null pointer 'fh'. Check lines: 5262, 5260.

flow_api_profile_inline.c (4307)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression 'err' is
always false.

flow_api_profile_inline.c (2040)
V560 <https://pvs-studio.com/en/docs/warnings/v560/> A part of conditional
expression is always true: match_cnt == 1.

flow_api_profile_inline.c (196)
V1032 <https://pvs-studio.com/en/docs/warnings/v1032/> The pointer is cast
to a more strictly aligned pointer type

flow_api_profile_inline.c (254)
V1032 <https://pvs-studio.com/en/docs/warnings/v1032/> The pointer is cast
to a more strictly aligned pointer type

flow_api_profile_inline.c (294)
V1032 <https://pvs-studio.com/en/docs/warnings/v1032/> The pointer is cast
to a more strictly aligned pointer type

flow_api_profile_inline.c (347)
V1032 <https://pvs-studio.com/en/docs/warnings/v1032/> The pointer is cast
to a more strictly aligned pointer type

flow_api_profile_inline.c (434)
V1032 <https://pvs-studio.com/en/docs/warnings/v1032/> The pointer 'data'
is cast to a more strictly aligned pointer type.

flow_api_profile_inline.c (510)
V1032 <https://pvs-studio.com/en/docs/warnings/v1032/> The pointer 'data'
is cast to a more strictly aligned pointer type.

flow_api_profile_inline.c (980)
V1032 <https://pvs-studio.com/en/docs/warnings/v1032/> The pointer is cast
to a more strictly aligned pointer type

flow_api_profile_inline.c (4758)
V523 <https://pvs-studio.com/en/docs/warnings/v523/> The 'then' statement
is equivalent to the 'else' statement.

flow_api_profile_inline.c (2272)
V525 <https://pvs-studio.com/en/docs/warnings/v525/> The code contains the
collection of similar blocks. Check items 'qw_data', 'qw_data', 'qw_mask'
in lines 2272, 2273, 2275.

flow_api_profile_inline.c (1160)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the eighth actual argument of the 'rte_log' function. The
UNSIGNED integer type argument is expected.

flow_api_profile_inline.c (1224)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

flow_api_profile_inline.c (3133)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

flow_api_profile_inline.c (4507)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

flow_api_profile_inline.c (3573)
V1048 <https://pvs-studio.com/en/docs/warnings/v1048/> The
'action_set_data.contains_jump' variable was assigned the same value.

flow_api_profile_inline.c (972)
V1051 <https://pvs-studio.com/en/docs/warnings/v1051/> Consider checking
for misprints. It's possible that the 'flm_id' should be checked here.

flow_nthw_cat.c (29)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

flow_nthw_csu.c (33)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

flow_nthw_flm.c (30)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

flow_nthw_flm.c (736)
V1020 <https://pvs-studio.com/en/docs/warnings/v1020/> The function exited
without calling the 'rte_spinlock_unlock' function. Check lines: 736, 729.

flow_nthw_hfu.c (33)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

flow_nthw_hsh.c (34)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

flow_nthw_info.c (34)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

flow_nthw_km.c (43)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

flow_nthw_pdb.c (34)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

flow_nthw_qsl.c (34)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

flow_nthw_rpp_lr.c (33)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

flow_nthw_rpp_lr.c (65)
V1004 <https://pvs-studio.com/en/docs/warnings/v1004/> The 'p->m_rpp_lr'
pointer was used unsafely after it was verified against nullptr. Check
lines: 57, 65.

flow_nthw_slc_lr.c (34)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

flow_nthw_tx_cpy.c (34)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

flow_nthw_tx_ins.c (33)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

flow_nthw_tx_rpl.c (33)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

nthw_fpga_model.c (491)
V595 <https://pvs-studio.com/en/docs/warnings/v595/> The 'p->m_rpp_lr'
pointer was utilized before it was verified against nullptr. Check lines:
'nthw_fpga_model.c:479', 'nthw_fpga_model.c:491', 'flow_nthw_rpp_lr.c:65',
'flow_nthw_rpp_lr.c:69'.

nthw_fpga_model.c (186)
V597 <https://pvs-studio.com/en/docs/warnings/v597/> The compiler could
delete the 'memset' function call, which is used to flush 'p' object. The
memset_s() function should be used to erase the private data.

nthw_fpga_model.c (365)
V522 <https://pvs-studio.com/en/docs/warnings/v522/> Dereferencing of the
null pointer might take place. The potential null pointer is passed into
'nthw_fpga_get_param_info' function. Inspect the second argument. Check
lines: 'nthw_fpga_model.c:365', 'nthw_fpga.c:25', 'nthw_fpga.c:687'.

nthw_fpga_model.c (906)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the 14th actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_fpga_model.c (906)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_rac.c (515)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression '(word_cnt
+ 3) > (0x4000)' is always false.

nthw_rac.c (34)
V575 <https://pvs-studio.com/en/docs/warnings/v575/> The potential null
pointer is passed into 'memset' function. Inspect the first argument. Check
lines: 34, 33.

nthw_rac.c (265)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the eighth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_rac.c (469)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the eighth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_rac.c (508)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the eighth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_rac.c (560)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_rac.c (578)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_rac.c (747)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_rac.c (768)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

nthw_rac.c (94)
V1048 <https://pvs-studio.com/en/docs/warnings/v1048/> The
'p->mp_reg_dbg_data' variable was assigned the same value.

ntnic_meter.c (89)
V525 <https://pvs-studio.com/en/docs/warnings/v525/> The code contains the
collection of similar blocks. Check items '0', '1', '0', '0', '0', '0' in
lines 89, 90, 91, 94, 95, 96.

nthw_stat.c (257)
V1048 <https://pvs-studio.com/en/docs/warnings/v1048/> The
'p->mn_stat_layout_version' variable was assigned the same value.

ntnic_ethdev.c (2194)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression 'err == 0'
is always true.

ntnic_ethdev.c (334)
V595 <https://pvs-studio.com/en/docs/warnings/v595/> The 'internals->p_drv'
pointer was utilized before it was verified against nullptr. Check lines:
334, 350.

ntnic_ethdev.c (2268)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression '(1 <<
n_intf_no) & ~n_port_mask' is always false.

ntnic_ethdev.c (191)
V560 <https://pvs-studio.com/en/docs/warnings/v560/> A part of conditional
expression is always false: !p_nt4ga_stat.

ntnic_ethdev.c (238)
V560 <https://pvs-studio.com/en/docs/warnings/v560/> A part of conditional
expression is always false: !p_nt4ga_stat.

ntnic_ethdev.c (1763)
V1044 <https://pvs-studio.com/en/docs/warnings/v1044/> Loop break
conditions do not depend on the number of iterations.

ntnic_ethdev.c (1900)
V1044 <https://pvs-studio.com/en/docs/warnings/v1044/> Loop break
conditions do not depend on the number of iterations.

ntnic_ethdev.c (1935)
V1044 <https://pvs-studio.com/en/docs/warnings/v1044/> Loop break
conditions do not depend on the number of iterations.

ntnic_ethdev.c (1942)
V1044 <https://pvs-studio.com/en/docs/warnings/v1044/> Loop break
conditions do not depend on the number of iterations.

ntnic_ethdev.c (1370)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression 'port ==
internals->n_intf_no' is always true.

ntnic_ethdev.c (1396)
V547 <https://pvs-studio.com/en/docs/warnings/v547/> Expression 'port ==
internals->n_intf_no' is always true.

ntnic_ethdev.c (375)
V574 <https://pvs-studio.com/en/docs/warnings/v574/> The 'hw_recv' pointer
is used simultaneously as an array and as a pointer to single object. Check
lines: 375, 457.

ntnic_ethdev.c (844)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

ntnic_ethdev.c (866)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the tenth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

ntnic_ethdev.c (907)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

ntnic_ethdev.c (974)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the seventh actual argument of the 'rte_log' function.
The UNSIGNED integer type argument is expected.

ntnic_ethdev.c (974)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
UNSIGNED integer type argument is expected.

ntnic_ethdev.c (1012)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

ntnic_ethdev.c (1042)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

ntnic_ethdev.c (1076)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

ntnic_ethdev.c (1136)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

ntnic_ethdev.c (1277)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
UNSIGNED integer type argument is expected.

ntnic_ethdev.c (1335)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
UNSIGNED integer type argument is expected.

ntnic_ethdev.c (2302)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

ntnic_ethdev.c (2308)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the sixth actual argument of the 'rte_log' function. The
SIGNED integer type argument is expected.

ntnic_filter.c (481)
V595 <https://pvs-studio.com/en/docs/warnings/v595/> The 'internals'
pointer was utilized before it was verified against nullptr. Check lines:
481, 487.

ntnic_filter.c (1159)
V560 <https://pvs-studio.com/en/docs/warnings/v560/> A part of conditional
expression is always false: !p_nt4ga_stat.

ntnic_filter.c (357)
V576 <https://pvs-studio.com/en/docs/warnings/v576/> Incorrect format.
Consider checking the fifth actual argument of the 'rte_log' function. The
UNSIGNED integer type argument is expected.

ntnic_filter.c (1121)
V1027 <https://pvs-studio.com/en/docs/warnings/v1027/> Pointer to an object
of the 'flow_handle' class is cast to unrelated 'rte_flow' class.

ntnic_filter.c (1143)
V1027 <https://pvs-studio.com/en/docs/warnings/v1027/> Pointer to an object
of the 'rte_flow' class is cast to unrelated 'flow_handle' class.

ntnic_vfio.c (81)
V1048 <https://pvs-studio.com/en/docs/warnings/v1048/> The
'vfio->container_fd' variable was assigned the same value.

On Thu, Feb 20, 2025 at 2:04 PM Serhii Iliushyk <sil-plv@napatech.com>
wrote:

> This patchset adds support for the new adapter NT400D13.
>
> Danylo Vodopianov (23):
>   net/ntnic: add link agx 100g
>   net/ntnic: add link state machine
>   net/ntnic: add rpf and gfg init
>   net/ntnic: add agx setup for port
>   net/ntnic: add host loopback init
>   net/ntnic: add line loopback init
>   net/ntnic: add 100 gbps port init
>   net/ntnic: add port post init
>   net/ntnic: add nim low power API
>   net/ntnic: add link handling API
>   net/ntnic: add port init to the state machine
>   net/ntnic: add port disable API
>   net/ntnic: add nt400d13 pcm init
>   net/ntnic: add HIF clock test
>   net/ntnic: add nt400d13 PRM module init
>   net/ntnic: add nt400d13 PRM module reset
>   net/ntnic: add SPI v3 support for FPGA
>   net/ntnic: add i2cm init
>   net/ntnic: add pca init
>   net/ntnic: add pcal init
>   net/ntnic: add reset PHY init
>   net/ntnic: add igam module init
>   net/ntnic: init IGAM and config PLL for FPGA
>
> Serhii Iliushyk (9):
>   net/ntnic: add minimal initialization new NIC NT400D13
>   net/ntnic: add minimal reset FPGA
>   net/ntnic: add FPGA modules and registers
>   net/ntnic: add setup for fpga reset
>   net/ntnic: add default reset setting for NT400D13
>   net/ntnic: add DDR calibration to reset stage
>   net/ntnic: add PHY ftile reset
>   net/ntnic: add clock init
>   net/ntnic: revert untrusted loop bound
>
>  doc/guides/nics/ntnic.rst                     |    7 +-
>  doc/guides/rel_notes/release_25_03.rst        |    4 +
>  drivers/net/ntnic/adapter/nt4ga_adapter.c     |    9 +
>  drivers/net/ntnic/include/nt4ga_link.h        |    7 +
>  drivers/net/ntnic/include/nthw_gfg.h          |   33 +
>  drivers/net/ntnic/include/ntnic_nim.h         |    5 +
>  .../include/ntnic_nthw_fpga_rst_nt400dxx.h    |   34 +
>  .../link_agx_100g/nt4ga_agx_link_100g.c       | 1029 ++++++
>  drivers/net/ntnic/meson.build                 |   16 +
>  drivers/net/ntnic/nim/i2c_nim.c               |  158 +-
>  drivers/net/ntnic/nim/i2c_nim.h               |    6 +
>  ...00D13_U62_Si5332-GM2-RevD-1_V5-Registers.h |  425 +++
>  .../net/ntnic/nthw/core/include/nthw_fpga.h   |   10 +
>  .../net/ntnic/nthw/core/include/nthw_gmf.h    |    2 +
>  .../net/ntnic/nthw/core/include/nthw_hif.h    |    4 +
>  .../net/ntnic/nthw/core/include/nthw_i2cm.h   |    3 +
>  .../net/ntnic/nthw/core/include/nthw_igam.h   |   40 +
>  .../ntnic/nthw/core/include/nthw_pca9532.h    |   25 +
>  .../ntnic/nthw/core/include/nthw_pcal6416a.h  |   33 +
>  .../nthw/core/include/nthw_pcm_nt400dxx.h     |   40 +
>  .../ntnic/nthw/core/include/nthw_phy_tile.h   |  156 +
>  .../nthw/core/include/nthw_prm_nt400dxx.h     |   32 +
>  .../nthw/core/include/nthw_si5332_si5156.h    |   63 +
>  .../net/ntnic/nthw/core/include/nthw_spi_v3.h |  107 +
>  .../net/ntnic/nthw/core/include/nthw_spim.h   |   58 +
>  .../net/ntnic/nthw/core/include/nthw_spis.h   |   63 +
>  .../nthw/core/nt400dxx/nthw_fpga_nt400dxx.c   |  220 ++
>  .../core/nt400dxx/reset/nthw_fpga_rst9574.c   |  377 ++
>  .../nt400dxx/reset/nthw_fpga_rst_nt400dxx.c   |  427 +++
>  drivers/net/ntnic/nthw/core/nthw_fpga.c       |  464 +++
>  drivers/net/ntnic/nthw/core/nthw_gfg.c        |  340 ++
>  drivers/net/ntnic/nthw/core/nthw_gmf.c        |   41 +
>  drivers/net/ntnic/nthw/core/nthw_hif.c        |   92 +
>  drivers/net/ntnic/nthw/core/nthw_i2cm.c       |  139 +
>  drivers/net/ntnic/nthw/core/nthw_igam.c       |   93 +
>  drivers/net/ntnic/nthw/core/nthw_pca9532.c    |   60 +
>  drivers/net/ntnic/nthw/core/nthw_pcal6416a.c  |  103 +
>  .../net/ntnic/nthw/core/nthw_pcm_nt400dxx.c   |   80 +
>  drivers/net/ntnic/nthw/core/nthw_phy_tile.c   | 1242 +++++++
>  .../net/ntnic/nthw/core/nthw_prm_nt400dxx.c   |   55 +
>  .../net/ntnic/nthw/core/nthw_si5332_si5156.c  |  142 +
>  drivers/net/ntnic/nthw/core/nthw_spi_v3.c     |  358 ++
>  drivers/net/ntnic/nthw/core/nthw_spim.c       |  113 +
>  drivers/net/ntnic/nthw/core/nthw_spis.c       |  121 +
>  drivers/net/ntnic/nthw/nthw_drv.h             |   31 +
>  drivers/net/ntnic/nthw/nthw_platform.c        |    3 +
>  drivers/net/ntnic/nthw/nthw_platform_drv.h    |    2 +
>  .../supported/nthw_fpga_9574_055_049_0000.c   | 3124 +++++++++++++++++
>  .../nthw/supported/nthw_fpga_instances.c      |    5 +-
>  .../nthw/supported/nthw_fpga_instances.h      |    1 +
>  .../ntnic/nthw/supported/nthw_fpga_mod_defs.h |   11 +
>  .../nthw/supported/nthw_fpga_mod_str_map.c    |   11 +
>  .../ntnic/nthw/supported/nthw_fpga_reg_defs.h |   11 +
>  .../nthw/supported/nthw_fpga_reg_defs_igam.h  |   32 +
>  .../supported/nthw_fpga_reg_defs_pci_ta.h     |   33 +
>  .../nthw_fpga_reg_defs_pcm_nt400dxx.h         |   29 +
>  .../nthw/supported/nthw_fpga_reg_defs_pdi.h   |   49 +
>  .../supported/nthw_fpga_reg_defs_phy_tile.h   |  213 ++
>  .../nthw_fpga_reg_defs_prm_nt400dxx.h         |   26 +
>  .../nthw/supported/nthw_fpga_reg_defs_rfd.h   |   38 +
>  .../supported/nthw_fpga_reg_defs_rst9574.h    |   35 +
>  .../nthw/supported/nthw_fpga_reg_defs_spim.h  |   76 +
>  .../nthw/supported/nthw_fpga_reg_defs_spis.h  |   51 +
>  .../nthw/supported/nthw_fpga_reg_defs_tint.h  |   28 +
>  drivers/net/ntnic/ntnic_ethdev.c              |    1 +
>  drivers/net/ntnic/ntnic_filter/ntnic_filter.c |    2 +-
>  drivers/net/ntnic/ntnic_mod_reg.c             |   47 +
>  drivers/net/ntnic/ntnic_mod_reg.h             |   25 +
>  68 files changed, 10709 insertions(+), 11 deletions(-)
>  create mode 100644 drivers/net/ntnic/include/nthw_gfg.h
>  create mode 100644
> drivers/net/ntnic/include/ntnic_nthw_fpga_rst_nt400dxx.h
>  create mode 100644
> drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
>  create mode 100644
> drivers/net/ntnic/nthw/core/include/NT400D13_U62_Si5332-GM2-RevD-1_V5-Registers.h
>  create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_igam.h
>  create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_pca9532.h
>  create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_pcal6416a.h
>  create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_pcm_nt400dxx.h
>  create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_phy_tile.h
>  create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_prm_nt400dxx.h
>  create mode 100644
> drivers/net/ntnic/nthw/core/include/nthw_si5332_si5156.h
>  create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_spi_v3.h
>  create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_spim.h
>  create mode 100644 drivers/net/ntnic/nthw/core/include/nthw_spis.h
>  create mode 100644
> drivers/net/ntnic/nthw/core/nt400dxx/nthw_fpga_nt400dxx.c
>  create mode 100644
> drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst9574.c
>  create mode 100644
> drivers/net/ntnic/nthw/core/nt400dxx/reset/nthw_fpga_rst_nt400dxx.c
>  create mode 100644 drivers/net/ntnic/nthw/core/nthw_gfg.c
>  create mode 100644 drivers/net/ntnic/nthw/core/nthw_igam.c
>  create mode 100644 drivers/net/ntnic/nthw/core/nthw_pca9532.c
>  create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
>  create mode 100644 drivers/net/ntnic/nthw/core/nthw_pcm_nt400dxx.c
>  create mode 100644 drivers/net/ntnic/nthw/core/nthw_phy_tile.c
>  create mode 100644 drivers/net/ntnic/nthw/core/nthw_prm_nt400dxx.c
>  create mode 100644 drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
>  create mode 100644 drivers/net/ntnic/nthw/core/nthw_spi_v3.c
>  create mode 100644 drivers/net/ntnic/nthw/core/nthw_spim.c
>  create mode 100644 drivers/net/ntnic/nthw/core/nthw_spis.c
>  create mode 100644
> drivers/net/ntnic/nthw/supported/nthw_fpga_9574_055_049_0000.c
>  create mode 100644
> drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_igam.h
>  create mode 100644
> drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pci_ta.h
>  create mode 100644
> drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pcm_nt400dxx.h
>  create mode 100644
> drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_pdi.h
>  create mode 100644
> drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_phy_tile.h
>  create mode 100644
> drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_prm_nt400dxx.h
>  create mode 100644
> drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_rfd.h
>  create mode 100644
> drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_rst9574.h
>  create mode 100644
> drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_spim.h
>  create mode 100644
> drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_spis.h
>  create mode 100644
> drivers/net/ntnic/nthw/supported/nthw_fpga_reg_defs_tint.h
>
> --
> 2.45.0
>
>

[-- Attachment #2: Type: text/html, Size: 127854 bytes --]

^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2025-02-20 23:49 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-02-20 22:03 [PATCH v1 00/32] add new adapter NT400D13 Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 01/32] net/ntnic: add link agx 100g Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 02/32] net/ntnic: add link state machine Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 03/32] net/ntnic: add rpf and gfg init Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 04/32] net/ntnic: add agx setup for port Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 05/32] net/ntnic: add host loopback init Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 06/32] net/ntnic: add line " Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 07/32] net/ntnic: add 100 gbps port init Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 08/32] net/ntnic: add port post init Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 09/32] net/ntnic: add nim low power API Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 10/32] net/ntnic: add link handling API Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 11/32] net/ntnic: add port init to the state machine Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 12/32] net/ntnic: add port disable API Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 13/32] net/ntnic: add minimal initialization new NIC NT400D13 Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 14/32] net/ntnic: add minimal reset FPGA Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 15/32] net/ntnic: add FPGA modules and registers Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 16/32] net/ntnic: add setup for fpga reset Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 17/32] net/ntnic: add default reset setting for NT400D13 Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 18/32] net/ntnic: add DDR calibration to reset stage Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 19/32] net/ntnic: add PHY ftile reset Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 20/32] net/ntnic: add clock init Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 21/32] net/ntnic: add nt400d13 pcm init Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 22/32] net/ntnic: add HIF clock test Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 23/32] net/ntnic: add nt400d13 PRM module init Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 24/32] net/ntnic: add nt400d13 PRM module reset Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 25/32] net/ntnic: add SPI v3 support for FPGA Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 26/32] net/ntnic: add i2cm init Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 27/32] net/ntnic: add pca init Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 28/32] net/ntnic: add pcal init Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 29/32] net/ntnic: add reset PHY init Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 30/32] net/ntnic: add igam module init Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 31/32] net/ntnic: init IGAM and config PLL for FPGA Serhii Iliushyk
2025-02-20 22:03 ` [PATCH v1 32/32] net/ntnic: revert untrusted loop bound Serhii Iliushyk
2025-02-20 22:31   ` Stephen Hemminger
2025-02-20 23:49 ` [PATCH v1 00/32] add new adapter NT400D13 Stephen Hemminger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).