xref: /linux/drivers/crypto/cavium/nitrox/nitrox_hal.c (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/delay.h>
3 #include <linux/string.h>
4 
5 #include "nitrox_dev.h"
6 #include "nitrox_csr.h"
7 #include "nitrox_hal.h"
8 
9 #define PLL_REF_CLK 50
10 #define MAX_CSR_RETRIES 10
11 
12 /**
13  * emu_enable_cores - Enable EMU cluster cores.
14  * @ndev: NITROX device
15  */
16 static void emu_enable_cores(struct nitrox_device *ndev)
17 {
18 	union emu_se_enable emu_se;
19 	union emu_ae_enable emu_ae;
20 	int i;
21 
22 	/* AE cores 20 per cluster */
23 	emu_ae.value = 0;
24 	emu_ae.s.enable = 0xfffff;
25 
26 	/* SE cores 16 per cluster */
27 	emu_se.value = 0;
28 	emu_se.s.enable = 0xffff;
29 
30 	/* enable per cluster cores */
31 	for (i = 0; i < NR_CLUSTERS; i++) {
32 		nitrox_write_csr(ndev, EMU_AE_ENABLEX(i), emu_ae.value);
33 		nitrox_write_csr(ndev, EMU_SE_ENABLEX(i), emu_se.value);
34 	}
35 }
36 
37 /**
38  * nitrox_config_emu_unit - configure EMU unit.
39  * @ndev: NITROX device
40  */
41 void nitrox_config_emu_unit(struct nitrox_device *ndev)
42 {
43 	union emu_wd_int_ena_w1s emu_wd_int;
44 	union emu_ge_int_ena_w1s emu_ge_int;
45 	u64 offset;
46 	int i;
47 
48 	/* enable cores */
49 	emu_enable_cores(ndev);
50 
51 	/* enable general error and watch dog interrupts */
52 	emu_ge_int.value = 0;
53 	emu_ge_int.s.se_ge = 0xffff;
54 	emu_ge_int.s.ae_ge = 0xfffff;
55 	emu_wd_int.value = 0;
56 	emu_wd_int.s.se_wd = 1;
57 
58 	for (i = 0; i < NR_CLUSTERS; i++) {
59 		offset = EMU_WD_INT_ENA_W1SX(i);
60 		nitrox_write_csr(ndev, offset, emu_wd_int.value);
61 		offset = EMU_GE_INT_ENA_W1SX(i);
62 		nitrox_write_csr(ndev, offset, emu_ge_int.value);
63 	}
64 }
65 
66 static void reset_pkt_input_ring(struct nitrox_device *ndev, int ring)
67 {
68 	union nps_pkt_in_instr_ctl pkt_in_ctl;
69 	union nps_pkt_in_done_cnts pkt_in_cnts;
70 	int max_retries = MAX_CSR_RETRIES;
71 	u64 offset;
72 
73 	/* step 1: disable the ring, clear enable bit */
74 	offset = NPS_PKT_IN_INSTR_CTLX(ring);
75 	pkt_in_ctl.value = nitrox_read_csr(ndev, offset);
76 	pkt_in_ctl.s.enb = 0;
77 	nitrox_write_csr(ndev, offset, pkt_in_ctl.value);
78 
79 	/* step 2: wait to clear [ENB] */
80 	usleep_range(100, 150);
81 	do {
82 		pkt_in_ctl.value = nitrox_read_csr(ndev, offset);
83 		if (!pkt_in_ctl.s.enb)
84 			break;
85 		udelay(50);
86 	} while (max_retries--);
87 
88 	/* step 3: clear done counts */
89 	offset = NPS_PKT_IN_DONE_CNTSX(ring);
90 	pkt_in_cnts.value = nitrox_read_csr(ndev, offset);
91 	nitrox_write_csr(ndev, offset, pkt_in_cnts.value);
92 	usleep_range(50, 100);
93 }
94 
95 void enable_pkt_input_ring(struct nitrox_device *ndev, int ring)
96 {
97 	union nps_pkt_in_instr_ctl pkt_in_ctl;
98 	int max_retries = MAX_CSR_RETRIES;
99 	u64 offset;
100 
101 	/* 64-byte instruction size */
102 	offset = NPS_PKT_IN_INSTR_CTLX(ring);
103 	pkt_in_ctl.value = nitrox_read_csr(ndev, offset);
104 	pkt_in_ctl.s.is64b = 1;
105 	pkt_in_ctl.s.enb = 1;
106 	nitrox_write_csr(ndev, offset, pkt_in_ctl.value);
107 
108 	/* wait for set [ENB] */
109 	do {
110 		pkt_in_ctl.value = nitrox_read_csr(ndev, offset);
111 		if (pkt_in_ctl.s.enb)
112 			break;
113 		udelay(50);
114 	} while (max_retries--);
115 }
116 
117 /**
118  * nitrox_config_pkt_input_rings - configure Packet Input Rings
119  * @ndev: NITROX device
120  */
121 void nitrox_config_pkt_input_rings(struct nitrox_device *ndev)
122 {
123 	int i;
124 
125 	for (i = 0; i < ndev->nr_queues; i++) {
126 		struct nitrox_cmdq *cmdq = &ndev->pkt_inq[i];
127 		union nps_pkt_in_instr_rsize pkt_in_rsize;
128 		union nps_pkt_in_instr_baoff_dbell pkt_in_dbell;
129 		u64 offset;
130 
131 		reset_pkt_input_ring(ndev, i);
132 
133 		/**
134 		 * step 4:
135 		 * configure ring base address 16-byte aligned,
136 		 * size and interrupt threshold.
137 		 */
138 		offset = NPS_PKT_IN_INSTR_BADDRX(i);
139 		nitrox_write_csr(ndev, offset, cmdq->dma);
140 
141 		/* configure ring size */
142 		offset = NPS_PKT_IN_INSTR_RSIZEX(i);
143 		pkt_in_rsize.value = 0;
144 		pkt_in_rsize.s.rsize = ndev->qlen;
145 		nitrox_write_csr(ndev, offset, pkt_in_rsize.value);
146 
147 		/* set high threshold for pkt input ring interrupts */
148 		offset = NPS_PKT_IN_INT_LEVELSX(i);
149 		nitrox_write_csr(ndev, offset, 0xffffffff);
150 
151 		/* step 5: clear off door bell counts */
152 		offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(i);
153 		pkt_in_dbell.value = 0;
154 		pkt_in_dbell.s.dbell = 0xffffffff;
155 		nitrox_write_csr(ndev, offset, pkt_in_dbell.value);
156 
157 		/* enable the ring */
158 		enable_pkt_input_ring(ndev, i);
159 	}
160 }
161 
162 static void reset_pkt_solicit_port(struct nitrox_device *ndev, int port)
163 {
164 	union nps_pkt_slc_ctl pkt_slc_ctl;
165 	union nps_pkt_slc_cnts pkt_slc_cnts;
166 	int max_retries = MAX_CSR_RETRIES;
167 	u64 offset;
168 
169 	/* step 1: disable slc port */
170 	offset = NPS_PKT_SLC_CTLX(port);
171 	pkt_slc_ctl.value = nitrox_read_csr(ndev, offset);
172 	pkt_slc_ctl.s.enb = 0;
173 	nitrox_write_csr(ndev, offset, pkt_slc_ctl.value);
174 
175 	/* step 2 */
176 	usleep_range(100, 150);
177 	/* wait to clear [ENB] */
178 	do {
179 		pkt_slc_ctl.value = nitrox_read_csr(ndev, offset);
180 		if (!pkt_slc_ctl.s.enb)
181 			break;
182 		udelay(50);
183 	} while (max_retries--);
184 
185 	/* step 3: clear slc counters */
186 	offset = NPS_PKT_SLC_CNTSX(port);
187 	pkt_slc_cnts.value = nitrox_read_csr(ndev, offset);
188 	nitrox_write_csr(ndev, offset, pkt_slc_cnts.value);
189 	usleep_range(50, 100);
190 }
191 
192 void enable_pkt_solicit_port(struct nitrox_device *ndev, int port)
193 {
194 	union nps_pkt_slc_ctl pkt_slc_ctl;
195 	int max_retries = MAX_CSR_RETRIES;
196 	u64 offset;
197 
198 	offset = NPS_PKT_SLC_CTLX(port);
199 	pkt_slc_ctl.value = 0;
200 	pkt_slc_ctl.s.enb = 1;
201 	/*
202 	 * 8 trailing 0x00 bytes will be added
203 	 * to the end of the outgoing packet.
204 	 */
205 	pkt_slc_ctl.s.z = 1;
206 	/* enable response header */
207 	pkt_slc_ctl.s.rh = 1;
208 	nitrox_write_csr(ndev, offset, pkt_slc_ctl.value);
209 
210 	/* wait to set [ENB] */
211 	do {
212 		pkt_slc_ctl.value = nitrox_read_csr(ndev, offset);
213 		if (pkt_slc_ctl.s.enb)
214 			break;
215 		udelay(50);
216 	} while (max_retries--);
217 }
218 
219 static void config_pkt_solicit_port(struct nitrox_device *ndev, int port)
220 {
221 	union nps_pkt_slc_int_levels pkt_slc_int;
222 	u64 offset;
223 
224 	reset_pkt_solicit_port(ndev, port);
225 
226 	/* step 4: configure interrupt levels */
227 	offset = NPS_PKT_SLC_INT_LEVELSX(port);
228 	pkt_slc_int.value = 0;
229 	/* time interrupt threshold */
230 	pkt_slc_int.s.timet = 0x3fffff;
231 	nitrox_write_csr(ndev, offset, pkt_slc_int.value);
232 
233 	/* enable the solicit port */
234 	enable_pkt_solicit_port(ndev, port);
235 }
236 
237 void nitrox_config_pkt_solicit_ports(struct nitrox_device *ndev)
238 {
239 	int i;
240 
241 	for (i = 0; i < ndev->nr_queues; i++)
242 		config_pkt_solicit_port(ndev, i);
243 }
244 
245 /**
246  * enable_nps_core_interrupts - enable NPS core interrutps
247  * @ndev: NITROX device.
248  *
249  * This includes NPS core interrupts.
250  */
251 static void enable_nps_core_interrupts(struct nitrox_device *ndev)
252 {
253 	union nps_core_int_ena_w1s core_int;
254 
255 	/* NPS core interrutps */
256 	core_int.value = 0;
257 	core_int.s.host_wr_err = 1;
258 	core_int.s.host_wr_timeout = 1;
259 	core_int.s.exec_wr_timeout = 1;
260 	core_int.s.npco_dma_malform = 1;
261 	core_int.s.host_nps_wr_err = 1;
262 	nitrox_write_csr(ndev, NPS_CORE_INT_ENA_W1S, core_int.value);
263 }
264 
265 void nitrox_config_nps_core_unit(struct nitrox_device *ndev)
266 {
267 	union nps_core_gbl_vfcfg core_gbl_vfcfg;
268 
269 	/* endian control information */
270 	nitrox_write_csr(ndev, NPS_CORE_CONTROL, 1ULL);
271 
272 	/* disable ILK interface */
273 	core_gbl_vfcfg.value = 0;
274 	core_gbl_vfcfg.s.ilk_disable = 1;
275 	core_gbl_vfcfg.s.cfg = __NDEV_MODE_PF;
276 	nitrox_write_csr(ndev, NPS_CORE_GBL_VFCFG, core_gbl_vfcfg.value);
277 
278 	/* enable nps core interrupts */
279 	enable_nps_core_interrupts(ndev);
280 }
281 
282 /**
283  * enable_nps_pkt_interrupts - enable NPS packet interrutps
284  * @ndev: NITROX device.
285  *
286  * This includes NPS packet in and slc interrupts.
287  */
288 static void enable_nps_pkt_interrupts(struct nitrox_device *ndev)
289 {
290 	/* NPS packet in ring interrupts */
291 	nitrox_write_csr(ndev, NPS_PKT_IN_RERR_LO_ENA_W1S, (~0ULL));
292 	nitrox_write_csr(ndev, NPS_PKT_IN_RERR_HI_ENA_W1S, (~0ULL));
293 	nitrox_write_csr(ndev, NPS_PKT_IN_ERR_TYPE_ENA_W1S, (~0ULL));
294 	/* NPS packet slc port interrupts */
295 	nitrox_write_csr(ndev, NPS_PKT_SLC_RERR_HI_ENA_W1S, (~0ULL));
296 	nitrox_write_csr(ndev, NPS_PKT_SLC_RERR_LO_ENA_W1S, (~0ULL));
297 	nitrox_write_csr(ndev, NPS_PKT_SLC_ERR_TYPE_ENA_W1S, (~0uLL));
298 }
299 
300 void nitrox_config_nps_pkt_unit(struct nitrox_device *ndev)
301 {
302 	/* config input and solicit ports */
303 	nitrox_config_pkt_input_rings(ndev);
304 	nitrox_config_pkt_solicit_ports(ndev);
305 
306 	/* enable nps packet interrupts */
307 	enable_nps_pkt_interrupts(ndev);
308 }
309 
310 static void reset_aqm_ring(struct nitrox_device *ndev, int ring)
311 {
312 	union aqmq_en aqmq_en_reg;
313 	union aqmq_activity_stat activity_stat;
314 	union aqmq_cmp_cnt cmp_cnt;
315 	int max_retries = MAX_CSR_RETRIES;
316 	u64 offset;
317 
318 	/* step 1: disable the queue */
319 	offset = AQMQ_ENX(ring);
320 	aqmq_en_reg.value = 0;
321 	aqmq_en_reg.queue_enable = 0;
322 	nitrox_write_csr(ndev, offset, aqmq_en_reg.value);
323 
324 	/* step 2: wait for AQMQ_ACTIVITY_STATX[QUEUE_ACTIVE] to clear */
325 	usleep_range(100, 150);
326 	offset = AQMQ_ACTIVITY_STATX(ring);
327 	do {
328 		activity_stat.value = nitrox_read_csr(ndev, offset);
329 		if (!activity_stat.queue_active)
330 			break;
331 		udelay(50);
332 	} while (max_retries--);
333 
334 	/* step 3: clear commands completed count */
335 	offset = AQMQ_CMP_CNTX(ring);
336 	cmp_cnt.value = nitrox_read_csr(ndev, offset);
337 	nitrox_write_csr(ndev, offset, cmp_cnt.value);
338 	usleep_range(50, 100);
339 }
340 
341 void enable_aqm_ring(struct nitrox_device *ndev, int ring)
342 {
343 	union aqmq_en aqmq_en_reg;
344 	u64 offset;
345 
346 	offset = AQMQ_ENX(ring);
347 	aqmq_en_reg.value = 0;
348 	aqmq_en_reg.queue_enable = 1;
349 	nitrox_write_csr(ndev, offset, aqmq_en_reg.value);
350 	usleep_range(50, 100);
351 }
352 
353 void nitrox_config_aqm_rings(struct nitrox_device *ndev)
354 {
355 	int ring;
356 
357 	for (ring = 0; ring < ndev->nr_queues; ring++) {
358 		struct nitrox_cmdq *cmdq = ndev->aqmq[ring];
359 		union aqmq_drbl drbl;
360 		union aqmq_qsz qsize;
361 		union aqmq_cmp_thr cmp_thr;
362 		u64 offset;
363 
364 		/* steps 1 - 3 */
365 		reset_aqm_ring(ndev, ring);
366 
367 		/* step 4: clear doorbell count of ring */
368 		offset = AQMQ_DRBLX(ring);
369 		drbl.value = 0;
370 		drbl.dbell_count = 0xFFFFFFFF;
371 		nitrox_write_csr(ndev, offset, drbl.value);
372 
373 		/* step 5: configure host ring details */
374 
375 		/* set host address for next command of ring */
376 		offset = AQMQ_NXT_CMDX(ring);
377 		nitrox_write_csr(ndev, offset, 0ULL);
378 
379 		/* set host address of ring base */
380 		offset = AQMQ_BADRX(ring);
381 		nitrox_write_csr(ndev, offset, cmdq->dma);
382 
383 		/* set ring size */
384 		offset = AQMQ_QSZX(ring);
385 		qsize.value = 0;
386 		qsize.host_queue_size = ndev->qlen;
387 		nitrox_write_csr(ndev, offset, qsize.value);
388 
389 		/* set command completion threshold */
390 		offset = AQMQ_CMP_THRX(ring);
391 		cmp_thr.value = 0;
392 		cmp_thr.commands_completed_threshold = 1;
393 		nitrox_write_csr(ndev, offset, cmp_thr.value);
394 
395 		/* step 6: enable the queue */
396 		enable_aqm_ring(ndev, ring);
397 	}
398 }
399 
400 static void enable_aqm_interrupts(struct nitrox_device *ndev)
401 {
402 	/* clear interrupt enable bits */
403 	nitrox_write_csr(ndev, AQM_DBELL_OVF_LO_ENA_W1S, (~0ULL));
404 	nitrox_write_csr(ndev, AQM_DBELL_OVF_HI_ENA_W1S, (~0ULL));
405 	nitrox_write_csr(ndev, AQM_DMA_RD_ERR_LO_ENA_W1S, (~0ULL));
406 	nitrox_write_csr(ndev, AQM_DMA_RD_ERR_HI_ENA_W1S, (~0ULL));
407 	nitrox_write_csr(ndev, AQM_EXEC_NA_LO_ENA_W1S, (~0ULL));
408 	nitrox_write_csr(ndev, AQM_EXEC_NA_HI_ENA_W1S, (~0ULL));
409 	nitrox_write_csr(ndev, AQM_EXEC_ERR_LO_ENA_W1S, (~0ULL));
410 	nitrox_write_csr(ndev, AQM_EXEC_ERR_HI_ENA_W1S, (~0ULL));
411 }
412 
413 void nitrox_config_aqm_unit(struct nitrox_device *ndev)
414 {
415 	/* config aqm command queues */
416 	nitrox_config_aqm_rings(ndev);
417 
418 	/* enable aqm interrupts */
419 	enable_aqm_interrupts(ndev);
420 }
421 
422 void nitrox_config_pom_unit(struct nitrox_device *ndev)
423 {
424 	union pom_int_ena_w1s pom_int;
425 	int i;
426 
427 	/* enable pom interrupts */
428 	pom_int.value = 0;
429 	pom_int.s.illegal_dport = 1;
430 	nitrox_write_csr(ndev, POM_INT_ENA_W1S, pom_int.value);
431 
432 	/* enable perf counters */
433 	for (i = 0; i < ndev->hw.se_cores; i++)
434 		nitrox_write_csr(ndev, POM_PERF_CTL, BIT_ULL(i));
435 }
436 
437 /**
438  * nitrox_config_rand_unit - enable NITROX random number unit
439  * @ndev: NITROX device
440  */
441 void nitrox_config_rand_unit(struct nitrox_device *ndev)
442 {
443 	union efl_rnm_ctl_status efl_rnm_ctl;
444 	u64 offset;
445 
446 	offset = EFL_RNM_CTL_STATUS;
447 	efl_rnm_ctl.value = nitrox_read_csr(ndev, offset);
448 	efl_rnm_ctl.s.ent_en = 1;
449 	efl_rnm_ctl.s.rng_en = 1;
450 	nitrox_write_csr(ndev, offset, efl_rnm_ctl.value);
451 }
452 
453 void nitrox_config_efl_unit(struct nitrox_device *ndev)
454 {
455 	int i;
456 
457 	for (i = 0; i < NR_CLUSTERS; i++) {
458 		union efl_core_int_ena_w1s efl_core_int;
459 		u64 offset;
460 
461 		/* EFL core interrupts */
462 		offset = EFL_CORE_INT_ENA_W1SX(i);
463 		efl_core_int.value = 0;
464 		efl_core_int.s.len_ovr = 1;
465 		efl_core_int.s.d_left = 1;
466 		efl_core_int.s.epci_decode_err = 1;
467 		nitrox_write_csr(ndev, offset, efl_core_int.value);
468 
469 		offset = EFL_CORE_VF_ERR_INT0_ENA_W1SX(i);
470 		nitrox_write_csr(ndev, offset, (~0ULL));
471 		offset = EFL_CORE_VF_ERR_INT1_ENA_W1SX(i);
472 		nitrox_write_csr(ndev, offset, (~0ULL));
473 	}
474 }
475 
476 void nitrox_config_bmi_unit(struct nitrox_device *ndev)
477 {
478 	union bmi_ctl bmi_ctl;
479 	union bmi_int_ena_w1s bmi_int_ena;
480 	u64 offset;
481 
482 	/* no threshold limits for PCIe */
483 	offset = BMI_CTL;
484 	bmi_ctl.value = nitrox_read_csr(ndev, offset);
485 	bmi_ctl.s.max_pkt_len = 0xff;
486 	bmi_ctl.s.nps_free_thrsh = 0xff;
487 	bmi_ctl.s.nps_hdrq_thrsh = 0x7a;
488 	nitrox_write_csr(ndev, offset, bmi_ctl.value);
489 
490 	/* enable interrupts */
491 	offset = BMI_INT_ENA_W1S;
492 	bmi_int_ena.value = 0;
493 	bmi_int_ena.s.max_len_err_nps = 1;
494 	bmi_int_ena.s.pkt_rcv_err_nps = 1;
495 	bmi_int_ena.s.fpf_undrrn = 1;
496 	nitrox_write_csr(ndev, offset, bmi_int_ena.value);
497 }
498 
499 void nitrox_config_bmo_unit(struct nitrox_device *ndev)
500 {
501 	union bmo_ctl2 bmo_ctl2;
502 	u64 offset;
503 
504 	/* no threshold limits for PCIe */
505 	offset = BMO_CTL2;
506 	bmo_ctl2.value = nitrox_read_csr(ndev, offset);
507 	bmo_ctl2.s.nps_slc_buf_thrsh = 0xff;
508 	nitrox_write_csr(ndev, offset, bmo_ctl2.value);
509 }
510 
511 void invalidate_lbc(struct nitrox_device *ndev)
512 {
513 	union lbc_inval_ctl lbc_ctl;
514 	union lbc_inval_status lbc_stat;
515 	int max_retries = MAX_CSR_RETRIES;
516 	u64 offset;
517 
518 	/* invalidate LBC */
519 	offset = LBC_INVAL_CTL;
520 	lbc_ctl.value = nitrox_read_csr(ndev, offset);
521 	lbc_ctl.s.cam_inval_start = 1;
522 	nitrox_write_csr(ndev, offset, lbc_ctl.value);
523 
524 	offset = LBC_INVAL_STATUS;
525 	do {
526 		lbc_stat.value = nitrox_read_csr(ndev, offset);
527 		if (lbc_stat.s.done)
528 			break;
529 		udelay(50);
530 	} while (max_retries--);
531 }
532 
533 void nitrox_config_lbc_unit(struct nitrox_device *ndev)
534 {
535 	union lbc_int_ena_w1s lbc_int_ena;
536 	u64 offset;
537 
538 	invalidate_lbc(ndev);
539 
540 	/* enable interrupts */
541 	offset = LBC_INT_ENA_W1S;
542 	lbc_int_ena.value = 0;
543 	lbc_int_ena.s.dma_rd_err = 1;
544 	lbc_int_ena.s.over_fetch_err = 1;
545 	lbc_int_ena.s.cam_inval_abort = 1;
546 	lbc_int_ena.s.cam_hard_err = 1;
547 	nitrox_write_csr(ndev, offset, lbc_int_ena.value);
548 
549 	offset = LBC_PLM_VF1_64_INT_ENA_W1S;
550 	nitrox_write_csr(ndev, offset, (~0ULL));
551 	offset = LBC_PLM_VF65_128_INT_ENA_W1S;
552 	nitrox_write_csr(ndev, offset, (~0ULL));
553 
554 	offset = LBC_ELM_VF1_64_INT_ENA_W1S;
555 	nitrox_write_csr(ndev, offset, (~0ULL));
556 	offset = LBC_ELM_VF65_128_INT_ENA_W1S;
557 	nitrox_write_csr(ndev, offset, (~0ULL));
558 }
559 
560 void config_nps_core_vfcfg_mode(struct nitrox_device *ndev, enum vf_mode mode)
561 {
562 	union nps_core_gbl_vfcfg vfcfg;
563 
564 	vfcfg.value = nitrox_read_csr(ndev, NPS_CORE_GBL_VFCFG);
565 	vfcfg.s.cfg = mode & 0x7;
566 
567 	nitrox_write_csr(ndev, NPS_CORE_GBL_VFCFG, vfcfg.value);
568 }
569 
570 static const char *get_core_option(u8 se_cores, u8 ae_cores)
571 {
572 	const char *option = "";
573 
574 	if (ae_cores == AE_MAX_CORES) {
575 		switch (se_cores) {
576 		case SE_MAX_CORES:
577 			option = "60";
578 			break;
579 		case 40:
580 			option = "60s";
581 			break;
582 		}
583 	} else if (ae_cores == (AE_MAX_CORES / 2)) {
584 		option = "30";
585 	} else {
586 		option = "60i";
587 	}
588 
589 	return option;
590 }
591 
592 static const char *get_feature_option(u8 zip_cores, int core_freq)
593 {
594 	if (zip_cores == 0)
595 		return "";
596 	else if (zip_cores < ZIP_MAX_CORES)
597 		return "-C15";
598 
599 	if (core_freq >= 850)
600 		return "-C45";
601 	else if (core_freq >= 750)
602 		return "-C35";
603 	else if (core_freq >= 550)
604 		return "-C25";
605 
606 	return "";
607 }
608 
609 void nitrox_get_hwinfo(struct nitrox_device *ndev)
610 {
611 	union emu_fuse_map emu_fuse;
612 	union rst_boot rst_boot;
613 	union fus_dat1 fus_dat1;
614 	unsigned char name[IFNAMSIZ * 2] = {};
615 	int i, dead_cores;
616 	u64 offset;
617 
618 	/* get core frequency */
619 	offset = RST_BOOT;
620 	rst_boot.value = nitrox_read_csr(ndev, offset);
621 	ndev->hw.freq = (rst_boot.pnr_mul + 3) * PLL_REF_CLK;
622 
623 	for (i = 0; i < NR_CLUSTERS; i++) {
624 		offset = EMU_FUSE_MAPX(i);
625 		emu_fuse.value = nitrox_read_csr(ndev, offset);
626 		if (emu_fuse.s.valid) {
627 			dead_cores = hweight32(emu_fuse.s.ae_fuse);
628 			ndev->hw.ae_cores += AE_CORES_PER_CLUSTER - dead_cores;
629 			dead_cores = hweight16(emu_fuse.s.se_fuse);
630 			ndev->hw.se_cores += SE_CORES_PER_CLUSTER - dead_cores;
631 		}
632 	}
633 	/* find zip hardware availability */
634 	offset = FUS_DAT1;
635 	fus_dat1.value = nitrox_read_csr(ndev, offset);
636 	if (!fus_dat1.nozip) {
637 		dead_cores = hweight8(fus_dat1.zip_info);
638 		ndev->hw.zip_cores = ZIP_MAX_CORES - dead_cores;
639 	}
640 
641 	/* determine the partname
642 	 * CNN55<core option>-<freq><pincount>-<feature option>-<rev>
643 	 */
644 	snprintf(name, sizeof(name), "CNN55%s-%3dBG676%s-1.%u",
645 		 get_core_option(ndev->hw.se_cores, ndev->hw.ae_cores),
646 		 ndev->hw.freq,
647 		 get_feature_option(ndev->hw.zip_cores, ndev->hw.freq),
648 		 ndev->hw.revision_id);
649 
650 	/* copy partname */
651 	strscpy(ndev->hw.partname, name);
652 }
653 
654 void enable_pf2vf_mbox_interrupts(struct nitrox_device *ndev)
655 {
656 	u64 value = ~0ULL;
657 	u64 reg_addr;
658 
659 	/* Mailbox interrupt low enable set register */
660 	reg_addr = NPS_PKT_MBOX_INT_LO_ENA_W1S;
661 	nitrox_write_csr(ndev, reg_addr, value);
662 
663 	/* Mailbox interrupt high enable set register */
664 	reg_addr = NPS_PKT_MBOX_INT_HI_ENA_W1S;
665 	nitrox_write_csr(ndev, reg_addr, value);
666 }
667 
668 void disable_pf2vf_mbox_interrupts(struct nitrox_device *ndev)
669 {
670 	u64 value = ~0ULL;
671 	u64 reg_addr;
672 
673 	/* Mailbox interrupt low enable clear register */
674 	reg_addr = NPS_PKT_MBOX_INT_LO_ENA_W1C;
675 	nitrox_write_csr(ndev, reg_addr, value);
676 
677 	/* Mailbox interrupt high enable clear register */
678 	reg_addr = NPS_PKT_MBOX_INT_HI_ENA_W1C;
679 	nitrox_write_csr(ndev, reg_addr, value);
680 }
681