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