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