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