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\n", 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\n", 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)\n", 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 87 if (p->mp_reg_build_seed) 88 p->mp_fld_build_seed = NULL; /* Reg/Fld not present on HIF */ 89 else 90 p->mp_fld_build_seed = NULL; 91 92 p->mp_reg_core_speed = NULL; /* Reg/Fld not present on HIF */ 93 94 if (p->mp_reg_core_speed) { 95 p->mp_fld_core_speed = NULL; /* Reg/Fld not present on HIF */ 96 p->mp_fld_ddr3_speed = NULL; /* Reg/Fld not present on HIF */ 97 98 } else { 99 p->mp_reg_core_speed = NULL; 100 p->mp_fld_core_speed = NULL; 101 p->mp_fld_ddr3_speed = NULL; 102 } 103 104 /* Optional registers since: 2018-04-25 */ 105 p->mp_reg_int_mask = NULL; /* Reg/Fld not present on HIF */ 106 p->mp_reg_int_clr = NULL; /* Reg/Fld not present on HIF */ 107 p->mp_reg_int_force = NULL; /* Reg/Fld not present on HIF */ 108 109 p->mp_fld_int_mask_timer = NULL; 110 p->mp_fld_int_clr_timer = NULL; 111 p->mp_fld_int_force_timer = NULL; 112 113 p->mp_fld_int_mask_port = NULL; 114 p->mp_fld_int_clr_port = NULL; 115 p->mp_fld_int_force_port = NULL; 116 117 p->mp_fld_int_mask_pps = NULL; 118 p->mp_fld_int_clr_pps = NULL; 119 p->mp_fld_int_force_pps = NULL; 120 121 p->mp_reg_ctrl = nthw_module_get_register(p->mp_mod_hif, HIF_CONTROL); 122 p->mp_fld_ctrl_fsr = nthw_register_query_field(p->mp_reg_ctrl, HIF_CONTROL_FSR); 123 124 p->mp_reg_stat_ctrl = nthw_module_get_register(p->mp_mod_hif, HIF_STAT_CTRL); 125 p->mp_fld_stat_ctrl_ena = 126 nthw_register_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_ENA); 127 p->mp_fld_stat_ctrl_req = 128 nthw_register_get_field(p->mp_reg_stat_ctrl, HIF_STAT_CTRL_STAT_REQ); 129 130 p->mp_reg_stat_rx = nthw_module_get_register(p->mp_mod_hif, HIF_STAT_RX); 131 p->mp_fld_stat_rx_counter = 132 nthw_register_get_field(p->mp_reg_stat_rx, HIF_STAT_RX_COUNTER); 133 134 p->mp_reg_stat_tx = nthw_module_get_register(p->mp_mod_hif, HIF_STAT_TX); 135 p->mp_fld_stat_tx_counter = 136 nthw_register_get_field(p->mp_reg_stat_tx, HIF_STAT_TX_COUNTER); 137 138 p->mp_reg_stat_ref_clk = nthw_module_get_register(p->mp_mod_hif, HIF_STAT_REFCLK); 139 p->mp_fld_stat_ref_clk_ref_clk = 140 nthw_register_get_field(p->mp_reg_stat_ref_clk, HIF_STAT_REFCLK_REFCLK250); 141 142 p->mp_reg_status = nthw_module_query_register(p->mp_mod_hif, HIF_STATUS); 143 144 if (p->mp_reg_status) { 145 p->mp_fld_status_tags_in_use = 146 nthw_register_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE); 147 p->mp_fld_status_wr_err = 148 nthw_register_query_field(p->mp_reg_status, HIF_STATUS_WR_ERR); 149 p->mp_fld_status_rd_err = 150 nthw_register_query_field(p->mp_reg_status, HIF_STATUS_RD_ERR); 151 152 } else { 153 p->mp_reg_status = nthw_module_query_register(p->mp_mod_hif, HIF_STATUS); 154 p->mp_fld_status_tags_in_use = 155 nthw_register_query_field(p->mp_reg_status, HIF_STATUS_TAGS_IN_USE); 156 p->mp_fld_status_wr_err = NULL; 157 p->mp_fld_status_rd_err = NULL; 158 } 159 160 p->mp_reg_pci_test0 = nthw_module_get_register(p->mp_mod_hif, HIF_TEST0); 161 p->mp_fld_pci_test0 = nthw_register_get_field(p->mp_reg_pci_test0, HIF_TEST0_DATA); 162 163 p->mp_reg_pci_test1 = nthw_module_get_register(p->mp_mod_hif, HIF_TEST1); 164 p->mp_fld_pci_test1 = nthw_register_get_field(p->mp_reg_pci_test1, HIF_TEST1_DATA); 165 166 /* Module::Version({2, 0})+ */ 167 p->mp_reg_pci_test2 = nthw_module_query_register(p->mp_mod_hif, HIF_TEST2); 168 169 if (p->mp_reg_pci_test2) 170 p->mp_fld_pci_test2 = nthw_register_get_field(p->mp_reg_pci_test2, HIF_TEST2_DATA); 171 172 else 173 p->mp_fld_pci_test2 = NULL; 174 175 /* Module::Version({1, 2})+ */ 176 p->mp_reg_pci_test3 = nthw_module_query_register(p->mp_mod_hif, HIF_TEST3); 177 178 if (p->mp_reg_pci_test3) 179 p->mp_fld_pci_test3 = nthw_register_get_field(p->mp_reg_pci_test3, HIF_TEST3_DATA); 180 181 else 182 p->mp_fld_pci_test3 = NULL; 183 184 /* Required to run TSM */ 185 p->mp_reg_sample_time = nthw_module_get_register(p->mp_mod_hif, HIF_SAMPLE_TIME); 186 187 if (p->mp_reg_sample_time) { 188 p->mp_fld_sample_time = nthw_register_get_field(p->mp_reg_sample_time, 189 HIF_SAMPLE_TIME_SAMPLE_TIME); 190 191 } else { 192 p->mp_fld_sample_time = NULL; 193 } 194 195 /* We need to optimize PCIe3 TLP-size read-request and extended tag usage */ 196 { 197 p->mp_reg_config = nthw_module_query_register(p->mp_mod_hif, HIF_CONFIG); 198 199 if (p->mp_reg_config) { 200 p->mp_fld_max_tlp = 201 nthw_register_get_field(p->mp_reg_config, HIF_CONFIG_MAX_TLP); 202 p->mp_fld_max_read = 203 nthw_register_get_field(p->mp_reg_config, HIF_CONFIG_MAX_READ); 204 p->mp_fld_ext_tag = 205 nthw_register_get_field(p->mp_reg_config, HIF_CONFIG_EXT_TAG); 206 207 } else { 208 p->mp_fld_max_tlp = NULL; 209 p->mp_fld_max_read = NULL; 210 p->mp_fld_ext_tag = NULL; 211 } 212 } 213 214 return 0; 215 } 216 217 int nthw_hif_trigger_sample_time(nthw_hif_t *p) 218 { 219 nthw_field_set_val_flush32(p->mp_fld_sample_time, 0xfee1dead); 220 221 return 0; 222 } 223 224 int nthw_hif_get_stat(nthw_hif_t *p, uint32_t *p_rx_cnt, uint32_t *p_tx_cnt, 225 uint32_t *p_ref_clk_cnt, uint32_t *p_tg_unit_size, uint32_t *p_tg_ref_freq, 226 uint64_t *p_tags_in_use, uint64_t *p_rd_err, uint64_t *p_wr_err) 227 { 228 *p_rx_cnt = nthw_field_get_updated(p->mp_fld_stat_rx_counter); 229 *p_tx_cnt = nthw_field_get_updated(p->mp_fld_stat_tx_counter); 230 231 *p_ref_clk_cnt = nthw_field_get_updated(p->mp_fld_stat_ref_clk_ref_clk); 232 233 *p_tg_unit_size = NTHW_TG_CNT_SIZE; 234 *p_tg_ref_freq = p->mn_fpga_hif_ref_clk_freq; 235 236 *p_tags_in_use = (p->mp_fld_status_tags_in_use 237 ? nthw_field_get_updated(p->mp_fld_status_tags_in_use) 238 : 0); 239 240 *p_rd_err = 241 (p->mp_fld_status_rd_err ? nthw_field_get_updated(p->mp_fld_status_rd_err) : 0); 242 *p_wr_err = 243 (p->mp_fld_status_wr_err ? nthw_field_get_updated(p->mp_fld_status_wr_err) : 0); 244 245 return 0; 246 } 247 248 int nthw_hif_get_stat_rate(nthw_hif_t *p, uint64_t *p_pci_rx_rate, uint64_t *p_pci_tx_rate, 249 uint64_t *p_ref_clk_cnt, uint64_t *p_tags_in_use, 250 uint64_t *p_rd_err_cnt, uint64_t *p_wr_err_cnt) 251 { 252 uint32_t rx_cnt, tx_cnt, ref_clk_cnt, tg_unit_size, tg_ref_freq; 253 uint64_t n_tags_in_use, n_rd_err, n_wr_err; 254 255 nthw_hif_get_stat(p, &rx_cnt, &tx_cnt, &ref_clk_cnt, &tg_unit_size, &tg_ref_freq, 256 &n_tags_in_use, &n_rd_err, &n_wr_err); 257 258 *p_tags_in_use = n_tags_in_use; 259 260 if (n_rd_err) 261 (*p_rd_err_cnt)++; 262 263 if (n_wr_err) 264 (*p_wr_err_cnt)++; 265 266 if (ref_clk_cnt) { 267 uint64_t rx_rate; 268 uint64_t tx_rate; 269 270 *p_ref_clk_cnt = ref_clk_cnt; 271 272 rx_rate = ((uint64_t)rx_cnt * tg_unit_size * tg_ref_freq) / (uint64_t)ref_clk_cnt; 273 *p_pci_rx_rate = rx_rate; 274 275 tx_rate = ((uint64_t)tx_cnt * tg_unit_size * tg_ref_freq) / (uint64_t)ref_clk_cnt; 276 *p_pci_tx_rate = tx_rate; 277 278 } else { 279 *p_pci_rx_rate = 0; 280 *p_pci_tx_rate = 0; 281 *p_ref_clk_cnt = 0; 282 } 283 284 return 0; 285 } 286 287 int nthw_hif_stat_req_enable(nthw_hif_t *p) 288 { 289 nthw_field_set_all(p->mp_fld_stat_ctrl_ena); 290 nthw_field_set_all(p->mp_fld_stat_ctrl_req); 291 nthw_field_flush_register(p->mp_fld_stat_ctrl_req); 292 return 0; 293 } 294 295 int nthw_hif_stat_req_disable(nthw_hif_t *p) 296 { 297 nthw_field_clr_all(p->mp_fld_stat_ctrl_ena); 298 nthw_field_set_all(p->mp_fld_stat_ctrl_req); 299 nthw_field_flush_register(p->mp_fld_stat_ctrl_req); 300 return 0; 301 } 302 303 int nthw_hif_end_point_counters_sample(nthw_hif_t *p, struct nthw_hif_end_point_counters *epc) 304 { 305 assert(epc); 306 307 /* Get stat rate and maintain rx/tx min/max */ 308 nthw_hif_get_stat_rate(p, &epc->cur_tx, &epc->cur_rx, &epc->n_ref_clk_cnt, 309 &epc->n_tags_in_use, &epc->n_rd_err, &epc->n_wr_err); 310 311 return 0; 312 } 313