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