175a6faf6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
298c4c201SDavid VomLehn /*
398c4c201SDavid VomLehn  * aQuantia Corporation Network Driver
4593f7b43SDmitry Bezrukov  * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
598c4c201SDavid VomLehn  */
698c4c201SDavid VomLehn 
798c4c201SDavid VomLehn /* File hw_atl_utils.c: Definition of common functions for Atlantic hardware
898c4c201SDavid VomLehn  * abstraction layer.
998c4c201SDavid VomLehn  */
1098c4c201SDavid VomLehn 
111a713f87SIgor Russkikh #include "../aq_nic.h"
1298c4c201SDavid VomLehn #include "../aq_hw_utils.h"
1398c4c201SDavid VomLehn #include "hw_atl_utils.h"
1498c4c201SDavid VomLehn #include "hw_atl_llh.h"
150c58c35fSIgor Russkikh #include "hw_atl_llh_internal.h"
1698c4c201SDavid VomLehn 
1798c4c201SDavid VomLehn #include <linux/random.h>
1898c4c201SDavid VomLehn 
1998c4c201SDavid VomLehn #define HW_ATL_UCP_0X370_REG    0x0370U
2098c4c201SDavid VomLehn 
2147203b34SIgor Russkikh #define HW_ATL_MIF_CMD          0x0200U
2247203b34SIgor Russkikh #define HW_ATL_MIF_ADDR         0x0208U
2347203b34SIgor Russkikh #define HW_ATL_MIF_VAL          0x020CU
2447203b34SIgor Russkikh 
256a7f2277SNikita Danilov #define HW_ATL_RPC_CONTROL_ADR  0x0338U
266a7f2277SNikita Danilov #define HW_ATL_RPC_STATE_ADR    0x033CU
276a7f2277SNikita Danilov 
280c58c35fSIgor Russkikh #define HW_ATL_MPI_FW_VERSION	0x18
2998c4c201SDavid VomLehn #define HW_ATL_MPI_CONTROL_ADR  0x0368U
3098c4c201SDavid VomLehn #define HW_ATL_MPI_STATE_ADR    0x036CU
3198c4c201SDavid VomLehn 
3298c4c201SDavid VomLehn #define HW_ATL_MPI_STATE_MSK      0x00FFU
3398c4c201SDavid VomLehn #define HW_ATL_MPI_STATE_SHIFT    0U
3444e00dd8SIgor Russkikh #define HW_ATL_MPI_SPEED_MSK      0x00FF0000U
3598c4c201SDavid VomLehn #define HW_ATL_MPI_SPEED_SHIFT    16U
3644e00dd8SIgor Russkikh #define HW_ATL_MPI_DIRTY_WAKE_MSK 0x02000000U
3798c4c201SDavid VomLehn 
38c8c82eb3SIgor Russkikh #define HW_ATL_MPI_DAISY_CHAIN_STATUS	0x704
39c8c82eb3SIgor Russkikh #define HW_ATL_MPI_BOOT_EXIT_CODE	0x388
40c8c82eb3SIgor Russkikh 
41c8c82eb3SIgor Russkikh #define HW_ATL_MAC_PHY_CONTROL	0x4000
42c8c82eb3SIgor Russkikh #define HW_ATL_MAC_PHY_MPI_RESET_BIT 0x1D
43c8c82eb3SIgor Russkikh 
440c58c35fSIgor Russkikh #define HW_ATL_FW_VER_1X 0x01050006U
45a57d3929SIgor Russkikh #define HW_ATL_FW_VER_2X 0x02000000U
46a57d3929SIgor Russkikh #define HW_ATL_FW_VER_3X 0x03000000U
470c58c35fSIgor Russkikh 
48c8c82eb3SIgor Russkikh #define FORCE_FLASHLESS 0
49c8c82eb3SIgor Russkikh 
50dc12f75aSNikita Danilov enum mcp_area {
51dc12f75aSNikita Danilov 	MCP_AREA_CONFIG = 0x80000000,
52dc12f75aSNikita Danilov 	MCP_AREA_SETTINGS = 0x20000000,
53dc12f75aSNikita Danilov };
54dc12f75aSNikita Danilov 
550c58c35fSIgor Russkikh static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
56e9157848SNikita Danilov 
57cce96d18SIgor Russkikh static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
58cce96d18SIgor Russkikh 				      enum hal_atl_utils_fw_state_e state);
590c58c35fSIgor Russkikh 
606a7f2277SNikita Danilov static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self);
616a7f2277SNikita Danilov static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self);
626a7f2277SNikita Danilov static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self);
636a7f2277SNikita Danilov static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self);
646a7f2277SNikita Danilov static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self);
656a7f2277SNikita Danilov 
660c58c35fSIgor Russkikh int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
670c58c35fSIgor Russkikh {
680c58c35fSIgor Russkikh 	int err = 0;
690c58c35fSIgor Russkikh 
70c8c82eb3SIgor Russkikh 	err = hw_atl_utils_soft_reset(self);
71c8c82eb3SIgor Russkikh 	if (err)
72c8c82eb3SIgor Russkikh 		return err;
73c8c82eb3SIgor Russkikh 
740c58c35fSIgor Russkikh 	hw_atl_utils_hw_chip_features_init(self,
750c58c35fSIgor Russkikh 					   &self->chip_features);
760c58c35fSIgor Russkikh 
770c58c35fSIgor Russkikh 	hw_atl_utils_get_fw_version(self, &self->fw_ver_actual);
780c58c35fSIgor Russkikh 
79c8c82eb3SIgor Russkikh 	if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
80c8c82eb3SIgor Russkikh 				   self->fw_ver_actual) == 0) {
810c58c35fSIgor Russkikh 		*fw_ops = &aq_fw_1x_ops;
82c8c82eb3SIgor Russkikh 	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X,
83c8c82eb3SIgor Russkikh 					  self->fw_ver_actual) == 0) {
84a57d3929SIgor Russkikh 		*fw_ops = &aq_fw_2x_ops;
85c8c82eb3SIgor Russkikh 	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X,
86c8c82eb3SIgor Russkikh 					  self->fw_ver_actual) == 0) {
87a57d3929SIgor Russkikh 		*fw_ops = &aq_fw_2x_ops;
88c8c82eb3SIgor Russkikh 	} else {
890c58c35fSIgor Russkikh 		aq_pr_err("Bad FW version detected: %x\n",
900c58c35fSIgor Russkikh 			  self->fw_ver_actual);
910c58c35fSIgor Russkikh 		return -EOPNOTSUPP;
920c58c35fSIgor Russkikh 	}
930c58c35fSIgor Russkikh 	self->aq_fw_ops = *fw_ops;
940c58c35fSIgor Russkikh 	err = self->aq_fw_ops->init(self);
957b0c342fSNikita Danilov 
960c58c35fSIgor Russkikh 	return err;
970c58c35fSIgor Russkikh }
980c58c35fSIgor Russkikh 
99c8c82eb3SIgor Russkikh static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self)
100c8c82eb3SIgor Russkikh {
1011bf9a752SIgor Russkikh 	u32 gsr, val;
102c8c82eb3SIgor Russkikh 	int k = 0;
103c8c82eb3SIgor Russkikh 
104c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, 0x404, 0x40e1);
105c8c82eb3SIgor Russkikh 	AQ_HW_SLEEP(50);
106c8c82eb3SIgor Russkikh 
107c8c82eb3SIgor Russkikh 	/* Cleanup SPI */
1081bf9a752SIgor Russkikh 	val = aq_hw_read_reg(self, 0x53C);
1091bf9a752SIgor Russkikh 	aq_hw_write_reg(self, 0x53C, val | 0x10);
110c8c82eb3SIgor Russkikh 
111c8c82eb3SIgor Russkikh 	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
112c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
113c8c82eb3SIgor Russkikh 
114c8c82eb3SIgor Russkikh 	/* Kickstart MAC */
115c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, 0x404, 0x80e0);
116c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, 0x32a8, 0x0);
117c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, 0x520, 0x1);
1181bf9a752SIgor Russkikh 
1191bf9a752SIgor Russkikh 	/* Reset SPI again because of possible interrupted SPI burst */
1201bf9a752SIgor Russkikh 	val = aq_hw_read_reg(self, 0x53C);
1211bf9a752SIgor Russkikh 	aq_hw_write_reg(self, 0x53C, val | 0x10);
122c8c82eb3SIgor Russkikh 	AQ_HW_SLEEP(10);
1231bf9a752SIgor Russkikh 	/* Clear SPI reset state */
1241bf9a752SIgor Russkikh 	aq_hw_write_reg(self, 0x53C, val & ~0x10);
1251bf9a752SIgor Russkikh 
126c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, 0x404, 0x180e0);
127c8c82eb3SIgor Russkikh 
128c8c82eb3SIgor Russkikh 	for (k = 0; k < 1000; k++) {
129c8c82eb3SIgor Russkikh 		u32 flb_status = aq_hw_read_reg(self,
130c8c82eb3SIgor Russkikh 						HW_ATL_MPI_DAISY_CHAIN_STATUS);
131c8c82eb3SIgor Russkikh 
132c8c82eb3SIgor Russkikh 		flb_status = flb_status & 0x10;
133c8c82eb3SIgor Russkikh 		if (flb_status)
134c8c82eb3SIgor Russkikh 			break;
135c8c82eb3SIgor Russkikh 		AQ_HW_SLEEP(10);
136c8c82eb3SIgor Russkikh 	}
137c8c82eb3SIgor Russkikh 	if (k == 1000) {
138c8c82eb3SIgor Russkikh 		aq_pr_err("MAC kickstart failed\n");
139c8c82eb3SIgor Russkikh 		return -EIO;
140c8c82eb3SIgor Russkikh 	}
141c8c82eb3SIgor Russkikh 
142c8c82eb3SIgor Russkikh 	/* FW reset */
143c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, 0x404, 0x80e0);
144c8c82eb3SIgor Russkikh 	AQ_HW_SLEEP(50);
145c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, 0x3a0, 0x1);
146c8c82eb3SIgor Russkikh 
147c8c82eb3SIgor Russkikh 	/* Kickstart PHY - skipped */
148c8c82eb3SIgor Russkikh 
149c8c82eb3SIgor Russkikh 	/* Global software reset*/
150c8c82eb3SIgor Russkikh 	hw_atl_rx_rx_reg_res_dis_set(self, 0U);
151c8c82eb3SIgor Russkikh 	hw_atl_tx_tx_reg_res_dis_set(self, 0U);
152c8c82eb3SIgor Russkikh 	aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
153c8c82eb3SIgor Russkikh 			    BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
154c8c82eb3SIgor Russkikh 			    HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
155c8c82eb3SIgor Russkikh 	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
156c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
157c8c82eb3SIgor Russkikh 
158c8c82eb3SIgor Russkikh 	for (k = 0; k < 1000; k++) {
159c8c82eb3SIgor Russkikh 		u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
160c8c82eb3SIgor Russkikh 
161c8c82eb3SIgor Russkikh 		if (fw_state)
162c8c82eb3SIgor Russkikh 			break;
163c8c82eb3SIgor Russkikh 		AQ_HW_SLEEP(10);
164c8c82eb3SIgor Russkikh 	}
165c8c82eb3SIgor Russkikh 	if (k == 1000) {
166c8c82eb3SIgor Russkikh 		aq_pr_err("FW kickstart failed\n");
167c8c82eb3SIgor Russkikh 		return -EIO;
168c8c82eb3SIgor Russkikh 	}
169d0f0fb25SIgor Russkikh 	/* Old FW requires fixed delay after init */
170d0f0fb25SIgor Russkikh 	AQ_HW_SLEEP(15);
171c8c82eb3SIgor Russkikh 
172c8c82eb3SIgor Russkikh 	return 0;
173c8c82eb3SIgor Russkikh }
174c8c82eb3SIgor Russkikh 
175c8c82eb3SIgor Russkikh static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self)
176c8c82eb3SIgor Russkikh {
1771bf9a752SIgor Russkikh 	u32 gsr, val, rbl_status;
178c8c82eb3SIgor Russkikh 	int k;
179c8c82eb3SIgor Russkikh 
180c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, 0x404, 0x40e1);
181c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, 0x3a0, 0x1);
182c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, 0x32a8, 0x0);
183c8c82eb3SIgor Russkikh 
184c8c82eb3SIgor Russkikh 	/* Alter RBL status */
185c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, 0x388, 0xDEAD);
186c8c82eb3SIgor Russkikh 
1871bf9a752SIgor Russkikh 	/* Cleanup SPI */
1881bf9a752SIgor Russkikh 	val = aq_hw_read_reg(self, 0x53C);
1891bf9a752SIgor Russkikh 	aq_hw_write_reg(self, 0x53C, val | 0x10);
1901bf9a752SIgor Russkikh 
191c8c82eb3SIgor Russkikh 	/* Global software reset*/
192c8c82eb3SIgor Russkikh 	hw_atl_rx_rx_reg_res_dis_set(self, 0U);
193c8c82eb3SIgor Russkikh 	hw_atl_tx_tx_reg_res_dis_set(self, 0U);
194c8c82eb3SIgor Russkikh 	aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
195c8c82eb3SIgor Russkikh 			    BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
196c8c82eb3SIgor Russkikh 			    HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
197c8c82eb3SIgor Russkikh 	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
198c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR,
199c8c82eb3SIgor Russkikh 			(gsr & 0xFFFFBFFF) | 0x8000);
200c8c82eb3SIgor Russkikh 
201c8c82eb3SIgor Russkikh 	if (FORCE_FLASHLESS)
202c8c82eb3SIgor Russkikh 		aq_hw_write_reg(self, 0x534, 0x0);
203c8c82eb3SIgor Russkikh 
204c8c82eb3SIgor Russkikh 	aq_hw_write_reg(self, 0x404, 0x40e0);
205c8c82eb3SIgor Russkikh 
206c8c82eb3SIgor Russkikh 	/* Wait for RBL boot */
207c8c82eb3SIgor Russkikh 	for (k = 0; k < 1000; k++) {
208c8c82eb3SIgor Russkikh 		rbl_status = aq_hw_read_reg(self, 0x388) & 0xFFFF;
209c8c82eb3SIgor Russkikh 		if (rbl_status && rbl_status != 0xDEAD)
210c8c82eb3SIgor Russkikh 			break;
211c8c82eb3SIgor Russkikh 		AQ_HW_SLEEP(10);
212c8c82eb3SIgor Russkikh 	}
213c8c82eb3SIgor Russkikh 	if (!rbl_status || rbl_status == 0xDEAD) {
214c8c82eb3SIgor Russkikh 		aq_pr_err("RBL Restart failed");
215c8c82eb3SIgor Russkikh 		return -EIO;
216c8c82eb3SIgor Russkikh 	}
217c8c82eb3SIgor Russkikh 
218c8c82eb3SIgor Russkikh 	/* Restore NVR */
219c8c82eb3SIgor Russkikh 	if (FORCE_FLASHLESS)
220c8c82eb3SIgor Russkikh 		aq_hw_write_reg(self, 0x534, 0xA0);
221c8c82eb3SIgor Russkikh 
222c8c82eb3SIgor Russkikh 	if (rbl_status == 0xF1A7) {
223c8c82eb3SIgor Russkikh 		aq_pr_err("No FW detected. Dynamic FW load not implemented\n");
224c8c82eb3SIgor Russkikh 		return -ENOTSUPP;
225c8c82eb3SIgor Russkikh 	}
226c8c82eb3SIgor Russkikh 
227c8c82eb3SIgor Russkikh 	for (k = 0; k < 1000; k++) {
228c8c82eb3SIgor Russkikh 		u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
229c8c82eb3SIgor Russkikh 
230c8c82eb3SIgor Russkikh 		if (fw_state)
231c8c82eb3SIgor Russkikh 			break;
232c8c82eb3SIgor Russkikh 		AQ_HW_SLEEP(10);
233c8c82eb3SIgor Russkikh 	}
234c8c82eb3SIgor Russkikh 	if (k == 1000) {
235c8c82eb3SIgor Russkikh 		aq_pr_err("FW kickstart failed\n");
236c8c82eb3SIgor Russkikh 		return -EIO;
237c8c82eb3SIgor Russkikh 	}
238d0f0fb25SIgor Russkikh 	/* Old FW requires fixed delay after init */
239d0f0fb25SIgor Russkikh 	AQ_HW_SLEEP(15);
240c8c82eb3SIgor Russkikh 
241c8c82eb3SIgor Russkikh 	return 0;
242c8c82eb3SIgor Russkikh }
243c8c82eb3SIgor Russkikh 
244c8c82eb3SIgor Russkikh int hw_atl_utils_soft_reset(struct aq_hw_s *self)
245c8c82eb3SIgor Russkikh {
246c8c82eb3SIgor Russkikh 	u32 boot_exit_code = 0;
2476a7f2277SNikita Danilov 	u32 val;
2487b0c342fSNikita Danilov 	int k;
249c8c82eb3SIgor Russkikh 
250c8c82eb3SIgor Russkikh 	for (k = 0; k < 1000; ++k) {
251c8c82eb3SIgor Russkikh 		u32 flb_status = aq_hw_read_reg(self,
252c8c82eb3SIgor Russkikh 						HW_ATL_MPI_DAISY_CHAIN_STATUS);
253c8c82eb3SIgor Russkikh 		boot_exit_code = aq_hw_read_reg(self,
254c8c82eb3SIgor Russkikh 						HW_ATL_MPI_BOOT_EXIT_CODE);
255c8c82eb3SIgor Russkikh 		if (flb_status != 0x06000000 || boot_exit_code != 0)
256c8c82eb3SIgor Russkikh 			break;
257c8c82eb3SIgor Russkikh 	}
258c8c82eb3SIgor Russkikh 
259c8c82eb3SIgor Russkikh 	if (k == 1000) {
260c8c82eb3SIgor Russkikh 		aq_pr_err("Neither RBL nor FLB firmware started\n");
261c8c82eb3SIgor Russkikh 		return -EOPNOTSUPP;
262c8c82eb3SIgor Russkikh 	}
263c8c82eb3SIgor Russkikh 
264c8c82eb3SIgor Russkikh 	self->rbl_enabled = (boot_exit_code != 0);
265c8c82eb3SIgor Russkikh 
266cce96d18SIgor Russkikh 	/* FW 1.x may bootup in an invalid POWER state (WOL feature).
267cce96d18SIgor Russkikh 	 * We should work around this by forcing its state back to DEINIT
268cce96d18SIgor Russkikh 	 */
269cce96d18SIgor Russkikh 	if (!hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
270cce96d18SIgor Russkikh 				    aq_hw_read_reg(self,
271cce96d18SIgor Russkikh 						   HW_ATL_MPI_FW_VERSION))) {
272cce96d18SIgor Russkikh 		int err = 0;
273cce96d18SIgor Russkikh 
274cce96d18SIgor Russkikh 		hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
2756a7f2277SNikita Danilov 		err = readx_poll_timeout_atomic(hw_atl_utils_mpi_get_state,
2766a7f2277SNikita Danilov 						self, val,
2776a7f2277SNikita Danilov 						(val & HW_ATL_MPI_STATE_MSK) ==
2786a7f2277SNikita Danilov 						 MPI_DEINIT,
2796a7f2277SNikita Danilov 						10, 10000U);
2804e3c7c00SYueHaibing 		if (err)
2814e3c7c00SYueHaibing 			return err;
282cce96d18SIgor Russkikh 	}
283cce96d18SIgor Russkikh 
284c8c82eb3SIgor Russkikh 	if (self->rbl_enabled)
285c8c82eb3SIgor Russkikh 		return hw_atl_utils_soft_reset_rbl(self);
286c8c82eb3SIgor Russkikh 	else
287c8c82eb3SIgor Russkikh 		return hw_atl_utils_soft_reset_flb(self);
288c8c82eb3SIgor Russkikh }
289c8c82eb3SIgor Russkikh 
290a57d3929SIgor Russkikh int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
29198c4c201SDavid VomLehn 				  u32 *p, u32 cnt)
29298c4c201SDavid VomLehn {
29398c4c201SDavid VomLehn 	int err = 0;
2946a7f2277SNikita Danilov 	u32 val;
29598c4c201SDavid VomLehn 
2966a7f2277SNikita Danilov 	err = readx_poll_timeout_atomic(hw_atl_sem_ram_get,
2976a7f2277SNikita Danilov 					self, val, val == 1U,
29898c4c201SDavid VomLehn 					1U, 10000U);
29998c4c201SDavid VomLehn 
30098c4c201SDavid VomLehn 	if (err < 0) {
30198c4c201SDavid VomLehn 		bool is_locked;
30298c4c201SDavid VomLehn 
3038e1c072fSIgor Russkikh 		hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
3040b926d46SNikita Danilov 		is_locked = hw_atl_sem_ram_get(self);
30598c4c201SDavid VomLehn 		if (!is_locked) {
30698c4c201SDavid VomLehn 			err = -ETIME;
30798c4c201SDavid VomLehn 			goto err_exit;
30898c4c201SDavid VomLehn 		}
30998c4c201SDavid VomLehn 	}
31098c4c201SDavid VomLehn 
31147203b34SIgor Russkikh 	aq_hw_write_reg(self, HW_ATL_MIF_ADDR, a);
31298c4c201SDavid VomLehn 
31347203b34SIgor Russkikh 	for (++cnt; --cnt && !err;) {
31447203b34SIgor Russkikh 		aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U);
31598c4c201SDavid VomLehn 
31647203b34SIgor Russkikh 		if (IS_CHIP_FEATURE(REVISION_B1))
3176a7f2277SNikita Danilov 			err = readx_poll_timeout_atomic(hw_atl_utils_mif_addr_get,
3186a7f2277SNikita Danilov 							self, val, val != a,
3196a7f2277SNikita Danilov 							1U, 1000U);
32047203b34SIgor Russkikh 		else
3216a7f2277SNikita Danilov 			err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
3226a7f2277SNikita Danilov 							self, val,
3236a7f2277SNikita Danilov 							!(val & 0x100),
3246a7f2277SNikita Danilov 							1U, 1000U);
32598c4c201SDavid VomLehn 
32647203b34SIgor Russkikh 		*(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL);
32747203b34SIgor Russkikh 		a += 4;
32898c4c201SDavid VomLehn 	}
32998c4c201SDavid VomLehn 
3308e1c072fSIgor Russkikh 	hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
33198c4c201SDavid VomLehn 
33298c4c201SDavid VomLehn err_exit:
33398c4c201SDavid VomLehn 	return err;
33498c4c201SDavid VomLehn }
33598c4c201SDavid VomLehn 
336dc12f75aSNikita Danilov static int hw_atl_utils_write_b1_mbox(struct aq_hw_s *self, u32 addr,
337dc12f75aSNikita Danilov 				      u32 *p, u32 cnt, enum mcp_area area)
33898c4c201SDavid VomLehn {
339dc12f75aSNikita Danilov 	u32 data_offset = 0;
340dc12f75aSNikita Danilov 	u32 offset = addr;
34198c4c201SDavid VomLehn 	int err = 0;
342dc12f75aSNikita Danilov 	u32 val;
34398c4c201SDavid VomLehn 
344dc12f75aSNikita Danilov 	switch (area) {
345dc12f75aSNikita Danilov 	case MCP_AREA_CONFIG:
346dc12f75aSNikita Danilov 		offset -= self->rpc_addr;
347dc12f75aSNikita Danilov 		break;
348930b9a05SNikita Danilov 
349dc12f75aSNikita Danilov 	case MCP_AREA_SETTINGS:
350dc12f75aSNikita Danilov 		offset -= self->settings_addr;
351dc12f75aSNikita Danilov 		break;
352dc12f75aSNikita Danilov 	}
35398c4c201SDavid VomLehn 
354dc12f75aSNikita Danilov 	offset = offset / sizeof(u32);
355dc12f75aSNikita Danilov 
356dc12f75aSNikita Danilov 	for (; data_offset < cnt; ++data_offset, ++offset) {
357dc12f75aSNikita Danilov 		aq_hw_write_reg(self, 0x328, p[data_offset]);
3583ee5c887SYana Esina 		aq_hw_write_reg(self, 0x32C,
359dc12f75aSNikita Danilov 				(area | (0xFFFF & (offset * 4))));
3603ee5c887SYana Esina 		hw_atl_mcp_up_force_intr_set(self, 1);
3613ee5c887SYana Esina 		/* 1000 times by 10us = 10ms */
3626a7f2277SNikita Danilov 		err = readx_poll_timeout_atomic(hw_atl_scrpad12_get,
3636a7f2277SNikita Danilov 						self, val,
364930b9a05SNikita Danilov 						(val & 0xF0000000) !=
365dc12f75aSNikita Danilov 						area,
3666a7f2277SNikita Danilov 						10U, 10000U);
36798c4c201SDavid VomLehn 
368dc12f75aSNikita Danilov 		if (err < 0)
369dc12f75aSNikita Danilov 			break;
370dc12f75aSNikita Danilov 	}
371dc12f75aSNikita Danilov 
372dc12f75aSNikita Danilov 	return err;
373dc12f75aSNikita Danilov }
374dc12f75aSNikita Danilov 
375dc12f75aSNikita Danilov static int hw_atl_utils_write_b0_mbox(struct aq_hw_s *self, u32 addr,
376dc12f75aSNikita Danilov 				      u32 *p, u32 cnt)
377dc12f75aSNikita Danilov {
378dc12f75aSNikita Danilov 	u32 offset = 0;
379dc12f75aSNikita Danilov 	int err = 0;
380dc12f75aSNikita Danilov 	u32 val;
381dc12f75aSNikita Danilov 
382dc12f75aSNikita Danilov 	aq_hw_write_reg(self, 0x208, addr);
38398c4c201SDavid VomLehn 
3843ee5c887SYana Esina 	for (; offset < cnt; ++offset) {
3853ee5c887SYana Esina 		aq_hw_write_reg(self, 0x20C, p[offset]);
3863ee5c887SYana Esina 		aq_hw_write_reg(self, 0x200, 0xC000);
38798c4c201SDavid VomLehn 
3886a7f2277SNikita Danilov 		err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
3896a7f2277SNikita Danilov 						self, val,
390dc12f75aSNikita Danilov 						(val & 0x100) == 0U,
391dc12f75aSNikita Danilov 						10U, 10000U);
392dc12f75aSNikita Danilov 
393dc12f75aSNikita Danilov 		if (err < 0)
394dc12f75aSNikita Danilov 			break;
39598c4c201SDavid VomLehn 	}
396dc12f75aSNikita Danilov 
397dc12f75aSNikita Danilov 	return err;
39898c4c201SDavid VomLehn }
39998c4c201SDavid VomLehn 
400dc12f75aSNikita Danilov static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 addr, u32 *p,
401dc12f75aSNikita Danilov 					 u32 cnt, enum mcp_area area)
402dc12f75aSNikita Danilov {
403dc12f75aSNikita Danilov 	int err = 0;
404dc12f75aSNikita Danilov 	u32 val;
405dc12f75aSNikita Danilov 
406dc12f75aSNikita Danilov 	err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, self,
407dc12f75aSNikita Danilov 					val, val == 1U,
408dc12f75aSNikita Danilov 					10U, 100000U);
409dc12f75aSNikita Danilov 	if (err < 0)
410dc12f75aSNikita Danilov 		goto err_exit;
411dc12f75aSNikita Danilov 
412dc12f75aSNikita Danilov 	if (IS_CHIP_FEATURE(REVISION_B1))
413dc12f75aSNikita Danilov 		err = hw_atl_utils_write_b1_mbox(self, addr, p, cnt, area);
414dc12f75aSNikita Danilov 	else
415dc12f75aSNikita Danilov 		err = hw_atl_utils_write_b0_mbox(self, addr, p, cnt);
416dc12f75aSNikita Danilov 
4178e1c072fSIgor Russkikh 	hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
41898c4c201SDavid VomLehn 
419dc12f75aSNikita Danilov 	if (err < 0)
420dc12f75aSNikita Danilov 		goto err_exit;
421dc12f75aSNikita Danilov 
422dc12f75aSNikita Danilov 	err = aq_hw_err_from_flags(self);
423dc12f75aSNikita Danilov 
42498c4c201SDavid VomLehn err_exit:
42598c4c201SDavid VomLehn 	return err;
42698c4c201SDavid VomLehn }
42798c4c201SDavid VomLehn 
428dc12f75aSNikita Danilov int hw_atl_write_fwcfg_dwords(struct aq_hw_s *self, u32 *p, u32 cnt)
429dc12f75aSNikita Danilov {
430dc12f75aSNikita Danilov 	return hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, p,
431dc12f75aSNikita Danilov 					     cnt, MCP_AREA_CONFIG);
432dc12f75aSNikita Danilov }
433dc12f75aSNikita Danilov 
434dc12f75aSNikita Danilov int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p,
435dc12f75aSNikita Danilov 				   u32 cnt)
436dc12f75aSNikita Danilov {
437dc12f75aSNikita Danilov 	return hw_atl_utils_fw_upload_dwords(self, self->settings_addr + offset,
438dc12f75aSNikita Danilov 					     p, cnt, MCP_AREA_SETTINGS);
439dc12f75aSNikita Danilov }
440dc12f75aSNikita Danilov 
44198c4c201SDavid VomLehn static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
44298c4c201SDavid VomLehn {
44398c4c201SDavid VomLehn 	const u32 dw_major_mask = 0xff000000U;
44498c4c201SDavid VomLehn 	const u32 dw_minor_mask = 0x00ffffffU;
4457b0c342fSNikita Danilov 	int err = 0;
44698c4c201SDavid VomLehn 
44798c4c201SDavid VomLehn 	err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0;
44898c4c201SDavid VomLehn 	if (err < 0)
44998c4c201SDavid VomLehn 		goto err_exit;
45098c4c201SDavid VomLehn 	err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
45198c4c201SDavid VomLehn 		-EOPNOTSUPP : 0;
4527b0c342fSNikita Danilov 
45398c4c201SDavid VomLehn err_exit:
45498c4c201SDavid VomLehn 	return err;
45598c4c201SDavid VomLehn }
45698c4c201SDavid VomLehn 
45798c4c201SDavid VomLehn static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
4584cbc9f92SIgor Russkikh 				 const struct aq_hw_caps_s *aq_hw_caps)
45998c4c201SDavid VomLehn {
46098c4c201SDavid VomLehn 	int err = 0;
46198c4c201SDavid VomLehn 
46298c4c201SDavid VomLehn 	if (!aq_hw_read_reg(self, 0x370U)) {
46398c4c201SDavid VomLehn 		unsigned int rnd = 0U;
46498c4c201SDavid VomLehn 		unsigned int ucp_0x370 = 0U;
46598c4c201SDavid VomLehn 
46698c4c201SDavid VomLehn 		get_random_bytes(&rnd, sizeof(unsigned int));
46798c4c201SDavid VomLehn 
46898c4c201SDavid VomLehn 		ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd);
46998c4c201SDavid VomLehn 		aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
47098c4c201SDavid VomLehn 	}
47198c4c201SDavid VomLehn 
4728e1c072fSIgor Russkikh 	hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U);
47398c4c201SDavid VomLehn 
47498c4c201SDavid VomLehn 	/* check 10 times by 1ms */
4756a7f2277SNikita Danilov 	err = readx_poll_timeout_atomic(hw_atl_scrpad25_get,
4766a7f2277SNikita Danilov 					self, self->mbox_addr,
4776a7f2277SNikita Danilov 					self->mbox_addr != 0U,
4786a7f2277SNikita Danilov 					1000U, 10000U);
47998c4c201SDavid VomLehn 
48098c4c201SDavid VomLehn 	return err;
48198c4c201SDavid VomLehn }
48298c4c201SDavid VomLehn 
48398c4c201SDavid VomLehn struct aq_hw_atl_utils_fw_rpc_tid_s {
48498c4c201SDavid VomLehn 	union {
48598c4c201SDavid VomLehn 		u32 val;
48698c4c201SDavid VomLehn 		struct {
48798c4c201SDavid VomLehn 			u16 tid;
48898c4c201SDavid VomLehn 			u16 len;
48998c4c201SDavid VomLehn 		};
49098c4c201SDavid VomLehn 	};
49198c4c201SDavid VomLehn };
49298c4c201SDavid VomLehn 
49398c4c201SDavid VomLehn #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
49498c4c201SDavid VomLehn 
4953ee5c887SYana Esina int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
49698c4c201SDavid VomLehn {
49798c4c201SDavid VomLehn 	struct aq_hw_atl_utils_fw_rpc_tid_s sw;
4987b0c342fSNikita Danilov 	int err = 0;
49998c4c201SDavid VomLehn 
50098c4c201SDavid VomLehn 	if (!IS_CHIP_FEATURE(MIPS)) {
50198c4c201SDavid VomLehn 		err = -1;
50298c4c201SDavid VomLehn 		goto err_exit;
50398c4c201SDavid VomLehn 	}
504dc12f75aSNikita Danilov 	err = hw_atl_write_fwcfg_dwords(self, (u32 *)(void *)&self->rpc,
50598c4c201SDavid VomLehn 					(rpc_size + sizeof(u32) -
50698c4c201SDavid VomLehn 					 sizeof(u8)) / sizeof(u32));
50798c4c201SDavid VomLehn 	if (err < 0)
50898c4c201SDavid VomLehn 		goto err_exit;
50998c4c201SDavid VomLehn 
5101a713f87SIgor Russkikh 	sw.tid = 0xFFFFU & (++self->rpc_tid);
51198c4c201SDavid VomLehn 	sw.len = (u16)rpc_size;
51298c4c201SDavid VomLehn 	aq_hw_write_reg(self, HW_ATL_RPC_CONTROL_ADR, sw.val);
51398c4c201SDavid VomLehn 
51498c4c201SDavid VomLehn err_exit:
51598c4c201SDavid VomLehn 	return err;
51698c4c201SDavid VomLehn }
51798c4c201SDavid VomLehn 
5183ee5c887SYana Esina int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
5198f60f762SNikita Danilov 			     struct hw_atl_utils_fw_rpc **rpc)
52098c4c201SDavid VomLehn {
52198c4c201SDavid VomLehn 	struct aq_hw_atl_utils_fw_rpc_tid_s sw;
52298c4c201SDavid VomLehn 	struct aq_hw_atl_utils_fw_rpc_tid_s fw;
5237b0c342fSNikita Danilov 	int err = 0;
52498c4c201SDavid VomLehn 
52598c4c201SDavid VomLehn 	do {
52698c4c201SDavid VomLehn 		sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR);
52798c4c201SDavid VomLehn 
5281a713f87SIgor Russkikh 		self->rpc_tid = sw.tid;
52998c4c201SDavid VomLehn 
5306a7f2277SNikita Danilov 		err = readx_poll_timeout_atomic(hw_atl_utils_rpc_state_get,
5316a7f2277SNikita Danilov 						self, fw.val,
5326a7f2277SNikita Danilov 						sw.tid == fw.tid,
5336a7f2277SNikita Danilov 						1000U, 100000U);
53498c4c201SDavid VomLehn 
53598c4c201SDavid VomLehn 		if (fw.len == 0xFFFFU) {
53698c4c201SDavid VomLehn 			err = hw_atl_utils_fw_rpc_call(self, sw.len);
53798c4c201SDavid VomLehn 			if (err < 0)
53898c4c201SDavid VomLehn 				goto err_exit;
53998c4c201SDavid VomLehn 		}
54098c4c201SDavid VomLehn 	} while (sw.tid != fw.tid || 0xFFFFU == fw.len);
54198c4c201SDavid VomLehn 
54298c4c201SDavid VomLehn 	if (rpc) {
54398c4c201SDavid VomLehn 		if (fw.len) {
54498c4c201SDavid VomLehn 			err =
54598c4c201SDavid VomLehn 			hw_atl_utils_fw_downld_dwords(self,
5461a713f87SIgor Russkikh 						      self->rpc_addr,
54798c4c201SDavid VomLehn 						      (u32 *)(void *)
5481a713f87SIgor Russkikh 						      &self->rpc,
54998c4c201SDavid VomLehn 						      (fw.len + sizeof(u32) -
55098c4c201SDavid VomLehn 						       sizeof(u8)) /
55198c4c201SDavid VomLehn 						      sizeof(u32));
55298c4c201SDavid VomLehn 			if (err < 0)
55398c4c201SDavid VomLehn 				goto err_exit;
55498c4c201SDavid VomLehn 		}
55598c4c201SDavid VomLehn 
5561a713f87SIgor Russkikh 		*rpc = &self->rpc;
55798c4c201SDavid VomLehn 	}
55898c4c201SDavid VomLehn 
55998c4c201SDavid VomLehn err_exit:
56098c4c201SDavid VomLehn 	return err;
56198c4c201SDavid VomLehn }
56298c4c201SDavid VomLehn 
5631a713f87SIgor Russkikh static int hw_atl_utils_mpi_create(struct aq_hw_s *self)
56498c4c201SDavid VomLehn {
56598c4c201SDavid VomLehn 	int err = 0;
56698c4c201SDavid VomLehn 
5671a713f87SIgor Russkikh 	err = hw_atl_utils_init_ucp(self, self->aq_nic_cfg->aq_hw_caps);
56898c4c201SDavid VomLehn 	if (err < 0)
56998c4c201SDavid VomLehn 		goto err_exit;
57098c4c201SDavid VomLehn 
57198c4c201SDavid VomLehn 	err = hw_atl_utils_fw_rpc_init(self);
57298c4c201SDavid VomLehn 	if (err < 0)
57398c4c201SDavid VomLehn 		goto err_exit;
57498c4c201SDavid VomLehn 
57598c4c201SDavid VomLehn err_exit:
57698c4c201SDavid VomLehn 	return err;
57798c4c201SDavid VomLehn }
57898c4c201SDavid VomLehn 
57965e665e6SIgor Russkikh int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
5808f60f762SNikita Danilov 			       struct hw_atl_utils_mbox_header *pmbox)
58165e665e6SIgor Russkikh {
58265e665e6SIgor Russkikh 	return hw_atl_utils_fw_downld_dwords(self,
5831a713f87SIgor Russkikh 					     self->mbox_addr,
58465e665e6SIgor Russkikh 					     (u32 *)(void *)pmbox,
58565e665e6SIgor Russkikh 					     sizeof(*pmbox) / sizeof(u32));
58665e665e6SIgor Russkikh }
58765e665e6SIgor Russkikh 
58898c4c201SDavid VomLehn void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
5898f60f762SNikita Danilov 				 struct hw_atl_utils_mbox *pmbox)
59098c4c201SDavid VomLehn {
59198c4c201SDavid VomLehn 	int err = 0;
59298c4c201SDavid VomLehn 
59398c4c201SDavid VomLehn 	err = hw_atl_utils_fw_downld_dwords(self,
5941a713f87SIgor Russkikh 					    self->mbox_addr,
59598c4c201SDavid VomLehn 					    (u32 *)(void *)pmbox,
59698c4c201SDavid VomLehn 					    sizeof(*pmbox) / sizeof(u32));
59798c4c201SDavid VomLehn 	if (err < 0)
59898c4c201SDavid VomLehn 		goto err_exit;
59998c4c201SDavid VomLehn 
60098c4c201SDavid VomLehn 	if (IS_CHIP_FEATURE(REVISION_A0)) {
60198c4c201SDavid VomLehn 		unsigned int mtu = self->aq_nic_cfg ?
60298c4c201SDavid VomLehn 					self->aq_nic_cfg->mtu : 1514U;
60398c4c201SDavid VomLehn 		pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
60498c4c201SDavid VomLehn 		pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
6051a713f87SIgor Russkikh 		pmbox->stats.dpc = atomic_read(&self->dpc);
60698c4c201SDavid VomLehn 	} else {
607ce4cdbe4SDmitry Bogdanov 		pmbox->stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
60898c4c201SDavid VomLehn 	}
60998c4c201SDavid VomLehn 
61098c4c201SDavid VomLehn err_exit:;
61198c4c201SDavid VomLehn }
61298c4c201SDavid VomLehn 
613dfbd0749SWei Yongjun static int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
61498c4c201SDavid VomLehn {
6150c58c35fSIgor Russkikh 	u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
61698c4c201SDavid VomLehn 
61744e00dd8SIgor Russkikh 	val = val & ~HW_ATL_MPI_SPEED_MSK;
61844e00dd8SIgor Russkikh 	val |= speed << HW_ATL_MPI_SPEED_SHIFT;
6190c58c35fSIgor Russkikh 	aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
62098c4c201SDavid VomLehn 
62198c4c201SDavid VomLehn 	return 0;
62298c4c201SDavid VomLehn }
62398c4c201SDavid VomLehn 
624dfbd0749SWei Yongjun static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
62544e00dd8SIgor Russkikh 				      enum hal_atl_utils_fw_state_e state)
62698c4c201SDavid VomLehn {
62744e00dd8SIgor Russkikh 	u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
6287b0c342fSNikita Danilov 	struct hw_atl_utils_mbox_header mbox;
6297b0c342fSNikita Danilov 	u32 transaction_id = 0;
6307b0c342fSNikita Danilov 	int err = 0;
63198c4c201SDavid VomLehn 
63298c4c201SDavid VomLehn 	if (state == MPI_RESET) {
63365e665e6SIgor Russkikh 		hw_atl_utils_mpi_read_mbox(self, &mbox);
63498c4c201SDavid VomLehn 
63565e665e6SIgor Russkikh 		transaction_id = mbox.transaction_id;
63698c4c201SDavid VomLehn 
6376a7f2277SNikita Danilov 		err = readx_poll_timeout_atomic(hw_atl_utils_get_mpi_mbox_tid,
6386a7f2277SNikita Danilov 						self, mbox.transaction_id,
6396a7f2277SNikita Danilov 						transaction_id !=
6406a7f2277SNikita Danilov 						mbox.transaction_id,
6416a7f2277SNikita Danilov 						1000U, 100000U);
64298c4c201SDavid VomLehn 		if (err < 0)
64398c4c201SDavid VomLehn 			goto err_exit;
64498c4c201SDavid VomLehn 	}
64544e00dd8SIgor Russkikh 	/* On interface DEINIT we disable DW (raise bit)
64644e00dd8SIgor Russkikh 	 * Otherwise enable DW (clear bit)
64744e00dd8SIgor Russkikh 	 */
64844e00dd8SIgor Russkikh 	if (state == MPI_DEINIT || state == MPI_POWER)
64944e00dd8SIgor Russkikh 		val |= HW_ATL_MPI_DIRTY_WAKE_MSK;
65044e00dd8SIgor Russkikh 	else
65144e00dd8SIgor Russkikh 		val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK;
65298c4c201SDavid VomLehn 
65344e00dd8SIgor Russkikh 	/* Set new state bits */
65444e00dd8SIgor Russkikh 	val = val & ~HW_ATL_MPI_STATE_MSK;
65544e00dd8SIgor Russkikh 	val |= state & HW_ATL_MPI_STATE_MSK;
65698c4c201SDavid VomLehn 
6570c58c35fSIgor Russkikh 	aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
6587b0c342fSNikita Danilov 
65944e00dd8SIgor Russkikh err_exit:
66044e00dd8SIgor Russkikh 	return err;
6610c58c35fSIgor Russkikh }
6620c58c35fSIgor Russkikh 
663bd8ed441SPavel Belous int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
66498c4c201SDavid VomLehn {
665bd8ed441SPavel Belous 	struct aq_hw_link_status_s *link_status = &self->aq_link_status;
6667b0c342fSNikita Danilov 	u32 mpi_state;
6677b0c342fSNikita Danilov 	u32 speed;
66898c4c201SDavid VomLehn 
6697b0c342fSNikita Danilov 	mpi_state = hw_atl_utils_mpi_get_state(self);
670ac70957eSIgor Russkikh 	speed = mpi_state >> HW_ATL_MPI_SPEED_SHIFT;
6717b0c342fSNikita Danilov 
6727b0c342fSNikita Danilov 	if (!speed) {
67398c4c201SDavid VomLehn 		link_status->mbps = 0U;
67498c4c201SDavid VomLehn 	} else {
6757b0c342fSNikita Danilov 		switch (speed) {
67698c4c201SDavid VomLehn 		case HAL_ATLANTIC_RATE_10G:
67798c4c201SDavid VomLehn 			link_status->mbps = 10000U;
67898c4c201SDavid VomLehn 			break;
67998c4c201SDavid VomLehn 
68098c4c201SDavid VomLehn 		case HAL_ATLANTIC_RATE_5G:
68198c4c201SDavid VomLehn 		case HAL_ATLANTIC_RATE_5GSR:
68298c4c201SDavid VomLehn 			link_status->mbps = 5000U;
68398c4c201SDavid VomLehn 			break;
68498c4c201SDavid VomLehn 
68598c4c201SDavid VomLehn 		case HAL_ATLANTIC_RATE_2GS:
68698c4c201SDavid VomLehn 			link_status->mbps = 2500U;
68798c4c201SDavid VomLehn 			break;
68898c4c201SDavid VomLehn 
68998c4c201SDavid VomLehn 		case HAL_ATLANTIC_RATE_1G:
69098c4c201SDavid VomLehn 			link_status->mbps = 1000U;
69198c4c201SDavid VomLehn 			break;
69298c4c201SDavid VomLehn 
69398c4c201SDavid VomLehn 		case HAL_ATLANTIC_RATE_100M:
69498c4c201SDavid VomLehn 			link_status->mbps = 100U;
69598c4c201SDavid VomLehn 			break;
69698c4c201SDavid VomLehn 
69798c4c201SDavid VomLehn 		default:
698a7bb1beaSIgor Russkikh 			return -EBUSY;
69998c4c201SDavid VomLehn 		}
70098c4c201SDavid VomLehn 	}
70198c4c201SDavid VomLehn 
70298c4c201SDavid VomLehn 	return 0;
70398c4c201SDavid VomLehn }
70498c4c201SDavid VomLehn 
70598c4c201SDavid VomLehn int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
70698c4c201SDavid VomLehn 				   u8 *mac)
70798c4c201SDavid VomLehn {
7087b0c342fSNikita Danilov 	u32 mac_addr[2];
7097b0c342fSNikita Danilov 	u32 efuse_addr;
71098c4c201SDavid VomLehn 	int err = 0;
71198c4c201SDavid VomLehn 	u32 h = 0U;
71298c4c201SDavid VomLehn 	u32 l = 0U;
71398c4c201SDavid VomLehn 
71498c4c201SDavid VomLehn 	if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
71598c4c201SDavid VomLehn 		unsigned int ucp_0x370 = 0;
7167b0c342fSNikita Danilov 		unsigned int rnd = 0;
71798c4c201SDavid VomLehn 
71898c4c201SDavid VomLehn 		get_random_bytes(&rnd, sizeof(unsigned int));
71998c4c201SDavid VomLehn 
72098c4c201SDavid VomLehn 		ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
72198c4c201SDavid VomLehn 		aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
72298c4c201SDavid VomLehn 	}
72398c4c201SDavid VomLehn 
7247b0c342fSNikita Danilov 	efuse_addr = aq_hw_read_reg(self, 0x00000374U);
7257b0c342fSNikita Danilov 
7267b0c342fSNikita Danilov 	err = hw_atl_utils_fw_downld_dwords(self, efuse_addr + (40U * 4U),
7277b0c342fSNikita Danilov 					    mac_addr, ARRAY_SIZE(mac_addr));
72898c4c201SDavid VomLehn 	if (err < 0) {
72998c4c201SDavid VomLehn 		mac_addr[0] = 0U;
73098c4c201SDavid VomLehn 		mac_addr[1] = 0U;
73198c4c201SDavid VomLehn 		err = 0;
73298c4c201SDavid VomLehn 	} else {
73398c4c201SDavid VomLehn 		mac_addr[0] = __swab32(mac_addr[0]);
73498c4c201SDavid VomLehn 		mac_addr[1] = __swab32(mac_addr[1]);
73598c4c201SDavid VomLehn 	}
73698c4c201SDavid VomLehn 
73798c4c201SDavid VomLehn 	ether_addr_copy(mac, (u8 *)mac_addr);
73898c4c201SDavid VomLehn 
73998c4c201SDavid VomLehn 	if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
74098c4c201SDavid VomLehn 		/* chip revision */
741e9157848SNikita Danilov 		l = 0xE3000000U |
742e9157848SNikita Danilov 		    (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) |
743e9157848SNikita Danilov 		    (0x00 << 16);
74498c4c201SDavid VomLehn 		h = 0x8001300EU;
74598c4c201SDavid VomLehn 
74698c4c201SDavid VomLehn 		mac[5] = (u8)(0xFFU & l);
74798c4c201SDavid VomLehn 		l >>= 8;
74898c4c201SDavid VomLehn 		mac[4] = (u8)(0xFFU & l);
74998c4c201SDavid VomLehn 		l >>= 8;
75098c4c201SDavid VomLehn 		mac[3] = (u8)(0xFFU & l);
75198c4c201SDavid VomLehn 		l >>= 8;
75298c4c201SDavid VomLehn 		mac[2] = (u8)(0xFFU & l);
75398c4c201SDavid VomLehn 		mac[1] = (u8)(0xFFU & h);
75498c4c201SDavid VomLehn 		h >>= 8;
75598c4c201SDavid VomLehn 		mac[0] = (u8)(0xFFU & h);
75698c4c201SDavid VomLehn 	}
75798c4c201SDavid VomLehn 
75898c4c201SDavid VomLehn 	return err;
75998c4c201SDavid VomLehn }
76098c4c201SDavid VomLehn 
76198c4c201SDavid VomLehn unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
76298c4c201SDavid VomLehn {
76398c4c201SDavid VomLehn 	unsigned int ret = 0U;
76498c4c201SDavid VomLehn 
76598c4c201SDavid VomLehn 	switch (mbps) {
76698c4c201SDavid VomLehn 	case 100U:
76798c4c201SDavid VomLehn 		ret = 5U;
76898c4c201SDavid VomLehn 		break;
76998c4c201SDavid VomLehn 
77098c4c201SDavid VomLehn 	case 1000U:
77198c4c201SDavid VomLehn 		ret = 4U;
77298c4c201SDavid VomLehn 		break;
77398c4c201SDavid VomLehn 
77498c4c201SDavid VomLehn 	case 2500U:
77598c4c201SDavid VomLehn 		ret = 3U;
77698c4c201SDavid VomLehn 		break;
77798c4c201SDavid VomLehn 
77898c4c201SDavid VomLehn 	case 5000U:
77998c4c201SDavid VomLehn 		ret = 1U;
78098c4c201SDavid VomLehn 		break;
78198c4c201SDavid VomLehn 
78298c4c201SDavid VomLehn 	case 10000U:
78398c4c201SDavid VomLehn 		ret = 0U;
78498c4c201SDavid VomLehn 		break;
78598c4c201SDavid VomLehn 
78698c4c201SDavid VomLehn 	default:
78798c4c201SDavid VomLehn 		break;
78898c4c201SDavid VomLehn 	}
7897b0c342fSNikita Danilov 
79098c4c201SDavid VomLehn 	return ret;
79198c4c201SDavid VomLehn }
79298c4c201SDavid VomLehn 
79398c4c201SDavid VomLehn void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
79498c4c201SDavid VomLehn {
7958e1c072fSIgor Russkikh 	u32 val = hw_atl_reg_glb_mif_id_get(self);
79698c4c201SDavid VomLehn 	u32 mif_rev = val & 0xFFU;
7977b0c342fSNikita Danilov 	u32 chip_features = 0U;
79898c4c201SDavid VomLehn 
79947203b34SIgor Russkikh 	if ((0xFU & mif_rev) == 1U) {
80047203b34SIgor Russkikh 		chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
80198c4c201SDavid VomLehn 			HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
80298c4c201SDavid VomLehn 			HAL_ATLANTIC_UTILS_CHIP_MIPS;
80347203b34SIgor Russkikh 	} else if ((0xFU & mif_rev) == 2U) {
80447203b34SIgor Russkikh 		chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
80547203b34SIgor Russkikh 			HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
80647203b34SIgor Russkikh 			HAL_ATLANTIC_UTILS_CHIP_MIPS |
80747203b34SIgor Russkikh 			HAL_ATLANTIC_UTILS_CHIP_TPO2 |
80847203b34SIgor Russkikh 			HAL_ATLANTIC_UTILS_CHIP_RPF2;
80947203b34SIgor Russkikh 	} else if ((0xFU & mif_rev) == 0xAU) {
81047203b34SIgor Russkikh 		chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 |
81198c4c201SDavid VomLehn 			HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
81298c4c201SDavid VomLehn 			HAL_ATLANTIC_UTILS_CHIP_MIPS |
81398c4c201SDavid VomLehn 			HAL_ATLANTIC_UTILS_CHIP_TPO2 |
81498c4c201SDavid VomLehn 			HAL_ATLANTIC_UTILS_CHIP_RPF2;
81598c4c201SDavid VomLehn 	}
81698c4c201SDavid VomLehn 
81798c4c201SDavid VomLehn 	*p = chip_features;
81898c4c201SDavid VomLehn }
81998c4c201SDavid VomLehn 
82044e00dd8SIgor Russkikh static int hw_atl_fw1x_deinit(struct aq_hw_s *self)
82198c4c201SDavid VomLehn {
82244e00dd8SIgor Russkikh 	hw_atl_utils_mpi_set_speed(self, 0);
82344e00dd8SIgor Russkikh 	hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
8247b0c342fSNikita Danilov 
82598c4c201SDavid VomLehn 	return 0;
82698c4c201SDavid VomLehn }
82798c4c201SDavid VomLehn 
82865e665e6SIgor Russkikh int hw_atl_utils_update_stats(struct aq_hw_s *self)
82965e665e6SIgor Russkikh {
830ce4cdbe4SDmitry Bogdanov 	struct aq_stats_s *cs = &self->curr_stats;
8317b0c342fSNikita Danilov 	struct hw_atl_utils_mbox mbox;
83265e665e6SIgor Russkikh 
83365e665e6SIgor Russkikh 	hw_atl_utils_mpi_read_stats(self, &mbox);
83465e665e6SIgor Russkikh 
8351a713f87SIgor Russkikh #define AQ_SDELTA(_N_) (self->curr_stats._N_ += \
8361a713f87SIgor Russkikh 			mbox.stats._N_ - self->last_stats._N_)
8371a713f87SIgor Russkikh 
838be08d839SIgor Russkikh 	if (self->aq_link_status.mbps) {
83965e665e6SIgor Russkikh 		AQ_SDELTA(uprc);
84065e665e6SIgor Russkikh 		AQ_SDELTA(mprc);
84165e665e6SIgor Russkikh 		AQ_SDELTA(bprc);
84265e665e6SIgor Russkikh 		AQ_SDELTA(erpt);
84365e665e6SIgor Russkikh 
84465e665e6SIgor Russkikh 		AQ_SDELTA(uptc);
84565e665e6SIgor Russkikh 		AQ_SDELTA(mptc);
84665e665e6SIgor Russkikh 		AQ_SDELTA(bptc);
84765e665e6SIgor Russkikh 		AQ_SDELTA(erpr);
84865e665e6SIgor Russkikh 
84965e665e6SIgor Russkikh 		AQ_SDELTA(ubrc);
85065e665e6SIgor Russkikh 		AQ_SDELTA(ubtc);
85165e665e6SIgor Russkikh 		AQ_SDELTA(mbrc);
85265e665e6SIgor Russkikh 		AQ_SDELTA(mbtc);
85365e665e6SIgor Russkikh 		AQ_SDELTA(bbrc);
85465e665e6SIgor Russkikh 		AQ_SDELTA(bbtc);
85565e665e6SIgor Russkikh 		AQ_SDELTA(dpc);
856be08d839SIgor Russkikh 	}
85765e665e6SIgor Russkikh #undef AQ_SDELTA
858ce4cdbe4SDmitry Bogdanov 
859ce4cdbe4SDmitry Bogdanov 	cs->dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counter_get(self);
860ce4cdbe4SDmitry Bogdanov 	cs->dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counter_get(self);
861ce4cdbe4SDmitry Bogdanov 	cs->dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counter_get(self);
862ce4cdbe4SDmitry Bogdanov 	cs->dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counter_get(self);
86365e665e6SIgor Russkikh 
8641a713f87SIgor Russkikh 	memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
86565e665e6SIgor Russkikh 
86665e665e6SIgor Russkikh 	return 0;
86765e665e6SIgor Russkikh }
86865e665e6SIgor Russkikh 
869be08d839SIgor Russkikh struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self)
87098c4c201SDavid VomLehn {
8711a713f87SIgor Russkikh 	return &self->curr_stats;
87298c4c201SDavid VomLehn }
87398c4c201SDavid VomLehn 
87498c4c201SDavid VomLehn static const u32 hw_atl_utils_hw_mac_regs[] = {
87598c4c201SDavid VomLehn 	0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
87698c4c201SDavid VomLehn 	0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
87798c4c201SDavid VomLehn 	0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
87898c4c201SDavid VomLehn 	0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
87998c4c201SDavid VomLehn 	0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
88098c4c201SDavid VomLehn 	0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
88198c4c201SDavid VomLehn 	0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
88298c4c201SDavid VomLehn 	0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
88398c4c201SDavid VomLehn 	0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
88498c4c201SDavid VomLehn 	0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
88598c4c201SDavid VomLehn 	0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
88698c4c201SDavid VomLehn 	0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
88798c4c201SDavid VomLehn 	0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
88898c4c201SDavid VomLehn 	0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
88998c4c201SDavid VomLehn 	0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
89098c4c201SDavid VomLehn 	0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
89198c4c201SDavid VomLehn 	0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
89298c4c201SDavid VomLehn 	0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
89398c4c201SDavid VomLehn 	0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
89498c4c201SDavid VomLehn 	0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
89598c4c201SDavid VomLehn 	0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
89698c4c201SDavid VomLehn 	0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
89798c4c201SDavid VomLehn };
89898c4c201SDavid VomLehn 
89998c4c201SDavid VomLehn int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
9004cbc9f92SIgor Russkikh 			     const struct aq_hw_caps_s *aq_hw_caps,
90198c4c201SDavid VomLehn 			     u32 *regs_buff)
90298c4c201SDavid VomLehn {
90398c4c201SDavid VomLehn 	unsigned int i = 0U;
90498c4c201SDavid VomLehn 
90598c4c201SDavid VomLehn 	for (i = 0; i < aq_hw_caps->mac_regs_count; i++)
90698c4c201SDavid VomLehn 		regs_buff[i] = aq_hw_read_reg(self,
90798c4c201SDavid VomLehn 					      hw_atl_utils_hw_mac_regs[i]);
9087b0c342fSNikita Danilov 
90998c4c201SDavid VomLehn 	return 0;
91098c4c201SDavid VomLehn }
91198c4c201SDavid VomLehn 
91298c4c201SDavid VomLehn int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
91398c4c201SDavid VomLehn {
91498c4c201SDavid VomLehn 	*fw_version = aq_hw_read_reg(self, 0x18U);
9157b0c342fSNikita Danilov 
91698c4c201SDavid VomLehn 	return 0;
91798c4c201SDavid VomLehn }
9180c58c35fSIgor Russkikh 
919837c6378SNikita Danilov static int aq_fw1x_set_wake_magic(struct aq_hw_s *self, bool wol_enabled,
920837c6378SNikita Danilov 				  u8 *mac)
921a0da96c0SYana Esina {
9228f60f762SNikita Danilov 	struct hw_atl_utils_fw_rpc *prpc = NULL;
923a0da96c0SYana Esina 	unsigned int rpc_size = 0U;
924a0da96c0SYana Esina 	int err = 0;
925a0da96c0SYana Esina 
926a0da96c0SYana Esina 	err = hw_atl_utils_fw_rpc_wait(self, &prpc);
927a0da96c0SYana Esina 	if (err < 0)
928a0da96c0SYana Esina 		goto err_exit;
929a0da96c0SYana Esina 
930a0da96c0SYana Esina 	memset(prpc, 0, sizeof(*prpc));
931a0da96c0SYana Esina 
932a0da96c0SYana Esina 	if (wol_enabled) {
933d993e14bSNikita Danilov 		rpc_size = offsetof(struct hw_atl_utils_fw_rpc, msg_wol_add) +
934d993e14bSNikita Danilov 			   sizeof(prpc->msg_wol_add);
935d993e14bSNikita Danilov 
936a0da96c0SYana Esina 
937a0da96c0SYana Esina 		prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD;
938d993e14bSNikita Danilov 		prpc->msg_wol_add.priority =
939a0da96c0SYana Esina 				HAL_ATLANTIC_UTILS_FW_MSG_WOL_PRIOR;
940d993e14bSNikita Danilov 		prpc->msg_wol_add.pattern_id =
941a0da96c0SYana Esina 				HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN;
942d993e14bSNikita Danilov 		prpc->msg_wol_add.packet_type =
943a0da96c0SYana Esina 				HAL_ATLANTIC_UTILS_FW_MSG_WOL_MAG_PKT;
944a0da96c0SYana Esina 
945d993e14bSNikita Danilov 		ether_addr_copy((u8 *)&prpc->msg_wol_add.magic_packet_pattern,
946d993e14bSNikita Danilov 				mac);
947a0da96c0SYana Esina 	} else {
948d993e14bSNikita Danilov 		rpc_size = sizeof(prpc->msg_wol_remove) +
949d993e14bSNikita Danilov 			   offsetof(struct hw_atl_utils_fw_rpc, msg_wol_remove);
950a0da96c0SYana Esina 
951a0da96c0SYana Esina 		prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL;
952d993e14bSNikita Danilov 		prpc->msg_wol_add.pattern_id =
953a0da96c0SYana Esina 				HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN;
954a0da96c0SYana Esina 	}
955a0da96c0SYana Esina 
956a0da96c0SYana Esina 	err = hw_atl_utils_fw_rpc_call(self, rpc_size);
957a0da96c0SYana Esina 
958a0da96c0SYana Esina err_exit:
959a0da96c0SYana Esina 	return err;
960a0da96c0SYana Esina }
961a0da96c0SYana Esina 
9623d5537f9SWei Yongjun static int aq_fw1x_set_power(struct aq_hw_s *self, unsigned int power_state,
963a0da96c0SYana Esina 			     u8 *mac)
964a0da96c0SYana Esina {
9658f60f762SNikita Danilov 	struct hw_atl_utils_fw_rpc *prpc = NULL;
966a0da96c0SYana Esina 	unsigned int rpc_size = 0U;
967a0da96c0SYana Esina 	int err = 0;
968a0da96c0SYana Esina 
969837c6378SNikita Danilov 	if (self->aq_nic_cfg->wol & WAKE_MAGIC) {
970837c6378SNikita Danilov 		err = aq_fw1x_set_wake_magic(self, 1, mac);
971a0da96c0SYana Esina 
972a0da96c0SYana Esina 		if (err < 0)
973a0da96c0SYana Esina 			goto err_exit;
974a0da96c0SYana Esina 
975a0da96c0SYana Esina 		rpc_size = sizeof(prpc->msg_id) +
976a0da96c0SYana Esina 			   sizeof(prpc->msg_enable_wakeup);
977a0da96c0SYana Esina 
978a0da96c0SYana Esina 		err = hw_atl_utils_fw_rpc_wait(self, &prpc);
979a0da96c0SYana Esina 
980a0da96c0SYana Esina 		if (err < 0)
981a0da96c0SYana Esina 			goto err_exit;
982a0da96c0SYana Esina 
983a0da96c0SYana Esina 		memset(prpc, 0, rpc_size);
984a0da96c0SYana Esina 
985a0da96c0SYana Esina 		prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_ENABLE_WAKEUP;
986a0da96c0SYana Esina 		prpc->msg_enable_wakeup.pattern_mask = 0x00000002;
987a0da96c0SYana Esina 
988a0da96c0SYana Esina 		err = hw_atl_utils_fw_rpc_call(self, rpc_size);
989a0da96c0SYana Esina 		if (err < 0)
990a0da96c0SYana Esina 			goto err_exit;
991a0da96c0SYana Esina 	}
992a0da96c0SYana Esina 	hw_atl_utils_mpi_set_speed(self, 0);
993a0da96c0SYana Esina 	hw_atl_utils_mpi_set_state(self, MPI_POWER);
994a0da96c0SYana Esina 
995a0da96c0SYana Esina err_exit:
996a0da96c0SYana Esina 	return err;
997a0da96c0SYana Esina }
998a0da96c0SYana Esina 
9996a7f2277SNikita Danilov static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self)
10006a7f2277SNikita Danilov {
10016a7f2277SNikita Danilov 	struct hw_atl_utils_mbox_header mbox;
10026a7f2277SNikita Danilov 
10036a7f2277SNikita Danilov 	hw_atl_utils_mpi_read_mbox(self, &mbox);
10046a7f2277SNikita Danilov 
10056a7f2277SNikita Danilov 	return mbox.transaction_id;
10066a7f2277SNikita Danilov }
10076a7f2277SNikita Danilov 
10086a7f2277SNikita Danilov static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self)
10096a7f2277SNikita Danilov {
10106a7f2277SNikita Danilov 	return aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
10116a7f2277SNikita Danilov }
10126a7f2277SNikita Danilov 
10136a7f2277SNikita Danilov static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self)
10146a7f2277SNikita Danilov {
10156a7f2277SNikita Danilov 	return aq_hw_read_reg(self, HW_ATL_MIF_CMD);
10166a7f2277SNikita Danilov }
10176a7f2277SNikita Danilov 
10186a7f2277SNikita Danilov static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self)
10196a7f2277SNikita Danilov {
10206a7f2277SNikita Danilov 	return aq_hw_read_reg(self, HW_ATL_MIF_ADDR);
10216a7f2277SNikita Danilov }
10226a7f2277SNikita Danilov 
10236a7f2277SNikita Danilov static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self)
10246a7f2277SNikita Danilov {
10256a7f2277SNikita Danilov 	return aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR);
10266a7f2277SNikita Danilov }
10276a7f2277SNikita Danilov 
10280c58c35fSIgor Russkikh const struct aq_fw_ops aq_fw_1x_ops = {
10290c58c35fSIgor Russkikh 	.init = hw_atl_utils_mpi_create,
103044e00dd8SIgor Russkikh 	.deinit = hw_atl_fw1x_deinit,
10310c58c35fSIgor Russkikh 	.reset = NULL,
10320c58c35fSIgor Russkikh 	.get_mac_permanent = hw_atl_utils_get_mac_permanent,
10330c58c35fSIgor Russkikh 	.set_link_speed = hw_atl_utils_mpi_set_speed,
10340c58c35fSIgor Russkikh 	.set_state = hw_atl_utils_mpi_set_state,
10350c58c35fSIgor Russkikh 	.update_link_status = hw_atl_utils_mpi_get_link_status,
10360c58c35fSIgor Russkikh 	.update_stats = hw_atl_utils_update_stats,
10378f894011SYana Esina 	.get_phy_temp = NULL,
1038a0da96c0SYana Esina 	.set_power = aq_fw1x_set_power,
103992ab6407SYana Esina 	.set_eee_rate = NULL,
104092ab6407SYana Esina 	.get_eee_rate = NULL,
1041288551deSIgor Russkikh 	.set_flow_control = NULL,
1042910479a9SEgor Pomozov 	.send_fw_request = NULL,
1043910479a9SEgor Pomozov 	.enable_ptp = NULL,
1044d1287ce4SNikita Danilov 	.led_control = NULL,
10450c58c35fSIgor Russkikh };
1046