net/atlantic: use EEPROM magic as a device address
[dpdk.git] / 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_EEPROM 0x03010025
38 #define HW_ATL_FW_FEATURE_LED 0x03010026
39
40 struct fw2x_msg_wol_pattern {
41         u8 mask[16];
42         u32 crc;
43 } __attribute__((__packed__));
44
45 struct 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 } __attribute__((__packed__));
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
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         return err;
74 }
75
76 static int aq_fw2x_deinit(struct aq_hw_s *self)
77 {
78         int err = aq_fw2x_set_link_speed(self, 0);
79
80         if (!err)
81                 err = aq_fw2x_set_state(self, MPI_DEINIT);
82
83         return err;
84 }
85
86 static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed)
87 {
88         enum hw_atl_fw2x_rate rate = 0;
89
90         if (speed & AQ_NIC_RATE_10G)
91                 rate |= FW2X_RATE_10G;
92
93         if (speed & AQ_NIC_RATE_5G)
94                 rate |= FW2X_RATE_5G;
95
96         if (speed & AQ_NIC_RATE_5G5R)
97                 rate |= FW2X_RATE_5G;
98
99         if (speed & AQ_NIC_RATE_2G5)
100                 rate |= FW2X_RATE_2G5;
101
102         if (speed & AQ_NIC_RATE_1G)
103                 rate |= FW2X_RATE_1G;
104
105         if (speed & AQ_NIC_RATE_100M)
106                 rate |= FW2X_RATE_100M;
107
108         return rate;
109 }
110
111 static u32 fw2x_to_eee_mask(u32 speed)
112 {
113         u32 rate = 0;
114
115         if (speed & HW_ATL_FW2X_CAP_EEE_10G_MASK)
116                 rate |= AQ_NIC_RATE_EEE_10G;
117
118         if (speed & HW_ATL_FW2X_CAP_EEE_5G_MASK)
119                 rate |= AQ_NIC_RATE_EEE_5G;
120
121         if (speed & HW_ATL_FW2X_CAP_EEE_2G5_MASK)
122                 rate |= AQ_NIC_RATE_EEE_2G5;
123
124         if (speed & HW_ATL_FW2X_CAP_EEE_1G_MASK)
125                 rate |= AQ_NIC_RATE_EEE_1G;
126
127         return rate;
128 }
129
130 static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed)
131 {
132         u32 rate_mask = link_speed_mask_2fw2x_ratemask(speed);
133         u32 reg_val = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR);
134         u32 val = rate_mask | ((BIT(CAPS_LO_SMBUS_READ) |
135                                 BIT(CAPS_LO_SMBUS_WRITE) |
136                                 BIT(CAPS_LO_MACSEC)) & reg_val);
137
138         aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, val);
139
140         return 0;
141 }
142
143 static void aq_fw2x_set_mpi_flow_control(struct aq_hw_s *self, u32 *mpi_state)
144 {
145         if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_RX)
146                 *mpi_state |= BIT(CAPS_HI_PAUSE);
147         else
148                 *mpi_state &= ~BIT(CAPS_HI_PAUSE);
149
150         if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_TX)
151                 *mpi_state |= BIT(CAPS_HI_ASYMMETRIC_PAUSE);
152         else
153                 *mpi_state &= ~BIT(CAPS_HI_ASYMMETRIC_PAUSE);
154 }
155
156 static int aq_fw2x_set_state(struct aq_hw_s *self,
157                              enum hal_atl_utils_fw_state_e state)
158 {
159         u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
160
161         switch (state) {
162         case MPI_INIT:
163                 mpi_state &= ~BIT(CAPS_HI_LINK_DROP);
164                 aq_fw2x_set_mpi_flow_control(self, &mpi_state);
165                 break;
166         case MPI_DEINIT:
167                 mpi_state |= BIT(CAPS_HI_LINK_DROP);
168                 break;
169         case MPI_RESET:
170         case MPI_POWER:
171                 /* No actions */
172                 break;
173         }
174         aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
175         return 0;
176 }
177
178 static int aq_fw2x_update_link_status(struct aq_hw_s *self)
179 {
180         u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR);
181         u32 speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G |
182                                 FW2X_RATE_2G5 | FW2X_RATE_5G | FW2X_RATE_10G);
183         struct aq_hw_link_status_s *link_status = &self->aq_link_status;
184
185         if (speed) {
186                 if (speed & FW2X_RATE_10G)
187                         link_status->mbps = 10000;
188                 else if (speed & FW2X_RATE_5G)
189                         link_status->mbps = 5000;
190                 else if (speed & FW2X_RATE_2G5)
191                         link_status->mbps = 2500;
192                 else if (speed & FW2X_RATE_1G)
193                         link_status->mbps = 1000;
194                 else if (speed & FW2X_RATE_100M)
195                         link_status->mbps = 100;
196                 else
197                         link_status->mbps = 10000;
198         } else {
199                 link_status->mbps = 0;
200         }
201
202         return 0;
203 }
204
205 static
206 int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
207 {
208         int err = 0;
209         u32 h = 0U;
210         u32 l = 0U;
211         u32 mac_addr[2] = { 0 };
212         u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
213
214         if (efuse_addr != 0) {
215                 err = hw_atl_utils_fw_downld_dwords(self,
216                                                     efuse_addr + (40U * 4U),
217                                                     mac_addr,
218                                                     ARRAY_SIZE(mac_addr));
219                 if (err)
220                         return err;
221                 mac_addr[0] = rte_constant_bswap32(mac_addr[0]);
222                 mac_addr[1] = rte_constant_bswap32(mac_addr[1]);
223         }
224
225         ether_addr_copy((struct ether_addr *)mac_addr,
226                         (struct ether_addr *)mac);
227
228         if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
229                 unsigned int rnd = (uint32_t)rte_rand();
230
231                 //get_random_bytes(&rnd, sizeof(unsigned int));
232
233                 l = 0xE3000000U
234                         | (0xFFFFU & rnd)
235                         | (0x00 << 16);
236                 h = 0x8001300EU;
237
238                 mac[5] = (u8)(0xFFU & l);
239                 l >>= 8;
240                 mac[4] = (u8)(0xFFU & l);
241                 l >>= 8;
242                 mac[3] = (u8)(0xFFU & l);
243                 l >>= 8;
244                 mac[2] = (u8)(0xFFU & l);
245                 mac[1] = (u8)(0xFFU & h);
246                 h >>= 8;
247                 mac[0] = (u8)(0xFFU & h);
248         }
249         return err;
250 }
251
252 static int aq_fw2x_update_stats(struct aq_hw_s *self)
253 {
254         int err = 0;
255         u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
256         u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
257
258         /* Toggle statistics bit for FW to update */
259         mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
260         aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
261
262         /* Wait FW to report back */
263         AQ_HW_WAIT_FOR(orig_stats_val !=
264                        (aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
265                                        BIT(CAPS_HI_STATISTICS)),
266                        1U, 10000U);
267         if (err)
268                 return err;
269
270         return hw_atl_utils_update_stats(self);
271 }
272
273 static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
274 {
275         int err = 0;
276         u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
277         u32 temp_val = mpi_opts & BIT(CAPS_HI_TEMPERATURE);
278         u32 temp_res;
279
280         /* Toggle statistics bit for FW to 0x36C.18 (CAPS_HI_TEMPERATURE) */
281         mpi_opts = mpi_opts ^ BIT(CAPS_HI_TEMPERATURE);
282         aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
283
284         /* Wait FW to report back */
285         AQ_HW_WAIT_FOR(temp_val !=
286                         (aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
287                                         BIT(CAPS_HI_TEMPERATURE)), 1U, 10000U);
288         err = hw_atl_utils_fw_downld_dwords(self,
289                                 self->mbox_addr +
290                                 offsetof(struct hw_aq_atl_utils_mbox, info) +
291                                 offsetof(struct hw_aq_info, phy_temperature),
292                                 &temp_res,
293                                 sizeof(temp_res) / sizeof(u32));
294
295         if (err)
296                 return err;
297
298         *temp = temp_res  * 100 / 256;
299         return 0;
300 }
301
302 static int aq_fw2x_get_cable_len(struct aq_hw_s *self, int *cable_len)
303 {
304         int err = 0;
305         u32 cable_len_res;
306
307         err = hw_atl_utils_fw_downld_dwords(self,
308                                 self->mbox_addr +
309                                 offsetof(struct hw_aq_atl_utils_mbox, info) +
310                                 offsetof(struct hw_aq_info, phy_temperature),
311                                 &cable_len_res,
312                                 sizeof(cable_len_res) / sizeof(u32));
313
314         if (err)
315                 return err;
316
317         *cable_len = (cable_len_res >> 16) & 0xFF;
318         return 0;
319 }
320
321 #ifndef ETH_ALEN
322 #define ETH_ALEN 6
323 #endif
324
325 static int aq_fw2x_set_sleep_proxy(struct aq_hw_s *self, u8 *mac)
326 {
327         int err = 0;
328         struct hw_aq_atl_utils_fw_rpc *rpc = NULL;
329         struct offload_info *cfg = NULL;
330         unsigned int rpc_size = 0U;
331         u32 mpi_opts;
332
333         rpc_size = sizeof(rpc->msg_id) + sizeof(*cfg);
334
335         err = hw_atl_utils_fw_rpc_wait(self, &rpc);
336         if (err < 0)
337                 goto err_exit;
338
339         memset(rpc, 0, rpc_size);
340         cfg = (struct offload_info *)(&rpc->msg_id + 1);
341
342         memcpy(cfg->mac_addr, mac, ETH_ALEN);
343         cfg->len = sizeof(*cfg);
344
345         /* Clear bit 0x36C.23 */
346         mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
347         mpi_opts &= ~HW_ATL_FW2X_CAP_SLEEP_PROXY;
348
349         aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
350
351         err = hw_atl_utils_fw_rpc_call(self, rpc_size);
352         if (err < 0)
353                 goto err_exit;
354
355         /* Set bit 0x36C.23 */
356         mpi_opts |= HW_ATL_FW2X_CAP_SLEEP_PROXY;
357         aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
358
359         AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
360                         HW_ATL_FW2X_CAP_SLEEP_PROXY), 1U, 10000U);
361 err_exit:
362         return err;
363 }
364
365 static int aq_fw2x_set_wol_params(struct aq_hw_s *self, u8 *mac)
366 {
367         int err = 0;
368         struct fw2x_msg_wol *msg = NULL;
369         u32 mpi_opts;
370
371         struct hw_aq_atl_utils_fw_rpc *rpc = NULL;
372
373         err = hw_atl_utils_fw_rpc_wait(self, &rpc);
374         if (err < 0)
375                 goto err_exit;
376
377         msg = (struct fw2x_msg_wol *)rpc;
378
379         msg->msg_id = HAL_ATLANTIC_UTILS_FW2X_MSG_WOL;
380         msg->magic_packet_enabled = true;
381         memcpy(msg->hw_addr, mac, ETH_ALEN);
382
383         mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
384         mpi_opts &= ~(HW_ATL_FW2X_CAP_SLEEP_PROXY | HW_ATL_FW2X_CAP_WOL);
385
386         aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
387
388         err = hw_atl_utils_fw_rpc_call(self, sizeof(*msg));
389         if (err < 0)
390                 goto err_exit;
391
392         /* Set bit 0x36C.24 */
393         mpi_opts |= HW_ATL_FW2X_CAP_WOL;
394         aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
395
396         AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
397                         HW_ATL_FW2X_CAP_WOL), 1U, 10000U);
398 err_exit:
399         return err;
400 }
401
402 static int aq_fw2x_set_power(struct aq_hw_s *self,
403                              unsigned int power_state __rte_unused,
404                              u8 *mac)
405 {
406         int err = 0;
407
408         if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) {
409                 err = aq_fw2x_set_sleep_proxy(self, mac);
410                 if (err < 0)
411                         goto err_exit;
412                 err = aq_fw2x_set_wol_params(self, mac);
413                 if (err < 0)
414                         goto err_exit;
415         }
416 err_exit:
417         return err;
418 }
419
420 static int aq_fw2x_set_eee_rate(struct aq_hw_s *self, u32 speed)
421 {
422         u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
423         mpi_opts &= ~(HW_ATL_FW2X_CAP_EEE_1G_MASK |
424                 HW_ATL_FW2X_CAP_EEE_2G5_MASK | HW_ATL_FW2X_CAP_EEE_5G_MASK |
425                 HW_ATL_FW2X_CAP_EEE_10G_MASK);
426
427         if (speed & AQ_NIC_RATE_EEE_10G)
428                 mpi_opts |= HW_ATL_FW2X_CAP_EEE_10G_MASK;
429
430         if (speed & AQ_NIC_RATE_EEE_5G)
431                 mpi_opts |= HW_ATL_FW2X_CAP_EEE_5G_MASK;
432
433         if (speed & AQ_NIC_RATE_EEE_2G5)
434                 mpi_opts |= HW_ATL_FW2X_CAP_EEE_2G5_MASK;
435
436         if (speed & AQ_NIC_RATE_EEE_1G)
437                 mpi_opts |= HW_ATL_FW2X_CAP_EEE_1G_MASK;
438
439         aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
440
441         return 0;
442 }
443
444 static int aq_fw2x_get_eee_rate(struct aq_hw_s *self, u32 *rate,
445                                         u32 *supported_rates)
446 {
447         int err = 0;
448         u32 caps_hi;
449         u32 mpi_state;
450
451         err = hw_atl_utils_fw_downld_dwords(self,
452                                 self->mbox_addr +
453                                 offsetof(struct hw_aq_atl_utils_mbox, info) +
454                                 offsetof(struct hw_aq_info, caps_hi),
455                                 &caps_hi,
456                                 sizeof(caps_hi) / sizeof(u32));
457
458         if (err)
459                 return err;
460
461         *supported_rates = fw2x_to_eee_mask(caps_hi);
462
463         mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR);
464         *rate = fw2x_to_eee_mask(mpi_state);
465
466         return err;
467 }
468
469
470
471 static int aq_fw2x_set_flow_control(struct aq_hw_s *self)
472 {
473         u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
474
475         aq_fw2x_set_mpi_flow_control(self, &mpi_state);
476
477         aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
478
479         return 0;
480 }
481
482 static int aq_fw2x_led_control(struct aq_hw_s *self, u32 mode)
483 {
484         if (self->fw_ver_actual < HW_ATL_FW_FEATURE_LED)
485                 return -EOPNOTSUPP;
486
487         aq_hw_write_reg(self, HW_ATL_FW2X_MPI_LED_ADDR, mode);
488         return 0;
489 }
490
491 static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
492                               u32 *data, u32 len, u32 offset)
493 {
494         int err = 0;
495         struct smbus_read_request request;
496         u32 mpi_opts;
497         u32 result = 0;
498
499         if (self->fw_ver_actual < HW_ATL_FW_FEATURE_EEPROM)
500                 return -EOPNOTSUPP;
501
502         request.device_id = dev_addr;
503         request.address = offset;
504         request.length = len;
505
506         /* Write SMBUS request to cfg memory */
507         err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
508                                 (u32 *)(void *)&request,
509                                 sizeof(request) / sizeof(u32));
510
511         if (err < 0)
512                 return err;
513
514         /* Toggle 0x368.CAPS_LO_SMBUS_READ bit */
515         mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR);
516         mpi_opts ^= BIT(CAPS_LO_SMBUS_READ);
517
518         aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, mpi_opts);
519
520         /* Wait until REQUEST_BIT matched in 0x370 */
521
522         AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR) &
523                 BIT(CAPS_LO_SMBUS_READ)) == (mpi_opts & BIT(CAPS_LO_SMBUS_READ)),
524                 10U, 10000U);
525
526         if (err < 0)
527                 return err;
528
529         err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr + sizeof(u32),
530                         &result,
531                         sizeof(result) / sizeof(u32));
532
533         if (err < 0)
534                 return err;
535
536         if (result == 0) {
537                 err = hw_atl_utils_fw_downld_dwords(self,
538                                 self->rpc_addr + sizeof(u32) * 2,
539                                 data,
540                                 RTE_ALIGN(len, sizeof(u32)));
541
542                 if (err < 0)
543                         return err;
544         }
545
546         return 0;
547 }
548
549
550 static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
551                               u32 *data, u32 len)
552 {
553         struct smbus_write_request request;
554         u32 mpi_opts, result = 0;
555         int err = 0;
556
557         if (self->fw_ver_actual < HW_ATL_FW_FEATURE_EEPROM)
558                 return -EOPNOTSUPP;
559
560         request.device_id = dev_addr;
561         request.address = 0;
562         request.length = len;
563
564         /* Write SMBUS request to cfg memory */
565         err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
566                                 (u32 *)(void *)&request,
567                                 sizeof(request) / sizeof(u32));
568
569         if (err < 0)
570                 return err;
571
572         /* Write SMBUS data to cfg memory */
573         err = hw_atl_utils_fw_upload_dwords(self,
574                                 self->rpc_addr + sizeof(request),
575                                 (u32 *)(void *)data,
576                                 RTE_ALIGN(len, sizeof(u32)));
577
578         if (err < 0)
579                 return err;
580
581         /* Toggle 0x368.CAPS_LO_SMBUS_WRITE bit */
582         mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR);
583         mpi_opts ^= BIT(CAPS_LO_SMBUS_WRITE);
584
585         aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, mpi_opts);
586
587         /* Wait until REQUEST_BIT matched in 0x370 */
588         AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR) &
589                 BIT(CAPS_LO_SMBUS_WRITE)) == (mpi_opts & BIT(CAPS_LO_SMBUS_WRITE)),
590                 10U, 10000U);
591
592         if (err < 0)
593                 return err;
594
595         /* Read status of write operation */
596         err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr + sizeof(u32),
597                                 &result,
598                                 sizeof(result) / sizeof(u32));
599
600         if (err < 0)
601                 return err;
602
603         return 0;
604 }
605
606 const struct aq_fw_ops aq_fw_2x_ops = {
607         .init = aq_fw2x_init,
608         .deinit = aq_fw2x_deinit,
609         .reset = NULL,
610         .get_mac_permanent = aq_fw2x_get_mac_permanent,
611         .set_link_speed = aq_fw2x_set_link_speed,
612         .set_state = aq_fw2x_set_state,
613         .update_link_status = aq_fw2x_update_link_status,
614         .update_stats = aq_fw2x_update_stats,
615         .set_power = aq_fw2x_set_power,
616         .get_temp = aq_fw2x_get_temp,
617         .get_cable_len = aq_fw2x_get_cable_len,
618         .set_eee_rate = aq_fw2x_set_eee_rate,
619         .get_eee_rate = aq_fw2x_get_eee_rate,
620         .set_flow_control = aq_fw2x_set_flow_control,
621         .led_control = aq_fw2x_led_control,
622         .get_eeprom = aq_fw2x_get_eeprom,
623         .set_eeprom = aq_fw2x_set_eeprom,
624 };