1 /* 2 * SPDX-License-Identifier: BSD-3-Clause 3 * Copyright(c) 2023 Napatech A/S 4 */ 5 6 #include "ntlog.h" 7 8 #include "nthw_drv.h" 9 #include "nthw_register.h" 10 11 #include "nthw_fpga.h" 12 13 #include "nthw_fpga_instances.h" 14 #include "nthw_fpga_mod_str_map.h" 15 16 #include "nthw_tsm.h" 17 18 #include <arpa/inet.h> 19 20 int nthw_fpga_get_param_info(struct fpga_info_s *p_fpga_info, nthw_fpga_t *p_fpga) 21 { 22 mcu_info_t *p_mcu_info = &p_fpga_info->mcu_info; 23 24 const int n_nims = nthw_fpga_get_product_param(p_fpga, NT_NIMS, -1); 25 const int n_phy_ports = nthw_fpga_get_product_param(p_fpga, NT_PHY_PORTS, -1); 26 const int n_phy_quads = nthw_fpga_get_product_param(p_fpga, NT_PHY_QUADS, -1); 27 const int n_rx_ports = nthw_fpga_get_product_param(p_fpga, NT_RX_PORTS, -1); 28 const int n_tx_ports = nthw_fpga_get_product_param(p_fpga, NT_TX_PORTS, -1); 29 const int n_vf_offset = nthw_fpga_get_product_param(p_fpga, NT_HIF_VF_OFFSET, 4); 30 31 p_fpga_info->n_nims = n_nims; 32 p_fpga_info->n_phy_ports = n_phy_ports; 33 p_fpga_info->n_phy_quads = n_phy_quads; 34 p_fpga_info->n_rx_ports = n_rx_ports; 35 p_fpga_info->n_tx_ports = n_tx_ports; 36 p_fpga_info->n_vf_offset = n_vf_offset; 37 p_fpga_info->profile = FPGA_INFO_PROFILE_UNKNOWN; 38 39 /* Check for MCU */ 40 if (nthw_fpga_get_product_param(p_fpga, NT_MCU_PRESENT, 0) != 0) { 41 p_mcu_info->mb_has_mcu = true; 42 /* Check MCU Type */ 43 p_mcu_info->mn_mcu_type = nthw_fpga_get_product_param(p_fpga, NT_MCU_TYPE, -1); 44 /* MCU DRAM size */ 45 p_mcu_info->mn_mcu_dram_size = 46 nthw_fpga_get_product_param(p_fpga, NT_MCU_DRAM_SIZE, -1); 47 48 } else { 49 p_mcu_info->mb_has_mcu = false; 50 p_mcu_info->mn_mcu_type = -1; 51 p_mcu_info->mn_mcu_dram_size = -1; 52 } 53 54 /* Check for VSWITCH FPGA */ 55 if (nthw_fpga_get_product_param(p_fpga, NT_NFV_OVS_PRODUCT, 0) != 0) { 56 p_fpga_info->profile = FPGA_INFO_PROFILE_VSWITCH; 57 58 } else if (nthw_fpga_get_product_param(p_fpga, NT_IOA_PRESENT, 0) != 0) { 59 /* Check for VSWITCH FPGA - legacy */ 60 p_fpga_info->profile = FPGA_INFO_PROFILE_VSWITCH; 61 62 } else if (nthw_fpga_get_product_param(p_fpga, NT_QM_PRESENT, 0) != 0) { 63 p_fpga_info->profile = FPGA_INFO_PROFILE_CAPTURE; 64 65 } else { 66 p_fpga_info->profile = FPGA_INFO_PROFILE_INLINE; 67 } 68 69 return 0; 70 } 71 72 int nthw_fpga_iic_scan(nthw_fpga_t *p_fpga, const int n_instance_no_begin, 73 const int n_instance_no_end) 74 { 75 int i; 76 77 assert(n_instance_no_begin <= n_instance_no_end); 78 79 for (i = n_instance_no_begin; i <= n_instance_no_end; i++) { 80 nthw_iic_t *p_nthw_iic = nthw_iic_new(); 81 82 if (p_nthw_iic) { 83 const int rc = nthw_iic_init(p_nthw_iic, p_fpga, i, 8); 84 85 if (rc == 0) { 86 nthw_iic_set_retry_params(p_nthw_iic, -1, 100, 100, 3, 3); 87 nthw_iic_scan(p_nthw_iic); 88 } 89 90 nthw_iic_delete(p_nthw_iic); 91 p_nthw_iic = NULL; 92 } 93 } 94 95 return 0; 96 } 97 98 int nthw_fpga_silabs_detect(nthw_fpga_t *p_fpga, const int n_instance_no, const int n_dev_addr, 99 const int n_page_reg_addr) 100 { 101 const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; 102 (void)p_adapter_id_str; 103 uint64_t ident = -1; 104 int res = -1; 105 106 nthw_iic_t *p_nthw_iic = nthw_iic_new(); 107 108 if (p_nthw_iic) { 109 uint8_t data; 110 uint8_t a_silabs_ident[8]; 111 nthw_iic_init(p_nthw_iic, p_fpga, n_instance_no, 8); 112 113 data = 0; 114 /* switch to page 0 */ 115 nthw_iic_write_data(p_nthw_iic, (uint8_t)n_dev_addr, (uint8_t)n_page_reg_addr, 1, 116 &data); 117 res = nthw_iic_read_data(p_nthw_iic, (uint8_t)n_dev_addr, 0x00, 118 sizeof(a_silabs_ident), a_silabs_ident); 119 120 if (res == 0) { 121 int i; 122 123 for (i = 0; i < (int)sizeof(a_silabs_ident); i++) { 124 ident <<= 8; 125 ident |= a_silabs_ident[i]; 126 } 127 } 128 129 nthw_iic_delete(p_nthw_iic); 130 p_nthw_iic = NULL; 131 132 /* Conclude SiLabs part */ 133 if (res == 0) { 134 if (a_silabs_ident[3] == 0x53) { 135 if (a_silabs_ident[2] == 0x40) 136 res = 5340; 137 138 else if (a_silabs_ident[2] == 0x41) 139 res = 5341; 140 141 } else if (a_silabs_ident[2] == 38) { 142 res = 5338; 143 144 } else { 145 res = -1; 146 } 147 } 148 } 149 150 NT_LOG(DBG, NTHW, "%s: %016" PRIX64 ": %d", p_adapter_id_str, ident, res); 151 return res; 152 } 153 154 /* 155 * NT200A02, NT200A01-HWbuild2 156 */ 157 int nthw_fpga_si5340_clock_synth_init_fmt2(nthw_fpga_t *p_fpga, const uint8_t n_iic_addr, 158 const clk_profile_data_fmt2_t *p_clk_profile, 159 const int n_clk_profile_rec_cnt) 160 { 161 int res; 162 nthw_iic_t *p_nthw_iic = nthw_iic_new(); 163 nthw_si5340_t *p_nthw_si5340 = nthw_si5340_new(); 164 165 assert(p_nthw_iic); 166 assert(p_nthw_si5340); 167 nthw_iic_init(p_nthw_iic, p_fpga, 0, 8);/* I2C cycle time 125Mhz ~ 8ns */ 168 169 nthw_si5340_init(p_nthw_si5340, p_nthw_iic, n_iic_addr);/* si5340_u23_i2c_addr_7bit */ 170 res = nthw_si5340_config_fmt2(p_nthw_si5340, p_clk_profile, n_clk_profile_rec_cnt); 171 nthw_si5340_delete(p_nthw_si5340); 172 p_nthw_si5340 = NULL; 173 174 return res; 175 } 176 177 int nthw_fpga_init(struct fpga_info_s *p_fpga_info) 178 { 179 const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str; 180 181 nthw_hif_t *p_nthw_hif = NULL; 182 nthw_pcie3_t *p_nthw_pcie3 = NULL; 183 nthw_rac_t *p_nthw_rac = NULL; 184 nthw_tsm_t *p_nthw_tsm = NULL; 185 186 mcu_info_t *p_mcu_info = &p_fpga_info->mcu_info; 187 uint64_t n_fpga_ident = 0; 188 nthw_fpga_mgr_t *p_fpga_mgr = NULL; 189 nthw_fpga_t *p_fpga = NULL; 190 191 char s_fpga_prod_ver_rev_str[32] = { 0 }; 192 193 int res = 0; 194 195 assert(p_fpga_info); 196 197 { 198 const uint64_t n_fpga_ident = nthw_fpga_read_ident(p_fpga_info); 199 const uint32_t n_fpga_build_time = nthw_fpga_read_buildtime(p_fpga_info); 200 const int n_fpga_type_id = nthw_fpga_extract_type_id(n_fpga_ident); 201 const int n_fpga_prod_id = nthw_fpga_extract_prod_id(n_fpga_ident); 202 const int n_fpga_ver_id = nthw_fpga_extract_ver_id(n_fpga_ident); 203 const int n_fpga_rev_id = nthw_fpga_extract_rev_id(n_fpga_ident); 204 205 p_fpga_info->n_fpga_ident = n_fpga_ident; 206 p_fpga_info->n_fpga_type_id = n_fpga_type_id; 207 p_fpga_info->n_fpga_prod_id = n_fpga_prod_id; 208 p_fpga_info->n_fpga_ver_id = n_fpga_ver_id; 209 p_fpga_info->n_fpga_rev_id = n_fpga_rev_id; 210 p_fpga_info->n_fpga_build_time = n_fpga_build_time; 211 212 snprintf(s_fpga_prod_ver_rev_str, sizeof(s_fpga_prod_ver_rev_str), 213 "%04d-%04d-%02d-%02d", n_fpga_type_id, n_fpga_prod_id, n_fpga_ver_id, 214 n_fpga_rev_id); 215 216 NT_LOG(INF, NTHW, "%s: FPGA %s (%" PRIX64 ") [%08X]", p_adapter_id_str, 217 s_fpga_prod_ver_rev_str, n_fpga_ident, n_fpga_build_time); 218 } 219 220 n_fpga_ident = p_fpga_info->n_fpga_ident; 221 222 p_fpga_mgr = nthw_fpga_mgr_new(); 223 if (p_fpga_mgr) { 224 nthw_fpga_mgr_init(p_fpga_mgr, nthw_fpga_instances, 225 (const void *)sa_nthw_fpga_mod_str_map); 226 nthw_fpga_mgr_log_dump(p_fpga_mgr); 227 p_fpga = nthw_fpga_mgr_query_fpga(p_fpga_mgr, n_fpga_ident, p_fpga_info); 228 p_fpga_info->mp_fpga = p_fpga; 229 230 if (p_fpga == NULL) { 231 NT_LOG(ERR, NTHW, "%s: Unsupported FPGA: %s (%08X)", p_adapter_id_str, 232 s_fpga_prod_ver_rev_str, p_fpga_info->n_fpga_build_time); 233 return -1; 234 } 235 236 nthw_fpga_mgr_delete(p_fpga_mgr); 237 p_fpga_mgr = NULL; 238 } 239 240 /* Read Fpga param info */ 241 nthw_fpga_get_param_info(p_fpga_info, p_fpga); 242 243 /* debug: report params */ 244 NT_LOG(DBG, NTHW, "%s: NT_NIMS=%d", p_adapter_id_str, p_fpga_info->n_nims); 245 NT_LOG(DBG, NTHW, "%s: NT_PHY_PORTS=%d", p_adapter_id_str, p_fpga_info->n_phy_ports); 246 NT_LOG(DBG, NTHW, "%s: NT_PHY_QUADS=%d", p_adapter_id_str, p_fpga_info->n_phy_quads); 247 NT_LOG(DBG, NTHW, "%s: NT_RX_PORTS=%d", p_adapter_id_str, p_fpga_info->n_rx_ports); 248 NT_LOG(DBG, NTHW, "%s: NT_TX_PORTS=%d", p_adapter_id_str, p_fpga_info->n_tx_ports); 249 NT_LOG(DBG, NTHW, "%s: nProfile=%d", p_adapter_id_str, (int)p_fpga_info->profile); 250 NT_LOG(DBG, NTHW, "%s: bHasMcu=%d", p_adapter_id_str, p_mcu_info->mb_has_mcu); 251 NT_LOG(DBG, NTHW, "%s: McuType=%d", p_adapter_id_str, p_mcu_info->mn_mcu_type); 252 NT_LOG(DBG, NTHW, "%s: McuDramSize=%d", p_adapter_id_str, p_mcu_info->mn_mcu_dram_size); 253 254 p_nthw_rac = nthw_rac_new(); 255 256 if (p_nthw_rac == NULL) { 257 NT_LOG(ERR, NTHW, "%s: Unsupported FPGA: RAC is not found: %s (%08X)", 258 p_adapter_id_str, s_fpga_prod_ver_rev_str, p_fpga_info->n_fpga_build_time); 259 return -1; 260 } 261 262 nthw_rac_init(p_nthw_rac, p_fpga, p_fpga_info); 263 nthw_rac_rab_flush(p_nthw_rac); 264 p_fpga_info->mp_nthw_rac = p_nthw_rac; 265 266 bool included = true; 267 struct nt200a0x_ops *nt200a0x_ops = get_nt200a0x_ops(); 268 269 switch (p_fpga_info->n_nthw_adapter_id) { 270 case NT_HW_ADAPTER_ID_NT200A02: 271 if (nt200a0x_ops != NULL) 272 res = nt200a0x_ops->nthw_fpga_nt200a0x_init(p_fpga_info); 273 274 else 275 included = false; 276 277 break; 278 default: 279 NT_LOG(ERR, NTHW, "%s: Unsupported HW product id: %d", p_adapter_id_str, 280 p_fpga_info->n_nthw_adapter_id); 281 res = -1; 282 break; 283 } 284 285 if (!included) { 286 NT_LOG(ERR, NTHW, "%s: NOT INCLUDED HW product: %d", p_adapter_id_str, 287 p_fpga_info->n_nthw_adapter_id); 288 res = -1; 289 } 290 291 if (res) { 292 NT_LOG(ERR, NTHW, "%s: status: 0x%08X", p_adapter_id_str, res); 293 return res; 294 } 295 296 res = nthw_pcie3_init(NULL, p_fpga, 0); /* Probe for module */ 297 298 if (res == 0) { 299 p_nthw_pcie3 = nthw_pcie3_new(); 300 301 if (p_nthw_pcie3) { 302 res = nthw_pcie3_init(p_nthw_pcie3, p_fpga, 0); 303 304 if (res == 0) { 305 NT_LOG(DBG, NTHW, "%s: Pcie3 module found", p_adapter_id_str); 306 nthw_pcie3_trigger_sample_time(p_nthw_pcie3); 307 308 } else { 309 nthw_pcie3_delete(p_nthw_pcie3); 310 p_nthw_pcie3 = NULL; 311 } 312 } 313 314 p_fpga_info->mp_nthw_pcie3 = p_nthw_pcie3; 315 } 316 317 if (p_nthw_pcie3 == NULL) { 318 p_nthw_hif = nthw_hif_new(); 319 320 if (p_nthw_hif) { 321 res = nthw_hif_init(p_nthw_hif, p_fpga, 0); 322 323 if (res == 0) { 324 NT_LOG(DBG, NTHW, "%s: Hif module found", p_adapter_id_str); 325 nthw_hif_trigger_sample_time(p_nthw_hif); 326 327 } else { 328 nthw_hif_delete(p_nthw_hif); 329 p_nthw_hif = NULL; 330 } 331 } 332 } 333 334 p_fpga_info->mp_nthw_hif = p_nthw_hif; 335 336 337 p_nthw_tsm = nthw_tsm_new(); 338 339 if (p_nthw_tsm) { 340 nthw_tsm_init(p_nthw_tsm, p_fpga, 0); 341 342 nthw_tsm_set_config_ts_format(p_nthw_tsm, 1); /* 1 = TSM: TS format native */ 343 344 /* Timer T0 - stat toggle timer */ 345 nthw_tsm_set_timer_t0_enable(p_nthw_tsm, false); 346 nthw_tsm_set_timer_t0_max_count(p_nthw_tsm, 50 * 1000 * 1000); /* ns */ 347 nthw_tsm_set_timer_t0_enable(p_nthw_tsm, true); 348 349 /* Timer T1 - keep alive timer */ 350 nthw_tsm_set_timer_t1_enable(p_nthw_tsm, false); 351 nthw_tsm_set_timer_t1_max_count(p_nthw_tsm, 100 * 1000 * 1000); /* ns */ 352 nthw_tsm_set_timer_t1_enable(p_nthw_tsm, true); 353 } 354 355 p_fpga_info->mp_nthw_tsm = p_nthw_tsm; 356 357 /* TSM sample triggering: test validation... */ 358 #if defined(DEBUG) && (1) 359 { 360 uint64_t n_time, n_ts; 361 int i; 362 363 for (i = 0; i < 4; i++) { 364 if (p_nthw_hif) 365 nthw_hif_trigger_sample_time(p_nthw_hif); 366 367 else if (p_nthw_pcie3) 368 nthw_pcie3_trigger_sample_time(p_nthw_pcie3); 369 370 nthw_tsm_get_time(p_nthw_tsm, &n_time); 371 nthw_tsm_get_ts(p_nthw_tsm, &n_ts); 372 373 NT_LOG(DBG, NTHW, "%s: TSM time: %016" PRIX64 " %016" PRIX64 "\n", 374 p_adapter_id_str, n_time, n_ts); 375 376 nt_os_wait_usec(1000); 377 } 378 } 379 #endif 380 381 return res; 382 } 383 384 int nthw_fpga_shutdown(struct fpga_info_s *p_fpga_info) 385 { 386 int res = -1; 387 388 if (p_fpga_info) { 389 if (p_fpga_info && p_fpga_info->mp_nthw_rac) 390 res = nthw_rac_rab_reset(p_fpga_info->mp_nthw_rac); 391 } 392 393 return res; 394 } 395 396 static struct nt200a0x_ops *nt200a0x_ops; 397 398 void register_nt200a0x_ops(struct nt200a0x_ops *ops) 399 { 400 nt200a0x_ops = ops; 401 } 402 403 struct nt200a0x_ops *get_nt200a0x_ops(void) 404 { 405 if (nt200a0x_ops == NULL) 406 nt200a0x_ops_init(); 407 return nt200a0x_ops; 408 } 409