xref: /dpdk/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c (revision e77506397fc8005c5129e22e9e2d15d5876790fd)
1 // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2 /* Copyright (C) 2014-2017 aQuantia Corporation. */
3 
4 /* File hw_atl_utils_fw2x.c: Definition of firmware 2.x functions for
5  * Atlantic hardware abstraction layer.
6  */
7 
8 #include <rte_ether.h>
9 #include <pthread.h>
10 #include "../atl_hw_regs.h"
11 
12 #include "../atl_types.h"
13 #include "hw_atl_utils.h"
14 #include "hw_atl_llh.h"
15 
16 #define HW_ATL_FW2X_MPI_EFUSE_ADDR	0x364
17 #define HW_ATL_FW2X_MPI_MBOX_ADDR	0x360
18 #define HW_ATL_FW2X_MPI_RPC_ADDR	0x334
19 
20 #define HW_ATL_FW2X_MPI_CONTROL_ADDR	0x368
21 #define HW_ATL_FW2X_MPI_CONTROL2_ADDR	0x36C
22 #define HW_ATL_FW2X_MPI_LED_ADDR	0x31c
23 
24 #define HW_ATL_FW2X_MPI_STATE_ADDR	0x370
25 #define HW_ATL_FW2X_MPI_STATE2_ADDR	0x374
26 
27 #define HW_ATL_FW2X_CAP_SLEEP_PROXY BIT(CAPS_HI_SLEEP_PROXY)
28 #define HW_ATL_FW2X_CAP_WOL BIT(CAPS_HI_WOL)
29 
30 #define HW_ATL_FW2X_CAP_EEE_1G_MASK   BIT(CAPS_HI_1000BASET_FD_EEE)
31 #define HW_ATL_FW2X_CAP_EEE_2G5_MASK  BIT(CAPS_HI_2P5GBASET_FD_EEE)
32 #define HW_ATL_FW2X_CAP_EEE_5G_MASK   BIT(CAPS_HI_5GBASET_FD_EEE)
33 #define HW_ATL_FW2X_CAP_EEE_10G_MASK  BIT(CAPS_HI_10GBASET_FD_EEE)
34 
35 #define HAL_ATLANTIC_WOL_FILTERS_COUNT     8
36 #define HAL_ATLANTIC_UTILS_FW2X_MSG_WOL    0x0E
37 
38 #define HW_ATL_FW_FEATURE_LED 0x03010026
39 
40 struct __rte_packed_begin fw2x_msg_wol_pattern {
41 	u8 mask[16];
42 	u32 crc;
43 } __rte_packed_end;
44 
45 struct __rte_packed_begin fw2x_msg_wol {
46 	u32 msg_id;
47 	u8 hw_addr[6];
48 	u8 magic_packet_enabled;
49 	u8 filter_count;
50 	struct fw2x_msg_wol_pattern filter[HAL_ATLANTIC_WOL_FILTERS_COUNT];
51 	u8 link_up_enabled;
52 	u8 link_down_enabled;
53 	u16 reserved;
54 	u32 link_up_timeout;
55 	u32 link_down_timeout;
56 } __rte_packed_end;
57 
58 static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed);
59 static int aq_fw2x_set_state(struct aq_hw_s *self,
60 			     enum hal_atl_utils_fw_state_e state);
61 
62 static int aq_fw2x_init(struct aq_hw_s *self)
63 {
64 	int err = 0;
65 	struct hw_aq_atl_utils_mbox mbox;
66 
67 	/* check 10 times by 1ms */
68 	AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
69 		       aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR)),
70 		       1000U, 10U);
71 	AQ_HW_WAIT_FOR(0U != (self->rpc_addr =
72 		       aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR)),
73 		       1000U, 100U);
74 
75 	/* Read caps */
76 	hw_atl_utils_mpi_read_stats(self, &mbox);
77 
78 	self->caps_lo = mbox.info.caps_lo;
79 
80 	return err;
81 }
82 
83 static int aq_fw2x_deinit(struct aq_hw_s *self)
84 {
85 	int err = aq_fw2x_set_link_speed(self, 0);
86 
87 	if (!err)
88 		err = aq_fw2x_set_state(self, MPI_DEINIT);
89 
90 	return err;
91 }
92 
93 static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed)
94 {
95 	enum hw_atl_fw2x_rate rate = 0;
96 
97 	if (speed & AQ_NIC_RATE_10G)
98 		rate |= FW2X_RATE_10G;
99 
100 	if (speed & AQ_NIC_RATE_5G)
101 		rate |= FW2X_RATE_5G;
102 
103 	if (speed & AQ_NIC_RATE_5G5R)
104 		rate |= FW2X_RATE_5G;
105 
106 	if (speed & AQ_NIC_RATE_2G5)
107 		rate |= FW2X_RATE_2G5;
108 
109 	if (speed & AQ_NIC_RATE_1G)
110 		rate |= FW2X_RATE_1G;
111 
112 	if (speed & AQ_NIC_RATE_100M)
113 		rate |= FW2X_RATE_100M;
114 
115 	return rate;
116 }
117 
118 static u32 fw2x_to_eee_mask(u32 speed)
119 {
120 	u32 rate = 0;
121 
122 	if (speed & HW_ATL_FW2X_CAP_EEE_10G_MASK)
123 		rate |= AQ_NIC_RATE_EEE_10G;
124 
125 	if (speed & HW_ATL_FW2X_CAP_EEE_5G_MASK)
126 		rate |= AQ_NIC_RATE_EEE_5G;
127 
128 	if (speed & HW_ATL_FW2X_CAP_EEE_2G5_MASK)
129 		rate |= AQ_NIC_RATE_EEE_2G5;
130 
131 	if (speed & HW_ATL_FW2X_CAP_EEE_1G_MASK)
132 		rate |= AQ_NIC_RATE_EEE_1G;
133 
134 	return rate;
135 }
136 
137 static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed)
138 {
139 	u32 rate_mask = link_speed_mask_2fw2x_ratemask(speed);
140 	u32 reg_val = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR);
141 	u32 val = rate_mask | ((BIT(CAPS_LO_SMBUS_READ) |
142 				BIT(CAPS_LO_SMBUS_WRITE) |
143 				BIT(CAPS_LO_MACSEC)) & reg_val);
144 
145 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, val);
146 
147 	return 0;
148 }
149 
150 static void aq_fw2x_set_mpi_flow_control(struct aq_hw_s *self, u32 *mpi_state)
151 {
152 	if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_RX)
153 		*mpi_state |= BIT(CAPS_HI_PAUSE);
154 	else
155 		*mpi_state &= ~BIT(CAPS_HI_PAUSE);
156 
157 	if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_TX)
158 		*mpi_state |= BIT(CAPS_HI_ASYMMETRIC_PAUSE);
159 	else
160 		*mpi_state &= ~BIT(CAPS_HI_ASYMMETRIC_PAUSE);
161 }
162 
163 static int aq_fw2x_set_state(struct aq_hw_s *self,
164 			     enum hal_atl_utils_fw_state_e state)
165 {
166 	u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
167 
168 	switch (state) {
169 	case MPI_INIT:
170 		mpi_state &= ~BIT(CAPS_HI_LINK_DROP);
171 		aq_fw2x_set_mpi_flow_control(self, &mpi_state);
172 		break;
173 	case MPI_DEINIT:
174 		mpi_state |= BIT(CAPS_HI_LINK_DROP);
175 		break;
176 	case MPI_RESET:
177 	case MPI_POWER:
178 		/* No actions */
179 		break;
180 	}
181 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
182 	return 0;
183 }
184 
185 static int aq_fw2x_update_link_status(struct aq_hw_s *self)
186 {
187 	u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR);
188 	u32 speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G |
189 				FW2X_RATE_2G5 | FW2X_RATE_5G | FW2X_RATE_10G);
190 	struct aq_hw_link_status_s *link_status = &self->aq_link_status;
191 
192 	if (speed) {
193 		if (speed & FW2X_RATE_10G)
194 			link_status->mbps = 10000;
195 		else if (speed & FW2X_RATE_5G)
196 			link_status->mbps = 5000;
197 		else if (speed & FW2X_RATE_2G5)
198 			link_status->mbps = 2500;
199 		else if (speed & FW2X_RATE_1G)
200 			link_status->mbps = 1000;
201 		else if (speed & FW2X_RATE_100M)
202 			link_status->mbps = 100;
203 		else
204 			link_status->mbps = 10000;
205 	} else {
206 		link_status->mbps = 0;
207 	}
208 
209 	return 0;
210 }
211 
212 static
213 int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
214 {
215 	int err = 0;
216 	u32 h = 0U;
217 	u32 l = 0U;
218 	u32 mac_addr[2] = { 0 };
219 	u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
220 
221 	pthread_mutex_lock(&self->mbox_mutex);
222 
223 	if (efuse_addr != 0) {
224 		err = hw_atl_utils_fw_downld_dwords(self,
225 						    efuse_addr + (40U * 4U),
226 						    mac_addr,
227 						    ARRAY_SIZE(mac_addr));
228 		if (err)
229 			goto exit;
230 		mac_addr[0] = rte_constant_bswap32(mac_addr[0]);
231 		mac_addr[1] = rte_constant_bswap32(mac_addr[1]);
232 	}
233 
234 	rte_ether_addr_copy((struct rte_ether_addr *)mac_addr,
235 			(struct rte_ether_addr *)mac);
236 
237 	if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
238 		unsigned int rnd = (uint32_t)rte_rand();
239 
240 		//get_random_bytes(&rnd, sizeof(unsigned int));
241 
242 		l = 0xE3000000U
243 			| (0xFFFFU & rnd)
244 			| (0x00 << 16);
245 		h = 0x8001300EU;
246 
247 		mac[5] = (u8)(0xFFU & l);
248 		l >>= 8;
249 		mac[4] = (u8)(0xFFU & l);
250 		l >>= 8;
251 		mac[3] = (u8)(0xFFU & l);
252 		l >>= 8;
253 		mac[2] = (u8)(0xFFU & l);
254 		mac[1] = (u8)(0xFFU & h);
255 		h >>= 8;
256 		mac[0] = (u8)(0xFFU & h);
257 	}
258 
259 exit:
260 	pthread_mutex_unlock(&self->mbox_mutex);
261 
262 	return err;
263 }
264 
265 static int aq_fw2x_update_stats(struct aq_hw_s *self)
266 {
267 	int err = 0;
268 	u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
269 	u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
270 
271 
272 	pthread_mutex_lock(&self->mbox_mutex);
273 
274 	/* Toggle statistics bit for FW to update */
275 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
276 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
277 
278 	/* Wait FW to report back */
279 	AQ_HW_WAIT_FOR(orig_stats_val !=
280 		       (aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
281 				       BIT(CAPS_HI_STATISTICS)),
282 		       1U, 10000U);
283 	if (err)
284 		goto exit;
285 
286 	err = hw_atl_utils_update_stats(self);
287 
288 exit:
289 	pthread_mutex_unlock(&self->mbox_mutex);
290 
291 	return err;
292 
293 }
294 
295 static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
296 {
297 	int err = 0;
298 	u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
299 	u32 temp_val = mpi_opts & BIT(CAPS_HI_TEMPERATURE);
300 	u32 temp_res;
301 
302 	pthread_mutex_lock(&self->mbox_mutex);
303 
304 	/* Toggle statistics bit for FW to 0x36C.18 (CAPS_HI_TEMPERATURE) */
305 	mpi_opts = mpi_opts ^ BIT(CAPS_HI_TEMPERATURE);
306 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
307 
308 	/* Wait FW to report back */
309 	AQ_HW_WAIT_FOR(temp_val !=
310 			(aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
311 					BIT(CAPS_HI_TEMPERATURE)), 1U, 10000U);
312 	err = hw_atl_utils_fw_downld_dwords(self,
313 				self->mbox_addr +
314 				offsetof(struct hw_aq_atl_utils_mbox, info) +
315 				offsetof(struct hw_aq_info, phy_temperature),
316 				&temp_res,
317 				sizeof(temp_res) / sizeof(u32));
318 
319 
320 	pthread_mutex_unlock(&self->mbox_mutex);
321 
322 	if (err)
323 		return err;
324 
325 	*temp = temp_res  * 100 / 256;
326 	return 0;
327 }
328 
329 static int aq_fw2x_get_cable_len(struct aq_hw_s *self, int *cable_len)
330 {
331 	int err = 0;
332 	u32 cable_len_res;
333 
334 	err = hw_atl_utils_fw_downld_dwords(self,
335 				self->mbox_addr +
336 				offsetof(struct hw_aq_atl_utils_mbox, info) +
337 				offsetof(struct hw_aq_info, phy_temperature),
338 				&cable_len_res,
339 				sizeof(cable_len_res) / sizeof(u32));
340 
341 	if (err)
342 		return err;
343 
344 	*cable_len = (cable_len_res >> 16) & 0xFF;
345 	return 0;
346 }
347 
348 #ifndef ETH_ALEN
349 #define ETH_ALEN 6
350 #endif
351 
352 static int aq_fw2x_set_sleep_proxy(struct aq_hw_s *self, u8 *mac)
353 {
354 	int err = 0;
355 	struct hw_aq_atl_utils_fw_rpc *rpc = NULL;
356 	struct offload_info *cfg = NULL;
357 	unsigned int rpc_size = 0U;
358 	u32 mpi_opts;
359 
360 	rpc_size = sizeof(rpc->msg_id) + sizeof(*cfg);
361 
362 	err = hw_atl_utils_fw_rpc_wait(self, &rpc);
363 	if (err < 0)
364 		goto err_exit;
365 
366 	memset(rpc, 0, rpc_size);
367 	cfg = (struct offload_info *)(&rpc->msg_id + 1);
368 
369 	memcpy(cfg->mac_addr, mac, ETH_ALEN);
370 	cfg->len = sizeof(*cfg);
371 
372 	/* Clear bit 0x36C.23 */
373 	mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
374 	mpi_opts &= ~HW_ATL_FW2X_CAP_SLEEP_PROXY;
375 
376 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
377 
378 	err = hw_atl_utils_fw_rpc_call(self, rpc_size);
379 	if (err < 0)
380 		goto err_exit;
381 
382 	/* Set bit 0x36C.23 */
383 	mpi_opts |= HW_ATL_FW2X_CAP_SLEEP_PROXY;
384 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
385 
386 	AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
387 			HW_ATL_FW2X_CAP_SLEEP_PROXY), 1U, 10000U);
388 err_exit:
389 	return err;
390 }
391 
392 static int aq_fw2x_set_wol_params(struct aq_hw_s *self, u8 *mac)
393 {
394 	int err = 0;
395 	struct fw2x_msg_wol *msg = NULL;
396 	u32 mpi_opts;
397 
398 	struct hw_aq_atl_utils_fw_rpc *rpc = NULL;
399 
400 	err = hw_atl_utils_fw_rpc_wait(self, &rpc);
401 	if (err < 0)
402 		goto err_exit;
403 
404 	msg = (struct fw2x_msg_wol *)rpc;
405 
406 	msg->msg_id = HAL_ATLANTIC_UTILS_FW2X_MSG_WOL;
407 	msg->magic_packet_enabled = true;
408 	memcpy(msg->hw_addr, mac, ETH_ALEN);
409 
410 	mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
411 	mpi_opts &= ~(HW_ATL_FW2X_CAP_SLEEP_PROXY | HW_ATL_FW2X_CAP_WOL);
412 
413 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
414 
415 	err = hw_atl_utils_fw_rpc_call(self, sizeof(*msg));
416 	if (err < 0)
417 		goto err_exit;
418 
419 	/* Set bit 0x36C.24 */
420 	mpi_opts |= HW_ATL_FW2X_CAP_WOL;
421 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
422 
423 	AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
424 			HW_ATL_FW2X_CAP_WOL), 1U, 10000U);
425 err_exit:
426 	return err;
427 }
428 
429 static int aq_fw2x_set_power(struct aq_hw_s *self,
430 			     unsigned int power_state __rte_unused,
431 			     u8 *mac)
432 {
433 	int err = 0;
434 
435 	if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) {
436 		err = aq_fw2x_set_sleep_proxy(self, mac);
437 		if (err < 0)
438 			goto err_exit;
439 		err = aq_fw2x_set_wol_params(self, mac);
440 		if (err < 0)
441 			goto err_exit;
442 	}
443 err_exit:
444 	return err;
445 }
446 
447 static int aq_fw2x_set_eee_rate(struct aq_hw_s *self, u32 speed)
448 {
449 	u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
450 	mpi_opts &= ~(HW_ATL_FW2X_CAP_EEE_1G_MASK |
451 		HW_ATL_FW2X_CAP_EEE_2G5_MASK | HW_ATL_FW2X_CAP_EEE_5G_MASK |
452 		HW_ATL_FW2X_CAP_EEE_10G_MASK);
453 
454 	if (speed & AQ_NIC_RATE_EEE_10G)
455 		mpi_opts |= HW_ATL_FW2X_CAP_EEE_10G_MASK;
456 
457 	if (speed & AQ_NIC_RATE_EEE_5G)
458 		mpi_opts |= HW_ATL_FW2X_CAP_EEE_5G_MASK;
459 
460 	if (speed & AQ_NIC_RATE_EEE_2G5)
461 		mpi_opts |= HW_ATL_FW2X_CAP_EEE_2G5_MASK;
462 
463 	if (speed & AQ_NIC_RATE_EEE_1G)
464 		mpi_opts |= HW_ATL_FW2X_CAP_EEE_1G_MASK;
465 
466 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
467 
468 	return 0;
469 }
470 
471 static int aq_fw2x_get_eee_rate(struct aq_hw_s *self, u32 *rate,
472 					u32 *supported_rates)
473 {
474 	int err = 0;
475 	u32 caps_hi;
476 	u32 mpi_state;
477 
478 	err = hw_atl_utils_fw_downld_dwords(self,
479 				self->mbox_addr +
480 				offsetof(struct hw_aq_atl_utils_mbox, info) +
481 				offsetof(struct hw_aq_info, caps_hi),
482 				&caps_hi,
483 				sizeof(caps_hi) / sizeof(u32));
484 
485 	if (err)
486 		return err;
487 
488 	*supported_rates = fw2x_to_eee_mask(caps_hi);
489 
490 	mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR);
491 	*rate = fw2x_to_eee_mask(mpi_state);
492 
493 	return err;
494 }
495 
496 static int aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fc)
497 {
498 	u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
499 
500 	*fc = ((mpi_state & BIT(CAPS_HI_PAUSE)) ? AQ_NIC_FC_RX : 0) |
501 	      ((mpi_state & BIT(CAPS_HI_ASYMMETRIC_PAUSE)) ? AQ_NIC_FC_TX : 0);
502 
503 	return 0;
504 }
505 
506 static int aq_fw2x_set_flow_control(struct aq_hw_s *self)
507 {
508 	u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
509 
510 	aq_fw2x_set_mpi_flow_control(self, &mpi_state);
511 
512 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
513 
514 	return 0;
515 }
516 
517 static int aq_fw2x_led_control(struct aq_hw_s *self, u32 mode)
518 {
519 	if (self->fw_ver_actual < HW_ATL_FW_FEATURE_LED)
520 		return -EOPNOTSUPP;
521 
522 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_LED_ADDR, mode);
523 	return 0;
524 }
525 
526 static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
527 			      u32 *data, u32 len, u32 offset)
528 {
529 	u32 bytes_remains = len % sizeof(u32);
530 	u32 num_dwords = len / sizeof(u32);
531 	struct smbus_request request;
532 	u32 result = 0;
533 	u32 mpi_opts;
534 	int err = 0;
535 
536 	if ((self->caps_lo & BIT(CAPS_LO_SMBUS_READ)) == 0)
537 		return -EOPNOTSUPP;
538 
539 	pthread_mutex_lock(&self->mbox_mutex);
540 
541 	request.msg_id = 0;
542 	request.device_id = dev_addr;
543 	request.address = offset;
544 	request.length = len;
545 
546 	/* Write SMBUS request to cfg memory */
547 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
548 				(u32 *)(void *)&request,
549 				sizeof(request) / sizeof(u32));
550 
551 	if (err < 0)
552 		goto exit;
553 
554 	/* Toggle 0x368.CAPS_LO_SMBUS_READ bit */
555 	mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR);
556 	mpi_opts ^= BIT(CAPS_LO_SMBUS_READ);
557 
558 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, mpi_opts);
559 
560 	/* Wait until REQUEST_BIT matched in 0x370 */
561 
562 	AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR) &
563 		BIT(CAPS_LO_SMBUS_READ)) == (mpi_opts & BIT(CAPS_LO_SMBUS_READ)),
564 		10U, 10000U);
565 
566 	if (err < 0)
567 		goto exit;
568 
569 	err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr + sizeof(u32),
570 			&result,
571 			sizeof(result) / sizeof(u32));
572 
573 	if (err < 0)
574 		goto exit;
575 
576 	if (result) {
577 		err = -EIO;
578 		goto exit;
579 	}
580 
581 	if (num_dwords) {
582 		err = hw_atl_utils_fw_downld_dwords(self,
583 			self->rpc_addr + sizeof(u32) * 2,
584 			data,
585 			num_dwords);
586 
587 		if (err < 0)
588 			goto exit;
589 	}
590 
591 	if (bytes_remains) {
592 		u32 val = 0;
593 
594 		err = hw_atl_utils_fw_downld_dwords(self,
595 			self->rpc_addr + (sizeof(u32) * 2) +
596 			(num_dwords * sizeof(u32)),
597 			&val,
598 			1);
599 
600 		if (err < 0)
601 			goto exit;
602 
603 		rte_memcpy((u8 *)data + len - bytes_remains,
604 				&val, bytes_remains);
605 	}
606 
607 exit:
608 	pthread_mutex_unlock(&self->mbox_mutex);
609 
610 	return err;
611 }
612 
613 
614 static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
615 			      u32 *data, u32 len, u32 offset)
616 {
617 	struct smbus_request request;
618 	u32 mpi_opts, result = 0;
619 	int err = 0;
620 
621 	if ((self->caps_lo & BIT(CAPS_LO_SMBUS_WRITE)) == 0)
622 		return -EOPNOTSUPP;
623 
624 	request.msg_id = 0;
625 	request.device_id = dev_addr;
626 	request.address = offset;
627 	request.length = len;
628 
629 	pthread_mutex_lock(&self->mbox_mutex);
630 
631 	/* Write SMBUS request to cfg memory */
632 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
633 				(u32 *)(void *)&request,
634 				sizeof(request) / sizeof(u32));
635 
636 	if (err < 0)
637 		goto exit;
638 
639 	/* Write SMBUS data to cfg memory */
640 	u32 num_dwords = len / sizeof(u32);
641 	u32 bytes_remains = len % sizeof(u32);
642 
643 	if (num_dwords) {
644 		err = hw_atl_utils_fw_upload_dwords(self,
645 			self->rpc_addr + sizeof(request),
646 			(u32 *)(void *)data,
647 			num_dwords);
648 
649 		if (err < 0)
650 			goto exit;
651 	}
652 
653 	if (bytes_remains) {
654 		u32 val = 0;
655 
656 		rte_memcpy(&val, (u8 *)data + (sizeof(u32) * num_dwords),
657 			   bytes_remains);
658 
659 		err = hw_atl_utils_fw_upload_dwords(self,
660 			self->rpc_addr + sizeof(request) +
661 			(num_dwords * sizeof(u32)),
662 			&val,
663 			1);
664 
665 		if (err < 0)
666 			goto exit;
667 	}
668 
669 	/* Toggle 0x368.CAPS_LO_SMBUS_WRITE bit */
670 	mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR);
671 	mpi_opts ^= BIT(CAPS_LO_SMBUS_WRITE);
672 
673 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, mpi_opts);
674 
675 	/* Wait until REQUEST_BIT matched in 0x370 */
676 	AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR) &
677 		BIT(CAPS_LO_SMBUS_WRITE)) == (mpi_opts & BIT(CAPS_LO_SMBUS_WRITE)),
678 		10U, 10000U);
679 
680 	if (err < 0)
681 		goto exit;
682 
683 	/* Read status of write operation */
684 	err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr + sizeof(u32),
685 				&result,
686 				sizeof(result) / sizeof(u32));
687 
688 	if (err < 0)
689 		goto exit;
690 
691 	if (result) {
692 		err = -EIO;
693 		goto exit;
694 	}
695 
696 exit:
697 	pthread_mutex_unlock(&self->mbox_mutex);
698 
699 	return err;
700 }
701 
702 static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
703 				struct macsec_msg_fw_request *req,
704 				struct macsec_msg_fw_response *response)
705 {
706 	int err = 0;
707 	u32 mpi_opts = 0;
708 
709 	if (!req || !response)
710 		return 0;
711 
712 	if ((self->caps_lo & BIT(CAPS_LO_MACSEC)) == 0)
713 		return -EOPNOTSUPP;
714 
715 	pthread_mutex_lock(&self->mbox_mutex);
716 
717 	/* Write macsec request to cfg memory */
718 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
719 		(u32 *)(void *)req,
720 		RTE_ALIGN(sizeof(*req) / sizeof(u32), sizeof(u32)));
721 
722 	if (err < 0)
723 		goto exit;
724 
725 	/* Toggle 0x368.CAPS_LO_MACSEC bit */
726 	mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR);
727 	mpi_opts ^= BIT(CAPS_LO_MACSEC);
728 
729 	aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, mpi_opts);
730 
731 	/* Wait until REQUEST_BIT matched in 0x370 */
732 	AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR) &
733 		BIT(CAPS_LO_MACSEC)) == (mpi_opts & BIT(CAPS_LO_MACSEC)),
734 		1000U, 10000U);
735 
736 	if (err < 0)
737 		goto exit;
738 
739 	/* Read status of write operation */
740 	err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr + sizeof(u32),
741 		(u32 *)(void *)response,
742 		RTE_ALIGN(sizeof(*response) / sizeof(u32), sizeof(u32)));
743 
744 exit:
745 	pthread_mutex_unlock(&self->mbox_mutex);
746 
747 	return err;
748 }
749 
750 const struct aq_fw_ops aq_fw_2x_ops = {
751 	.init = aq_fw2x_init,
752 	.deinit = aq_fw2x_deinit,
753 	.reset = NULL,
754 	.get_mac_permanent = aq_fw2x_get_mac_permanent,
755 	.set_link_speed = aq_fw2x_set_link_speed,
756 	.set_state = aq_fw2x_set_state,
757 	.update_link_status = aq_fw2x_update_link_status,
758 	.update_stats = aq_fw2x_update_stats,
759 	.set_power = aq_fw2x_set_power,
760 	.get_temp = aq_fw2x_get_temp,
761 	.get_cable_len = aq_fw2x_get_cable_len,
762 	.set_eee_rate = aq_fw2x_set_eee_rate,
763 	.get_eee_rate = aq_fw2x_get_eee_rate,
764 	.get_flow_control = aq_fw2x_get_flow_control,
765 	.set_flow_control = aq_fw2x_set_flow_control,
766 	.led_control = aq_fw2x_led_control,
767 	.get_eeprom = aq_fw2x_get_eeprom,
768 	.set_eeprom = aq_fw2x_set_eeprom,
769 	.send_macsec_req = aq_fw2x_send_macsec_request,
770 };
771