1 /* 2 * SPDX-License-Identifier: BSD-3-Clause 3 * Copyright(c) 2023 Napatech A/S 4 */ 5 6 #include "nt_util.h" 7 #include "ntlog.h" 8 9 #include "nthw_drv.h" 10 #include "nthw_register.h" 11 12 #include "nthw_hif.h" 13 14 nthw_hif_t *nthw_hif_new(void) 15 { 16 nthw_hif_t *p = malloc(sizeof(nthw_hif_t)); 17 18 if (p) 19 memset(p, 0, sizeof(nthw_hif_t)); 20 21 return p; 22 } 23 24 void nthw_hif_delete(nthw_hif_t *p) 25 { 26 if (p) { 27 memset(p, 0, sizeof(nthw_hif_t)); 28 free(p); 29 } 30 } 31 32 int nthw_hif_init(nthw_hif_t *p, nthw_fpga_t *p_fpga, int n_instance) 33 { 34 const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; 35 (void)p_adapter_id_str; 36 nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_HIF, n_instance); 37 38 if (p == NULL) 39 return mod == NULL ? -1 : 0; 40 41 if (mod == NULL) { 42 NT_LOG(ERR, NTHW, "%s: HIF %d: no such instance", 43 p_fpga->p_fpga_info->mp_adapter_id_str, n_instance); 44 return -1; 45 } 46 47 p->mp_fpga = p_fpga; 48 p->mn_instance = n_instance; 49 p->mp_mod_hif = mod; 50 51 /* default for (Xilinx-based) products until august 2022: (1e6/4000 = 250 MHz) */ 52 p->mn_fpga_param_hif_per_ps = nthw_fpga_get_product_param(p->mp_fpga, NT_HIF_PER_PS, 4000); 53 p->mn_fpga_hif_ref_clk_freq = 54 (uint32_t)(1000000000000ULL / (unsigned int)p->mn_fpga_param_hif_per_ps); 55 56 p->mp_reg_prod_id_lsb = nthw_module_get_register(p->mp_mod_hif, HIF_PROD_ID_LSB); 57 p->mp_fld_prod_id_lsb_rev_id = 58 nthw_register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_REV_ID); 59 p->mp_fld_prod_id_lsb_ver_id = 60 nthw_register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_VER_ID); 61 p->mp_fld_prod_id_lsb_group_id = 62 nthw_register_get_field(p->mp_reg_prod_id_lsb, HIF_PROD_ID_LSB_GROUP_ID); 63 64 p->mp_reg_prod_id_msb = nthw_module_get_register(p->mp_mod_hif, HIF_PROD_ID_MSB); 65 p->mp_fld_prod_id_msb_type_id = 66 nthw_register_get_field(p->mp_reg_prod_id_msb, HIF_PROD_ID_MSB_TYPE_ID); 67 p->mp_fld_prod_id_msb_build_no = 68 nthw_register_get_field(p->mp_reg_prod_id_msb, HIF_PROD_ID_MSB_BUILD_NO); 69 70 p->mp_reg_build_time = nthw_module_get_register(p->mp_mod_hif, HIF_BUILD_TIME); 71 p->mp_fld_build_time = nthw_register_get_field(p->mp_reg_build_time, HIF_BUILD_TIME_TIME); 72 73 p->mn_fpga_id_prod = nthw_field_get_updated(p->mp_fld_prod_id_lsb_group_id); 74 p->mn_fpga_id_ver = nthw_field_get_updated(p->mp_fld_prod_id_lsb_ver_id); 75 p->mn_fpga_id_rev = nthw_field_get_updated(p->mp_fld_prod_id_lsb_rev_id); 76 p->mn_fpga_id_build_no = nthw_field_get_updated(p->mp_fld_prod_id_msb_build_no); 77 p->mn_fpga_id_item = nthw_field_get_updated(p->mp_fld_prod_id_msb_type_id); 78 79 NT_LOG(DBG, NTHW, "%s: HIF %d: %d-%d-%d-%d-%d", p_adapter_id_str, p->mn_instance, 80 p->mn_fpga_id_item, p->mn_fpga_id_prod, p->mn_fpga_id_ver, 81 p->mn_fpga_id_rev, p->mn_fpga_id_build_no); 82 NT_LOG(DBG, NTHW, "%s: HIF %d: HIF ref clock: %d Hz (%d ticks/ps)", p_adapter_id_str, 83 p->mn_instance, p->mn_fpga_hif_ref_clk_freq, p->mn_fpga_param_hif_per_ps); 84 85 p->mp_reg_build_seed = NULL; /* Reg/Fld not present on HIF */ 86 p->mp_fld_build_seed = NULL; /* Reg/Fld not present on HIF */ 87 88 p->mp_reg_core_speed = NULL; /* Reg/Fld not present on HIF */ 89 p->mp_fld_core_speed = NULL; /* Reg/Fld not present on HIF */ 90 p->mp_fld_ddr3_speed = NULL; /* Reg/Fld not present on HIF */ 91 92 /* Optional registers since: 2018-04-25 */ 93 p->mp_reg_int_mask = NULL; /* Reg/Fld not present on HIF */ 94 p->mp_reg_int_clr = NULL; /* Reg/Fld not present on HIF */ 95 p->mp_reg_int_force = NULL; /* Reg/Fld not present on HIF */ 96 97 p->mp_fld_int_mask_timer = NULL; 98 p->mp_fld_int_clr_timer = NULL; 99 p->mp_fld_int_force_timer = NULL; 100 101 p->mp_fld_int_mask_port = NULL; 102 p->mp_fld_int_clr_port = NULL; 103 p->mp_fld_int_force_port = NULL; 104 105 p->mp_fld_int_mask_pps = NULL; 106 p->mp_fld_int_clr_pps = NULL; 107 p->mp_fld_int_force_pps = NULL; 108 109 p->mp_reg_ctrl = nthw_module_get_register(p->mp_mod_hif, HIF_CONTROL); 110 p->mp_fld_ctrl_fsr = nthw_register_query_field(p->mp_reg_ctrl, HIF_CONTROL_FSR); 111 112 p->mp_reg_stat_ctrl = nthw_module_get_register(p->mp_mod_hif, HIF_STAT_CTRL); 113 p->mp_fld_stat_ctrl_ena = 114 nthw_register_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_ENA); 115 p->mp_fld_stat_ctrl_req = 116 nthw_register_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_REQ); 117 118 p->mp_reg_stat_rx = nthw_module_get_register(p->mp_mod_hif, HIF_STAT_RX); 119 p->mp_fld_stat_rx_counter = 120 nthw_register_get_field(p->mp_reg_stat_rx, HIF_STAT_RX_COUNTER); 121 122 p->mp_reg_stat_tx = nthw_module_get_register(p->mp_mod_hif, HIF_STAT_TX); 123 p->mp_fld_stat_tx_counter = 124 nthw_register_get_field(p->mp_reg_stat_tx, HIF_STAT_TX_COUNTER); 125 126 p->mp_reg_stat_ref_clk = nthw_module_get_register(p->mp_mod_hif, HIF_STAT_REFCLK); 127 p->mp_fld_stat_ref_clk_ref_clk = 128 nthw_register_get_field(p->mp_reg_stat_ref_clk, HIF_STAT_REFCLK_REFCLK250); 129 130 p->mp_reg_status = nthw_module_query_register(p->mp_mod_hif, HIF_STATUS); 131 132 if (p->mp_reg_status) { 133 p->mp_fld_status_tags_in_use = 134 nthw_register_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE); 135 p->mp_fld_status_wr_err = 136 nthw_register_query_field(p->mp_reg_status, HIF_STATUS_WR_ERR); 137 p->mp_fld_status_rd_err = 138 nthw_register_query_field(p->mp_reg_status, HIF_STATUS_RD_ERR); 139 140 } else { 141 p->mp_reg_status = nthw_module_query_register(p->mp_mod_hif, HIF_STATUS); 142 p->mp_fld_status_tags_in_use = 143 nthw_register_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE); 144 p->mp_fld_status_wr_err = NULL; 145 p->mp_fld_status_rd_err = NULL; 146 } 147 148 p->mp_reg_pci_test0 = nthw_module_get_register(p->mp_mod_hif, HIF_TEST0); 149 p->mp_fld_pci_test0 = nthw_register_get_field(p->mp_reg_pci_test0, HIF_TEST0_DATA); 150 151 p->mp_reg_pci_test1 = nthw_module_get_register(p->mp_mod_hif, HIF_TEST1); 152 p->mp_fld_pci_test1 = nthw_register_get_field(p->mp_reg_pci_test1, HIF_TEST1_DATA); 153 154 /* Module::Version({2, 0})+ */ 155 p->mp_reg_pci_test2 = nthw_module_query_register(p->mp_mod_hif, HIF_TEST2); 156 157 if (p->mp_reg_pci_test2) 158 p->mp_fld_pci_test2 = nthw_register_get_field(p->mp_reg_pci_test2, HIF_TEST2_DATA); 159 160 else 161 p->mp_fld_pci_test2 = NULL; 162 163 /* Module::Version({1, 2})+ */ 164 p->mp_reg_pci_test3 = nthw_module_query_register(p->mp_mod_hif, HIF_TEST3); 165 166 if (p->mp_reg_pci_test3) 167 p->mp_fld_pci_test3 = nthw_register_get_field(p->mp_reg_pci_test3, HIF_TEST3_DATA); 168 169 else 170 p->mp_fld_pci_test3 = NULL; 171 172 /* Required to run TSM */ 173 p->mp_reg_sample_time = nthw_module_get_register(p->mp_mod_hif, HIF_SAMPLE_TIME); 174 175 if (p->mp_reg_sample_time) { 176 p->mp_fld_sample_time = nthw_register_get_field(p->mp_reg_sample_time, 177 HIF_SAMPLE_TIME_SAMPLE_TIME); 178 179 } else { 180 p->mp_fld_sample_time = NULL; 181 } 182 183 /* We need to optimize PCIe3 TLP-size read-request and extended tag usage */ 184 { 185 p->mp_reg_config = nthw_module_query_register(p->mp_mod_hif, HIF_CONFIG); 186 187 if (p->mp_reg_config) { 188 p->mp_fld_max_tlp = 189 nthw_register_get_field(p->mp_reg_config, HIF_CONFIG_MAX_TLP); 190 p->mp_fld_max_read = 191 nthw_register_get_field(p->mp_reg_config, HIF_CONFIG_MAX_READ); 192 p->mp_fld_ext_tag = 193 nthw_register_get_field(p->mp_reg_config, HIF_CONFIG_EXT_TAG); 194 195 } else { 196 p->mp_fld_max_tlp = NULL; 197 p->mp_fld_max_read = NULL; 198 p->mp_fld_ext_tag = NULL; 199 } 200 } 201 202 return 0; 203 } 204 205 int nthw_hif_trigger_sample_time(nthw_hif_t *p) 206 { 207 nthw_field_set_val_flush32(p->mp_fld_sample_time, 0xfee1dead); 208 209 return 0; 210 } 211 212 int nthw_hif_get_stat(nthw_hif_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt, 213 uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size, uint32_t *p_tg_ref_freq, 214 uint64_t *p_tags_in_use, uint64_t *p_rd_err, uint64_t *p_wr_err) 215 { 216 *p_rx_cnt = nthw_field_get_updated(p->mp_fld_stat_rx_counter); 217 *p_tx_cnt = nthw_field_get_updated(p->mp_fld_stat_tx_counter); 218 219 *p_ref_clk_cnt = nthw_field_get_updated(p->mp_fld_stat_ref_clk_ref_clk); 220 221 *p_tg_unit_size = NTHW_TG_CNT_SIZE; 222 *p_tg_ref_freq = p->mn_fpga_hif_ref_clk_freq; 223 224 *p_tags_in_use = (p->mp_fld_status_tags_in_use 225 ? nthw_field_get_updated(p->mp_fld_status_tags_in_use) 226 : 0); 227 228 *p_rd_err = 229 (p->mp_fld_status_rd_err ? nthw_field_get_updated(p->mp_fld_status_rd_err) : 0); 230 *p_wr_err = 231 (p->mp_fld_status_wr_err ? nthw_field_get_updated(p->mp_fld_status_wr_err) : 0); 232 233 return 0; 234 } 235 236 int nthw_hif_get_stat_rate(nthw_hif_t *p, uint64_t *p_pci_rx_rate, uint64_t *p_pci_tx_rate, 237 uint64_t *p_ref_clk_cnt, uint64_t *p_tags_in_use, 238 uint64_t *p_rd_err_cnt, uint64_t *p_wr_err_cnt) 239 { 240 uint32_t rx_cnt, tx_cnt, ref_clk_cnt, tg_unit_size, tg_ref_freq; 241 uint64_t n_tags_in_use, n_rd_err, n_wr_err; 242 243 nthw_hif_get_stat(p, &rx_cnt, &tx_cnt, &ref_clk_cnt, &tg_unit_size, &tg_ref_freq, 244 &n_tags_in_use, &n_rd_err, &n_wr_err); 245 246 *p_tags_in_use = n_tags_in_use; 247 248 if (n_rd_err) 249 (*p_rd_err_cnt)++; 250 251 if (n_wr_err) 252 (*p_wr_err_cnt)++; 253 254 if (ref_clk_cnt) { 255 uint64_t rx_rate; 256 uint64_t tx_rate; 257 258 *p_ref_clk_cnt = ref_clk_cnt; 259 260 rx_rate = ((uint64_t)rx_cnt * tg_unit_size * tg_ref_freq) / (uint64_t)ref_clk_cnt; 261 *p_pci_rx_rate = rx_rate; 262 263 tx_rate = ((uint64_t)tx_cnt * tg_unit_size * tg_ref_freq) / (uint64_t)ref_clk_cnt; 264 *p_pci_tx_rate = tx_rate; 265 266 } else { 267 *p_pci_rx_rate = 0; 268 *p_pci_tx_rate = 0; 269 *p_ref_clk_cnt = 0; 270 } 271 272 return 0; 273 } 274 275 int nthw_hif_stat_req_enable(nthw_hif_t *p) 276 { 277 nthw_field_set_all(p->mp_fld_stat_ctrl_ena); 278 nthw_field_set_all(p->mp_fld_stat_ctrl_req); 279 nthw_field_flush_register(p->mp_fld_stat_ctrl_req); 280 return 0; 281 } 282 283 int nthw_hif_stat_req_disable(nthw_hif_t *p) 284 { 285 nthw_field_clr_all(p->mp_fld_stat_ctrl_ena); 286 nthw_field_set_all(p->mp_fld_stat_ctrl_req); 287 nthw_field_flush_register(p->mp_fld_stat_ctrl_req); 288 return 0; 289 } 290 291 int nthw_hif_end_point_counters_sample(nthw_hif_t *p, struct nthw_hif_end_point_counters *epc) 292 { 293 assert(epc); 294 295 /* Get stat rate and maintain rx/tx min/max */ 296 nthw_hif_get_stat_rate(p, &epc->cur_tx, &epc->cur_rx, &epc->n_ref_clk_cnt, 297 &epc->n_tags_in_use, &epc->n_rd_err, &epc->n_wr_err); 298 299 return 0; 300 } 301