1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * aQuantia Corporation Network Driver
4  * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
5  */
6 
7 /* File hw_atl_utils_fw2x.c: Definition of firmware 2.x functions for
8  * Atlantic hardware abstraction layer.
9  */
10 
11 #include "../aq_hw.h"
12 #include "../aq_hw_utils.h"
13 #include "../aq_pci_func.h"
14 #include "../aq_ring.h"
15 #include "../aq_vec.h"
16 #include "../aq_nic.h"
17 #include "hw_atl_utils.h"
18 #include "hw_atl_llh.h"
19 
20 #define HW_ATL_FW2X_MPI_LED_ADDR         0x31c
21 #define HW_ATL_FW2X_MPI_RPC_ADDR         0x334
22 
23 #define HW_ATL_FW2X_MPI_MBOX_ADDR        0x360
24 #define HW_ATL_FW2X_MPI_EFUSE_ADDR       0x364
25 #define HW_ATL_FW2X_MPI_CONTROL_ADDR     0x368
26 #define HW_ATL_FW2X_MPI_CONTROL2_ADDR    0x36C
27 #define HW_ATL_FW2X_MPI_STATE_ADDR       0x370
28 #define HW_ATL_FW2X_MPI_STATE2_ADDR      0x374
29 
30 #define HW_ATL_FW3X_EXT_CONTROL_ADDR     0x378
31 #define HW_ATL_FW3X_EXT_STATE_ADDR       0x37c
32 
33 #define HW_ATL_FW2X_CAP_PAUSE            BIT(CAPS_HI_PAUSE)
34 #define HW_ATL_FW2X_CAP_ASYM_PAUSE       BIT(CAPS_HI_ASYMMETRIC_PAUSE)
35 #define HW_ATL_FW2X_CAP_SLEEP_PROXY      BIT(CAPS_HI_SLEEP_PROXY)
36 #define HW_ATL_FW2X_CAP_WOL              BIT(CAPS_HI_WOL)
37 
38 #define HW_ATL_FW2X_CTRL_WAKE_ON_LINK     BIT(CTRL_WAKE_ON_LINK)
39 #define HW_ATL_FW2X_CTRL_SLEEP_PROXY      BIT(CTRL_SLEEP_PROXY)
40 #define HW_ATL_FW2X_CTRL_WOL              BIT(CTRL_WOL)
41 #define HW_ATL_FW2X_CTRL_LINK_DROP        BIT(CTRL_LINK_DROP)
42 #define HW_ATL_FW2X_CTRL_PAUSE            BIT(CTRL_PAUSE)
43 #define HW_ATL_FW2X_CTRL_TEMPERATURE      BIT(CTRL_TEMPERATURE)
44 #define HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE BIT(CTRL_ASYMMETRIC_PAUSE)
45 #define HW_ATL_FW2X_CTRL_INT_LOOPBACK     BIT(CTRL_INT_LOOPBACK)
46 #define HW_ATL_FW2X_CTRL_EXT_LOOPBACK     BIT(CTRL_EXT_LOOPBACK)
47 #define HW_ATL_FW2X_CTRL_DOWNSHIFT        BIT(CTRL_DOWNSHIFT)
48 #define HW_ATL_FW2X_CTRL_FORCE_RECONNECT  BIT(CTRL_FORCE_RECONNECT)
49 
50 #define HW_ATL_FW2X_CAP_EEE_1G_MASK      BIT(CAPS_HI_1000BASET_FD_EEE)
51 #define HW_ATL_FW2X_CAP_EEE_2G5_MASK     BIT(CAPS_HI_2P5GBASET_FD_EEE)
52 #define HW_ATL_FW2X_CAP_EEE_5G_MASK      BIT(CAPS_HI_5GBASET_FD_EEE)
53 #define HW_ATL_FW2X_CAP_EEE_10G_MASK     BIT(CAPS_HI_10GBASET_FD_EEE)
54 
55 #define HAL_ATLANTIC_WOL_FILTERS_COUNT   8
56 #define HAL_ATLANTIC_UTILS_FW2X_MSG_WOL  0x0E
57 
58 #define HW_ATL_FW_VER_LED                0x03010026U
59 #define HW_ATL_FW_VER_MEDIA_CONTROL      0x0301005aU
60 
61 struct __packed fw2x_msg_wol_pattern {
62 	u8 mask[16];
63 	u32 crc;
64 };
65 
66 struct __packed fw2x_msg_wol {
67 	u32 msg_id;
68 	u8 hw_addr[ETH_ALEN];
69 	u8 magic_packet_enabled;
70 	u8 filter_count;
71 	struct fw2x_msg_wol_pattern filter[HAL_ATLANTIC_WOL_FILTERS_COUNT];
72 	u8 link_up_enabled;
73 	u8 link_down_enabled;
74 	u16 reserved;
75 	u32 link_up_timeout;
76 	u32 link_down_timeout;
77 };
78 
79 static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed);
80 static int aq_fw2x_set_state(struct aq_hw_s *self,
81 			     enum hal_atl_utils_fw_state_e state);
82 
83 static u32 aq_fw2x_mbox_get(struct aq_hw_s *self);
84 static u32 aq_fw2x_rpc_get(struct aq_hw_s *self);
85 static int aq_fw2x_settings_get(struct aq_hw_s *self, u32 *addr);
86 static u32 aq_fw2x_state2_get(struct aq_hw_s *self);
87 
88 static int aq_fw2x_init(struct aq_hw_s *self)
89 {
90 	int err = 0;
91 
92 	/* check 10 times by 1ms */
93 	err = readx_poll_timeout_atomic(aq_fw2x_mbox_get,
94 					self, self->mbox_addr,
95 					self->mbox_addr != 0U,
96 					1000U, 10000U);
97 
98 	err = readx_poll_timeout_atomic(aq_fw2x_rpc_get,
99 					self, self->rpc_addr,
100 					self->rpc_addr != 0U,
101 					1000U, 100000U);
102 
103 	err = aq_fw2x_settings_get(self, &self->settings_addr);
104 
105 	return err;
106 }
107 
108 static int aq_fw2x_deinit(struct aq_hw_s *self)
109 {
110 	int err = aq_fw2x_set_link_speed(self, 0);
111 
112 	if (!err)
113 		err = aq_fw2x_set_state(self, MPI_DEINIT);
114 
115 	return err;
116 }
117 
118 static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed)
119 {
120 	enum hw_atl_fw2x_rate rate = 0;
121 
122 	if (speed & AQ_NIC_RATE_10G)
123 		rate |= FW2X_RATE_10G;
124 
125 	if (speed & AQ_NIC_RATE_5G)
126 		rate |= FW2X_RATE_5G;
127 
128 	if (speed & AQ_NIC_RATE_5GSR)
129 		rate |= FW2X_RATE_5G;
130 
131 	if (speed & AQ_NIC_RATE_2GS)
132 		rate |= FW2X_RATE_2G5;
133 
134 	if (speed & AQ_NIC_RATE_1G)
135 		rate |= FW2X_RATE_1G;
136 
137 	if (speed & AQ_NIC_RATE_100M)
138 		rate |= FW2X_RATE_100M;
139 
140 	return rate;
141 }
142 
143 static u32 fw2x_to_eee_mask(u32 speed)
144 {
145 	u32 rate = 0;
146 
147 	if (speed & HW_ATL_FW2X_CAP_EEE_10G_MASK)
148 		rate |= AQ_NIC_RATE_EEE_10G;
149 	if (speed & HW_ATL_FW2X_CAP_EEE_5G_MASK)
150 		rate |= AQ_NIC_RATE_EEE_5G;
151 	if (speed & HW_ATL_FW2X_CAP_EEE_2G5_MASK)
152 		rate |= AQ_NIC_RATE_EEE_2GS;
153 	if (speed & HW_ATL_FW2X_CAP_EEE_1G_MASK)
154 		rate |= AQ_NIC_RATE_EEE_1G;
155 
156 	return rate;
157 }
158 
159 static u32 eee_mask_to_fw2x(u32 speed)
160 {
161 	u32 rate = 0;
162 
163 	if (speed & AQ_NIC_RATE_EEE_10G)
164 		rate |= HW_ATL_FW2X_CAP_EEE_10G_MASK;
165 	if (speed & AQ_NIC_RATE_EEE_5G)
166 		rate |= HW_ATL_FW2X_CAP_EEE_5G_MASK;
167 	if (speed & AQ_NIC_RATE_EEE_2GS)
168 		rate |= HW_ATL_FW2X_CAP_EEE_2G5_MASK;
169 	if (speed & AQ_NIC_RATE_EEE_1G)
170 		rate |= HW_ATL_FW2X_CAP_EEE_1G_MASK;
171 
172 	return rate;
173 }
174 
175 static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed)
176 {
177 	u32 val = link_speed_mask_2fw2x_ratemask(speed);
178 
179 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, val);
180 
181 	return 0;
182 }
183 
184 static void aq_fw2x_upd_flow_control_bits(struct aq_hw_s *self,
185 					  u32 *mpi_state, u32 fc)
186 {
187 	*mpi_state &= ~(HW_ATL_FW2X_CTRL_PAUSE |
188 			HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE);
189 
190 	switch (fc) {
191 	/* There is not explicit mode of RX only pause frames,
192 	 * thus, we join this mode with FC full.
193 	 * FC full is either Rx, either Tx, or both.
194 	 */
195 	case AQ_NIC_FC_FULL:
196 	case AQ_NIC_FC_RX:
197 		*mpi_state |= HW_ATL_FW2X_CTRL_PAUSE |
198 			      HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE;
199 		break;
200 	case AQ_NIC_FC_TX:
201 		*mpi_state |= HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE;
202 		break;
203 	}
204 }
205 
206 static void aq_fw2x_upd_eee_rate_bits(struct aq_hw_s *self, u32 *mpi_opts,
207 				      u32 eee_speeds)
208 {
209 	*mpi_opts &= ~(HW_ATL_FW2X_CAP_EEE_1G_MASK |
210 		       HW_ATL_FW2X_CAP_EEE_2G5_MASK |
211 		       HW_ATL_FW2X_CAP_EEE_5G_MASK |
212 		       HW_ATL_FW2X_CAP_EEE_10G_MASK);
213 
214 	*mpi_opts |= eee_mask_to_fw2x(eee_speeds);
215 }
216 
217 static int aq_fw2x_set_state(struct aq_hw_s *self,
218 			     enum hal_atl_utils_fw_state_e state)
219 {
220 	u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
221 	struct aq_nic_cfg_s *cfg = self->aq_nic_cfg;
222 
223 	switch (state) {
224 	case MPI_INIT:
225 		mpi_state &= ~BIT(CAPS_HI_LINK_DROP);
226 		aq_fw2x_upd_eee_rate_bits(self, &mpi_state, cfg->eee_speeds);
227 		aq_fw2x_upd_flow_control_bits(self, &mpi_state,
228 					      self->aq_nic_cfg->fc.req);
229 		break;
230 	case MPI_DEINIT:
231 		mpi_state |= BIT(CAPS_HI_LINK_DROP);
232 		break;
233 	case MPI_RESET:
234 	case MPI_POWER:
235 		/* No actions */
236 		break;
237 	}
238 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
239 
240 	return 0;
241 }
242 
243 static int aq_fw2x_update_link_status(struct aq_hw_s *self)
244 {
245 	struct aq_hw_link_status_s *link_status = &self->aq_link_status;
246 	u32 mpi_state;
247 	u32 speed;
248 
249 	mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR);
250 	speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G |
251 			     FW2X_RATE_2G5 | FW2X_RATE_5G |
252 			     FW2X_RATE_10G);
253 
254 	if (speed) {
255 		if (speed & FW2X_RATE_10G)
256 			link_status->mbps = 10000;
257 		else if (speed & FW2X_RATE_5G)
258 			link_status->mbps = 5000;
259 		else if (speed & FW2X_RATE_2G5)
260 			link_status->mbps = 2500;
261 		else if (speed & FW2X_RATE_1G)
262 			link_status->mbps = 1000;
263 		else if (speed & FW2X_RATE_100M)
264 			link_status->mbps = 100;
265 		else
266 			link_status->mbps = 10000;
267 	} else {
268 		link_status->mbps = 0;
269 	}
270 
271 	return 0;
272 }
273 
274 static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
275 {
276 	u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
277 	u32 mac_addr[2] = { 0 };
278 	int err = 0;
279 	u32 h = 0U;
280 	u32 l = 0U;
281 
282 	if (efuse_addr != 0) {
283 		err = hw_atl_utils_fw_downld_dwords(self,
284 						    efuse_addr + (40U * 4U),
285 						    mac_addr,
286 						    ARRAY_SIZE(mac_addr));
287 		if (err)
288 			return err;
289 		mac_addr[0] = __swab32(mac_addr[0]);
290 		mac_addr[1] = __swab32(mac_addr[1]);
291 	}
292 
293 	ether_addr_copy(mac, (u8 *)mac_addr);
294 
295 	if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
296 		unsigned int rnd = 0;
297 
298 		get_random_bytes(&rnd, sizeof(unsigned int));
299 
300 		l = 0xE3000000U | (0xFFFFU & rnd) | (0x00 << 16);
301 		h = 0x8001300EU;
302 
303 		mac[5] = (u8)(0xFFU & l);
304 		l >>= 8;
305 		mac[4] = (u8)(0xFFU & l);
306 		l >>= 8;
307 		mac[3] = (u8)(0xFFU & l);
308 		l >>= 8;
309 		mac[2] = (u8)(0xFFU & l);
310 		mac[1] = (u8)(0xFFU & h);
311 		h >>= 8;
312 		mac[0] = (u8)(0xFFU & h);
313 	}
314 
315 	return err;
316 }
317 
318 static int aq_fw2x_update_stats(struct aq_hw_s *self)
319 {
320 	u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
321 	u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
322 	u32 stats_val;
323 	int err = 0;
324 
325 	/* Toggle statistics bit for FW to update */
326 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
327 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
328 
329 	/* Wait FW to report back */
330 	err = readx_poll_timeout_atomic(aq_fw2x_state2_get,
331 					self, stats_val,
332 					orig_stats_val != (stats_val &
333 					BIT(CAPS_HI_STATISTICS)),
334 					1U, 10000U);
335 	if (err)
336 		return err;
337 
338 	return hw_atl_utils_update_stats(self);
339 }
340 
341 static int aq_fw2x_get_phy_temp(struct aq_hw_s *self, int *temp)
342 {
343 	u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
344 	u32 temp_val = mpi_opts & HW_ATL_FW2X_CTRL_TEMPERATURE;
345 	u32 phy_temp_offset;
346 	u32 temp_res;
347 	int err = 0;
348 	u32 val;
349 
350 	phy_temp_offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox,
351 						     info.phy_temperature);
352 
353 	/* Toggle statistics bit for FW to 0x36C.18 (CTRL_TEMPERATURE) */
354 	mpi_opts = mpi_opts ^ HW_ATL_FW2X_CTRL_TEMPERATURE;
355 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
356 	/* Wait FW to report back */
357 	err = readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val,
358 					temp_val !=
359 					(val & HW_ATL_FW2X_CTRL_TEMPERATURE),
360 					1U, 10000U);
361 	err = hw_atl_utils_fw_downld_dwords(self, phy_temp_offset,
362 					    &temp_res, 1);
363 
364 	if (err)
365 		return err;
366 
367 	/* Convert PHY temperature from 1/256 degree Celsius
368 	 * to 1/1000 degree Celsius.
369 	 */
370 	*temp = (temp_res & 0xFFFF) * 1000 / 256;
371 
372 	return 0;
373 }
374 
375 static int aq_fw2x_set_wol(struct aq_hw_s *self, u8 *mac)
376 {
377 	struct hw_atl_utils_fw_rpc *rpc = NULL;
378 	struct offload_info *info = NULL;
379 	u32 wol_bits = 0;
380 	u32 rpc_size;
381 	int err = 0;
382 	u32 val;
383 
384 	if (self->aq_nic_cfg->wol & WAKE_PHY) {
385 		aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR,
386 				HW_ATL_FW2X_CTRL_LINK_DROP);
387 		readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val,
388 					  (val &
389 					   HW_ATL_FW2X_CTRL_LINK_DROP) != 0,
390 					  1000, 100000);
391 		wol_bits |= HW_ATL_FW2X_CTRL_WAKE_ON_LINK;
392 	}
393 
394 	if (self->aq_nic_cfg->wol & WAKE_MAGIC) {
395 		wol_bits |= HW_ATL_FW2X_CTRL_SLEEP_PROXY |
396 			    HW_ATL_FW2X_CTRL_WOL;
397 
398 		err = hw_atl_utils_fw_rpc_wait(self, &rpc);
399 		if (err < 0)
400 			goto err_exit;
401 
402 		rpc_size = sizeof(*info) +
403 			   offsetof(struct hw_atl_utils_fw_rpc, fw2x_offloads);
404 		memset(rpc, 0, rpc_size);
405 		info = &rpc->fw2x_offloads;
406 		memcpy(info->mac_addr, mac, ETH_ALEN);
407 		info->len = sizeof(*info);
408 
409 		err = hw_atl_utils_fw_rpc_call(self, rpc_size);
410 		if (err < 0)
411 			goto err_exit;
412 	}
413 
414 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, wol_bits);
415 
416 err_exit:
417 	return err;
418 }
419 
420 static int aq_fw2x_set_power(struct aq_hw_s *self, unsigned int power_state,
421 			     u8 *mac)
422 {
423 	int err = 0;
424 
425 	if (self->aq_nic_cfg->wol)
426 		err = aq_fw2x_set_wol(self, mac);
427 
428 	return err;
429 }
430 
431 static int aq_fw2x_send_fw_request(struct aq_hw_s *self,
432 				   const struct hw_fw_request_iface *fw_req,
433 				   size_t size)
434 {
435 	u32 ctrl2, orig_ctrl2;
436 	u32 dword_cnt;
437 	int err = 0;
438 	u32 val;
439 
440 	/* Write data to drvIface Mailbox */
441 	dword_cnt = size / sizeof(u32);
442 	if (size % sizeof(u32))
443 		dword_cnt++;
444 	err = hw_atl_write_fwcfg_dwords(self, (void *)fw_req, dword_cnt);
445 	if (err < 0)
446 		goto err_exit;
447 
448 	/* Toggle statistics bit for FW to update */
449 	ctrl2 = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
450 	orig_ctrl2 = ctrl2 & BIT(CAPS_HI_FW_REQUEST);
451 	ctrl2 = ctrl2 ^ BIT(CAPS_HI_FW_REQUEST);
452 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, ctrl2);
453 
454 	/* Wait FW to report back */
455 	err = readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val,
456 					orig_ctrl2 != (val &
457 						       BIT(CAPS_HI_FW_REQUEST)),
458 					1U, 10000U);
459 
460 err_exit:
461 	return err;
462 }
463 
464 static void aq_fw3x_enable_ptp(struct aq_hw_s *self, int enable)
465 {
466 	u32 ptp_opts = aq_hw_read_reg(self, HW_ATL_FW3X_EXT_STATE_ADDR);
467 	u32 all_ptp_features = BIT(CAPS_EX_PHY_PTP_EN) |
468 						   BIT(CAPS_EX_PTP_GPIO_EN);
469 
470 	if (enable)
471 		ptp_opts |= all_ptp_features;
472 	else
473 		ptp_opts &= ~all_ptp_features;
474 
475 	aq_hw_write_reg(self, HW_ATL_FW3X_EXT_CONTROL_ADDR, ptp_opts);
476 }
477 
478 static int aq_fw2x_led_control(struct aq_hw_s *self, u32 mode)
479 {
480 	if (self->fw_ver_actual < HW_ATL_FW_VER_LED)
481 		return -EOPNOTSUPP;
482 
483 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_LED_ADDR, mode);
484 
485 	return 0;
486 }
487 
488 static int aq_fw2x_set_eee_rate(struct aq_hw_s *self, u32 speed)
489 {
490 	u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
491 
492 	aq_fw2x_upd_eee_rate_bits(self, &mpi_opts, speed);
493 
494 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
495 
496 	return 0;
497 }
498 
499 static int aq_fw2x_get_eee_rate(struct aq_hw_s *self, u32 *rate,
500 				u32 *supported_rates)
501 {
502 	u32 mpi_state;
503 	u32 caps_hi;
504 	int err = 0;
505 	u32 offset;
506 
507 	offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox,
508 					    info.caps_hi);
509 
510 	err = hw_atl_utils_fw_downld_dwords(self, offset, &caps_hi, 1);
511 
512 	if (err)
513 		return err;
514 
515 	*supported_rates = fw2x_to_eee_mask(caps_hi);
516 
517 	mpi_state = aq_fw2x_state2_get(self);
518 	*rate = fw2x_to_eee_mask(mpi_state);
519 
520 	return err;
521 }
522 
523 static int aq_fw2x_renegotiate(struct aq_hw_s *self)
524 {
525 	u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
526 
527 	mpi_opts |= BIT(CTRL_FORCE_RECONNECT);
528 
529 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
530 
531 	return 0;
532 }
533 
534 static int aq_fw2x_set_flow_control(struct aq_hw_s *self)
535 {
536 	u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
537 
538 	aq_fw2x_upd_flow_control_bits(self, &mpi_state,
539 				      self->aq_nic_cfg->fc.req);
540 
541 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
542 
543 	return 0;
544 }
545 
546 static u32 aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fcmode)
547 {
548 	u32 mpi_state = aq_fw2x_state2_get(self);
549 	*fcmode = 0;
550 
551 	if (mpi_state & HW_ATL_FW2X_CAP_PAUSE)
552 		*fcmode |= AQ_NIC_FC_RX;
553 
554 	if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE)
555 		*fcmode |= AQ_NIC_FC_TX;
556 
557 	return 0;
558 }
559 
560 static int aq_fw2x_set_phyloopback(struct aq_hw_s *self, u32 mode, bool enable)
561 {
562 	u32 mpi_opts;
563 
564 	switch (mode) {
565 	case AQ_HW_LOOPBACK_PHYINT_SYS:
566 		mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
567 		if (enable)
568 			mpi_opts |= HW_ATL_FW2X_CTRL_INT_LOOPBACK;
569 		else
570 			mpi_opts &= ~HW_ATL_FW2X_CTRL_INT_LOOPBACK;
571 		aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
572 		break;
573 	case AQ_HW_LOOPBACK_PHYEXT_SYS:
574 		mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
575 		if (enable)
576 			mpi_opts |= HW_ATL_FW2X_CTRL_EXT_LOOPBACK;
577 		else
578 			mpi_opts &= ~HW_ATL_FW2X_CTRL_EXT_LOOPBACK;
579 		aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
580 		break;
581 	default:
582 		return -EINVAL;
583 	}
584 
585 	return 0;
586 }
587 
588 static u32 aq_fw2x_mbox_get(struct aq_hw_s *self)
589 {
590 	return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR);
591 }
592 
593 static u32 aq_fw2x_rpc_get(struct aq_hw_s *self)
594 {
595 	return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR);
596 }
597 
598 static int aq_fw2x_settings_get(struct aq_hw_s *self, u32 *addr)
599 {
600 	int err = 0;
601 	u32 offset;
602 
603 	offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox,
604 					    info.setting_address);
605 
606 	err = hw_atl_utils_fw_downld_dwords(self, offset, addr, 1);
607 
608 	return err;
609 }
610 
611 static u32 aq_fw2x_state2_get(struct aq_hw_s *self)
612 {
613 	return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR);
614 }
615 
616 const struct aq_fw_ops aq_fw_2x_ops = {
617 	.init               = aq_fw2x_init,
618 	.deinit             = aq_fw2x_deinit,
619 	.reset              = NULL,
620 	.renegotiate        = aq_fw2x_renegotiate,
621 	.get_mac_permanent  = aq_fw2x_get_mac_permanent,
622 	.set_link_speed     = aq_fw2x_set_link_speed,
623 	.set_state          = aq_fw2x_set_state,
624 	.update_link_status = aq_fw2x_update_link_status,
625 	.update_stats       = aq_fw2x_update_stats,
626 	.get_phy_temp       = aq_fw2x_get_phy_temp,
627 	.set_power          = aq_fw2x_set_power,
628 	.set_eee_rate       = aq_fw2x_set_eee_rate,
629 	.get_eee_rate       = aq_fw2x_get_eee_rate,
630 	.set_flow_control   = aq_fw2x_set_flow_control,
631 	.get_flow_control   = aq_fw2x_get_flow_control,
632 	.send_fw_request    = aq_fw2x_send_fw_request,
633 	.enable_ptp         = aq_fw3x_enable_ptp,
634 	.led_control        = aq_fw2x_led_control,
635 	.set_phyloopback    = aq_fw2x_set_phyloopback,
636 };
637