xref: /dpdk/drivers/net/atlantic/hw_atl/hw_atl_utils.c (revision a720e6740afcd6d21955d188c6e6a7136fcc7d6c)
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 			if (err) {
309 				err = -ETIMEDOUT;
310 				goto err_exit;
311 			}
312 
313 		*(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL);
314 		a += 4;
315 	}
316 
317 	hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
318 
319 err_exit:
320 	return err;
321 }
322 
323 int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
324 					 u32 cnt)
325 {
326 	int err = 0;
327 	bool is_locked;
328 
329 	is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
330 	if (!is_locked) {
331 		err = -ETIMEDOUT;
332 		goto err_exit;
333 	}
334 	if (IS_CHIP_FEATURE(REVISION_B1)) {
335 		u32 offset = 0;
336 
337 		for (; offset < cnt; ++offset) {
338 			aq_hw_write_reg(self, 0x328, p[offset]);
339 			aq_hw_write_reg(self, 0x32C,
340 				(0x80000000 | (0xFFFF & (offset * 4))));
341 			hw_atl_mcp_up_force_intr_set(self, 1);
342 			/* 1000 times by 10us = 10ms */
343 			AQ_HW_WAIT_FOR((aq_hw_read_reg(self,
344 					0x32C) & 0xF0000000) != 0x80000000,
345 					10, 1000);
346 		}
347 	} else {
348 		u32 offset = 0;
349 
350 		aq_hw_write_reg(self, 0x208, a);
351 
352 		for (; offset < cnt; ++offset) {
353 			aq_hw_write_reg(self, 0x20C, p[offset]);
354 			aq_hw_write_reg(self, 0x200, 0xC000);
355 
356 			AQ_HW_WAIT_FOR((aq_hw_read_reg(self, 0x200U)
357 					& 0x100) == 0, 10, 1000);
358 		}
359 	}
360 
361 	hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
362 
363 err_exit:
364 	return err;
365 }
366 
367 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
368 {
369 	int err = 0;
370 	const u32 dw_major_mask = 0xff000000U;
371 	const u32 dw_minor_mask = 0x00ffffffU;
372 
373 	err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0;
374 	if (err < 0)
375 		goto err_exit;
376 	err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
377 		-EOPNOTSUPP : 0;
378 err_exit:
379 	return err;
380 }
381 
382 static int hw_atl_utils_init_ucp(struct aq_hw_s *self)
383 {
384 	int err = 0;
385 
386 	if (!aq_hw_read_reg(self, 0x370U)) {
387 		unsigned int rnd = (uint32_t)rte_rand();
388 		unsigned int ucp_0x370 = 0U;
389 
390 		ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd);
391 		aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
392 	}
393 
394 	hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U);
395 
396 	/* check 10 times by 1ms */
397 	AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
398 		       aq_hw_read_reg(self, 0x360U)), 1000U, 10U);
399 	AQ_HW_WAIT_FOR(0U != (self->rpc_addr =
400 		       aq_hw_read_reg(self, 0x334U)), 1000U, 100U);
401 
402 	return err;
403 }
404 
405 #define HW_ATL_RPC_CONTROL_ADR 0x0338U
406 #define HW_ATL_RPC_STATE_ADR   0x033CU
407 
408 struct aq_hw_atl_utils_fw_rpc_tid_s {
409 	union {
410 		u32 val;
411 		struct {
412 			u16 tid;
413 			u16 len;
414 		};
415 	};
416 };
417 
418 #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
419 
420 int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
421 {
422 	int err = 0;
423 	struct aq_hw_atl_utils_fw_rpc_tid_s sw;
424 
425 	if (!IS_CHIP_FEATURE(MIPS)) {
426 		err = -1;
427 		goto err_exit;
428 	}
429 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
430 					    (u32 *)(void *)&self->rpc,
431 					    (rpc_size + sizeof(u32) -
432 					    sizeof(u8)) / sizeof(u32));
433 	if (err < 0)
434 		goto err_exit;
435 
436 	sw.tid = 0xFFFFU & (++self->rpc_tid);
437 	sw.len = (u16)rpc_size;
438 	aq_hw_write_reg(self, HW_ATL_RPC_CONTROL_ADR, sw.val);
439 
440 err_exit:
441 	return err;
442 }
443 
444 int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
445 				    struct hw_aq_atl_utils_fw_rpc **rpc)
446 {
447 	int err = 0;
448 	struct aq_hw_atl_utils_fw_rpc_tid_s sw;
449 	struct aq_hw_atl_utils_fw_rpc_tid_s fw;
450 
451 	do {
452 		sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR);
453 
454 		self->rpc_tid = sw.tid;
455 
456 		AQ_HW_WAIT_FOR(sw.tid ==
457 				(fw.val =
458 				aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR),
459 				fw.tid), 1000U, 100U);
460 		if (err < 0)
461 			goto err_exit;
462 
463 		if (fw.len == 0xFFFFU) {
464 			err = hw_atl_utils_fw_rpc_call(self, sw.len);
465 			if (err < 0)
466 				goto err_exit;
467 		}
468 	} while (sw.tid != fw.tid || 0xFFFFU == fw.len);
469 
470 	if (rpc) {
471 		if (fw.len) {
472 			err =
473 			hw_atl_utils_fw_downld_dwords(self,
474 						      self->rpc_addr,
475 						      (u32 *)(void *)
476 						      &self->rpc,
477 						      (fw.len + sizeof(u32) -
478 						      sizeof(u8)) /
479 						      sizeof(u32));
480 			if (err < 0)
481 				goto err_exit;
482 		}
483 
484 		*rpc = &self->rpc;
485 	}
486 
487 err_exit:
488 	return err;
489 }
490 
491 static int hw_atl_utils_mpi_create(struct aq_hw_s *self)
492 {
493 	int err = 0;
494 
495 	err = hw_atl_utils_init_ucp(self);
496 	if (err < 0)
497 		goto err_exit;
498 
499 	err = hw_atl_utils_fw_rpc_init(self);
500 	if (err < 0)
501 		goto err_exit;
502 
503 err_exit:
504 	return err;
505 }
506 
507 int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
508 			       struct hw_aq_atl_utils_mbox_header *pmbox)
509 {
510 	return hw_atl_utils_fw_downld_dwords(self,
511 				      self->mbox_addr,
512 				      (u32 *)(void *)pmbox,
513 				      sizeof(*pmbox) / sizeof(u32));
514 }
515 
516 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
517 				 struct hw_aq_atl_utils_mbox *pmbox)
518 {
519 	int err = 0;
520 
521 	err = hw_atl_utils_fw_downld_dwords(self,
522 					    self->mbox_addr,
523 					    (u32 *)(void *)pmbox,
524 					    sizeof(*pmbox) / sizeof(u32));
525 	if (err < 0)
526 		goto err_exit;
527 
528 	if (IS_CHIP_FEATURE(REVISION_A0)) {
529 		unsigned int mtu = 1514;
530 		pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
531 		pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
532 	} else {
533 		pmbox->stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
534 	}
535 
536 err_exit:;
537 }
538 
539 static
540 int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
541 {
542 	u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
543 
544 	val = val & ~HW_ATL_MPI_SPEED_MSK;
545 	val |= speed << HW_ATL_MPI_SPEED_SHIFT;
546 	aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
547 
548 	return 0;
549 }
550 
551 int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
552 				enum hal_atl_utils_fw_state_e state)
553 {
554 	int err = 0;
555 	u32 transaction_id = 0;
556 	struct hw_aq_atl_utils_mbox_header mbox;
557 	u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
558 
559 	if (state == MPI_RESET) {
560 		hw_atl_utils_mpi_read_mbox(self, &mbox);
561 
562 		transaction_id = mbox.transaction_id;
563 
564 		AQ_HW_WAIT_FOR(transaction_id !=
565 				(hw_atl_utils_mpi_read_mbox(self, &mbox),
566 				 mbox.transaction_id),
567 			       1000U, 100U);
568 		if (err < 0)
569 			goto err_exit;
570 	}
571 	/* On interface DEINIT we disable DW (raise bit)
572 	 * Otherwise enable DW (clear bit)
573 	 */
574 	if (state == MPI_DEINIT || state == MPI_POWER)
575 		val |= HW_ATL_MPI_DIRTY_WAKE_MSK;
576 	else
577 		val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK;
578 
579 	/* Set new state bits */
580 	val = val & ~HW_ATL_MPI_STATE_MSK;
581 	val |= state & HW_ATL_MPI_STATE_MSK;
582 
583 	aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
584 err_exit:
585 	return err;
586 }
587 
588 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
589 {
590 	u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
591 	u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
592 	struct aq_hw_link_status_s *link_status = &self->aq_link_status;
593 
594 	if (!link_speed_mask) {
595 		link_status->mbps = 0U;
596 	} else {
597 		switch (link_speed_mask) {
598 		case HAL_ATLANTIC_RATE_10G:
599 			link_status->mbps = 10000U;
600 			break;
601 
602 		case HAL_ATLANTIC_RATE_5G:
603 		case HAL_ATLANTIC_RATE_5GSR:
604 			link_status->mbps = 5000U;
605 			break;
606 
607 		case HAL_ATLANTIC_RATE_2GS:
608 			link_status->mbps = 2500U;
609 			break;
610 
611 		case HAL_ATLANTIC_RATE_1G:
612 			link_status->mbps = 1000U;
613 			break;
614 
615 		case HAL_ATLANTIC_RATE_100M:
616 			link_status->mbps = 100U;
617 			break;
618 
619 		default:
620 			return -EBUSY;
621 		}
622 	}
623 
624 	return 0;
625 }
626 
627 static int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
628 				   u8 *mac)
629 {
630 	int err = 0;
631 	u32 h = 0U;
632 	u32 l = 0U;
633 	u32 mac_addr[2];
634 
635 	if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
636 		unsigned int rnd = (uint32_t)rte_rand();
637 		unsigned int ucp_0x370 = 0;
638 
639 		//get_random_bytes(&rnd, sizeof(unsigned int));
640 
641 		ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
642 		aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
643 	}
644 
645 	err = hw_atl_utils_fw_downld_dwords(self,
646 					    aq_hw_read_reg(self, 0x00000374U) +
647 					    (40U * 4U),
648 					    mac_addr,
649 					    ARRAY_SIZE(mac_addr));
650 	if (err < 0) {
651 		mac_addr[0] = 0U;
652 		mac_addr[1] = 0U;
653 		err = 0;
654 	} else {
655 		mac_addr[0] = rte_constant_bswap32(mac_addr[0]);
656 		mac_addr[1] = rte_constant_bswap32(mac_addr[1]);
657 	}
658 
659 	ether_addr_copy((struct ether_addr *)mac_addr,
660 			(struct ether_addr *)mac);
661 
662 	if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
663 		/* chip revision */
664 		l = 0xE3000000U
665 			| (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG))
666 			| (0x00 << 16);
667 		h = 0x8001300EU;
668 
669 		mac[5] = (u8)(0xFFU & l);
670 		l >>= 8;
671 		mac[4] = (u8)(0xFFU & l);
672 		l >>= 8;
673 		mac[3] = (u8)(0xFFU & l);
674 		l >>= 8;
675 		mac[2] = (u8)(0xFFU & l);
676 		mac[1] = (u8)(0xFFU & h);
677 		h >>= 8;
678 		mac[0] = (u8)(0xFFU & h);
679 	}
680 
681 	return err;
682 }
683 
684 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
685 {
686 	unsigned int ret = 0U;
687 
688 	switch (mbps) {
689 	case 100U:
690 		ret = 5U;
691 		break;
692 
693 	case 1000U:
694 		ret = 4U;
695 		break;
696 
697 	case 2500U:
698 		ret = 3U;
699 		break;
700 
701 	case 5000U:
702 		ret = 1U;
703 		break;
704 
705 	case 10000U:
706 		ret = 0U;
707 		break;
708 
709 	default:
710 		break;
711 	}
712 	return ret;
713 }
714 
715 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
716 {
717 	u32 chip_features = 0U;
718 	u32 val = hw_atl_reg_glb_mif_id_get(self);
719 	u32 mif_rev = val & 0xFFU;
720 
721 	if ((0xFU & mif_rev) == 1U) {
722 		chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
723 			HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
724 			HAL_ATLANTIC_UTILS_CHIP_MIPS;
725 	} else if ((0xFU & mif_rev) == 2U) {
726 		chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
727 			HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
728 			HAL_ATLANTIC_UTILS_CHIP_MIPS |
729 			HAL_ATLANTIC_UTILS_CHIP_TPO2 |
730 			HAL_ATLANTIC_UTILS_CHIP_RPF2;
731 	} else if ((0xFU & mif_rev) == 0xAU) {
732 		chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 |
733 			HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
734 			HAL_ATLANTIC_UTILS_CHIP_MIPS |
735 			HAL_ATLANTIC_UTILS_CHIP_TPO2 |
736 			HAL_ATLANTIC_UTILS_CHIP_RPF2;
737 	}
738 
739 	*p = chip_features;
740 }
741 
742 static int hw_atl_fw1x_deinit(struct aq_hw_s *self)
743 {
744 	hw_atl_utils_mpi_set_speed(self, 0);
745 	hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
746 	return 0;
747 }
748 
749 int hw_atl_utils_update_stats(struct aq_hw_s *self)
750 {
751 	struct hw_aq_atl_utils_mbox mbox;
752 
753 	hw_atl_utils_mpi_read_stats(self, &mbox);
754 
755 #define AQ_SDELTA(_N_) (self->curr_stats._N_ += \
756 			mbox.stats._N_ - self->last_stats._N_)
757 
758 	if (1) {//self->aq_link_status.mbps) {
759 		AQ_SDELTA(uprc);
760 		AQ_SDELTA(mprc);
761 		AQ_SDELTA(bprc);
762 		AQ_SDELTA(erpt);
763 
764 		AQ_SDELTA(uptc);
765 		AQ_SDELTA(mptc);
766 		AQ_SDELTA(bptc);
767 		AQ_SDELTA(erpr);
768 		AQ_SDELTA(ubrc);
769 		AQ_SDELTA(ubtc);
770 		AQ_SDELTA(mbrc);
771 		AQ_SDELTA(mbtc);
772 		AQ_SDELTA(bbrc);
773 		AQ_SDELTA(bbtc);
774 		AQ_SDELTA(dpc);
775 	}
776 #undef AQ_SDELTA
777 	self->curr_stats.dma_pkt_rc =
778 	   hw_atl_stats_rx_dma_good_pkt_counterlsw_get(self) +
779 	   ((u64)hw_atl_stats_rx_dma_good_pkt_countermsw_get(self) << 32);
780 	self->curr_stats.dma_pkt_tc =
781 	   hw_atl_stats_tx_dma_good_pkt_counterlsw_get(self) +
782 	   ((u64)hw_atl_stats_tx_dma_good_pkt_countermsw_get(self) << 32);
783 	self->curr_stats.dma_oct_rc =
784 	   hw_atl_stats_rx_dma_good_octet_counterlsw_get(self) +
785 	   ((u64)hw_atl_stats_rx_dma_good_octet_countermsw_get(self) << 32);
786 	self->curr_stats.dma_oct_tc =
787 	   hw_atl_stats_tx_dma_good_octet_counterlsw_get(self) +
788 	   ((u64)hw_atl_stats_tx_dma_good_octet_countermsw_get(self) << 32);
789 
790 	self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
791 
792 	memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
793 
794 	return 0;
795 }
796 
797 struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self)
798 {
799 	return &self->curr_stats;
800 }
801 
802 static const u32 hw_atl_utils_hw_mac_regs[] = {
803 	0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
804 	0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
805 	0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
806 	0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
807 	0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
808 	0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
809 	0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
810 	0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
811 	0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
812 	0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
813 	0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
814 	0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
815 	0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
816 	0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
817 	0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
818 	0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
819 	0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
820 	0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
821 	0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
822 	0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
823 	0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
824 	0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
825 };
826 
827 unsigned int hw_atl_utils_hw_get_reg_length(void)
828 {
829 	return ARRAY_SIZE(hw_atl_utils_hw_mac_regs);
830 }
831 
832 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
833 			     u32 *regs_buff)
834 {
835 	unsigned int i = 0U;
836 	unsigned int mac_regs_count = hw_atl_utils_hw_get_reg_length();
837 
838 	for (i = 0; i < mac_regs_count; i++)
839 		regs_buff[i] = aq_hw_read_reg(self,
840 					      hw_atl_utils_hw_mac_regs[i]);
841 	return 0;
842 }
843 
844 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
845 {
846 	*fw_version = aq_hw_read_reg(self, 0x18U);
847 	return 0;
848 }
849 
850 static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac)
851 {
852 	struct hw_aq_atl_utils_fw_rpc *prpc = NULL;
853 	unsigned int rpc_size = 0U;
854 	int err = 0;
855 
856 	err = hw_atl_utils_fw_rpc_wait(self, &prpc);
857 	if (err < 0)
858 		goto err_exit;
859 
860 	memset(prpc, 0, sizeof(*prpc));
861 
862 	if (wol_enabled) {
863 		rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_wol);
864 
865 		prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD;
866 		prpc->msg_wol.priority = 0x10000000; /* normal priority */
867 		prpc->msg_wol.pattern_id = 1U;
868 		prpc->msg_wol.wol_packet_type = 2U; /* Magic Packet */
869 
870 		ether_addr_copy((struct ether_addr *)mac,
871 			(struct ether_addr *)&prpc->msg_wol.wol_pattern);
872 	} else {
873 		rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_del_id);
874 
875 		prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL;
876 		prpc->msg_wol.pattern_id = 1U;
877 	}
878 
879 	err = hw_atl_utils_fw_rpc_call(self, rpc_size);
880 
881 err_exit:
882 	return err;
883 }
884 
885 static
886 int aq_fw1x_set_power(struct aq_hw_s *self,
887 		      unsigned int power_state __rte_unused,
888 		      u8 *mac)
889 {
890 	struct hw_aq_atl_utils_fw_rpc *prpc = NULL;
891 	unsigned int rpc_size = 0U;
892 	int err = 0;
893 	if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) {
894 		err = aq_fw1x_set_wol(self, 1, mac);
895 
896 		if (err < 0)
897 			goto err_exit;
898 
899 		rpc_size = sizeof(prpc->msg_id) +
900 				sizeof(prpc->msg_enable_wakeup);
901 
902 		err = hw_atl_utils_fw_rpc_wait(self, &prpc);
903 
904 		if (err < 0)
905 			goto err_exit;
906 
907 		memset(prpc, 0, rpc_size);
908 
909 		prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_ENABLE_WAKEUP;
910 		prpc->msg_enable_wakeup.pattern_mask = 0x00000002;
911 
912 		err = hw_atl_utils_fw_rpc_call(self, rpc_size);
913 		if (err < 0)
914 			goto err_exit;
915 	}
916 
917 	hw_atl_utils_mpi_set_speed(self, 0);
918 	hw_atl_utils_mpi_set_state(self, MPI_POWER);
919 err_exit:
920 	return err;
921 }
922 
923 
924 
925 const struct aq_fw_ops aq_fw_1x_ops = {
926 	.init = hw_atl_utils_mpi_create,
927 	.deinit = hw_atl_fw1x_deinit,
928 	.reset = NULL,
929 	.get_mac_permanent = hw_atl_utils_get_mac_permanent,
930 	.set_link_speed = hw_atl_utils_mpi_set_speed,
931 	.set_state = hw_atl_utils_mpi_set_state,
932 	.update_link_status = hw_atl_utils_mpi_get_link_status,
933 	.update_stats = hw_atl_utils_update_stats,
934 	.set_power = aq_fw1x_set_power,
935 	.get_temp = NULL,
936 	.get_cable_len = NULL,
937 	.set_eee_rate = NULL,
938 	.get_eee_rate = NULL,
939 	.set_flow_control = NULL,
940 	.led_control = NULL,
941 	.get_eeprom = NULL,
942 	.set_eeprom = NULL,
943 };
944