xref: /dpdk/drivers/net/ntnic/nthw/core/nthw_fpga.c (revision 7917b0d38e92e8b9ec5a870415b791420e10f11a)
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