]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/dpdk/drivers/net/atlantic/hw_atl/hw_atl_utils.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / seastar / dpdk / drivers / net / atlantic / hw_atl / hw_atl_utils.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.c: Definition of common functions for Atlantic hardware
5 * abstraction layer.
6 */
7
8 #include <stdio.h>
9 #include <errno.h>
10 #include <stdint.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <stdarg.h>
14 #include <inttypes.h>
15 #include <rte_ether.h>
16 #include "../atl_hw_regs.h"
17
18 #include "hw_atl_llh.h"
19 #include "hw_atl_llh_internal.h"
20 #include "../atl_logs.h"
21
22 #define HW_ATL_UCP_0X370_REG 0x0370U
23
24 #define HW_ATL_MIF_CMD 0x0200U
25 #define HW_ATL_MIF_ADDR 0x0208U
26 #define HW_ATL_MIF_VAL 0x020CU
27
28 #define HW_ATL_FW_SM_RAM 0x2U
29 #define HW_ATL_MPI_FW_VERSION 0x18
30 #define HW_ATL_MPI_CONTROL_ADR 0x0368U
31 #define HW_ATL_MPI_STATE_ADR 0x036CU
32
33 #define HW_ATL_MPI_STATE_MSK 0x00FFU
34 #define HW_ATL_MPI_STATE_SHIFT 0U
35 #define HW_ATL_MPI_SPEED_MSK 0x00FF0000U
36 #define HW_ATL_MPI_SPEED_SHIFT 16U
37 #define HW_ATL_MPI_DIRTY_WAKE_MSK 0x02000000U
38
39 #define HW_ATL_MPI_DAISY_CHAIN_STATUS 0x704
40 #define HW_ATL_MPI_BOOT_EXIT_CODE 0x388
41
42 #define HW_ATL_MAC_PHY_CONTROL 0x4000
43 #define HW_ATL_MAC_PHY_MPI_RESET_BIT 0x1D
44
45 #define HW_ATL_FW_VER_1X 0x01050006U
46 #define HW_ATL_FW_VER_2X 0x02000000U
47 #define HW_ATL_FW_VER_3X 0x03000000U
48
49 #define FORCE_FLASHLESS 0
50
51 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
52 static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
53 enum hal_atl_utils_fw_state_e state);
54
55
56 int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
57 {
58 int err = 0;
59
60 err = hw_atl_utils_soft_reset(self);
61 if (err)
62 return err;
63
64 hw_atl_utils_hw_chip_features_init(self,
65 &self->chip_features);
66
67 hw_atl_utils_get_fw_version(self, &self->fw_ver_actual);
68
69 if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
70 self->fw_ver_actual) == 0) {
71 *fw_ops = &aq_fw_1x_ops;
72 } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X,
73 self->fw_ver_actual) == 0) {
74 *fw_ops = &aq_fw_2x_ops;
75 } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X,
76 self->fw_ver_actual) == 0) {
77 *fw_ops = &aq_fw_2x_ops;
78 } else {
79 PMD_DRV_LOG(ERR, "Bad FW version detected: %x\n",
80 self->fw_ver_actual);
81 return -EOPNOTSUPP;
82 }
83 self->aq_fw_ops = *fw_ops;
84 err = self->aq_fw_ops->init(self);
85 return err;
86 }
87
88 static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self)
89 {
90 u32 gsr, val;
91 int k = 0;
92
93 aq_hw_write_reg(self, 0x404, 0x40e1);
94 AQ_HW_SLEEP(50);
95
96 /* Cleanup SPI */
97 val = aq_hw_read_reg(self, 0x53C);
98 aq_hw_write_reg(self, 0x53C, val | 0x10);
99
100 gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
101 aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
102
103 /* Kickstart MAC */
104 aq_hw_write_reg(self, 0x404, 0x80e0);
105 aq_hw_write_reg(self, 0x32a8, 0x0);
106 aq_hw_write_reg(self, 0x520, 0x1);
107
108 /* Reset SPI again because of possible interrupted SPI burst */
109 val = aq_hw_read_reg(self, 0x53C);
110 aq_hw_write_reg(self, 0x53C, val | 0x10);
111 AQ_HW_SLEEP(10);
112 /* Clear SPI reset state */
113 aq_hw_write_reg(self, 0x53C, val & ~0x10);
114
115 aq_hw_write_reg(self, 0x404, 0x180e0);
116
117 for (k = 0; k < 1000; k++) {
118 u32 flb_status = aq_hw_read_reg(self,
119 HW_ATL_MPI_DAISY_CHAIN_STATUS);
120
121 flb_status = flb_status & 0x10;
122 if (flb_status)
123 break;
124 AQ_HW_SLEEP(10);
125 }
126 if (k == 1000) {
127 PMD_DRV_LOG(ERR, "MAC kickstart failed\n");
128 return -EIO;
129 }
130
131 /* FW reset */
132 aq_hw_write_reg(self, 0x404, 0x80e0);
133 AQ_HW_SLEEP(50);
134 aq_hw_write_reg(self, 0x3a0, 0x1);
135
136 /* Kickstart PHY - skipped */
137
138 /* Global software reset*/
139 hw_atl_rx_rx_reg_res_dis_set(self, 0U);
140 hw_atl_tx_tx_reg_res_dis_set(self, 0U);
141 aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
142 BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
143 HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
144 gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
145 aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
146
147 for (k = 0; k < 1000; k++) {
148 u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
149
150 if (fw_state)
151 break;
152 AQ_HW_SLEEP(10);
153 }
154 if (k == 1000) {
155 PMD_DRV_LOG(ERR, "FW kickstart failed\n");
156 return -EIO;
157 }
158 /* Old FW requires fixed delay after init */
159 AQ_HW_SLEEP(15);
160
161 return 0;
162 }
163
164 static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self)
165 {
166 u32 gsr, val, rbl_status;
167 int k;
168
169 aq_hw_write_reg(self, 0x404, 0x40e1);
170 aq_hw_write_reg(self, 0x3a0, 0x1);
171 aq_hw_write_reg(self, 0x32a8, 0x0);
172
173 /* Alter RBL status */
174 aq_hw_write_reg(self, 0x388, 0xDEAD);
175
176 /* Cleanup SPI */
177 val = aq_hw_read_reg(self, 0x53C);
178 aq_hw_write_reg(self, 0x53C, val | 0x10);
179
180 /* Global software reset*/
181 hw_atl_rx_rx_reg_res_dis_set(self, 0U);
182 hw_atl_tx_tx_reg_res_dis_set(self, 0U);
183 aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
184 BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
185 HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
186 gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
187 aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR,
188 (gsr & 0xFFFFBFFF) | 0x8000);
189
190 if (FORCE_FLASHLESS)
191 aq_hw_write_reg(self, 0x534, 0x0);
192
193 aq_hw_write_reg(self, 0x404, 0x40e0);
194
195 /* Wait for RBL boot */
196 for (k = 0; k < 1000; k++) {
197 rbl_status = aq_hw_read_reg(self, 0x388) & 0xFFFF;
198 if (rbl_status && rbl_status != 0xDEAD)
199 break;
200 AQ_HW_SLEEP(10);
201 }
202 if (!rbl_status || rbl_status == 0xDEAD) {
203 PMD_DRV_LOG(ERR, "RBL Restart failed");
204 return -EIO;
205 }
206
207 /* Restore NVR */
208 if (FORCE_FLASHLESS)
209 aq_hw_write_reg(self, 0x534, 0xA0);
210
211 if (rbl_status == 0xF1A7) {
212 PMD_DRV_LOG(ERR, "No FW detected. Dynamic FW load not implemented\n");
213 return -EOPNOTSUPP;
214 }
215
216 for (k = 0; k < 1000; k++) {
217 u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
218
219 if (fw_state)
220 break;
221 AQ_HW_SLEEP(10);
222 }
223 if (k == 1000) {
224 PMD_DRV_LOG(ERR, "FW kickstart failed\n");
225 return -EIO;
226 }
227 /* Old FW requires fixed delay after init */
228 AQ_HW_SLEEP(15);
229
230 return 0;
231 }
232
233 int hw_atl_utils_soft_reset(struct aq_hw_s *self)
234 {
235 int err = 0;
236 int k;
237 u32 boot_exit_code = 0;
238
239 for (k = 0; k < 1000; ++k) {
240 u32 flb_status = aq_hw_read_reg(self,
241 HW_ATL_MPI_DAISY_CHAIN_STATUS);
242 boot_exit_code = aq_hw_read_reg(self,
243 HW_ATL_MPI_BOOT_EXIT_CODE);
244 if (flb_status != 0x06000000 || boot_exit_code != 0)
245 break;
246 }
247
248 if (k == 1000) {
249 PMD_DRV_LOG(ERR, "Neither RBL nor FLB firmware started\n");
250 return -EOPNOTSUPP;
251 }
252
253 self->rbl_enabled = (boot_exit_code != 0);
254
255 /* FW 1.x may bootup in an invalid POWER state (WOL feature).
256 * We should work around this by forcing its state back to DEINIT
257 */
258 if (!hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
259 aq_hw_read_reg(self,
260 HW_ATL_MPI_FW_VERSION))) {
261 hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
262 AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR) &
263 HW_ATL_MPI_STATE_MSK) == MPI_DEINIT,
264 10, 1000U);
265 }
266
267 if (self->rbl_enabled)
268 err = hw_atl_utils_soft_reset_rbl(self);
269 else
270 err = hw_atl_utils_soft_reset_flb(self);
271
272 return err;
273 }
274
275 int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
276 u32 *p, u32 cnt)
277 {
278 int err = 0;
279
280 AQ_HW_WAIT_FOR(hw_atl_reg_glb_cpu_sem_get(self,
281 HW_ATL_FW_SM_RAM) == 1U,
282 1U, 10000U);
283
284 if (err < 0) {
285 bool is_locked;
286
287 hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
288 is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
289 if (!is_locked) {
290 err = -ETIMEDOUT;
291 goto err_exit;
292 }
293 }
294
295 aq_hw_write_reg(self, HW_ATL_MIF_ADDR, a);
296
297 for (++cnt; --cnt && !err;) {
298 aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U);
299
300 if (IS_CHIP_FEATURE(REVISION_B1))
301 AQ_HW_WAIT_FOR(a != aq_hw_read_reg(self,
302 HW_ATL_MIF_ADDR),
303 1, 1000U);
304 else
305 AQ_HW_WAIT_FOR(!(0x100 & aq_hw_read_reg(self,
306 HW_ATL_MIF_CMD)),
307 1, 1000U);
308 if (err) {
309 err = -ETIMEDOUT;
310 goto err_exit;
311 }
312
313 *(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL);
314 a += 4;
315 }
316
317 hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
318
319 err_exit:
320 return err;
321 }
322
323 int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
324 u32 cnt)
325 {
326 int err = 0;
327 bool is_locked;
328
329 is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
330 if (!is_locked) {
331 err = -ETIMEDOUT;
332 goto err_exit;
333 }
334 if (IS_CHIP_FEATURE(REVISION_B1)) {
335 u32 mbox_offset = (a - self->rpc_addr) / sizeof(u32);
336 u32 data_offset = 0;
337
338 for (; data_offset < cnt; ++mbox_offset, ++data_offset) {
339 aq_hw_write_reg(self, 0x328, p[data_offset]);
340 aq_hw_write_reg(self, 0x32C,
341 (0x80000000 | (0xFFFF & (mbox_offset * 4))));
342 hw_atl_mcp_up_force_intr_set(self, 1);
343 /* 1000 times by 10us = 10ms */
344 AQ_HW_WAIT_FOR((aq_hw_read_reg(self,
345 0x32C) & 0xF0000000) != 0x80000000,
346 10, 1000);
347 }
348 } else {
349 u32 offset = 0;
350
351 aq_hw_write_reg(self, 0x208, a);
352
353 for (; offset < cnt; ++offset) {
354 aq_hw_write_reg(self, 0x20C, p[offset]);
355 aq_hw_write_reg(self, 0x200, 0xC000);
356
357 AQ_HW_WAIT_FOR((aq_hw_read_reg(self, 0x200U)
358 & 0x100) == 0, 10, 1000);
359 }
360 }
361
362 hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
363
364 err_exit:
365 return err;
366 }
367
368 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
369 {
370 int err = 0;
371 const u32 dw_major_mask = 0xff000000U;
372 const u32 dw_minor_mask = 0x00ffffffU;
373
374 err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0;
375 if (err < 0)
376 goto err_exit;
377 err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
378 -EOPNOTSUPP : 0;
379 err_exit:
380 return err;
381 }
382
383 static int hw_atl_utils_init_ucp(struct aq_hw_s *self)
384 {
385 int err = 0;
386
387 if (!aq_hw_read_reg(self, 0x370U)) {
388 unsigned int rnd = (uint32_t)rte_rand();
389 unsigned int ucp_0x370 = 0U;
390
391 ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd);
392 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
393 }
394
395 hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U);
396
397 /* check 10 times by 1ms */
398 AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
399 aq_hw_read_reg(self, 0x360U)), 1000U, 10U);
400 AQ_HW_WAIT_FOR(0U != (self->rpc_addr =
401 aq_hw_read_reg(self, 0x334U)), 1000U, 100U);
402
403 return err;
404 }
405
406 #define HW_ATL_RPC_CONTROL_ADR 0x0338U
407 #define HW_ATL_RPC_STATE_ADR 0x033CU
408
409 struct aq_hw_atl_utils_fw_rpc_tid_s {
410 union {
411 u32 val;
412 struct {
413 u16 tid;
414 u16 len;
415 };
416 };
417 };
418
419 #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
420
421 int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
422 {
423 int err = 0;
424 struct aq_hw_atl_utils_fw_rpc_tid_s sw;
425
426 if (!IS_CHIP_FEATURE(MIPS)) {
427 err = -1;
428 goto err_exit;
429 }
430 err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
431 (u32 *)(void *)&self->rpc,
432 (rpc_size + sizeof(u32) -
433 sizeof(u8)) / sizeof(u32));
434 if (err < 0)
435 goto err_exit;
436
437 sw.tid = 0xFFFFU & (++self->rpc_tid);
438 sw.len = (u16)rpc_size;
439 aq_hw_write_reg(self, HW_ATL_RPC_CONTROL_ADR, sw.val);
440
441 err_exit:
442 return err;
443 }
444
445 int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
446 struct hw_aq_atl_utils_fw_rpc **rpc)
447 {
448 int err = 0;
449 struct aq_hw_atl_utils_fw_rpc_tid_s sw;
450 struct aq_hw_atl_utils_fw_rpc_tid_s fw;
451
452 do {
453 sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR);
454
455 self->rpc_tid = sw.tid;
456
457 AQ_HW_WAIT_FOR(sw.tid ==
458 (fw.val =
459 aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR),
460 fw.tid), 1000U, 100U);
461 if (err < 0)
462 goto err_exit;
463
464 if (fw.len == 0xFFFFU) {
465 err = hw_atl_utils_fw_rpc_call(self, sw.len);
466 if (err < 0)
467 goto err_exit;
468 }
469 } while (sw.tid != fw.tid || 0xFFFFU == fw.len);
470
471 if (rpc) {
472 if (fw.len) {
473 err =
474 hw_atl_utils_fw_downld_dwords(self,
475 self->rpc_addr,
476 (u32 *)(void *)
477 &self->rpc,
478 (fw.len + sizeof(u32) -
479 sizeof(u8)) /
480 sizeof(u32));
481 if (err < 0)
482 goto err_exit;
483 }
484
485 *rpc = &self->rpc;
486 }
487
488 err_exit:
489 return err;
490 }
491
492 static int hw_atl_utils_mpi_create(struct aq_hw_s *self)
493 {
494 int err = 0;
495
496 err = hw_atl_utils_init_ucp(self);
497 if (err < 0)
498 goto err_exit;
499
500 err = hw_atl_utils_fw_rpc_init(self);
501 if (err < 0)
502 goto err_exit;
503
504 err_exit:
505 return err;
506 }
507
508 int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
509 struct hw_aq_atl_utils_mbox_header *pmbox)
510 {
511 return hw_atl_utils_fw_downld_dwords(self,
512 self->mbox_addr,
513 (u32 *)(void *)pmbox,
514 sizeof(*pmbox) / sizeof(u32));
515 }
516
517 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
518 struct hw_aq_atl_utils_mbox *pmbox)
519 {
520 int err = 0;
521
522 err = hw_atl_utils_fw_downld_dwords(self,
523 self->mbox_addr,
524 (u32 *)(void *)pmbox,
525 sizeof(*pmbox) / sizeof(u32));
526 if (err < 0)
527 goto err_exit;
528
529 if (IS_CHIP_FEATURE(REVISION_A0)) {
530 unsigned int mtu = 1514;
531 pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
532 pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
533 } else {
534 pmbox->stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
535 }
536
537 err_exit:;
538 }
539
540 static
541 int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
542 {
543 u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
544
545 val = val & ~HW_ATL_MPI_SPEED_MSK;
546 val |= speed << HW_ATL_MPI_SPEED_SHIFT;
547 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
548
549 return 0;
550 }
551
552 int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
553 enum hal_atl_utils_fw_state_e state)
554 {
555 int err = 0;
556 u32 transaction_id = 0;
557 struct hw_aq_atl_utils_mbox_header mbox;
558 u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
559
560 if (state == MPI_RESET) {
561 hw_atl_utils_mpi_read_mbox(self, &mbox);
562
563 transaction_id = mbox.transaction_id;
564
565 AQ_HW_WAIT_FOR(transaction_id !=
566 (hw_atl_utils_mpi_read_mbox(self, &mbox),
567 mbox.transaction_id),
568 1000U, 100U);
569 if (err < 0)
570 goto err_exit;
571 }
572 /* On interface DEINIT we disable DW (raise bit)
573 * Otherwise enable DW (clear bit)
574 */
575 if (state == MPI_DEINIT || state == MPI_POWER)
576 val |= HW_ATL_MPI_DIRTY_WAKE_MSK;
577 else
578 val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK;
579
580 /* Set new state bits */
581 val = val & ~HW_ATL_MPI_STATE_MSK;
582 val |= state & HW_ATL_MPI_STATE_MSK;
583
584 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
585 err_exit:
586 return err;
587 }
588
589 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
590 {
591 u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
592 u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
593 struct aq_hw_link_status_s *link_status = &self->aq_link_status;
594
595 if (!link_speed_mask) {
596 link_status->mbps = 0U;
597 } else {
598 switch (link_speed_mask) {
599 case HAL_ATLANTIC_RATE_10G:
600 link_status->mbps = 10000U;
601 break;
602
603 case HAL_ATLANTIC_RATE_5G:
604 case HAL_ATLANTIC_RATE_5GSR:
605 link_status->mbps = 5000U;
606 break;
607
608 case HAL_ATLANTIC_RATE_2GS:
609 link_status->mbps = 2500U;
610 break;
611
612 case HAL_ATLANTIC_RATE_1G:
613 link_status->mbps = 1000U;
614 break;
615
616 case HAL_ATLANTIC_RATE_100M:
617 link_status->mbps = 100U;
618 break;
619
620 default:
621 return -EBUSY;
622 }
623 }
624
625 return 0;
626 }
627
628 static int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
629 u8 *mac)
630 {
631 int err = 0;
632 u32 h = 0U;
633 u32 l = 0U;
634 u32 mac_addr[2];
635
636 if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
637 unsigned int rnd = (uint32_t)rte_rand();
638 unsigned int ucp_0x370 = 0;
639
640 //get_random_bytes(&rnd, sizeof(unsigned int));
641
642 ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
643 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
644 }
645
646 err = hw_atl_utils_fw_downld_dwords(self,
647 aq_hw_read_reg(self, 0x00000374U) +
648 (40U * 4U),
649 mac_addr,
650 ARRAY_SIZE(mac_addr));
651 if (err < 0) {
652 mac_addr[0] = 0U;
653 mac_addr[1] = 0U;
654 err = 0;
655 } else {
656 mac_addr[0] = rte_constant_bswap32(mac_addr[0]);
657 mac_addr[1] = rte_constant_bswap32(mac_addr[1]);
658 }
659
660 ether_addr_copy((struct ether_addr *)mac_addr,
661 (struct ether_addr *)mac);
662
663 if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
664 /* chip revision */
665 l = 0xE3000000U
666 | (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG))
667 | (0x00 << 16);
668 h = 0x8001300EU;
669
670 mac[5] = (u8)(0xFFU & l);
671 l >>= 8;
672 mac[4] = (u8)(0xFFU & l);
673 l >>= 8;
674 mac[3] = (u8)(0xFFU & l);
675 l >>= 8;
676 mac[2] = (u8)(0xFFU & l);
677 mac[1] = (u8)(0xFFU & h);
678 h >>= 8;
679 mac[0] = (u8)(0xFFU & h);
680 }
681
682 return err;
683 }
684
685 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
686 {
687 unsigned int ret = 0U;
688
689 switch (mbps) {
690 case 100U:
691 ret = 5U;
692 break;
693
694 case 1000U:
695 ret = 4U;
696 break;
697
698 case 2500U:
699 ret = 3U;
700 break;
701
702 case 5000U:
703 ret = 1U;
704 break;
705
706 case 10000U:
707 ret = 0U;
708 break;
709
710 default:
711 break;
712 }
713 return ret;
714 }
715
716 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
717 {
718 u32 chip_features = 0U;
719 u32 val = hw_atl_reg_glb_mif_id_get(self);
720 u32 mif_rev = val & 0xFFU;
721
722 if ((0xFU & mif_rev) == 1U) {
723 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
724 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
725 HAL_ATLANTIC_UTILS_CHIP_MIPS;
726 } else if ((0xFU & mif_rev) == 2U) {
727 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
728 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
729 HAL_ATLANTIC_UTILS_CHIP_MIPS |
730 HAL_ATLANTIC_UTILS_CHIP_TPO2 |
731 HAL_ATLANTIC_UTILS_CHIP_RPF2;
732 } else if ((0xFU & mif_rev) == 0xAU) {
733 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 |
734 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
735 HAL_ATLANTIC_UTILS_CHIP_MIPS |
736 HAL_ATLANTIC_UTILS_CHIP_TPO2 |
737 HAL_ATLANTIC_UTILS_CHIP_RPF2;
738 }
739
740 *p = chip_features;
741 }
742
743 static int hw_atl_fw1x_deinit(struct aq_hw_s *self)
744 {
745 hw_atl_utils_mpi_set_speed(self, 0);
746 hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
747 return 0;
748 }
749
750 int hw_atl_utils_update_stats(struct aq_hw_s *self)
751 {
752 struct hw_aq_atl_utils_mbox mbox;
753
754 hw_atl_utils_mpi_read_stats(self, &mbox);
755
756 #define AQ_SDELTA(_N_) (self->curr_stats._N_ += \
757 mbox.stats._N_ - self->last_stats._N_)
758
759 if (1) {//self->aq_link_status.mbps) {
760 AQ_SDELTA(uprc);
761 AQ_SDELTA(mprc);
762 AQ_SDELTA(bprc);
763 AQ_SDELTA(erpt);
764
765 AQ_SDELTA(uptc);
766 AQ_SDELTA(mptc);
767 AQ_SDELTA(bptc);
768 AQ_SDELTA(erpr);
769 AQ_SDELTA(ubrc);
770 AQ_SDELTA(ubtc);
771 AQ_SDELTA(mbrc);
772 AQ_SDELTA(mbtc);
773 AQ_SDELTA(bbrc);
774 AQ_SDELTA(bbtc);
775 AQ_SDELTA(dpc);
776 }
777 #undef AQ_SDELTA
778 self->curr_stats.dma_pkt_rc =
779 hw_atl_stats_rx_dma_good_pkt_counterlsw_get(self) +
780 ((u64)hw_atl_stats_rx_dma_good_pkt_countermsw_get(self) << 32);
781 self->curr_stats.dma_pkt_tc =
782 hw_atl_stats_tx_dma_good_pkt_counterlsw_get(self) +
783 ((u64)hw_atl_stats_tx_dma_good_pkt_countermsw_get(self) << 32);
784 self->curr_stats.dma_oct_rc =
785 hw_atl_stats_rx_dma_good_octet_counterlsw_get(self) +
786 ((u64)hw_atl_stats_rx_dma_good_octet_countermsw_get(self) << 32);
787 self->curr_stats.dma_oct_tc =
788 hw_atl_stats_tx_dma_good_octet_counterlsw_get(self) +
789 ((u64)hw_atl_stats_tx_dma_good_octet_countermsw_get(self) << 32);
790
791 self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
792
793 memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
794
795 return 0;
796 }
797
798 struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self)
799 {
800 return &self->curr_stats;
801 }
802
803 static const u32 hw_atl_utils_hw_mac_regs[] = {
804 0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
805 0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
806 0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
807 0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
808 0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
809 0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
810 0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
811 0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
812 0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
813 0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
814 0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
815 0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
816 0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
817 0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
818 0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
819 0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
820 0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
821 0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
822 0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
823 0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
824 0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
825 0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
826 };
827
828 unsigned int hw_atl_utils_hw_get_reg_length(void)
829 {
830 return ARRAY_SIZE(hw_atl_utils_hw_mac_regs);
831 }
832
833 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
834 u32 *regs_buff)
835 {
836 unsigned int i = 0U;
837 unsigned int mac_regs_count = hw_atl_utils_hw_get_reg_length();
838
839 for (i = 0; i < mac_regs_count; i++)
840 regs_buff[i] = aq_hw_read_reg(self,
841 hw_atl_utils_hw_mac_regs[i]);
842 return 0;
843 }
844
845 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
846 {
847 *fw_version = aq_hw_read_reg(self, 0x18U);
848 return 0;
849 }
850
851 static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac)
852 {
853 struct hw_aq_atl_utils_fw_rpc *prpc = NULL;
854 unsigned int rpc_size = 0U;
855 int err = 0;
856
857 err = hw_atl_utils_fw_rpc_wait(self, &prpc);
858 if (err < 0)
859 goto err_exit;
860
861 memset(prpc, 0, sizeof(*prpc));
862
863 if (wol_enabled) {
864 rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_wol);
865
866 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD;
867 prpc->msg_wol.priority = 0x10000000; /* normal priority */
868 prpc->msg_wol.pattern_id = 1U;
869 prpc->msg_wol.wol_packet_type = 2U; /* Magic Packet */
870
871 ether_addr_copy((struct ether_addr *)mac,
872 (struct ether_addr *)&prpc->msg_wol.wol_pattern);
873 } else {
874 rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_del_id);
875
876 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL;
877 prpc->msg_wol.pattern_id = 1U;
878 }
879
880 err = hw_atl_utils_fw_rpc_call(self, rpc_size);
881
882 err_exit:
883 return err;
884 }
885
886 static
887 int aq_fw1x_set_power(struct aq_hw_s *self,
888 unsigned int power_state __rte_unused,
889 u8 *mac)
890 {
891 struct hw_aq_atl_utils_fw_rpc *prpc = NULL;
892 unsigned int rpc_size = 0U;
893 int err = 0;
894 if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) {
895 err = aq_fw1x_set_wol(self, 1, mac);
896
897 if (err < 0)
898 goto err_exit;
899
900 rpc_size = sizeof(prpc->msg_id) +
901 sizeof(prpc->msg_enable_wakeup);
902
903 err = hw_atl_utils_fw_rpc_wait(self, &prpc);
904
905 if (err < 0)
906 goto err_exit;
907
908 memset(prpc, 0, rpc_size);
909
910 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_ENABLE_WAKEUP;
911 prpc->msg_enable_wakeup.pattern_mask = 0x00000002;
912
913 err = hw_atl_utils_fw_rpc_call(self, rpc_size);
914 if (err < 0)
915 goto err_exit;
916 }
917
918 hw_atl_utils_mpi_set_speed(self, 0);
919 hw_atl_utils_mpi_set_state(self, MPI_POWER);
920 err_exit:
921 return err;
922 }
923
924
925
926 const struct aq_fw_ops aq_fw_1x_ops = {
927 .init = hw_atl_utils_mpi_create,
928 .deinit = hw_atl_fw1x_deinit,
929 .reset = NULL,
930 .get_mac_permanent = hw_atl_utils_get_mac_permanent,
931 .set_link_speed = hw_atl_utils_mpi_set_speed,
932 .set_state = hw_atl_utils_mpi_set_state,
933 .update_link_status = hw_atl_utils_mpi_get_link_status,
934 .update_stats = hw_atl_utils_update_stats,
935 .set_power = aq_fw1x_set_power,
936 .get_temp = NULL,
937 .get_cable_len = NULL,
938 .set_eee_rate = NULL,
939 .get_eee_rate = NULL,
940 .set_flow_control = NULL,
941 .led_control = NULL,
942 .get_eeprom = NULL,
943 .set_eeprom = NULL,
944 };