xref: /dpdk/drivers/net/ntnic/nthw/model/nthw_fpga_model.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * Copyright(c) 2023 Napatech A/S
4  */
5 
6 #include <time.h>
7 
8 #include "nthw_drv.h"
9 #include "nthw_register.h"
10 #include "nthw_fpga_model.h"
11 #include "nthw_rac.h"
12 #include "ntlog.h"
13 
14 /*
15  * NOTE: this needs to be (manually) synced with enum nthw_fpga_bus_type
16  */
17 static const char *const sa_nthw_fpga_bus_type_str[] = {
18 	"ERR",	/* NTHW_FPGA_BUS_TYPE_UNKNOWN, */
19 	"BAR",	/* NTHW_FPGA_BUS_TYPE_BAR, */
20 	"PCI",	/* NTHW_FPGA_BUS_TYPE_PCI, */
21 	"CCIP",	/* NTHW_FPGA_BUS_TYPE_CCIP, */
22 	"RAB0",	/* NTHW_FPGA_BUS_TYPE_RAB0, */
23 	"RAB1",	/* NTHW_FPGA_BUS_TYPE_RAB1, */
24 	"RAB2",	/* NTHW_FPGA_BUS_TYPE_RAB2, */
25 	"NMB",	/* NTHW_FPGA_BUS_TYPE_NMB, */
26 	"NDM",	/* NTHW_FPGA_BUS_TYPE_NDM, */
27 };
28 
29 static const char *get_bus_name(int n_bus_type_id)
30 {
31 	if (n_bus_type_id >= 1 && n_bus_type_id <= (int)ARRAY_SIZE(sa_nthw_fpga_bus_type_str))
32 		return sa_nthw_fpga_bus_type_str[n_bus_type_id];
33 
34 	else
35 		return "ERR";
36 }
37 
38 /*
39  * module name lookup by id from array
40  * Uses naive linear search as performance is not an issue here...
41  */
42 
43 static const struct {
44 	const nthw_id_t a;
45 	const char *b;
46 } *sa_nthw_fpga_mod_str_map;
47 
48 static const char *nthw_fpga_mod_id_to_str(nthw_id_t n_fpga_mod_id)
49 {
50 	int i;
51 
52 	if (sa_nthw_fpga_mod_str_map) {
53 		for (i = 0; sa_nthw_fpga_mod_str_map[i].a && sa_nthw_fpga_mod_str_map[i].b; i++)
54 			if ((nthw_id_t)sa_nthw_fpga_mod_str_map[i].a == n_fpga_mod_id)
55 				return sa_nthw_fpga_mod_str_map[i].b;
56 	}
57 
58 	return "unknown";
59 }
60 
61 static int nthw_read_data(struct fpga_info_s *p_fpga_info, bool trc, int n_bus_type_id,
62 	uint32_t addr, uint32_t len, uint32_t *p_data)
63 {
64 	int rc = -1;
65 
66 	assert(p_fpga_info);
67 	assert(p_data);
68 	assert(len >= 1);
69 
70 	switch (n_bus_type_id) {
71 	case NTHW_FPGA_BUS_TYPE_BAR:
72 	case NTHW_FPGA_BUS_TYPE_PCI:
73 		nthw_rac_bar0_read32(p_fpga_info, addr, len, p_data);
74 		rc = 0;
75 		break;
76 
77 	case NTHW_FPGA_BUS_TYPE_RAB0:
78 		assert(p_fpga_info->mp_nthw_rac);
79 		rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, trc, 0, addr, len, p_data);
80 		break;
81 
82 	case NTHW_FPGA_BUS_TYPE_RAB1:
83 		assert(p_fpga_info->mp_nthw_rac);
84 		rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, trc, 1, addr, len, p_data);
85 		break;
86 
87 	case NTHW_FPGA_BUS_TYPE_RAB2:
88 		assert(p_fpga_info->mp_nthw_rac);
89 		rc = nthw_rac_rab_read32(p_fpga_info->mp_nthw_rac, trc, 2, addr, len, p_data);
90 		break;
91 
92 	default:
93 		assert(false);
94 		return -1;
95 	}
96 
97 	return rc;
98 }
99 
100 static int nthw_write_data(struct fpga_info_s *p_fpga_info, bool trc, int n_bus_type_id,
101 	uint32_t addr, uint32_t len, const uint32_t *p_data)
102 {
103 	int rc = -1;
104 
105 	assert(p_fpga_info);
106 	assert(p_data);
107 	assert(len >= 1);
108 
109 	switch (n_bus_type_id) {
110 	case NTHW_FPGA_BUS_TYPE_BAR:
111 	case NTHW_FPGA_BUS_TYPE_PCI:
112 		nthw_rac_bar0_write32(p_fpga_info, addr, len, p_data);
113 		rc = 0;
114 		break;
115 
116 	case NTHW_FPGA_BUS_TYPE_RAB0:
117 		assert(p_fpga_info->mp_nthw_rac);
118 		rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, trc, 0, addr, len, p_data);
119 		break;
120 
121 	case NTHW_FPGA_BUS_TYPE_RAB1:
122 		assert(p_fpga_info->mp_nthw_rac);
123 		rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, trc, 1, addr, len, p_data);
124 		break;
125 
126 	case NTHW_FPGA_BUS_TYPE_RAB2:
127 		assert(p_fpga_info->mp_nthw_rac);
128 		rc = nthw_rac_rab_write32(p_fpga_info->mp_nthw_rac, trc, 2, addr, len, p_data);
129 		break;
130 
131 	default:
132 		assert(false);
133 		return -1;
134 	}
135 
136 	return rc;
137 }
138 
139 uint64_t nthw_fpga_read_ident(struct fpga_info_s *p_fpga_info)
140 {
141 	uint64_t n_fpga_ident;
142 	uint32_t n_fpga_ident_lo, n_fpga_ident_hi;
143 	nthw_rac_bar0_read32(p_fpga_info, 0x0, 1, &n_fpga_ident_lo);
144 	nthw_rac_bar0_read32(p_fpga_info, 0x8, 1, &n_fpga_ident_hi);
145 	n_fpga_ident = (((uint64_t)n_fpga_ident_hi << 32) | n_fpga_ident_lo);
146 	return n_fpga_ident;
147 }
148 
149 uint32_t nthw_fpga_read_buildtime(struct fpga_info_s *p_fpga_info)
150 {
151 	uint32_t n_fpga_build_time;
152 	nthw_rac_bar0_read32(p_fpga_info, 0x10, 1, &n_fpga_build_time);
153 	return n_fpga_build_time;
154 }
155 
156 int nthw_fpga_extract_type_id(const uint64_t n_fpga_ident)
157 {
158 	return (uint16_t)(n_fpga_ident >> 32) & 0xFF;
159 }
160 
161 int nthw_fpga_extract_prod_id(const uint64_t n_fpga_ident)
162 {
163 	return (uint16_t)(n_fpga_ident >> 16) & 0xFFFF;
164 }
165 
166 int nthw_fpga_extract_ver_id(const uint64_t n_fpga_ident)
167 {
168 	return (uint16_t)((n_fpga_ident >> 8) & 0xFF);
169 }
170 
171 int nthw_fpga_extract_rev_id(const uint64_t n_fpga_ident)
172 {
173 	return (uint16_t)(n_fpga_ident & 0xFF);
174 }
175 
176 /*
177  * FpgaMgr
178  */
179 nthw_fpga_mgr_t *nthw_fpga_mgr_new(void)
180 {
181 	nthw_fpga_mgr_t *p = malloc(sizeof(nthw_fpga_mgr_t));
182 	return p;
183 }
184 
185 void nthw_fpga_mgr_delete(nthw_fpga_mgr_t *p)
186 {
187 	memset(p, 0, sizeof(nthw_fpga_mgr_t));
188 	free(p);
189 }
190 
191 void nthw_fpga_mgr_init(nthw_fpga_mgr_t *p, struct nthw_fpga_prod_init **pa_nthw_fpga_instances,
192 	const void *pa_mod_str_map)
193 {
194 	size_t i = 0;
195 
196 	p->mpa_fpga_prod_init = pa_nthw_fpga_instances;
197 	sa_nthw_fpga_mod_str_map = pa_mod_str_map;
198 
199 	/* Count fpga instance in array */
200 	if (pa_nthw_fpga_instances) {
201 		for (i = 0;; i++)
202 			if (p->mpa_fpga_prod_init[i] == NULL)
203 				break;
204 	}
205 
206 	p->mn_fpgas = (int)i;
207 }
208 
209 static nthw_fpga_t *nthw_fpga_mgr_lookup_fpga(nthw_fpga_mgr_t *p, uint64_t n_fpga_id,
210 	struct fpga_info_s *p_fpga_info)
211 {
212 	const int n_fpga_prod_id = nthw_fpga_extract_prod_id(n_fpga_id);
213 	const int n_fpga_ver = nthw_fpga_extract_ver_id(n_fpga_id);
214 	const int n_fpga_rev = nthw_fpga_extract_rev_id(n_fpga_id);
215 	int i;
216 
217 	for (i = 0; i < p->mn_fpgas; i++) {
218 		nthw_fpga_prod_init_s *p_init = p->mpa_fpga_prod_init[i];
219 
220 		if (p_init->fpga_product_id == n_fpga_prod_id &&
221 			p_init->fpga_version == n_fpga_ver && p_init->fpga_revision == n_fpga_rev) {
222 			nthw_fpga_t *p_fpga = nthw_fpga_model_new();
223 			nthw_fpga_model_init(p_fpga, p_init, p_fpga_info);
224 			return p_fpga;
225 		}
226 	}
227 
228 	return NULL;
229 }
230 
231 nthw_fpga_t *nthw_fpga_mgr_query_fpga(nthw_fpga_mgr_t *p_fpga_mgr, uint64_t n_fpga_id,
232 	struct fpga_info_s *p_fpga_info)
233 {
234 	const int n_fpga_prod_id = nthw_fpga_extract_prod_id(n_fpga_id);
235 	const int n_fpga_ver = nthw_fpga_extract_ver_id(n_fpga_id);
236 	const int n_fpga_rev = nthw_fpga_extract_rev_id(n_fpga_id);
237 
238 	nthw_fpga_t *p_fpga = nthw_fpga_mgr_lookup_fpga(p_fpga_mgr, n_fpga_id, p_fpga_info);
239 
240 	if (p_fpga) {
241 	} else {
242 		NT_LOG(ERR, NTHW, "FPGA Id 0x%" PRIX64 ": %04d: %d.%d: no match found\n",
243 			n_fpga_id, n_fpga_prod_id, n_fpga_ver, n_fpga_rev);
244 	}
245 
246 	return p_fpga;
247 }
248 
249 
250 void nthw_fpga_mgr_log_dump(nthw_fpga_mgr_t *p)
251 {
252 	int i;
253 
254 	NT_LOG_DBGX(DEBUG, NTHW, "fpgas=%d\n", p->mn_fpgas);
255 
256 	for (i = 0; i < p->mn_fpgas; i++) {
257 		nthw_fpga_prod_init_s *p_init = p->mpa_fpga_prod_init[i];
258 		(void)p_init;
259 		NT_LOG_DBGX(DEBUG, NTHW, "fpga=%d/%d: %04d-%02d-%02d\n", i, p->mn_fpgas,
260 			p_init->fpga_product_id, p_init->fpga_version, p_init->fpga_revision);
261 	}
262 }
263 
264 /*
265  * Fpga
266  */
267 nthw_fpga_t *nthw_fpga_model_new(void)
268 {
269 	nthw_fpga_t *p = malloc(sizeof(nthw_fpga_t));
270 
271 	if (p)
272 		memset(p, 0, sizeof(nthw_fpga_t));
273 
274 	return p;
275 }
276 
277 void nthw_fpga_model_init(nthw_fpga_t *p, nthw_fpga_prod_init_s *p_init,
278 	struct fpga_info_s *p_fpga_info)
279 {
280 	int i;
281 
282 	p->p_fpga_info = p_fpga_info;
283 	p->mp_init = p_init;
284 
285 	p->mn_item_id = p_init->fpga_item_id;
286 	p->mn_product_id = p_init->fpga_product_id;
287 	p->mn_fpga_version = p_init->fpga_version;
288 	p->mn_fpga_revision = p_init->fpga_revision;
289 	p->mn_fpga_patch_no = p_init->fpga_patch_no;
290 	p->mn_fpga_build_no = p_init->fpga_build_no;
291 	p->mn_fpga_build_time = p_init->fpga_build_time;
292 
293 	p->mn_params = p_init->nb_prod_params;
294 
295 	if (p->mn_params) {
296 		p->mpa_params = malloc(p->mn_params * sizeof(nthw_param_t *));
297 
298 		if (p->mpa_params) {
299 			memset(p->mpa_params, 0, (p->mn_params * sizeof(nthw_param_t *)));
300 
301 			for (i = 0; i < p->mn_params; i++) {
302 				nthw_param_t *p_param = nthw_param_new();
303 
304 				nthw_param_init(p_param, p, &p_init->product_params[i]);
305 				p->mpa_params[i] = p_param;
306 			}
307 		}
308 	}
309 
310 	p->mn_modules = p_init->nb_modules;
311 
312 	if (p->mn_modules) {
313 		p->mpa_modules = malloc(p_init->nb_modules * sizeof(nthw_module_t *));
314 
315 		if (p->mpa_modules) {
316 			memset(p->mpa_modules, 0, (p->mn_modules * sizeof(nthw_module_t *)));
317 
318 			for (i = 0; i < p->mn_modules; i++) {
319 				nthw_module_t *p_mod = nthw_module_new();
320 
321 				nthw_module_init(p_mod, p, &p_init->modules[i]);
322 				p->mpa_modules[i] = p_mod;
323 			}
324 		}
325 	}
326 }
327 
328 void nthw_fpga_set_debug_mode(nthw_fpga_t *p, int debug_mode)
329 {
330 	int i;
331 
332 	p->m_debug_mode = debug_mode;
333 
334 	for (i = 0; i < p->mn_modules; i++) {
335 		nthw_module_t *p_mod = p->mpa_modules[i];
336 
337 		if (p_mod)
338 			nthw_module_set_debug_mode(p_mod, debug_mode);
339 	}
340 }
341 
342 static nthw_module_t *nthw_fpga_lookup_module(const nthw_fpga_t *p, nthw_id_t id, int instance)
343 {
344 	int i;
345 
346 	for (i = 0; i < p->mn_modules; i++) {
347 		nthw_module_t *p_mod = p->mpa_modules[i];
348 
349 		if (p_mod->mn_mod_id == id && p_mod->mn_instance == instance)
350 			return p_mod;
351 	}
352 
353 	return NULL;
354 }
355 
356 nthw_module_t *nthw_fpga_query_module(const nthw_fpga_t *p, nthw_id_t id, int instance)
357 {
358 	return nthw_fpga_lookup_module(p, id, instance);
359 }
360 
361 int nthw_fpga_get_product_param(const nthw_fpga_t *p, const nthw_id_t n_param_id,
362 	const int n_default_value)
363 {
364 	int i;
365 
366 	for (i = 0; i < p->mn_params; i++) {
367 		nthw_param_t *p_param = p->mpa_params[i];
368 
369 		if (p_param->mn_param_id == n_param_id)
370 			return p_param->mn_param_value;
371 	}
372 
373 	return n_default_value;
374 }
375 
376 int nthw_fpga_get_product_id(const nthw_fpga_t *p)
377 {
378 	return p->mn_product_id;
379 }
380 
381 /*
382  * Param
383  */
384 nthw_param_t *nthw_param_new(void)
385 {
386 	nthw_param_t *p = malloc(sizeof(nthw_param_t));
387 
388 	return p;
389 }
390 
391 void nthw_param_init(nthw_param_t *p, nthw_fpga_t *p_fpga, nthw_fpga_prod_param_s *p_init)
392 {
393 	p->mp_owner = p_fpga;
394 	p->mp_init = p_init;
395 
396 	p->mn_param_id = p_init->id;
397 	p->mn_param_value = p_init->value;
398 }
399 
400 /*
401  * Module
402  */
403 nthw_module_t *nthw_module_new(void)
404 {
405 	nthw_module_t *p = malloc(sizeof(nthw_module_t));
406 
407 	return p;
408 }
409 
410 void nthw_module_init(nthw_module_t *p, nthw_fpga_t *p_fpga, nthw_fpga_module_init_s *p_init)
411 {
412 	int i;
413 
414 	p->mp_owner = p_fpga;
415 	p->mp_init = p_init;
416 
417 	p->mn_mod_id = p_init->id;
418 	p->mn_instance = p_init->instance;
419 
420 	/* Copy debug mode from owner */
421 	if (p->mp_owner)
422 		p->mn_debug_mode = p->mp_owner->m_debug_mode;
423 
424 	else
425 		p->mn_debug_mode = 0;
426 
427 	p->mn_mod_def_id = p_init->def_id;
428 	p->mn_major_version = p_init->major_version;
429 	p->mn_minor_version = p_init->minor_version;
430 	p->mn_bus = p_init->bus_id;
431 	p->mn_addr_base = p_init->addr_base;
432 
433 	p->mn_registers = p_init->nb_registers;
434 
435 	if (p->mn_registers) {
436 		p->mpa_registers = malloc(p->mn_registers * sizeof(nthw_register_t *));
437 
438 		if (p->mpa_registers) {
439 			memset(p->mpa_registers, 0, (p->mn_registers * sizeof(nthw_register_t *)));
440 
441 			for (i = 0; i < p->mn_registers; i++) {
442 				nthw_register_t *p_reg = nthw_register_new();
443 
444 				nthw_register_init(p_reg, p, &p_init->registers[i]);
445 				p->mpa_registers[i] = p_reg;
446 			}
447 		}
448 	}
449 }
450 
451 int nthw_module_get_major_version(const nthw_module_t *p)
452 {
453 	return p->mn_major_version;
454 }
455 
456 int nthw_module_get_minor_version(const nthw_module_t *p)
457 {
458 	return p->mn_minor_version;
459 }
460 
461 uint64_t nthw_module_get_version_packed64(const nthw_module_t *p)
462 {
463 	return (((uint64_t)p->mn_major_version & 0xFFFFFFFF) << 32) |
464 		(p->mn_minor_version & 0xFFFFFFFF);
465 }
466 
467 bool nthw_module_is_version_newer(const nthw_module_t *p, int major_version, int minor_version)
468 {
469 	if (major_version == p->mn_major_version)
470 		return p->mn_minor_version >= minor_version;
471 
472 	return p->mn_major_version >= major_version;
473 }
474 
475 static nthw_register_t *nthw_module_lookup_register(nthw_module_t *p, nthw_id_t id)
476 {
477 	int i;
478 	nthw_register_t *p_register = NULL;
479 
480 	for (i = 0; i < p->mn_registers; i++) {
481 		if (p->mpa_registers[i]->mn_id == id) {
482 			p_register = p->mpa_registers[i];
483 			break;
484 		}
485 	}
486 
487 	return p_register;
488 }
489 
490 nthw_register_t *nthw_module_query_register(nthw_module_t *p, nthw_id_t id)
491 {
492 	return nthw_module_lookup_register(p, id);
493 }
494 
495 nthw_register_t *nthw_module_get_register(nthw_module_t *p, nthw_id_t id)
496 {
497 	nthw_register_t *p_register;
498 
499 	if (p == NULL) {
500 		NT_LOG(ERR, NTHW, "Illegal module context for register %u\n", id);
501 		return NULL;
502 	}
503 
504 	p_register = nthw_module_lookup_register(p, id);
505 
506 	if (!p_register) {
507 		NT_LOG(ERR, NTHW, "Register %u not found in module: %s (%u)\n", id,
508 			nthw_fpga_mod_id_to_str(p->mn_mod_id), p->mn_mod_id);
509 	}
510 
511 	return p_register;
512 }
513 
514 int nthw_module_get_debug_mode(const nthw_module_t *p)
515 {
516 	return p->mn_debug_mode;
517 }
518 
519 void nthw_module_set_debug_mode(nthw_module_t *p, unsigned int debug_mode)
520 {
521 	int i;
522 
523 	p->mn_debug_mode = debug_mode;
524 
525 	for (i = 0; i < p->mn_registers; i++) {
526 		nthw_register_t *p_register = p->mpa_registers[i];
527 
528 		if (p_register)
529 			nthw_register_set_debug_mode(p_register, debug_mode);
530 	}
531 }
532 
533 int nthw_module_get_bus(const nthw_module_t *p)
534 {
535 	return p->mn_bus;
536 }
537 
538 /*
539  * Register
540  */
541 nthw_register_t *nthw_register_new(void)
542 {
543 	nthw_register_t *p = malloc(sizeof(nthw_register_t));
544 
545 	return p;
546 }
547 
548 void nthw_register_init(nthw_register_t *p, nthw_module_t *p_module,
549 	nthw_fpga_register_init_s *p_init)
550 {
551 	int i;
552 
553 	p->mp_owner = p_module;
554 
555 	p->mn_id = p_init->id;
556 	p->mn_bit_width = p_init->bw;
557 	p->mn_addr_rel = p_init->addr_rel;
558 	p->mn_addr = p_module->mn_addr_base + p_init->addr_rel;
559 	p->mn_type = p_init->type;
560 	/* Old P200 registers have no bw at register level - default to BW=-1 */
561 	p->mn_len = ((p_init->bw != (uint16_t)-1) ? ((p_init->bw + 31) >> 5) : 1);
562 	p->mn_debug_mode = p_module->mn_debug_mode;
563 
564 	p->mn_fields = p_init->nb_fields;
565 
566 	if (p->mn_fields) {
567 		p->mpa_fields = malloc(p->mn_fields * sizeof(nthw_field_t *));
568 
569 		if (p->mpa_fields) {
570 			memset(p->mpa_fields, 0, (p->mn_fields * sizeof(nthw_field_t *)));
571 
572 			for (i = 0; i < p->mn_fields; i++) {
573 				nthw_field_t *p_field = nthw_field_new();
574 
575 				nthw_field_init(p_field, p, &p_init->fields[i]);
576 				p->mpa_fields[i] = p_field;
577 			}
578 
579 			p->mp_shadow = malloc(p->mn_len * sizeof(uint32_t));
580 
581 			if (p->mp_shadow)
582 				memset(p->mp_shadow, 0x00, (p->mn_len * sizeof(uint32_t)));
583 
584 			p->mp_dirty = malloc(p->mn_len * sizeof(bool));
585 
586 			if (p->mp_dirty)
587 				memset(p->mp_dirty, 0x00, (p->mn_len * sizeof(bool)));
588 		}
589 	}
590 }
591 
592 uint32_t nthw_register_get_address(const nthw_register_t *p)
593 {
594 	return p->mn_addr;
595 }
596 
597 void nthw_register_reset(const nthw_register_t *p)
598 {
599 	int i;
600 	nthw_field_t *p_field = NULL;
601 
602 	for (i = 0; i < p->mn_fields; i++) {
603 		p_field = p->mpa_fields[i];
604 
605 		if (p_field)
606 			nthw_field_reset(p_field);
607 	}
608 }
609 
610 static nthw_field_t *nthw_register_lookup_field(const nthw_register_t *p, nthw_id_t id)
611 {
612 	int i;
613 	nthw_field_t *p_field = NULL;
614 
615 	if (!p)
616 		return NULL;
617 
618 	for (i = 0; i < p->mn_fields; i++) {
619 		if (p->mpa_fields[i]->mn_id == id) {
620 			p_field = p->mpa_fields[i];
621 			break;
622 		}
623 	}
624 
625 	return p_field;
626 }
627 
628 nthw_field_t *nthw_register_query_field(const nthw_register_t *p, nthw_id_t id)
629 {
630 	return nthw_register_lookup_field(p, id);
631 }
632 
633 nthw_field_t *nthw_register_get_field(const nthw_register_t *p, nthw_id_t id)
634 {
635 	nthw_field_t *p_field;
636 
637 	if (p == NULL) {
638 		NT_LOG(ERR, NTHW, "Illegal register context for field %u\n", id);
639 		return NULL;
640 	}
641 
642 	p_field = nthw_register_lookup_field(p, id);
643 
644 	if (!p_field) {
645 		NT_LOG(ERR, NTHW, "Field %u not found in module: %s (%u)\n", id,
646 			nthw_fpga_mod_id_to_str(p->mp_owner->mn_mod_id), p->mp_owner->mn_mod_id);
647 	}
648 
649 	return p_field;
650 }
651 
652 int nthw_register_get_bit_width(const nthw_register_t *p)
653 {
654 	return p->mn_bit_width;
655 }
656 
657 int nthw_register_get_debug_mode(const nthw_register_t *p)
658 {
659 	return p->mn_debug_mode;
660 }
661 
662 /*
663  * NOTE: do not set debug on fields - as register operation dumps typically are enough
664  */
665 void nthw_register_set_debug_mode(nthw_register_t *p, unsigned int debug_mode)
666 {
667 	int i;
668 
669 	p->mn_debug_mode = debug_mode;
670 
671 	for (i = 0; i < p->mn_fields; i++) {
672 		nthw_field_t *p_field = p->mpa_fields[i];
673 
674 		if (p_field)
675 			nthw_field_set_debug_mode(p_field, debug_mode);
676 	}
677 }
678 
679 static int nthw_register_read_data(const nthw_register_t *p)
680 {
681 	int rc = -1;
682 
683 	const int n_bus_type_id = nthw_module_get_bus(p->mp_owner);
684 	const uint32_t addr = p->mn_addr;
685 	const uint32_t len = p->mn_len;
686 	uint32_t *const p_data = p->mp_shadow;
687 	const bool trc = (p->mn_debug_mode & NTHW_REG_TRACE_ON_READ);
688 
689 	struct fpga_info_s *p_fpga_info = NULL;
690 
691 	if (p && p->mp_owner && p->mp_owner->mp_owner)
692 		p_fpga_info = p->mp_owner->mp_owner->p_fpga_info;
693 
694 	assert(p_fpga_info);
695 	assert(p_data);
696 
697 	rc = nthw_read_data(p_fpga_info, trc, n_bus_type_id, addr, len, p_data);
698 	return rc;
699 }
700 
701 static int nthw_register_write_data(const nthw_register_t *p, uint32_t cnt)
702 {
703 	int rc = -1;
704 
705 	const int n_bus_type_id = nthw_module_get_bus(p->mp_owner);
706 	const uint32_t addr = p->mn_addr;
707 	const uint32_t len = p->mn_len;
708 	uint32_t *const p_data = p->mp_shadow;
709 	const bool trc = (p->mn_debug_mode & NTHW_REG_TRACE_ON_WRITE);
710 
711 	struct fpga_info_s *p_fpga_info = NULL;
712 
713 	if (p && p->mp_owner && p->mp_owner->mp_owner)
714 		p_fpga_info = p->mp_owner->mp_owner->p_fpga_info;
715 
716 	assert(p_fpga_info);
717 	assert(p_data);
718 
719 	rc = nthw_write_data(p_fpga_info, trc, n_bus_type_id, addr, (len * cnt), p_data);
720 
721 	return rc;
722 }
723 
724 void nthw_register_get_val(const nthw_register_t *p, uint32_t *p_data, uint32_t len)
725 {
726 	uint32_t i;
727 
728 	if (len == (uint32_t)-1 || len > p->mn_len)
729 		len = p->mn_len;
730 
731 	assert(len <= p->mn_len);
732 	assert(p_data);
733 
734 	for (i = 0; i < len; i++)
735 		p_data[i] = p->mp_shadow[i];
736 }
737 
738 uint32_t nthw_register_get_val32(const nthw_register_t *p)
739 {
740 	uint32_t val = 0;
741 
742 	nthw_register_get_val(p, &val, 1);
743 	return val;
744 }
745 
746 void nthw_register_update(const nthw_register_t *p)
747 {
748 	if (p && p->mn_type != NTHW_FPGA_REG_TYPE_WO) {
749 		const char *const p_dev_name = "NA";
750 		(void)p_dev_name;
751 		const int n_bus_type_id = nthw_module_get_bus(p->mp_owner);
752 		const char *const p_bus_name = get_bus_name(n_bus_type_id);
753 		(void)p_bus_name;
754 		const uint32_t addr = p->mn_addr;
755 		(void)addr;
756 		const uint32_t len = p->mn_len;
757 		uint32_t *const p_data = p->mp_shadow;
758 
759 		nthw_register_read_data(p);
760 
761 		if (p->mn_debug_mode & NTHW_REG_DEBUG_ON_READ) {
762 			uint32_t i = len;
763 			uint32_t *ptr = p_data;
764 			(void)ptr;
765 			char *tmp_string = ntlog_helper_str_alloc("Register::read");
766 			ntlog_helper_str_add(tmp_string,
767 				"(Dev: %s, Bus: %s, Addr: 0x%08X, Cnt: %d, Data:",
768 				p_dev_name, p_bus_name, addr, len);
769 
770 			while (i--)
771 				ntlog_helper_str_add(tmp_string, " 0x%08X", *ptr++);
772 
773 			ntlog_helper_str_add(tmp_string, ")");
774 			NT_LOG(DBG, NTHW, "%s", tmp_string);
775 			ntlog_helper_str_free(tmp_string);
776 		}
777 	}
778 }
779 
780 uint32_t nthw_register_get_val_updated32(const nthw_register_t *p)
781 {
782 	uint32_t val = 0;
783 
784 	nthw_register_update(p);
785 	nthw_register_get_val(p, &val, 1);
786 	return val;
787 }
788 
789 void nthw_register_make_dirty(nthw_register_t *p)
790 {
791 	uint32_t i;
792 
793 	for (i = 0; i < p->mn_len; i++)
794 		p->mp_dirty[i] = true;
795 }
796 
797 void nthw_register_set_val(nthw_register_t *p, const uint32_t *p_data, uint32_t len)
798 {
799 	assert(len <= p->mn_len);
800 	assert(p_data);
801 
802 	if (len == (uint32_t)-1 || len > p->mn_len)
803 		len = p->mn_len;
804 
805 	if (p->mp_shadow != p_data)
806 		memcpy(p->mp_shadow, p_data, (len * sizeof(uint32_t)));
807 }
808 
809 void nthw_register_flush(const nthw_register_t *p, uint32_t cnt)
810 {
811 	int rc;
812 
813 	if (p->mn_type != NTHW_FPGA_REG_TYPE_RO) {
814 		const char *const p_dev_name = "NA";
815 		const int n_bus_type_id = nthw_module_get_bus(p->mp_owner);
816 		const char *p_bus_name = get_bus_name(n_bus_type_id);
817 		const uint32_t addr = p->mn_addr;
818 		const uint32_t len = p->mn_len;
819 		uint32_t *const p_data = p->mp_shadow;
820 		uint32_t i;
821 
822 		assert(len * cnt <= 256);
823 
824 		if (p->mn_debug_mode & NTHW_REG_DEBUG_ON_WRITE) {
825 			uint32_t i = len * cnt;
826 			uint32_t *ptr = p_data;
827 			char *tmp_string = ntlog_helper_str_alloc("Register::write");
828 
829 			ntlog_helper_str_add(tmp_string,
830 				"(Dev: %s, Bus: %s, Addr: 0x%08X, Cnt: %d, Data:",
831 				p_dev_name, p_bus_name, addr, i);
832 
833 			while (i--)
834 				ntlog_helper_str_add(tmp_string, " 0x%08X", *ptr++);
835 
836 			ntlog_helper_str_add(tmp_string, ")");
837 			NT_LOG(DBG, NTHW, "%s", tmp_string);
838 			ntlog_helper_str_free(tmp_string);
839 		}
840 
841 		rc = nthw_register_write_data(p, cnt);
842 
843 		if (rc)
844 			NT_LOG(ERR, NTHW, "Register write error %d\n", rc);
845 
846 		for (i = 0; i < cnt; i++)
847 			p->mp_dirty[i] = false;
848 	}
849 }
850 
851 void nthw_register_clr(nthw_register_t *p)
852 {
853 	memset(p->mp_shadow, 0, p->mn_len * sizeof(uint32_t));
854 	nthw_register_make_dirty(p);
855 }
856 
857 /*
858  * Field
859  */
860 nthw_field_t *nthw_field_new(void)
861 {
862 	nthw_field_t *p = malloc(sizeof(nthw_field_t));
863 
864 	return p;
865 }
866 
867 void nthw_field_init(nthw_field_t *p, nthw_register_t *p_reg, const nthw_fpga_field_init_s *p_init)
868 {
869 	p->mp_owner = p_reg;
870 
871 	p->mn_debug_mode = p_reg->mn_debug_mode;
872 
873 	p->mn_id = p_init->id;
874 	p->mn_bit_width = p_init->bw;
875 	p->mn_bit_pos_low = p_init->low;
876 	p->mn_reset_val = (uint32_t)p_init->reset_val;
877 	p->mn_first_word = p_init->low / 32;
878 	p->mn_first_bit = p_init->low % 32;
879 	p->mn_front_mask = 0;
880 	p->mn_body_length = 0;
881 	p->mn_words = (p_init->bw + 0x1f) / 0x20;
882 	p->mn_tail_mask = 0;
883 
884 	{
885 		int bits_remaining = p_init->bw;
886 		int front_mask_length = 32 - p->mn_first_bit;
887 
888 		if (front_mask_length > bits_remaining)
889 			front_mask_length = bits_remaining;
890 
891 		bits_remaining -= front_mask_length;
892 
893 		p->mn_front_mask =
894 			(uint32_t)(((1ULL << front_mask_length) - 1) << p->mn_first_bit);
895 
896 		p->mn_body_length = bits_remaining / 32;
897 		bits_remaining -= p->mn_body_length * 32;
898 		p->mn_tail_mask = (1 << bits_remaining) - 1;
899 
900 		if (p->mn_debug_mode >= 0x100) {
901 			NT_LOG_DBGX(DEBUG, NTHW,
902 				"fldid=%08d: [%08d:%08d] %08d/%08d: (%08d,%08d) (0x%08X,%08d,0x%08X)\n",
903 				p_init->id, p_init->low, (p_init->low + p_init->bw),
904 				p_init->bw, ((p_init->bw + 31) / 32), p->mn_first_word,
905 				p->mn_first_bit, p->mn_front_mask, p->mn_body_length,
906 				p->mn_tail_mask);
907 		}
908 	}
909 }
910 
911 int nthw_field_get_debug_mode(const nthw_field_t *p)
912 {
913 	return p->mn_debug_mode;
914 }
915 
916 void nthw_field_set_debug_mode(nthw_field_t *p, unsigned int debug_mode)
917 {
918 	p->mn_debug_mode = debug_mode;
919 }
920 
921 int nthw_field_get_bit_width(const nthw_field_t *p)
922 {
923 	return p->mn_bit_width;
924 }
925 
926 int nthw_field_get_bit_pos_low(const nthw_field_t *p)
927 {
928 	return p->mn_bit_pos_low;
929 }
930 
931 int nthw_field_get_bit_pos_high(const nthw_field_t *p)
932 {
933 	return p->mn_bit_pos_low + p->mn_bit_width - 1;
934 }
935 
936 uint32_t nthw_field_get_mask(const nthw_field_t *p)
937 {
938 	return p->mn_front_mask;
939 }
940 
941 void nthw_field_reset(const nthw_field_t *p)
942 {
943 	nthw_field_set_val32(p, (uint32_t)p->mn_reset_val);
944 }
945 
946 void nthw_field_get_val(const nthw_field_t *p, uint32_t *p_data, uint32_t len)
947 {
948 	uint32_t i;
949 	uint32_t data_index = 0;
950 	uint32_t shadow_index = p->mn_first_word;
951 
952 	union {
953 		uint32_t w32[2];
954 		uint64_t w64;
955 	} buf;
956 
957 	(void)len;
958 	assert(len <= p->mn_words);
959 
960 	/* handle front */
961 	buf.w32[0] = p->mp_owner->mp_shadow[shadow_index++] & p->mn_front_mask;
962 
963 	/* handle body */
964 	for (i = 0; i < p->mn_body_length; i++) {
965 		buf.w32[1] = p->mp_owner->mp_shadow[shadow_index++];
966 		buf.w64 = buf.w64 >> (p->mn_first_bit);
967 		assert(data_index < len);
968 		p_data[data_index++] = buf.w32[0];
969 		buf.w64 = buf.w64 >> (32 - p->mn_first_bit);
970 	}
971 
972 	/* handle tail */
973 	if (p->mn_tail_mask)
974 		buf.w32[1] = p->mp_owner->mp_shadow[shadow_index++] & p->mn_tail_mask;
975 
976 	else
977 		buf.w32[1] = 0;
978 
979 	buf.w64 = buf.w64 >> (p->mn_first_bit);
980 	p_data[data_index++] = buf.w32[0];
981 
982 	if (data_index < p->mn_words)
983 		p_data[data_index++] = buf.w32[1];
984 }
985 
986 void nthw_field_set_val(const nthw_field_t *p, const uint32_t *p_data, uint32_t len)
987 {
988 	uint32_t i;
989 	uint32_t data_index = 0;
990 	uint32_t shadow_index = p->mn_first_word;
991 
992 	union {
993 		uint32_t w32[2];
994 		uint64_t w64;
995 	} buf;
996 
997 	(void)len;
998 	assert(len == p->mn_words);
999 
1000 	/* handle front */
1001 	buf.w32[0] = 0;
1002 	buf.w32[1] = p_data[data_index++];
1003 	buf.w64 = buf.w64 >> (32 - p->mn_first_bit);
1004 	p->mp_owner->mp_shadow[shadow_index] =
1005 		(p->mp_owner->mp_shadow[shadow_index] & ~p->mn_front_mask) |
1006 		(buf.w32[0] & p->mn_front_mask);
1007 	shadow_index++;
1008 
1009 	/* handle body */
1010 	for (i = 0; i < p->mn_body_length; i++) {
1011 		buf.w64 = buf.w64 >> (p->mn_first_bit);
1012 		assert(data_index < len);
1013 		buf.w32[1] = p_data[data_index++];
1014 		buf.w64 = buf.w64 >> (32 - p->mn_first_bit);
1015 		p->mp_owner->mp_shadow[shadow_index++] = buf.w32[0];
1016 	}
1017 
1018 	/* handle tail */
1019 	if (p->mn_tail_mask) {
1020 		buf.w64 = buf.w64 >> (p->mn_first_bit);
1021 
1022 		if (data_index < len)
1023 			buf.w32[1] = p_data[data_index];
1024 
1025 		buf.w64 = buf.w64 >> (32 - p->mn_first_bit);
1026 		p->mp_owner->mp_shadow[shadow_index] =
1027 			(p->mp_owner->mp_shadow[shadow_index] & ~p->mn_tail_mask) |
1028 			(buf.w32[0] & p->mn_tail_mask);
1029 	}
1030 
1031 	nthw_register_make_dirty(p->mp_owner);
1032 }
1033 
1034 void nthw_field_set_val_flush(const nthw_field_t *p, const uint32_t *p_data, uint32_t len)
1035 {
1036 	nthw_field_set_val(p, p_data, len);
1037 	nthw_field_flush_register(p);
1038 }
1039 
1040 uint32_t nthw_field_get_val32(const nthw_field_t *p)
1041 {
1042 	uint32_t val;
1043 
1044 	nthw_field_get_val(p, &val, 1);
1045 	return val;
1046 }
1047 
1048 uint32_t nthw_field_get_updated(const nthw_field_t *p)
1049 {
1050 	uint32_t val;
1051 
1052 	nthw_register_update(p->mp_owner);
1053 	nthw_field_get_val(p, &val, 1);
1054 
1055 	return val;
1056 }
1057 
1058 void nthw_field_update_register(const nthw_field_t *p)
1059 {
1060 	nthw_register_update(p->mp_owner);
1061 }
1062 
1063 void nthw_field_flush_register(const nthw_field_t *p)
1064 {
1065 	nthw_register_flush(p->mp_owner, 1);
1066 }
1067 
1068 void nthw_field_set_val32(const nthw_field_t *p, uint32_t val)
1069 {
1070 	nthw_field_set_val(p, &val, 1);
1071 }
1072 
1073 void nthw_field_set_val_flush32(const nthw_field_t *p, uint32_t val)
1074 {
1075 	nthw_field_set_val(p, &val, 1);
1076 	nthw_register_flush(p->mp_owner, 1);
1077 }
1078 
1079 void nthw_field_clr_all(const nthw_field_t *p)
1080 {
1081 	assert(p->mn_body_length == 0);
1082 	nthw_field_set_val32(p, 0);
1083 }
1084 
1085 void nthw_field_clr_flush(const nthw_field_t *p)
1086 {
1087 	nthw_field_clr_all(p);
1088 	nthw_register_flush(p->mp_owner, 1);
1089 }
1090 
1091 void nthw_field_set_all(const nthw_field_t *p)
1092 {
1093 	assert(p->mn_body_length == 0);
1094 	nthw_field_set_val32(p, ~0);
1095 }
1096 
1097 void nthw_field_set_flush(const nthw_field_t *p)
1098 {
1099 	nthw_field_set_all(p);
1100 	nthw_register_flush(p->mp_owner, 1);
1101 }
1102 
1103 enum nthw_field_match {
1104 	NTHW_FIELD_MATCH_CLR_ALL,
1105 	NTHW_FIELD_MATCH_SET_ALL,
1106 	NTHW_FIELD_MATCH_CLR_ANY,
1107 	NTHW_FIELD_MATCH_SET_ANY,
1108 };
1109 
1110 static int nthw_field_wait_cond32(const nthw_field_t *p, enum nthw_field_match e_match,
1111 	int n_poll_iterations, int n_poll_interval)
1112 {
1113 	const uint32_t n_mask = (1 << p->mn_bit_width) - 1;
1114 
1115 	if (n_poll_iterations == -1)
1116 		n_poll_iterations = 10000;
1117 
1118 	if (n_poll_interval == -1)
1119 		n_poll_interval = 100;	/* usec */
1120 
1121 	if (p->mn_debug_mode) {
1122 		const char *const p_cond_name =
1123 			((e_match == NTHW_FIELD_MATCH_SET_ALL)
1124 				? "SetAll"
1125 				: ((e_match == NTHW_FIELD_MATCH_CLR_ALL)
1126 					? "ClrAll"
1127 					: ((e_match == NTHW_FIELD_MATCH_CLR_ANY) ? "ClrAny"
1128 						: "SetAny")));
1129 		(void)p_cond_name;
1130 		const char *const p_dev_name = "NA";
1131 		(void)p_dev_name;
1132 		const char *const p_bus_name =
1133 			get_bus_name(nthw_module_get_bus(p->mp_owner->mp_owner));
1134 		(void)p_bus_name;
1135 		uint32_t n_reg_addr = nthw_register_get_address(p->mp_owner);
1136 		(void)n_reg_addr;
1137 		uint32_t n_reg_mask = (((1 << p->mn_bit_width) - 1) << p->mn_bit_pos_low);
1138 		(void)n_reg_mask;
1139 
1140 		NT_LOG(DBG, NTHW,
1141 			"Register::Field::wait%s32(Dev: %s, Bus: %s, Addr: 0x%08X, Mask: 0x%08X, Iterations: %d, Interval: %d)\n",
1142 			p_cond_name, p_dev_name, p_bus_name, n_reg_addr, n_reg_mask,
1143 			n_poll_iterations, n_poll_interval);
1144 	}
1145 
1146 	while (true) {
1147 		uint32_t val = nthw_field_get_updated(p);
1148 
1149 		if (e_match == NTHW_FIELD_MATCH_SET_ANY && val != 0) {
1150 			return 0;
1151 
1152 		} else if (e_match == NTHW_FIELD_MATCH_SET_ALL && val == n_mask) {
1153 			return 0;
1154 
1155 		} else if (e_match == NTHW_FIELD_MATCH_CLR_ALL && val == 0) {
1156 			return 0;
1157 
1158 		} else if (e_match == NTHW_FIELD_MATCH_CLR_ANY) {
1159 			uint32_t mask = nthw_field_get_mask(p);
1160 
1161 			if (val != mask)
1162 				return 0;
1163 		}
1164 
1165 		n_poll_iterations--;
1166 
1167 		if (n_poll_iterations <= 0)
1168 			return -1;
1169 
1170 		nt_os_wait_usec(n_poll_interval);
1171 	}
1172 
1173 	return 0;
1174 }
1175 
1176 int nthw_field_wait_set_all32(const nthw_field_t *p, int n_poll_iterations, int n_poll_interval)
1177 {
1178 	return nthw_field_wait_cond32(p, NTHW_FIELD_MATCH_SET_ALL, n_poll_iterations,
1179 			n_poll_interval);
1180 }
1181 
1182 int nthw_field_wait_clr_all32(const nthw_field_t *p, int n_poll_iterations, int n_poll_interval)
1183 {
1184 	return nthw_field_wait_cond32(p, NTHW_FIELD_MATCH_CLR_ALL, n_poll_iterations,
1185 			n_poll_interval);
1186 }
1187 
1188 int nthw_field_wait_set_any32(const nthw_field_t *p, int n_poll_iterations, int n_poll_interval)
1189 {
1190 	return nthw_field_wait_cond32(p, NTHW_FIELD_MATCH_SET_ANY, n_poll_iterations,
1191 			n_poll_interval);
1192 }
1193