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