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