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