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