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