forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
....@@ -1,10 +1,8 @@
1
-/*
2
- * aQuantia Corporation Network Driver
3
- * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
1
+// SPDX-License-Identifier: GPL-2.0-only
2
+/* Atlantic Network Driver
43 *
5
- * This program is free software; you can redistribute it and/or modify it
6
- * under the terms and conditions of the GNU General Public License,
7
- * version 2, as published by the Free Software Foundation.
4
+ * Copyright (C) 2014-2019 aQuantia Corporation
5
+ * Copyright (C) 2019-2020 Marvell International Ltd.
86 */
97
108 /* File hw_atl_utils_fw2x.c: Definition of firmware 2.x functions for
....@@ -16,34 +14,100 @@
1614 #include "../aq_pci_func.h"
1715 #include "../aq_ring.h"
1816 #include "../aq_vec.h"
17
+#include "../aq_nic.h"
1918 #include "hw_atl_utils.h"
2019 #include "hw_atl_llh.h"
2120
22
-#define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364
23
-#define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360
24
-#define HW_ATL_FW2X_MPI_RPC_ADDR 0x334
21
+#define HW_ATL_FW2X_MPI_LED_ADDR 0x31c
22
+#define HW_ATL_FW2X_MPI_RPC_ADDR 0x334
2523
26
-#define HW_ATL_FW2X_MPI_CONTROL_ADDR 0x368
27
-#define HW_ATL_FW2X_MPI_CONTROL2_ADDR 0x36C
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
2830
29
-#define HW_ATL_FW2X_MPI_STATE_ADDR 0x370
30
-#define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374
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
+};
3184
3285 static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed);
3386 static int aq_fw2x_set_state(struct aq_hw_s *self,
3487 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);
3594
3695 static int aq_fw2x_init(struct aq_hw_s *self)
3796 {
3897 int err = 0;
3998
4099 /* check 10 times by 1ms */
41
- AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
42
- aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR)),
43
- 1000U, 10U);
44
- AQ_HW_WAIT_FOR(0U != (self->rpc_addr =
45
- aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR)),
46
- 1000U, 100U);
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);
47111
48112 return err;
49113 }
....@@ -68,10 +132,7 @@
68132 if (speed & AQ_NIC_RATE_5G)
69133 rate |= FW2X_RATE_5G;
70134
71
- if (speed & AQ_NIC_RATE_5GSR)
72
- rate |= FW2X_RATE_5G;
73
-
74
- if (speed & AQ_NIC_RATE_2GS)
135
+ if (speed & AQ_NIC_RATE_2G5)
75136 rate |= FW2X_RATE_2G5;
76137
77138 if (speed & AQ_NIC_RATE_1G)
....@@ -79,6 +140,38 @@
79140
80141 if (speed & AQ_NIC_RATE_100M)
81142 rate |= FW2X_RATE_100M;
143
+
144
+ return rate;
145
+}
146
+
147
+static u32 fw2x_to_eee_mask(u32 speed)
148
+{
149
+ u32 rate = 0;
150
+
151
+ if (speed & HW_ATL_FW2X_CAP_EEE_10G_MASK)
152
+ rate |= AQ_NIC_RATE_EEE_10G;
153
+ if (speed & HW_ATL_FW2X_CAP_EEE_5G_MASK)
154
+ rate |= AQ_NIC_RATE_EEE_5G;
155
+ if (speed & HW_ATL_FW2X_CAP_EEE_2G5_MASK)
156
+ rate |= AQ_NIC_RATE_EEE_2G5;
157
+ if (speed & HW_ATL_FW2X_CAP_EEE_1G_MASK)
158
+ rate |= AQ_NIC_RATE_EEE_1G;
159
+
160
+ return rate;
161
+}
162
+
163
+static u32 eee_mask_to_fw2x(u32 speed)
164
+{
165
+ u32 rate = 0;
166
+
167
+ if (speed & AQ_NIC_RATE_EEE_10G)
168
+ rate |= HW_ATL_FW2X_CAP_EEE_10G_MASK;
169
+ if (speed & AQ_NIC_RATE_EEE_5G)
170
+ rate |= HW_ATL_FW2X_CAP_EEE_5G_MASK;
171
+ if (speed & AQ_NIC_RATE_EEE_2G5)
172
+ rate |= HW_ATL_FW2X_CAP_EEE_2G5_MASK;
173
+ if (speed & AQ_NIC_RATE_EEE_1G)
174
+ rate |= HW_ATL_FW2X_CAP_EEE_1G_MASK;
82175
83176 return rate;
84177 }
....@@ -92,28 +185,51 @@
92185 return 0;
93186 }
94187
95
-static void aq_fw2x_set_mpi_flow_control(struct aq_hw_s *self, u32 *mpi_state)
188
+static void aq_fw2x_upd_flow_control_bits(struct aq_hw_s *self,
189
+ u32 *mpi_state, u32 fc)
96190 {
97
- if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_RX)
98
- *mpi_state |= BIT(CAPS_HI_PAUSE);
99
- else
100
- *mpi_state &= ~BIT(CAPS_HI_PAUSE);
191
+ *mpi_state &= ~(HW_ATL_FW2X_CTRL_PAUSE |
192
+ HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE);
101193
102
- if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_TX)
103
- *mpi_state |= BIT(CAPS_HI_ASYMMETRIC_PAUSE);
104
- else
105
- *mpi_state &= ~BIT(CAPS_HI_ASYMMETRIC_PAUSE);
194
+ switch (fc) {
195
+ /* There is not explicit mode of RX only pause frames,
196
+ * thus, we join this mode with FC full.
197
+ * FC full is either Rx, either Tx, or both.
198
+ */
199
+ case AQ_NIC_FC_FULL:
200
+ case AQ_NIC_FC_RX:
201
+ *mpi_state |= HW_ATL_FW2X_CTRL_PAUSE |
202
+ HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE;
203
+ break;
204
+ case AQ_NIC_FC_TX:
205
+ *mpi_state |= HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE;
206
+ break;
207
+ }
208
+}
209
+
210
+static void aq_fw2x_upd_eee_rate_bits(struct aq_hw_s *self, u32 *mpi_opts,
211
+ u32 eee_speeds)
212
+{
213
+ *mpi_opts &= ~(HW_ATL_FW2X_CAP_EEE_1G_MASK |
214
+ HW_ATL_FW2X_CAP_EEE_2G5_MASK |
215
+ HW_ATL_FW2X_CAP_EEE_5G_MASK |
216
+ HW_ATL_FW2X_CAP_EEE_10G_MASK);
217
+
218
+ *mpi_opts |= eee_mask_to_fw2x(eee_speeds);
106219 }
107220
108221 static int aq_fw2x_set_state(struct aq_hw_s *self,
109222 enum hal_atl_utils_fw_state_e state)
110223 {
111224 u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
225
+ struct aq_nic_cfg_s *cfg = self->aq_nic_cfg;
112226
113227 switch (state) {
114228 case MPI_INIT:
115229 mpi_state &= ~BIT(CAPS_HI_LINK_DROP);
116
- aq_fw2x_set_mpi_flow_control(self, &mpi_state);
230
+ aq_fw2x_upd_eee_rate_bits(self, &mpi_state, cfg->eee_speeds);
231
+ aq_fw2x_upd_flow_control_bits(self, &mpi_state,
232
+ self->aq_nic_cfg->fc.req);
117233 break;
118234 case MPI_DEINIT:
119235 mpi_state |= BIT(CAPS_HI_LINK_DROP);
....@@ -124,15 +240,20 @@
124240 break;
125241 }
126242 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
243
+
127244 return 0;
128245 }
129246
130247 static int aq_fw2x_update_link_status(struct aq_hw_s *self)
131248 {
132
- u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR);
133
- u32 speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G |
134
- FW2X_RATE_2G5 | FW2X_RATE_5G | FW2X_RATE_10G);
135249 struct aq_hw_link_status_s *link_status = &self->aq_link_status;
250
+ u32 mpi_state;
251
+ u32 speed;
252
+
253
+ mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR);
254
+ speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G |
255
+ FW2X_RATE_2G5 | FW2X_RATE_5G |
256
+ FW2X_RATE_10G);
136257
137258 if (speed) {
138259 if (speed & FW2X_RATE_10G)
....@@ -150,17 +271,16 @@
150271 } else {
151272 link_status->mbps = 0;
152273 }
274
+ link_status->full_duplex = true;
153275
154276 return 0;
155277 }
156278
157279 static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
158280 {
159
- int err = 0;
160
- u32 h = 0U;
161
- u32 l = 0U;
162
- u32 mac_addr[2] = { 0 };
163281 u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
282
+ u32 mac_addr[2] = { 0 };
283
+ int err = 0;
164284
165285 if (efuse_addr != 0) {
166286 err = hw_atl_utils_fw_downld_dwords(self,
....@@ -175,49 +295,220 @@
175295
176296 ether_addr_copy(mac, (u8 *)mac_addr);
177297
178
- if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
179
- unsigned int rnd = 0;
180
-
181
- get_random_bytes(&rnd, sizeof(unsigned int));
182
-
183
- l = 0xE3000000U
184
- | (0xFFFFU & rnd)
185
- | (0x00 << 16);
186
- h = 0x8001300EU;
187
-
188
- mac[5] = (u8)(0xFFU & l);
189
- l >>= 8;
190
- mac[4] = (u8)(0xFFU & l);
191
- l >>= 8;
192
- mac[3] = (u8)(0xFFU & l);
193
- l >>= 8;
194
- mac[2] = (u8)(0xFFU & l);
195
- mac[1] = (u8)(0xFFU & h);
196
- h >>= 8;
197
- mac[0] = (u8)(0xFFU & h);
198
- }
199298 return err;
200299 }
201300
202301 static int aq_fw2x_update_stats(struct aq_hw_s *self)
203302 {
204
- int err = 0;
205303 u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
206304 u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
305
+ u32 stats_val;
306
+ int err = 0;
207307
208308 /* Toggle statistics bit for FW to update */
209309 mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
210310 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
211311
212312 /* Wait FW to report back */
213
- AQ_HW_WAIT_FOR(orig_stats_val !=
214
- (aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
215
- BIT(CAPS_HI_STATISTICS)),
216
- 1U, 10000U);
313
+ err = readx_poll_timeout_atomic(aq_fw2x_state2_get,
314
+ self, stats_val,
315
+ orig_stats_val != (stats_val &
316
+ BIT(CAPS_HI_STATISTICS)),
317
+ 1U, 10000U);
217318 if (err)
218319 return err;
219320
220321 return hw_atl_utils_update_stats(self);
322
+}
323
+
324
+static int aq_fw2x_get_phy_temp(struct aq_hw_s *self, int *temp)
325
+{
326
+ u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
327
+ u32 temp_val = mpi_opts & HW_ATL_FW2X_CTRL_TEMPERATURE;
328
+ u32 phy_temp_offset;
329
+ u32 temp_res;
330
+ int err = 0;
331
+ u32 val;
332
+
333
+ phy_temp_offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox,
334
+ info.phy_temperature);
335
+
336
+ /* Toggle statistics bit for FW to 0x36C.18 (CTRL_TEMPERATURE) */
337
+ mpi_opts = mpi_opts ^ HW_ATL_FW2X_CTRL_TEMPERATURE;
338
+ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
339
+ /* Wait FW to report back */
340
+ err = readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val,
341
+ temp_val !=
342
+ (val & HW_ATL_FW2X_CTRL_TEMPERATURE),
343
+ 1U, 10000U);
344
+ err = hw_atl_utils_fw_downld_dwords(self, phy_temp_offset,
345
+ &temp_res, 1);
346
+
347
+ if (err)
348
+ return err;
349
+
350
+ /* Convert PHY temperature from 1/256 degree Celsius
351
+ * to 1/1000 degree Celsius.
352
+ */
353
+ *temp = (int16_t)(temp_res & 0xFFFF) * 1000 / 256;
354
+
355
+ return 0;
356
+}
357
+
358
+static int aq_fw2x_set_wol(struct aq_hw_s *self, u8 *mac)
359
+{
360
+ struct hw_atl_utils_fw_rpc *rpc = NULL;
361
+ struct offload_info *info = NULL;
362
+ u32 wol_bits = 0;
363
+ u32 rpc_size;
364
+ int err = 0;
365
+ u32 val;
366
+
367
+ if (self->aq_nic_cfg->wol & WAKE_PHY) {
368
+ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR,
369
+ HW_ATL_FW2X_CTRL_LINK_DROP);
370
+ readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val,
371
+ (val &
372
+ HW_ATL_FW2X_CTRL_LINK_DROP) != 0,
373
+ 1000, 100000);
374
+ wol_bits |= HW_ATL_FW2X_CTRL_WAKE_ON_LINK;
375
+ }
376
+
377
+ if (self->aq_nic_cfg->wol & WAKE_MAGIC) {
378
+ wol_bits |= HW_ATL_FW2X_CTRL_SLEEP_PROXY |
379
+ HW_ATL_FW2X_CTRL_WOL;
380
+
381
+ err = hw_atl_utils_fw_rpc_wait(self, &rpc);
382
+ if (err < 0)
383
+ goto err_exit;
384
+
385
+ rpc_size = sizeof(*info) +
386
+ offsetof(struct hw_atl_utils_fw_rpc, fw2x_offloads);
387
+ memset(rpc, 0, rpc_size);
388
+ info = &rpc->fw2x_offloads;
389
+ memcpy(info->mac_addr, mac, ETH_ALEN);
390
+ info->len = sizeof(*info);
391
+
392
+ err = hw_atl_utils_fw_rpc_call(self, rpc_size);
393
+ if (err < 0)
394
+ goto err_exit;
395
+ }
396
+
397
+ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, wol_bits);
398
+
399
+err_exit:
400
+ return err;
401
+}
402
+
403
+static int aq_fw2x_set_power(struct aq_hw_s *self, unsigned int power_state,
404
+ u8 *mac)
405
+{
406
+ int err = 0;
407
+
408
+ if (self->aq_nic_cfg->wol)
409
+ err = aq_fw2x_set_wol(self, mac);
410
+
411
+ return err;
412
+}
413
+
414
+static int aq_fw2x_send_fw_request(struct aq_hw_s *self,
415
+ const struct hw_fw_request_iface *fw_req,
416
+ size_t size)
417
+{
418
+ u32 ctrl2, orig_ctrl2;
419
+ u32 dword_cnt;
420
+ int err = 0;
421
+ u32 val;
422
+
423
+ /* Write data to drvIface Mailbox */
424
+ dword_cnt = size / sizeof(u32);
425
+ if (size % sizeof(u32))
426
+ dword_cnt++;
427
+ err = hw_atl_write_fwcfg_dwords(self, (void *)fw_req, dword_cnt);
428
+ if (err < 0)
429
+ goto err_exit;
430
+
431
+ /* Toggle statistics bit for FW to update */
432
+ ctrl2 = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
433
+ orig_ctrl2 = ctrl2 & BIT(CAPS_HI_FW_REQUEST);
434
+ ctrl2 = ctrl2 ^ BIT(CAPS_HI_FW_REQUEST);
435
+ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, ctrl2);
436
+
437
+ /* Wait FW to report back */
438
+ err = readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val,
439
+ orig_ctrl2 != (val &
440
+ BIT(CAPS_HI_FW_REQUEST)),
441
+ 1U, 10000U);
442
+
443
+err_exit:
444
+ return err;
445
+}
446
+
447
+static void aq_fw3x_enable_ptp(struct aq_hw_s *self, int enable)
448
+{
449
+ u32 ptp_opts = aq_hw_read_reg(self, HW_ATL_FW3X_EXT_STATE_ADDR);
450
+ u32 all_ptp_features = BIT(CAPS_EX_PHY_PTP_EN) |
451
+ BIT(CAPS_EX_PTP_GPIO_EN);
452
+
453
+ if (enable)
454
+ ptp_opts |= all_ptp_features;
455
+ else
456
+ ptp_opts &= ~all_ptp_features;
457
+
458
+ aq_hw_write_reg(self, HW_ATL_FW3X_EXT_CONTROL_ADDR, ptp_opts);
459
+}
460
+
461
+static void aq_fw3x_adjust_ptp(struct aq_hw_s *self, uint64_t adj)
462
+{
463
+ aq_hw_write_reg(self, HW_ATL_FW3X_PTP_ADJ_LSW_ADDR,
464
+ (adj >> 0) & 0xffffffff);
465
+ aq_hw_write_reg(self, HW_ATL_FW3X_PTP_ADJ_MSW_ADDR,
466
+ (adj >> 32) & 0xffffffff);
467
+}
468
+
469
+static int aq_fw2x_led_control(struct aq_hw_s *self, u32 mode)
470
+{
471
+ if (self->fw_ver_actual < HW_ATL_FW_VER_LED)
472
+ return -EOPNOTSUPP;
473
+
474
+ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_LED_ADDR, mode);
475
+
476
+ return 0;
477
+}
478
+
479
+static int aq_fw2x_set_eee_rate(struct aq_hw_s *self, u32 speed)
480
+{
481
+ u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
482
+
483
+ aq_fw2x_upd_eee_rate_bits(self, &mpi_opts, speed);
484
+
485
+ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
486
+
487
+ return 0;
488
+}
489
+
490
+static int aq_fw2x_get_eee_rate(struct aq_hw_s *self, u32 *rate,
491
+ u32 *supported_rates)
492
+{
493
+ u32 mpi_state;
494
+ u32 caps_hi;
495
+ int err = 0;
496
+ u32 offset;
497
+
498
+ offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox,
499
+ info.caps_hi);
500
+
501
+ err = hw_atl_utils_fw_downld_dwords(self, offset, &caps_hi, 1);
502
+
503
+ if (err)
504
+ return err;
505
+
506
+ *supported_rates = fw2x_to_eee_mask(caps_hi);
507
+
508
+ mpi_state = aq_fw2x_state2_get(self);
509
+ *rate = fw2x_to_eee_mask(mpi_state);
510
+
511
+ return err;
221512 }
222513
223514 static int aq_fw2x_renegotiate(struct aq_hw_s *self)
....@@ -235,22 +526,207 @@
235526 {
236527 u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
237528
238
- aq_fw2x_set_mpi_flow_control(self, &mpi_state);
529
+ aq_fw2x_upd_flow_control_bits(self, &mpi_state,
530
+ self->aq_nic_cfg->fc.req);
239531
240532 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
241533
242534 return 0;
243535 }
244536
537
+static u32 aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fcmode)
538
+{
539
+ u32 mpi_state = aq_fw2x_state2_get(self);
540
+ *fcmode = 0;
541
+
542
+ if (mpi_state & HW_ATL_FW2X_CAP_PAUSE)
543
+ *fcmode |= AQ_NIC_FC_RX;
544
+
545
+ if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE)
546
+ *fcmode |= AQ_NIC_FC_TX;
547
+
548
+ return 0;
549
+}
550
+
551
+static int aq_fw2x_set_phyloopback(struct aq_hw_s *self, u32 mode, bool enable)
552
+{
553
+ u32 mpi_opts;
554
+
555
+ switch (mode) {
556
+ case AQ_HW_LOOPBACK_PHYINT_SYS:
557
+ mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
558
+ if (enable)
559
+ mpi_opts |= HW_ATL_FW2X_CTRL_INT_LOOPBACK;
560
+ else
561
+ mpi_opts &= ~HW_ATL_FW2X_CTRL_INT_LOOPBACK;
562
+ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
563
+ break;
564
+ case AQ_HW_LOOPBACK_PHYEXT_SYS:
565
+ mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
566
+ if (enable)
567
+ mpi_opts |= HW_ATL_FW2X_CTRL_EXT_LOOPBACK;
568
+ else
569
+ mpi_opts &= ~HW_ATL_FW2X_CTRL_EXT_LOOPBACK;
570
+ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
571
+ break;
572
+ default:
573
+ return -EINVAL;
574
+ }
575
+
576
+ return 0;
577
+}
578
+
579
+static u32 aq_fw2x_mbox_get(struct aq_hw_s *self)
580
+{
581
+ return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR);
582
+}
583
+
584
+static u32 aq_fw2x_rpc_get(struct aq_hw_s *self)
585
+{
586
+ return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR);
587
+}
588
+
589
+static int aq_fw2x_settings_get(struct aq_hw_s *self, u32 *addr)
590
+{
591
+ int err = 0;
592
+ u32 offset;
593
+
594
+ offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox,
595
+ info.setting_address);
596
+
597
+ err = hw_atl_utils_fw_downld_dwords(self, offset, addr, 1);
598
+
599
+ return err;
600
+}
601
+
602
+static u32 aq_fw2x_state_get(struct aq_hw_s *self)
603
+{
604
+ return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR);
605
+}
606
+
607
+static u32 aq_fw2x_state2_get(struct aq_hw_s *self)
608
+{
609
+ return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR);
610
+}
611
+
612
+static int aq_fw2x_set_downshift(struct aq_hw_s *self, u32 counter)
613
+{
614
+ int err = 0;
615
+ u32 mpi_opts;
616
+ u32 offset;
617
+
618
+ offset = offsetof(struct hw_atl_utils_settings, downshift_retry_count);
619
+ err = hw_atl_write_fwsettings_dwords(self, offset, &counter, 1);
620
+ if (err)
621
+ return err;
622
+
623
+ mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
624
+ if (counter)
625
+ mpi_opts |= HW_ATL_FW2X_CTRL_DOWNSHIFT;
626
+ else
627
+ mpi_opts &= ~HW_ATL_FW2X_CTRL_DOWNSHIFT;
628
+ aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
629
+
630
+ return err;
631
+}
632
+
633
+static int aq_fw2x_set_media_detect(struct aq_hw_s *self, bool on)
634
+{
635
+ u32 enable;
636
+ u32 offset;
637
+
638
+ if (self->fw_ver_actual < HW_ATL_FW_VER_MEDIA_CONTROL)
639
+ return -EOPNOTSUPP;
640
+
641
+ offset = offsetof(struct hw_atl_utils_settings, media_detect);
642
+ enable = on;
643
+
644
+ return hw_atl_write_fwsettings_dwords(self, offset, &enable, 1);
645
+}
646
+
647
+static u32 aq_fw2x_get_link_capabilities(struct aq_hw_s *self)
648
+{
649
+ int err = 0;
650
+ u32 offset;
651
+ u32 val;
652
+
653
+ offset = self->mbox_addr +
654
+ offsetof(struct hw_atl_utils_mbox, info.caps_lo);
655
+
656
+ err = hw_atl_utils_fw_downld_dwords(self, offset, &val, 1);
657
+
658
+ if (err)
659
+ return 0;
660
+
661
+ return val;
662
+}
663
+
664
+static int aq_fw2x_send_macsec_req(struct aq_hw_s *hw,
665
+ struct macsec_msg_fw_request *req,
666
+ struct macsec_msg_fw_response *response)
667
+{
668
+ u32 low_status, low_req = 0;
669
+ u32 dword_cnt;
670
+ u32 caps_lo;
671
+ u32 offset;
672
+ int err;
673
+
674
+ if (!req || !response)
675
+ return -EINVAL;
676
+
677
+ caps_lo = aq_fw2x_get_link_capabilities(hw);
678
+ if (!(caps_lo & BIT(CAPS_LO_MACSEC)))
679
+ return -EOPNOTSUPP;
680
+
681
+ /* Write macsec request to cfg memory */
682
+ dword_cnt = (sizeof(*req) + sizeof(u32) - 1) / sizeof(u32);
683
+ err = hw_atl_write_fwcfg_dwords(hw, (void *)req, dword_cnt);
684
+ if (err < 0)
685
+ return err;
686
+
687
+ /* Toggle 0x368.CAPS_LO_MACSEC bit */
688
+ low_req = aq_hw_read_reg(hw, HW_ATL_FW2X_MPI_CONTROL_ADDR);
689
+ low_req ^= HW_ATL_FW2X_CAP_MACSEC;
690
+ aq_hw_write_reg(hw, HW_ATL_FW2X_MPI_CONTROL_ADDR, low_req);
691
+
692
+ /* Wait FW to report back */
693
+ err = readx_poll_timeout_atomic(aq_fw2x_state_get, hw, low_status,
694
+ low_req != (low_status & BIT(CAPS_LO_MACSEC)), 1U, 10000U);
695
+ if (err)
696
+ return -EIO;
697
+
698
+ /* Read status of write operation */
699
+ offset = hw->rpc_addr + sizeof(u32);
700
+ err = hw_atl_utils_fw_downld_dwords(hw, offset, (u32 *)(void *)response,
701
+ sizeof(*response) / sizeof(u32));
702
+
703
+ return err;
704
+}
705
+
245706 const struct aq_fw_ops aq_fw_2x_ops = {
246
- .init = aq_fw2x_init,
247
- .deinit = aq_fw2x_deinit,
248
- .reset = NULL,
249
- .renegotiate = aq_fw2x_renegotiate,
250
- .get_mac_permanent = aq_fw2x_get_mac_permanent,
251
- .set_link_speed = aq_fw2x_set_link_speed,
252
- .set_state = aq_fw2x_set_state,
707
+ .init = aq_fw2x_init,
708
+ .deinit = aq_fw2x_deinit,
709
+ .reset = NULL,
710
+ .renegotiate = aq_fw2x_renegotiate,
711
+ .get_mac_permanent = aq_fw2x_get_mac_permanent,
712
+ .set_link_speed = aq_fw2x_set_link_speed,
713
+ .set_state = aq_fw2x_set_state,
253714 .update_link_status = aq_fw2x_update_link_status,
254
- .update_stats = aq_fw2x_update_stats,
715
+ .update_stats = aq_fw2x_update_stats,
716
+ .get_mac_temp = NULL,
717
+ .get_phy_temp = aq_fw2x_get_phy_temp,
718
+ .set_power = aq_fw2x_set_power,
719
+ .set_eee_rate = aq_fw2x_set_eee_rate,
720
+ .get_eee_rate = aq_fw2x_get_eee_rate,
255721 .set_flow_control = aq_fw2x_set_flow_control,
722
+ .get_flow_control = aq_fw2x_get_flow_control,
723
+ .send_fw_request = aq_fw2x_send_fw_request,
724
+ .enable_ptp = aq_fw3x_enable_ptp,
725
+ .led_control = aq_fw2x_led_control,
726
+ .set_phyloopback = aq_fw2x_set_phyloopback,
727
+ .set_downshift = aq_fw2x_set_downshift,
728
+ .set_media_detect = aq_fw2x_set_media_detect,
729
+ .adjust_ptp = aq_fw3x_adjust_ptp,
730
+ .get_link_capabilities = aq_fw2x_get_link_capabilities,
731
+ .send_macsec_req = aq_fw2x_send_macsec_req,
256732 };