Add reset functions and reset procedure for module PHY FTILE Signed-off-by: Serhii Iliushyk <sil-...@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