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