New upstream version 18.11-rc1
[deb_dpdk.git] / 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
309                 *(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL);
310                 a += 4;
311         }
312
313         hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
314
315 err_exit:
316         return err;
317 }
318
319 int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
320                                          u32 cnt)
321 {
322         int err = 0;
323         bool is_locked;
324
325         is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
326         if (!is_locked) {
327                 err = -ETIMEDOUT;
328                 goto err_exit;
329         }
330         if (IS_CHIP_FEATURE(REVISION_B1)) {
331                 u32 offset = 0;
332
333                 for (; offset < cnt; ++offset) {
334                         aq_hw_write_reg(self, 0x328, p[offset]);
335                         aq_hw_write_reg(self, 0x32C,
336                                 (0x80000000 | (0xFFFF & (offset * 4))));
337                         hw_atl_mcp_up_force_intr_set(self, 1);
338                         /* 1000 times by 10us = 10ms */
339                         AQ_HW_WAIT_FOR((aq_hw_read_reg(self,
340                                         0x32C) & 0xF0000000) != 0x80000000,
341                                         10, 1000);
342                 }
343         } else {
344                 u32 offset = 0;
345
346                 aq_hw_write_reg(self, 0x208, a);
347
348                 for (; offset < cnt; ++offset) {
349                         aq_hw_write_reg(self, 0x20C, p[offset]);
350                         aq_hw_write_reg(self, 0x200, 0xC000);
351
352                         AQ_HW_WAIT_FOR((aq_hw_read_reg(self, 0x200U)
353                                         & 0x100) == 0, 10, 1000);
354                 }
355         }
356
357         hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
358
359 err_exit:
360         return err;
361 }
362
363 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
364 {
365         int err = 0;
366         const u32 dw_major_mask = 0xff000000U;
367         const u32 dw_minor_mask = 0x00ffffffU;
368
369         err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0;
370         if (err < 0)
371                 goto err_exit;
372         err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
373                 -EOPNOTSUPP : 0;
374 err_exit:
375         return err;
376 }
377
378 static int hw_atl_utils_init_ucp(struct aq_hw_s *self)
379 {
380         int err = 0;
381
382         if (!aq_hw_read_reg(self, 0x370U)) {
383                 unsigned int rnd = (uint32_t)rte_rand();
384                 unsigned int ucp_0x370 = 0U;
385
386                 ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd);
387                 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
388         }
389
390         hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U);
391
392         /* check 10 times by 1ms */
393         AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
394                        aq_hw_read_reg(self, 0x360U)), 1000U, 10U);
395         AQ_HW_WAIT_FOR(0U != (self->rpc_addr =
396                        aq_hw_read_reg(self, 0x334U)), 1000U, 100U);
397
398         return err;
399 }
400
401 #define HW_ATL_RPC_CONTROL_ADR 0x0338U
402 #define HW_ATL_RPC_STATE_ADR   0x033CU
403
404 struct aq_hw_atl_utils_fw_rpc_tid_s {
405         union {
406                 u32 val;
407                 struct {
408                         u16 tid;
409                         u16 len;
410                 };
411         };
412 };
413
414 #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
415
416 int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
417 {
418         int err = 0;
419         struct aq_hw_atl_utils_fw_rpc_tid_s sw;
420
421         if (!IS_CHIP_FEATURE(MIPS)) {
422                 err = -1;
423                 goto err_exit;
424         }
425         err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
426                                             (u32 *)(void *)&self->rpc,
427                                             (rpc_size + sizeof(u32) -
428                                             sizeof(u8)) / sizeof(u32));
429         if (err < 0)
430                 goto err_exit;
431
432         sw.tid = 0xFFFFU & (++self->rpc_tid);
433         sw.len = (u16)rpc_size;
434         aq_hw_write_reg(self, HW_ATL_RPC_CONTROL_ADR, sw.val);
435
436 err_exit:
437         return err;
438 }
439
440 int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
441                                     struct hw_aq_atl_utils_fw_rpc **rpc)
442 {
443         int err = 0;
444         struct aq_hw_atl_utils_fw_rpc_tid_s sw;
445         struct aq_hw_atl_utils_fw_rpc_tid_s fw;
446
447         do {
448                 sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR);
449
450                 self->rpc_tid = sw.tid;
451
452                 AQ_HW_WAIT_FOR(sw.tid ==
453                                 (fw.val =
454                                 aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR),
455                                 fw.tid), 1000U, 100U);
456                 if (err < 0)
457                         goto err_exit;
458
459                 if (fw.len == 0xFFFFU) {
460                         err = hw_atl_utils_fw_rpc_call(self, sw.len);
461                         if (err < 0)
462                                 goto err_exit;
463                 }
464         } while (sw.tid != fw.tid || 0xFFFFU == fw.len);
465         if (err < 0)
466                 goto err_exit;
467
468         if (rpc) {
469                 if (fw.len) {
470                         err =
471                         hw_atl_utils_fw_downld_dwords(self,
472                                                       self->rpc_addr,
473                                                       (u32 *)(void *)
474                                                       &self->rpc,
475                                                       (fw.len + sizeof(u32) -
476                                                       sizeof(u8)) /
477                                                       sizeof(u32));
478                         if (err < 0)
479                                 goto err_exit;
480                 }
481
482                 *rpc = &self->rpc;
483         }
484
485 err_exit:
486         return err;
487 }
488
489 static int hw_atl_utils_mpi_create(struct aq_hw_s *self)
490 {
491         int err = 0;
492
493         err = hw_atl_utils_init_ucp(self);
494         if (err < 0)
495                 goto err_exit;
496
497         err = hw_atl_utils_fw_rpc_init(self);
498         if (err < 0)
499                 goto err_exit;
500
501 err_exit:
502         return err;
503 }
504
505 int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
506                                struct hw_aq_atl_utils_mbox_header *pmbox)
507 {
508         return hw_atl_utils_fw_downld_dwords(self,
509                                       self->mbox_addr,
510                                       (u32 *)(void *)pmbox,
511                                       sizeof(*pmbox) / sizeof(u32));
512 }
513
514 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
515                                  struct hw_aq_atl_utils_mbox *pmbox)
516 {
517         int err = 0;
518
519         err = hw_atl_utils_fw_downld_dwords(self,
520                                             self->mbox_addr,
521                                             (u32 *)(void *)pmbox,
522                                             sizeof(*pmbox) / sizeof(u32));
523         if (err < 0)
524                 goto err_exit;
525
526         if (IS_CHIP_FEATURE(REVISION_A0)) {
527                 unsigned int mtu = 1514;
528                 pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
529                 pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
530         } else {
531                 pmbox->stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
532         }
533
534 err_exit:;
535 }
536
537 static
538 int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
539 {
540         u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
541
542         val = val & ~HW_ATL_MPI_SPEED_MSK;
543         val |= speed << HW_ATL_MPI_SPEED_SHIFT;
544         aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
545
546         return 0;
547 }
548
549 int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
550                                 enum hal_atl_utils_fw_state_e state)
551 {
552         int err = 0;
553         u32 transaction_id = 0;
554         struct hw_aq_atl_utils_mbox_header mbox;
555         u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
556
557         if (state == MPI_RESET) {
558                 hw_atl_utils_mpi_read_mbox(self, &mbox);
559
560                 transaction_id = mbox.transaction_id;
561
562                 AQ_HW_WAIT_FOR(transaction_id !=
563                                 (hw_atl_utils_mpi_read_mbox(self, &mbox),
564                                  mbox.transaction_id),
565                                1000U, 100U);
566                 if (err < 0)
567                         goto err_exit;
568         }
569         /* On interface DEINIT we disable DW (raise bit)
570          * Otherwise enable DW (clear bit)
571          */
572         if (state == MPI_DEINIT || state == MPI_POWER)
573                 val |= HW_ATL_MPI_DIRTY_WAKE_MSK;
574         else
575                 val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK;
576
577         /* Set new state bits */
578         val = val & ~HW_ATL_MPI_STATE_MSK;
579         val |= state & HW_ATL_MPI_STATE_MSK;
580
581         aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
582 err_exit:
583         return err;
584 }
585
586 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
587 {
588         u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
589         u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
590         struct aq_hw_link_status_s *link_status = &self->aq_link_status;
591
592         if (!link_speed_mask) {
593                 link_status->mbps = 0U;
594         } else {
595                 switch (link_speed_mask) {
596                 case HAL_ATLANTIC_RATE_10G:
597                         link_status->mbps = 10000U;
598                         break;
599
600                 case HAL_ATLANTIC_RATE_5G:
601                 case HAL_ATLANTIC_RATE_5GSR:
602                         link_status->mbps = 5000U;
603                         break;
604
605                 case HAL_ATLANTIC_RATE_2GS:
606                         link_status->mbps = 2500U;
607                         break;
608
609                 case HAL_ATLANTIC_RATE_1G:
610                         link_status->mbps = 1000U;
611                         break;
612
613                 case HAL_ATLANTIC_RATE_100M:
614                         link_status->mbps = 100U;
615                         break;
616
617                 default:
618                         return -EBUSY;
619                 }
620         }
621
622         return 0;
623 }
624
625 static int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
626                                    u8 *mac)
627 {
628         int err = 0;
629         u32 h = 0U;
630         u32 l = 0U;
631         u32 mac_addr[2];
632
633         if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
634                 unsigned int rnd = (uint32_t)rte_rand();
635                 unsigned int ucp_0x370 = 0;
636
637                 //get_random_bytes(&rnd, sizeof(unsigned int));
638
639                 ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
640                 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
641         }
642
643         err = hw_atl_utils_fw_downld_dwords(self,
644                                             aq_hw_read_reg(self, 0x00000374U) +
645                                             (40U * 4U),
646                                             mac_addr,
647                                             ARRAY_SIZE(mac_addr));
648         if (err < 0) {
649                 mac_addr[0] = 0U;
650                 mac_addr[1] = 0U;
651                 err = 0;
652         } else {
653                 mac_addr[0] = rte_constant_bswap32(mac_addr[0]);
654                 mac_addr[1] = rte_constant_bswap32(mac_addr[1]);
655         }
656
657         ether_addr_copy((struct ether_addr *)mac_addr,
658                         (struct ether_addr *)mac);
659
660         if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
661                 /* chip revision */
662                 l = 0xE3000000U
663                         | (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG))
664                         | (0x00 << 16);
665                 h = 0x8001300EU;
666
667                 mac[5] = (u8)(0xFFU & l);
668                 l >>= 8;
669                 mac[4] = (u8)(0xFFU & l);
670                 l >>= 8;
671                 mac[3] = (u8)(0xFFU & l);
672                 l >>= 8;
673                 mac[2] = (u8)(0xFFU & l);
674                 mac[1] = (u8)(0xFFU & h);
675                 h >>= 8;
676                 mac[0] = (u8)(0xFFU & h);
677         }
678
679         return err;
680 }
681
682 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
683 {
684         unsigned int ret = 0U;
685
686         switch (mbps) {
687         case 100U:
688                 ret = 5U;
689                 break;
690
691         case 1000U:
692                 ret = 4U;
693                 break;
694
695         case 2500U:
696                 ret = 3U;
697                 break;
698
699         case 5000U:
700                 ret = 1U;
701                 break;
702
703         case 10000U:
704                 ret = 0U;
705                 break;
706
707         default:
708                 break;
709         }
710         return ret;
711 }
712
713 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
714 {
715         u32 chip_features = 0U;
716         u32 val = hw_atl_reg_glb_mif_id_get(self);
717         u32 mif_rev = val & 0xFFU;
718
719         if ((0xFU & mif_rev) == 1U) {
720                 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
721                         HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
722                         HAL_ATLANTIC_UTILS_CHIP_MIPS;
723         } else if ((0xFU & mif_rev) == 2U) {
724                 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
725                         HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
726                         HAL_ATLANTIC_UTILS_CHIP_MIPS |
727                         HAL_ATLANTIC_UTILS_CHIP_TPO2 |
728                         HAL_ATLANTIC_UTILS_CHIP_RPF2;
729         } else if ((0xFU & mif_rev) == 0xAU) {
730                 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 |
731                         HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
732                         HAL_ATLANTIC_UTILS_CHIP_MIPS |
733                         HAL_ATLANTIC_UTILS_CHIP_TPO2 |
734                         HAL_ATLANTIC_UTILS_CHIP_RPF2;
735         }
736
737         *p = chip_features;
738 }
739
740 static int hw_atl_fw1x_deinit(struct aq_hw_s *self)
741 {
742         hw_atl_utils_mpi_set_speed(self, 0);
743         hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
744         return 0;
745 }
746
747 int hw_atl_utils_update_stats(struct aq_hw_s *self)
748 {
749         struct hw_aq_atl_utils_mbox mbox;
750
751         hw_atl_utils_mpi_read_stats(self, &mbox);
752
753 #define AQ_SDELTA(_N_) (self->curr_stats._N_ += \
754                         mbox.stats._N_ - self->last_stats._N_)
755
756         if (1) {//self->aq_link_status.mbps) {
757                 AQ_SDELTA(uprc);
758                 AQ_SDELTA(mprc);
759                 AQ_SDELTA(bprc);
760                 AQ_SDELTA(erpt);
761
762                 AQ_SDELTA(uptc);
763                 AQ_SDELTA(mptc);
764                 AQ_SDELTA(bptc);
765                 AQ_SDELTA(erpr);
766                 AQ_SDELTA(ubrc);
767                 AQ_SDELTA(ubtc);
768                 AQ_SDELTA(mbrc);
769                 AQ_SDELTA(mbtc);
770                 AQ_SDELTA(bbrc);
771                 AQ_SDELTA(bbtc);
772                 AQ_SDELTA(dpc);
773         }
774 #undef AQ_SDELTA
775         self->curr_stats.dma_pkt_rc =
776            hw_atl_stats_rx_dma_good_pkt_counterlsw_get(self) +
777            ((u64)hw_atl_stats_rx_dma_good_pkt_countermsw_get(self) << 32);
778         self->curr_stats.dma_pkt_tc =
779            hw_atl_stats_tx_dma_good_pkt_counterlsw_get(self) +
780            ((u64)hw_atl_stats_tx_dma_good_pkt_countermsw_get(self) << 32);
781         self->curr_stats.dma_oct_rc =
782            hw_atl_stats_rx_dma_good_octet_counterlsw_get(self) +
783            ((u64)hw_atl_stats_rx_dma_good_octet_countermsw_get(self) << 32);
784         self->curr_stats.dma_oct_tc =
785            hw_atl_stats_tx_dma_good_octet_counterlsw_get(self) +
786            ((u64)hw_atl_stats_tx_dma_good_octet_countermsw_get(self) << 32);
787
788         self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
789
790         memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
791
792         return 0;
793 }
794
795 struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self)
796 {
797         return &self->curr_stats;
798 }
799
800 static const u32 hw_atl_utils_hw_mac_regs[] = {
801         0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
802         0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
803         0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
804         0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
805         0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
806         0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
807         0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
808         0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
809         0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
810         0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
811         0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
812         0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
813         0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
814         0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
815         0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
816         0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
817         0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
818         0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
819         0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
820         0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
821         0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
822         0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
823 };
824
825 unsigned int hw_atl_utils_hw_get_reg_length(void)
826 {
827         return ARRAY_SIZE(hw_atl_utils_hw_mac_regs);
828 }
829
830 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
831                              u32 *regs_buff)
832 {
833         unsigned int i = 0U;
834         unsigned int mac_regs_count = hw_atl_utils_hw_get_reg_length();
835
836         for (i = 0; i < mac_regs_count; i++)
837                 regs_buff[i] = aq_hw_read_reg(self,
838                                               hw_atl_utils_hw_mac_regs[i]);
839         return 0;
840 }
841
842 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
843 {
844         *fw_version = aq_hw_read_reg(self, 0x18U);
845         return 0;
846 }
847
848 static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac)
849 {
850         struct hw_aq_atl_utils_fw_rpc *prpc = NULL;
851         unsigned int rpc_size = 0U;
852         int err = 0;
853
854         err = hw_atl_utils_fw_rpc_wait(self, &prpc);
855         if (err < 0)
856                 goto err_exit;
857
858         memset(prpc, 0, sizeof(*prpc));
859
860         if (wol_enabled) {
861                 rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_wol);
862
863                 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD;
864                 prpc->msg_wol.priority = 0x10000000; /* normal priority */
865                 prpc->msg_wol.pattern_id = 1U;
866                 prpc->msg_wol.wol_packet_type = 2U; /* Magic Packet */
867
868                 ether_addr_copy((struct ether_addr *)mac,
869                         (struct ether_addr *)&prpc->msg_wol.wol_pattern);
870         } else {
871                 rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_del_id);
872
873                 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL;
874                 prpc->msg_wol.pattern_id = 1U;
875         }
876
877         err = hw_atl_utils_fw_rpc_call(self, rpc_size);
878         if (err < 0)
879                 goto err_exit;
880 err_exit:
881         return err;
882 }
883
884 static
885 int aq_fw1x_set_power(struct aq_hw_s *self,
886                       unsigned int power_state __rte_unused,
887                       u8 *mac)
888 {
889         struct hw_aq_atl_utils_fw_rpc *prpc = NULL;
890         unsigned int rpc_size = 0U;
891         int err = 0;
892         if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) {
893                 err = aq_fw1x_set_wol(self, 1, mac);
894
895                 if (err < 0)
896                         goto err_exit;
897
898                 rpc_size = sizeof(prpc->msg_id) +
899                                 sizeof(prpc->msg_enable_wakeup);
900
901                 err = hw_atl_utils_fw_rpc_wait(self, &prpc);
902
903                 if (err < 0)
904                         goto err_exit;
905
906                 memset(prpc, 0, rpc_size);
907
908                 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_ENABLE_WAKEUP;
909                 prpc->msg_enable_wakeup.pattern_mask = 0x00000002;
910
911                 err = hw_atl_utils_fw_rpc_call(self, rpc_size);
912                 if (err < 0)
913                         goto err_exit;
914         }
915
916         hw_atl_utils_mpi_set_speed(self, 0);
917         hw_atl_utils_mpi_set_state(self, MPI_POWER);
918 err_exit:
919         return err;
920 }
921
922
923
924 const struct aq_fw_ops aq_fw_1x_ops = {
925         .init = hw_atl_utils_mpi_create,
926         .deinit = hw_atl_fw1x_deinit,
927         .reset = NULL,
928         .get_mac_permanent = hw_atl_utils_get_mac_permanent,
929         .set_link_speed = hw_atl_utils_mpi_set_speed,
930         .set_state = hw_atl_utils_mpi_set_state,
931         .update_link_status = hw_atl_utils_mpi_get_link_status,
932         .update_stats = hw_atl_utils_update_stats,
933         .set_power = aq_fw1x_set_power,
934         .get_temp = NULL,
935         .get_cable_len = NULL,
936         .set_eee_rate = NULL,
937         .get_eee_rate = NULL,
938         .set_flow_control = NULL,
939         .led_control = NULL,
940         .get_eeprom = NULL,
941         .set_eeprom = NULL,
942 };