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