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