xref: /dpdk/drivers/net/atlantic/hw_atl/hw_atl_utils.c (revision 25d11a86c56d50947af33d0b79ede622809bd8b9)
1 // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2 /* Copyright (C) 2014-2017 aQuantia Corporation. */
3 
4 /* File hw_atl_utils.c: Definition of common functions for Atlantic hardware
5  * abstraction layer.
6  */
7 
8 #include <stdio.h>
9 #include <errno.h>
10 #include <stdint.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <stdarg.h>
14 #include <inttypes.h>
15 #include <rte_ether.h>
16 #include "../atl_hw_regs.h"
17 
18 #include "hw_atl_llh.h"
19 #include "hw_atl_llh_internal.h"
20 #include "../atl_logs.h"
21 
22 #define HW_ATL_UCP_0X370_REG    0x0370U
23 
24 #define HW_ATL_MIF_CMD          0x0200U
25 #define HW_ATL_MIF_ADDR         0x0208U
26 #define HW_ATL_MIF_VAL          0x020CU
27 
28 #define HW_ATL_FW_SM_RAM        0x2U
29 #define HW_ATL_MPI_FW_VERSION	0x18
30 #define HW_ATL_MPI_CONTROL_ADR  0x0368U
31 #define HW_ATL_MPI_STATE_ADR    0x036CU
32 
33 #define HW_ATL_MPI_STATE_MSK      0x00FFU
34 #define HW_ATL_MPI_STATE_SHIFT    0U
35 #define HW_ATL_MPI_SPEED_MSK      0x00FF0000U
36 #define HW_ATL_MPI_SPEED_SHIFT    16U
37 #define HW_ATL_MPI_DIRTY_WAKE_MSK 0x02000000U
38 
39 #define HW_ATL_MPI_DAISY_CHAIN_STATUS	0x704
40 #define HW_ATL_MPI_BOOT_EXIT_CODE	0x388
41 
42 #define HW_ATL_MAC_PHY_CONTROL	0x4000
43 #define HW_ATL_MAC_PHY_MPI_RESET_BIT 0x1D
44 
45 #define HW_ATL_FW_VER_1X 0x01050006U
46 #define HW_ATL_FW_VER_2X 0x02000000U
47 #define HW_ATL_FW_VER_3X 0x03000000U
48 
49 #define FORCE_FLASHLESS 0
50 
51 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
52 static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
53 				enum hal_atl_utils_fw_state_e state);
54 
55 
56 int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
57 {
58 	int err = 0;
59 
60 	err = hw_atl_utils_soft_reset(self);
61 	if (err)
62 		return err;
63 
64 	hw_atl_utils_hw_chip_features_init(self,
65 					   &self->chip_features);
66 
67 	hw_atl_utils_get_fw_version(self, &self->fw_ver_actual);
68 
69 	if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
70 				   self->fw_ver_actual) == 0) {
71 		*fw_ops = &aq_fw_1x_ops;
72 	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X,
73 					self->fw_ver_actual) == 0) {
74 		*fw_ops = &aq_fw_2x_ops;
75 	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X,
76 					self->fw_ver_actual) == 0) {
77 		*fw_ops = &aq_fw_2x_ops;
78 	} else {
79 		PMD_DRV_LOG(ERR, "Bad FW version detected: %x\n",
80 			  self->fw_ver_actual);
81 		return -EOPNOTSUPP;
82 	}
83 	self->aq_fw_ops = *fw_ops;
84 	err = self->aq_fw_ops->init(self);
85 	return err;
86 }
87 
88 static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self)
89 {
90 	u32 gsr, val;
91 	int k = 0;
92 
93 	aq_hw_write_reg(self, 0x404, 0x40e1);
94 	AQ_HW_SLEEP(50);
95 
96 	/* Cleanup SPI */
97 	val = aq_hw_read_reg(self, 0x53C);
98 	aq_hw_write_reg(self, 0x53C, val | 0x10);
99 
100 	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
101 	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
102 
103 	/* Kickstart MAC */
104 	aq_hw_write_reg(self, 0x404, 0x80e0);
105 	aq_hw_write_reg(self, 0x32a8, 0x0);
106 	aq_hw_write_reg(self, 0x520, 0x1);
107 
108 	/* Reset SPI again because of possible interrupted SPI burst */
109 	val = aq_hw_read_reg(self, 0x53C);
110 	aq_hw_write_reg(self, 0x53C, val | 0x10);
111 	AQ_HW_SLEEP(10);
112 	/* Clear SPI reset state */
113 	aq_hw_write_reg(self, 0x53C, val & ~0x10);
114 
115 	aq_hw_write_reg(self, 0x404, 0x180e0);
116 
117 	for (k = 0; k < 1000; k++) {
118 		u32 flb_status = aq_hw_read_reg(self,
119 						HW_ATL_MPI_DAISY_CHAIN_STATUS);
120 
121 		flb_status = flb_status & 0x10;
122 		if (flb_status)
123 			break;
124 		AQ_HW_SLEEP(10);
125 	}
126 	if (k == 1000) {
127 		PMD_DRV_LOG(ERR, "MAC kickstart failed\n");
128 		return -EIO;
129 	}
130 
131 	/* FW reset */
132 	aq_hw_write_reg(self, 0x404, 0x80e0);
133 	AQ_HW_SLEEP(50);
134 	aq_hw_write_reg(self, 0x3a0, 0x1);
135 
136 	/* Kickstart PHY - skipped */
137 
138 	/* Global software reset*/
139 	hw_atl_rx_rx_reg_res_dis_set(self, 0U);
140 	hw_atl_tx_tx_reg_res_dis_set(self, 0U);
141 	aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
142 			    BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
143 			    HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
144 	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
145 	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
146 
147 	for (k = 0; k < 1000; k++) {
148 		u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
149 
150 		if (fw_state)
151 			break;
152 		AQ_HW_SLEEP(10);
153 	}
154 	if (k == 1000) {
155 		PMD_DRV_LOG(ERR, "FW kickstart failed\n");
156 		return -EIO;
157 	}
158 	/* Old FW requires fixed delay after init */
159 	AQ_HW_SLEEP(15);
160 
161 	return 0;
162 }
163 
164 static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self)
165 {
166 	u32 gsr, val, rbl_status;
167 	int k;
168 
169 	aq_hw_write_reg(self, 0x404, 0x40e1);
170 	aq_hw_write_reg(self, 0x3a0, 0x1);
171 	aq_hw_write_reg(self, 0x32a8, 0x0);
172 
173 	/* Alter RBL status */
174 	aq_hw_write_reg(self, 0x388, 0xDEAD);
175 
176 	/* Cleanup SPI */
177 	val = aq_hw_read_reg(self, 0x53C);
178 	aq_hw_write_reg(self, 0x53C, val | 0x10);
179 
180 	/* Global software reset*/
181 	hw_atl_rx_rx_reg_res_dis_set(self, 0U);
182 	hw_atl_tx_tx_reg_res_dis_set(self, 0U);
183 	aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
184 			    BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
185 			    HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
186 	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
187 	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR,
188 			(gsr & 0xFFFFBFFF) | 0x8000);
189 
190 	if (FORCE_FLASHLESS)
191 		aq_hw_write_reg(self, 0x534, 0x0);
192 
193 	aq_hw_write_reg(self, 0x404, 0x40e0);
194 
195 	/* Wait for RBL boot */
196 	for (k = 0; k < 1000; k++) {
197 		rbl_status = aq_hw_read_reg(self, 0x388) & 0xFFFF;
198 		if (rbl_status && rbl_status != 0xDEAD)
199 			break;
200 		AQ_HW_SLEEP(10);
201 	}
202 	if (!rbl_status || rbl_status == 0xDEAD) {
203 		PMD_DRV_LOG(ERR, "RBL Restart failed");
204 		return -EIO;
205 	}
206 
207 	/* Restore NVR */
208 	if (FORCE_FLASHLESS)
209 		aq_hw_write_reg(self, 0x534, 0xA0);
210 
211 	if (rbl_status == 0xF1A7) {
212 		PMD_DRV_LOG(ERR, "No FW detected. Dynamic FW load not implemented\n");
213 		return -EOPNOTSUPP;
214 	}
215 
216 	for (k = 0; k < 1000; k++) {
217 		u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
218 
219 		if (fw_state)
220 			break;
221 		AQ_HW_SLEEP(10);
222 	}
223 	if (k == 1000) {
224 		PMD_DRV_LOG(ERR, "FW kickstart failed\n");
225 		return -EIO;
226 	}
227 	/* Old FW requires fixed delay after init */
228 	AQ_HW_SLEEP(15);
229 
230 	return 0;
231 }
232 
233 int hw_atl_utils_soft_reset(struct aq_hw_s *self)
234 {
235 	int err = 0;
236 	int k;
237 	u32 boot_exit_code = 0;
238 
239 	for (k = 0; k < 1000; ++k) {
240 		u32 flb_status = aq_hw_read_reg(self,
241 						HW_ATL_MPI_DAISY_CHAIN_STATUS);
242 		boot_exit_code = aq_hw_read_reg(self,
243 						HW_ATL_MPI_BOOT_EXIT_CODE);
244 		if (flb_status != 0x06000000 || boot_exit_code != 0)
245 			break;
246 	}
247 
248 	if (k == 1000) {
249 		PMD_DRV_LOG(ERR, "Neither RBL nor FLB firmware started\n");
250 		return -EOPNOTSUPP;
251 	}
252 
253 	self->rbl_enabled = (boot_exit_code != 0);
254 
255 	/* FW 1.x may bootup in an invalid POWER state (WOL feature).
256 	 * We should work around this by forcing its state back to DEINIT
257 	 */
258 	if (!hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
259 				    aq_hw_read_reg(self,
260 						   HW_ATL_MPI_FW_VERSION))) {
261 		hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
262 		AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR) &
263 			       HW_ATL_MPI_STATE_MSK) == MPI_DEINIT,
264 			       10, 1000U);
265 	}
266 
267 	if (self->rbl_enabled)
268 		err = hw_atl_utils_soft_reset_rbl(self);
269 	else
270 		err = hw_atl_utils_soft_reset_flb(self);
271 
272 	return err;
273 }
274 
275 int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
276 				  u32 *p, u32 cnt)
277 {
278 	int err = 0;
279 
280 	AQ_HW_WAIT_FOR(hw_atl_reg_glb_cpu_sem_get(self,
281 						  HW_ATL_FW_SM_RAM) == 1U,
282 						  1U, 10000U);
283 
284 	if (err < 0) {
285 		bool is_locked;
286 
287 		hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
288 		is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
289 		if (!is_locked) {
290 			err = -ETIMEDOUT;
291 			goto err_exit;
292 		}
293 	}
294 
295 	aq_hw_write_reg(self, HW_ATL_MIF_ADDR, a);
296 
297 	for (++cnt; --cnt && !err;) {
298 		aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U);
299 
300 		if (IS_CHIP_FEATURE(REVISION_B1))
301 			AQ_HW_WAIT_FOR(a != aq_hw_read_reg(self,
302 							   HW_ATL_MIF_ADDR),
303 				       1, 1000U);
304 		else
305 			AQ_HW_WAIT_FOR(!(0x100 & aq_hw_read_reg(self,
306 							   HW_ATL_MIF_CMD)),
307 				       1, 1000U);
308 
309 		*(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL);
310 		a += 4;
311 	}
312 
313 	hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
314 
315 err_exit:
316 	return err;
317 }
318 
319 int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
320 					 u32 cnt)
321 {
322 	int err = 0;
323 	bool is_locked;
324 
325 	is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
326 	if (!is_locked) {
327 		err = -ETIMEDOUT;
328 		goto err_exit;
329 	}
330 	if (IS_CHIP_FEATURE(REVISION_B1)) {
331 		u32 offset = 0;
332 
333 		for (; offset < cnt; ++offset) {
334 			aq_hw_write_reg(self, 0x328, p[offset]);
335 			aq_hw_write_reg(self, 0x32C,
336 				(0x80000000 | (0xFFFF & (offset * 4))));
337 			hw_atl_mcp_up_force_intr_set(self, 1);
338 			/* 1000 times by 10us = 10ms */
339 			AQ_HW_WAIT_FOR((aq_hw_read_reg(self,
340 					0x32C) & 0xF0000000) != 0x80000000,
341 					10, 1000);
342 		}
343 	} else {
344 		u32 offset = 0;
345 
346 		aq_hw_write_reg(self, 0x208, a);
347 
348 		for (; offset < cnt; ++offset) {
349 			aq_hw_write_reg(self, 0x20C, p[offset]);
350 			aq_hw_write_reg(self, 0x200, 0xC000);
351 
352 			AQ_HW_WAIT_FOR((aq_hw_read_reg(self, 0x200U)
353 					& 0x100) == 0, 10, 1000);
354 		}
355 	}
356 
357 	hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
358 
359 err_exit:
360 	return err;
361 }
362 
363 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
364 {
365 	int err = 0;
366 	const u32 dw_major_mask = 0xff000000U;
367 	const u32 dw_minor_mask = 0x00ffffffU;
368 
369 	err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0;
370 	if (err < 0)
371 		goto err_exit;
372 	err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
373 		-EOPNOTSUPP : 0;
374 err_exit:
375 	return err;
376 }
377 
378 static int hw_atl_utils_init_ucp(struct aq_hw_s *self)
379 {
380 	int err = 0;
381 
382 	if (!aq_hw_read_reg(self, 0x370U)) {
383 		unsigned int rnd = (uint32_t)rte_rand();
384 		unsigned int ucp_0x370 = 0U;
385 
386 		ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd);
387 		aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
388 	}
389 
390 	hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U);
391 
392 	/* check 10 times by 1ms */
393 	AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
394 		       aq_hw_read_reg(self, 0x360U)), 1000U, 10U);
395 	AQ_HW_WAIT_FOR(0U != (self->rpc_addr =
396 		       aq_hw_read_reg(self, 0x334U)), 1000U, 100U);
397 
398 	return err;
399 }
400 
401 #define HW_ATL_RPC_CONTROL_ADR 0x0338U
402 #define HW_ATL_RPC_STATE_ADR   0x033CU
403 
404 struct aq_hw_atl_utils_fw_rpc_tid_s {
405 	union {
406 		u32 val;
407 		struct {
408 			u16 tid;
409 			u16 len;
410 		};
411 	};
412 };
413 
414 #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
415 
416 int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
417 {
418 	int err = 0;
419 	struct aq_hw_atl_utils_fw_rpc_tid_s sw;
420 
421 	if (!IS_CHIP_FEATURE(MIPS)) {
422 		err = -1;
423 		goto err_exit;
424 	}
425 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
426 					    (u32 *)(void *)&self->rpc,
427 					    (rpc_size + sizeof(u32) -
428 					    sizeof(u8)) / sizeof(u32));
429 	if (err < 0)
430 		goto err_exit;
431 
432 	sw.tid = 0xFFFFU & (++self->rpc_tid);
433 	sw.len = (u16)rpc_size;
434 	aq_hw_write_reg(self, HW_ATL_RPC_CONTROL_ADR, sw.val);
435 
436 err_exit:
437 	return err;
438 }
439 
440 int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
441 				    struct hw_aq_atl_utils_fw_rpc **rpc)
442 {
443 	int err = 0;
444 	struct aq_hw_atl_utils_fw_rpc_tid_s sw;
445 	struct aq_hw_atl_utils_fw_rpc_tid_s fw;
446 
447 	do {
448 		sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR);
449 
450 		self->rpc_tid = sw.tid;
451 
452 		AQ_HW_WAIT_FOR(sw.tid ==
453 				(fw.val =
454 				aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR),
455 				fw.tid), 1000U, 100U);
456 		if (err < 0)
457 			goto err_exit;
458 
459 		if (fw.len == 0xFFFFU) {
460 			err = hw_atl_utils_fw_rpc_call(self, sw.len);
461 			if (err < 0)
462 				goto err_exit;
463 		}
464 	} while (sw.tid != fw.tid || 0xFFFFU == fw.len);
465 	if (err < 0)
466 		goto err_exit;
467 
468 	if (rpc) {
469 		if (fw.len) {
470 			err =
471 			hw_atl_utils_fw_downld_dwords(self,
472 						      self->rpc_addr,
473 						      (u32 *)(void *)
474 						      &self->rpc,
475 						      (fw.len + sizeof(u32) -
476 						      sizeof(u8)) /
477 						      sizeof(u32));
478 			if (err < 0)
479 				goto err_exit;
480 		}
481 
482 		*rpc = &self->rpc;
483 	}
484 
485 err_exit:
486 	return err;
487 }
488 
489 static int hw_atl_utils_mpi_create(struct aq_hw_s *self)
490 {
491 	int err = 0;
492 
493 	err = hw_atl_utils_init_ucp(self);
494 	if (err < 0)
495 		goto err_exit;
496 
497 	err = hw_atl_utils_fw_rpc_init(self);
498 	if (err < 0)
499 		goto err_exit;
500 
501 err_exit:
502 	return err;
503 }
504 
505 int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
506 			       struct hw_aq_atl_utils_mbox_header *pmbox)
507 {
508 	return hw_atl_utils_fw_downld_dwords(self,
509 				      self->mbox_addr,
510 				      (u32 *)(void *)pmbox,
511 				      sizeof(*pmbox) / sizeof(u32));
512 }
513 
514 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
515 				 struct hw_aq_atl_utils_mbox *pmbox)
516 {
517 	int err = 0;
518 
519 	err = hw_atl_utils_fw_downld_dwords(self,
520 					    self->mbox_addr,
521 					    (u32 *)(void *)pmbox,
522 					    sizeof(*pmbox) / sizeof(u32));
523 	if (err < 0)
524 		goto err_exit;
525 
526 	if (IS_CHIP_FEATURE(REVISION_A0)) {
527 		unsigned int mtu = 1514;
528 		pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
529 		pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
530 	} else {
531 		pmbox->stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
532 	}
533 
534 err_exit:;
535 }
536 
537 static
538 int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
539 {
540 	u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
541 
542 	val = val & ~HW_ATL_MPI_SPEED_MSK;
543 	val |= speed << HW_ATL_MPI_SPEED_SHIFT;
544 	aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
545 
546 	return 0;
547 }
548 
549 int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
550 				enum hal_atl_utils_fw_state_e state)
551 {
552 	int err = 0;
553 	u32 transaction_id = 0;
554 	struct hw_aq_atl_utils_mbox_header mbox;
555 	u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
556 
557 	if (state == MPI_RESET) {
558 		hw_atl_utils_mpi_read_mbox(self, &mbox);
559 
560 		transaction_id = mbox.transaction_id;
561 
562 		AQ_HW_WAIT_FOR(transaction_id !=
563 				(hw_atl_utils_mpi_read_mbox(self, &mbox),
564 				 mbox.transaction_id),
565 			       1000U, 100U);
566 		if (err < 0)
567 			goto err_exit;
568 	}
569 	/* On interface DEINIT we disable DW (raise bit)
570 	 * Otherwise enable DW (clear bit)
571 	 */
572 	if (state == MPI_DEINIT || state == MPI_POWER)
573 		val |= HW_ATL_MPI_DIRTY_WAKE_MSK;
574 	else
575 		val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK;
576 
577 	/* Set new state bits */
578 	val = val & ~HW_ATL_MPI_STATE_MSK;
579 	val |= state & HW_ATL_MPI_STATE_MSK;
580 
581 	aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
582 err_exit:
583 	return err;
584 }
585 
586 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
587 {
588 	u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
589 	u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
590 	struct aq_hw_link_status_s *link_status = &self->aq_link_status;
591 
592 	if (!link_speed_mask) {
593 		link_status->mbps = 0U;
594 	} else {
595 		switch (link_speed_mask) {
596 		case HAL_ATLANTIC_RATE_10G:
597 			link_status->mbps = 10000U;
598 			break;
599 
600 		case HAL_ATLANTIC_RATE_5G:
601 		case HAL_ATLANTIC_RATE_5GSR:
602 			link_status->mbps = 5000U;
603 			break;
604 
605 		case HAL_ATLANTIC_RATE_2GS:
606 			link_status->mbps = 2500U;
607 			break;
608 
609 		case HAL_ATLANTIC_RATE_1G:
610 			link_status->mbps = 1000U;
611 			break;
612 
613 		case HAL_ATLANTIC_RATE_100M:
614 			link_status->mbps = 100U;
615 			break;
616 
617 		default:
618 			return -EBUSY;
619 		}
620 	}
621 
622 	return 0;
623 }
624 
625 static int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
626 				   u8 *mac)
627 {
628 	int err = 0;
629 	u32 h = 0U;
630 	u32 l = 0U;
631 	u32 mac_addr[2];
632 
633 	if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
634 		unsigned int rnd = (uint32_t)rte_rand();
635 		unsigned int ucp_0x370 = 0;
636 
637 		//get_random_bytes(&rnd, sizeof(unsigned int));
638 
639 		ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
640 		aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
641 	}
642 
643 	err = hw_atl_utils_fw_downld_dwords(self,
644 					    aq_hw_read_reg(self, 0x00000374U) +
645 					    (40U * 4U),
646 					    mac_addr,
647 					    ARRAY_SIZE(mac_addr));
648 	if (err < 0) {
649 		mac_addr[0] = 0U;
650 		mac_addr[1] = 0U;
651 		err = 0;
652 	} else {
653 		mac_addr[0] = rte_constant_bswap32(mac_addr[0]);
654 		mac_addr[1] = rte_constant_bswap32(mac_addr[1]);
655 	}
656 
657 	ether_addr_copy((struct ether_addr *)mac_addr,
658 			(struct ether_addr *)mac);
659 
660 	if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
661 		/* chip revision */
662 		l = 0xE3000000U
663 			| (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG))
664 			| (0x00 << 16);
665 		h = 0x8001300EU;
666 
667 		mac[5] = (u8)(0xFFU & l);
668 		l >>= 8;
669 		mac[4] = (u8)(0xFFU & l);
670 		l >>= 8;
671 		mac[3] = (u8)(0xFFU & l);
672 		l >>= 8;
673 		mac[2] = (u8)(0xFFU & l);
674 		mac[1] = (u8)(0xFFU & h);
675 		h >>= 8;
676 		mac[0] = (u8)(0xFFU & h);
677 	}
678 
679 	return err;
680 }
681 
682 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
683 {
684 	unsigned int ret = 0U;
685 
686 	switch (mbps) {
687 	case 100U:
688 		ret = 5U;
689 		break;
690 
691 	case 1000U:
692 		ret = 4U;
693 		break;
694 
695 	case 2500U:
696 		ret = 3U;
697 		break;
698 
699 	case 5000U:
700 		ret = 1U;
701 		break;
702 
703 	case 10000U:
704 		ret = 0U;
705 		break;
706 
707 	default:
708 		break;
709 	}
710 	return ret;
711 }
712 
713 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
714 {
715 	u32 chip_features = 0U;
716 	u32 val = hw_atl_reg_glb_mif_id_get(self);
717 	u32 mif_rev = val & 0xFFU;
718 
719 	if ((0xFU & mif_rev) == 1U) {
720 		chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
721 			HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
722 			HAL_ATLANTIC_UTILS_CHIP_MIPS;
723 	} else if ((0xFU & mif_rev) == 2U) {
724 		chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
725 			HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
726 			HAL_ATLANTIC_UTILS_CHIP_MIPS |
727 			HAL_ATLANTIC_UTILS_CHIP_TPO2 |
728 			HAL_ATLANTIC_UTILS_CHIP_RPF2;
729 	} else if ((0xFU & mif_rev) == 0xAU) {
730 		chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 |
731 			HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
732 			HAL_ATLANTIC_UTILS_CHIP_MIPS |
733 			HAL_ATLANTIC_UTILS_CHIP_TPO2 |
734 			HAL_ATLANTIC_UTILS_CHIP_RPF2;
735 	}
736 
737 	*p = chip_features;
738 }
739 
740 static int hw_atl_fw1x_deinit(struct aq_hw_s *self)
741 {
742 	hw_atl_utils_mpi_set_speed(self, 0);
743 	hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
744 	return 0;
745 }
746 
747 int hw_atl_utils_update_stats(struct aq_hw_s *self)
748 {
749 	struct hw_aq_atl_utils_mbox mbox;
750 
751 	hw_atl_utils_mpi_read_stats(self, &mbox);
752 
753 #define AQ_SDELTA(_N_) (self->curr_stats._N_ += \
754 			mbox.stats._N_ - self->last_stats._N_)
755 
756 	if (1) {//self->aq_link_status.mbps) {
757 		AQ_SDELTA(uprc);
758 		AQ_SDELTA(mprc);
759 		AQ_SDELTA(bprc);
760 		AQ_SDELTA(erpt);
761 
762 		AQ_SDELTA(uptc);
763 		AQ_SDELTA(mptc);
764 		AQ_SDELTA(bptc);
765 		AQ_SDELTA(erpr);
766 		AQ_SDELTA(ubrc);
767 		AQ_SDELTA(ubtc);
768 		AQ_SDELTA(mbrc);
769 		AQ_SDELTA(mbtc);
770 		AQ_SDELTA(bbrc);
771 		AQ_SDELTA(bbtc);
772 		AQ_SDELTA(dpc);
773 	}
774 #undef AQ_SDELTA
775 	self->curr_stats.dma_pkt_rc =
776 	   hw_atl_stats_rx_dma_good_pkt_counterlsw_get(self) +
777 	   ((u64)hw_atl_stats_rx_dma_good_pkt_countermsw_get(self) << 32);
778 	self->curr_stats.dma_pkt_tc =
779 	   hw_atl_stats_tx_dma_good_pkt_counterlsw_get(self) +
780 	   ((u64)hw_atl_stats_tx_dma_good_pkt_countermsw_get(self) << 32);
781 	self->curr_stats.dma_oct_rc =
782 	   hw_atl_stats_rx_dma_good_octet_counterlsw_get(self) +
783 	   ((u64)hw_atl_stats_rx_dma_good_octet_countermsw_get(self) << 32);
784 	self->curr_stats.dma_oct_tc =
785 	   hw_atl_stats_tx_dma_good_octet_counterlsw_get(self) +
786 	   ((u64)hw_atl_stats_tx_dma_good_octet_countermsw_get(self) << 32);
787 
788 	self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
789 
790 	memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
791 
792 	return 0;
793 }
794 
795 struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self)
796 {
797 	return &self->curr_stats;
798 }
799 
800 static const u32 hw_atl_utils_hw_mac_regs[] = {
801 	0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
802 	0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
803 	0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
804 	0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
805 	0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
806 	0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
807 	0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
808 	0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
809 	0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
810 	0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
811 	0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
812 	0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
813 	0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
814 	0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
815 	0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
816 	0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
817 	0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
818 	0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
819 	0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
820 	0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
821 	0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
822 	0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
823 };
824 
825 unsigned int hw_atl_utils_hw_get_reg_length(void)
826 {
827 	return ARRAY_SIZE(hw_atl_utils_hw_mac_regs);
828 }
829 
830 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
831 			     u32 *regs_buff)
832 {
833 	unsigned int i = 0U;
834 	unsigned int mac_regs_count = hw_atl_utils_hw_get_reg_length();
835 
836 	for (i = 0; i < mac_regs_count; i++)
837 		regs_buff[i] = aq_hw_read_reg(self,
838 					      hw_atl_utils_hw_mac_regs[i]);
839 	return 0;
840 }
841 
842 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
843 {
844 	*fw_version = aq_hw_read_reg(self, 0x18U);
845 	return 0;
846 }
847 
848 static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac)
849 {
850 	struct hw_aq_atl_utils_fw_rpc *prpc = NULL;
851 	unsigned int rpc_size = 0U;
852 	int err = 0;
853 
854 	err = hw_atl_utils_fw_rpc_wait(self, &prpc);
855 	if (err < 0)
856 		goto err_exit;
857 
858 	memset(prpc, 0, sizeof(*prpc));
859 
860 	if (wol_enabled) {
861 		rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_wol);
862 
863 		prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD;
864 		prpc->msg_wol.priority = 0x10000000; /* normal priority */
865 		prpc->msg_wol.pattern_id = 1U;
866 		prpc->msg_wol.wol_packet_type = 2U; /* Magic Packet */
867 
868 		ether_addr_copy((struct ether_addr *)mac,
869 			(struct ether_addr *)&prpc->msg_wol.wol_pattern);
870 	} else {
871 		rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_del_id);
872 
873 		prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL;
874 		prpc->msg_wol.pattern_id = 1U;
875 	}
876 
877 	err = hw_atl_utils_fw_rpc_call(self, rpc_size);
878 	if (err < 0)
879 		goto err_exit;
880 err_exit:
881 	return err;
882 }
883 
884 static
885 int aq_fw1x_set_power(struct aq_hw_s *self,
886 		      unsigned int power_state __rte_unused,
887 		      u8 *mac)
888 {
889 	struct hw_aq_atl_utils_fw_rpc *prpc = NULL;
890 	unsigned int rpc_size = 0U;
891 	int err = 0;
892 	if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) {
893 		err = aq_fw1x_set_wol(self, 1, mac);
894 
895 		if (err < 0)
896 			goto err_exit;
897 
898 		rpc_size = sizeof(prpc->msg_id) +
899 				sizeof(prpc->msg_enable_wakeup);
900 
901 		err = hw_atl_utils_fw_rpc_wait(self, &prpc);
902 
903 		if (err < 0)
904 			goto err_exit;
905 
906 		memset(prpc, 0, rpc_size);
907 
908 		prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_ENABLE_WAKEUP;
909 		prpc->msg_enable_wakeup.pattern_mask = 0x00000002;
910 
911 		err = hw_atl_utils_fw_rpc_call(self, rpc_size);
912 		if (err < 0)
913 			goto err_exit;
914 	}
915 
916 	hw_atl_utils_mpi_set_speed(self, 0);
917 	hw_atl_utils_mpi_set_state(self, MPI_POWER);
918 err_exit:
919 	return err;
920 }
921 
922 
923 
924 const struct aq_fw_ops aq_fw_1x_ops = {
925 	.init = hw_atl_utils_mpi_create,
926 	.deinit = hw_atl_fw1x_deinit,
927 	.reset = NULL,
928 	.get_mac_permanent = hw_atl_utils_get_mac_permanent,
929 	.set_link_speed = hw_atl_utils_mpi_set_speed,
930 	.set_state = hw_atl_utils_mpi_set_state,
931 	.update_link_status = hw_atl_utils_mpi_get_link_status,
932 	.update_stats = hw_atl_utils_update_stats,
933 	.set_power = aq_fw1x_set_power,
934 	.get_temp = NULL,
935 	.get_cable_len = NULL,
936 	.set_eee_rate = NULL,
937 	.get_eee_rate = NULL,
938 	.set_flow_control = NULL,
939 	.led_control = NULL,
940 	.get_eeprom = NULL,
941 	.set_eeprom = NULL,
942 };
943