13f02b9f99c5dd3e75b30baf16be8ee57332fb1c
[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
466         if (rpc) {
467                 if (fw.len) {
468                         err =
469                         hw_atl_utils_fw_downld_dwords(self,
470                                                       self->rpc_addr,
471                                                       (u32 *)(void *)
472                                                       &self->rpc,
473                                                       (fw.len + sizeof(u32) -
474                                                       sizeof(u8)) /
475                                                       sizeof(u32));
476                         if (err < 0)
477                                 goto err_exit;
478                 }
479
480                 *rpc = &self->rpc;
481         }
482
483 err_exit:
484         return err;
485 }
486
487 static int hw_atl_utils_mpi_create(struct aq_hw_s *self)
488 {
489         int err = 0;
490
491         err = hw_atl_utils_init_ucp(self);
492         if (err < 0)
493                 goto err_exit;
494
495         err = hw_atl_utils_fw_rpc_init(self);
496         if (err < 0)
497                 goto err_exit;
498
499 err_exit:
500         return err;
501 }
502
503 int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
504                                struct hw_aq_atl_utils_mbox_header *pmbox)
505 {
506         return hw_atl_utils_fw_downld_dwords(self,
507                                       self->mbox_addr,
508                                       (u32 *)(void *)pmbox,
509                                       sizeof(*pmbox) / sizeof(u32));
510 }
511
512 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
513                                  struct hw_aq_atl_utils_mbox *pmbox)
514 {
515         int err = 0;
516
517         err = hw_atl_utils_fw_downld_dwords(self,
518                                             self->mbox_addr,
519                                             (u32 *)(void *)pmbox,
520                                             sizeof(*pmbox) / sizeof(u32));
521         if (err < 0)
522                 goto err_exit;
523
524         if (IS_CHIP_FEATURE(REVISION_A0)) {
525                 unsigned int mtu = 1514;
526                 pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
527                 pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
528         } else {
529                 pmbox->stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
530         }
531
532 err_exit:;
533 }
534
535 static
536 int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
537 {
538         u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
539
540         val = val & ~HW_ATL_MPI_SPEED_MSK;
541         val |= speed << HW_ATL_MPI_SPEED_SHIFT;
542         aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
543
544         return 0;
545 }
546
547 int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
548                                 enum hal_atl_utils_fw_state_e state)
549 {
550         int err = 0;
551         u32 transaction_id = 0;
552         struct hw_aq_atl_utils_mbox_header mbox;
553         u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
554
555         if (state == MPI_RESET) {
556                 hw_atl_utils_mpi_read_mbox(self, &mbox);
557
558                 transaction_id = mbox.transaction_id;
559
560                 AQ_HW_WAIT_FOR(transaction_id !=
561                                 (hw_atl_utils_mpi_read_mbox(self, &mbox),
562                                  mbox.transaction_id),
563                                1000U, 100U);
564                 if (err < 0)
565                         goto err_exit;
566         }
567         /* On interface DEINIT we disable DW (raise bit)
568          * Otherwise enable DW (clear bit)
569          */
570         if (state == MPI_DEINIT || state == MPI_POWER)
571                 val |= HW_ATL_MPI_DIRTY_WAKE_MSK;
572         else
573                 val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK;
574
575         /* Set new state bits */
576         val = val & ~HW_ATL_MPI_STATE_MSK;
577         val |= state & HW_ATL_MPI_STATE_MSK;
578
579         aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
580 err_exit:
581         return err;
582 }
583
584 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
585 {
586         u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
587         u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
588         struct aq_hw_link_status_s *link_status = &self->aq_link_status;
589
590         if (!link_speed_mask) {
591                 link_status->mbps = 0U;
592         } else {
593                 switch (link_speed_mask) {
594                 case HAL_ATLANTIC_RATE_10G:
595                         link_status->mbps = 10000U;
596                         break;
597
598                 case HAL_ATLANTIC_RATE_5G:
599                 case HAL_ATLANTIC_RATE_5GSR:
600                         link_status->mbps = 5000U;
601                         break;
602
603                 case HAL_ATLANTIC_RATE_2GS:
604                         link_status->mbps = 2500U;
605                         break;
606
607                 case HAL_ATLANTIC_RATE_1G:
608                         link_status->mbps = 1000U;
609                         break;
610
611                 case HAL_ATLANTIC_RATE_100M:
612                         link_status->mbps = 100U;
613                         break;
614
615                 default:
616                         return -EBUSY;
617                 }
618         }
619
620         return 0;
621 }
622
623 static int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
624                                    u8 *mac)
625 {
626         int err = 0;
627         u32 h = 0U;
628         u32 l = 0U;
629         u32 mac_addr[2];
630
631         if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
632                 unsigned int rnd = (uint32_t)rte_rand();
633                 unsigned int ucp_0x370 = 0;
634
635                 //get_random_bytes(&rnd, sizeof(unsigned int));
636
637                 ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
638                 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
639         }
640
641         err = hw_atl_utils_fw_downld_dwords(self,
642                                             aq_hw_read_reg(self, 0x00000374U) +
643                                             (40U * 4U),
644                                             mac_addr,
645                                             ARRAY_SIZE(mac_addr));
646         if (err < 0) {
647                 mac_addr[0] = 0U;
648                 mac_addr[1] = 0U;
649                 err = 0;
650         } else {
651                 mac_addr[0] = rte_constant_bswap32(mac_addr[0]);
652                 mac_addr[1] = rte_constant_bswap32(mac_addr[1]);
653         }
654
655         ether_addr_copy((struct ether_addr *)mac_addr,
656                         (struct ether_addr *)mac);
657
658         if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
659                 /* chip revision */
660                 l = 0xE3000000U
661                         | (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG))
662                         | (0x00 << 16);
663                 h = 0x8001300EU;
664
665                 mac[5] = (u8)(0xFFU & l);
666                 l >>= 8;
667                 mac[4] = (u8)(0xFFU & l);
668                 l >>= 8;
669                 mac[3] = (u8)(0xFFU & l);
670                 l >>= 8;
671                 mac[2] = (u8)(0xFFU & l);
672                 mac[1] = (u8)(0xFFU & h);
673                 h >>= 8;
674                 mac[0] = (u8)(0xFFU & h);
675         }
676
677         return err;
678 }
679
680 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
681 {
682         unsigned int ret = 0U;
683
684         switch (mbps) {
685         case 100U:
686                 ret = 5U;
687                 break;
688
689         case 1000U:
690                 ret = 4U;
691                 break;
692
693         case 2500U:
694                 ret = 3U;
695                 break;
696
697         case 5000U:
698                 ret = 1U;
699                 break;
700
701         case 10000U:
702                 ret = 0U;
703                 break;
704
705         default:
706                 break;
707         }
708         return ret;
709 }
710
711 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
712 {
713         u32 chip_features = 0U;
714         u32 val = hw_atl_reg_glb_mif_id_get(self);
715         u32 mif_rev = val & 0xFFU;
716
717         if ((0xFU & mif_rev) == 1U) {
718                 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
719                         HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
720                         HAL_ATLANTIC_UTILS_CHIP_MIPS;
721         } else if ((0xFU & mif_rev) == 2U) {
722                 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
723                         HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
724                         HAL_ATLANTIC_UTILS_CHIP_MIPS |
725                         HAL_ATLANTIC_UTILS_CHIP_TPO2 |
726                         HAL_ATLANTIC_UTILS_CHIP_RPF2;
727         } else if ((0xFU & mif_rev) == 0xAU) {
728                 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 |
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         }
734
735         *p = chip_features;
736 }
737
738 static int hw_atl_fw1x_deinit(struct aq_hw_s *self)
739 {
740         hw_atl_utils_mpi_set_speed(self, 0);
741         hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
742         return 0;
743 }
744
745 int hw_atl_utils_update_stats(struct aq_hw_s *self)
746 {
747         struct hw_aq_atl_utils_mbox mbox;
748
749         hw_atl_utils_mpi_read_stats(self, &mbox);
750
751 #define AQ_SDELTA(_N_) (self->curr_stats._N_ += \
752                         mbox.stats._N_ - self->last_stats._N_)
753
754         if (1) {//self->aq_link_status.mbps) {
755                 AQ_SDELTA(uprc);
756                 AQ_SDELTA(mprc);
757                 AQ_SDELTA(bprc);
758                 AQ_SDELTA(erpt);
759
760                 AQ_SDELTA(uptc);
761                 AQ_SDELTA(mptc);
762                 AQ_SDELTA(bptc);
763                 AQ_SDELTA(erpr);
764                 AQ_SDELTA(ubrc);
765                 AQ_SDELTA(ubtc);
766                 AQ_SDELTA(mbrc);
767                 AQ_SDELTA(mbtc);
768                 AQ_SDELTA(bbrc);
769                 AQ_SDELTA(bbtc);
770                 AQ_SDELTA(dpc);
771         }
772 #undef AQ_SDELTA
773         self->curr_stats.dma_pkt_rc =
774            hw_atl_stats_rx_dma_good_pkt_counterlsw_get(self) +
775            ((u64)hw_atl_stats_rx_dma_good_pkt_countermsw_get(self) << 32);
776         self->curr_stats.dma_pkt_tc =
777            hw_atl_stats_tx_dma_good_pkt_counterlsw_get(self) +
778            ((u64)hw_atl_stats_tx_dma_good_pkt_countermsw_get(self) << 32);
779         self->curr_stats.dma_oct_rc =
780            hw_atl_stats_rx_dma_good_octet_counterlsw_get(self) +
781            ((u64)hw_atl_stats_rx_dma_good_octet_countermsw_get(self) << 32);
782         self->curr_stats.dma_oct_tc =
783            hw_atl_stats_tx_dma_good_octet_counterlsw_get(self) +
784            ((u64)hw_atl_stats_tx_dma_good_octet_countermsw_get(self) << 32);
785
786         self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
787
788         memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
789
790         return 0;
791 }
792
793 struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self)
794 {
795         return &self->curr_stats;
796 }
797
798 static const u32 hw_atl_utils_hw_mac_regs[] = {
799         0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
800         0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
801         0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
802         0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
803         0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
804         0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
805         0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
806         0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
807         0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
808         0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
809         0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
810         0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
811         0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
812         0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
813         0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
814         0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
815         0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
816         0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
817         0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
818         0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
819         0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
820         0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
821 };
822
823 unsigned int hw_atl_utils_hw_get_reg_length(void)
824 {
825         return ARRAY_SIZE(hw_atl_utils_hw_mac_regs);
826 }
827
828 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
829                              u32 *regs_buff)
830 {
831         unsigned int i = 0U;
832         unsigned int mac_regs_count = hw_atl_utils_hw_get_reg_length();
833
834         for (i = 0; i < mac_regs_count; i++)
835                 regs_buff[i] = aq_hw_read_reg(self,
836                                               hw_atl_utils_hw_mac_regs[i]);
837         return 0;
838 }
839
840 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
841 {
842         *fw_version = aq_hw_read_reg(self, 0x18U);
843         return 0;
844 }
845
846 static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac)
847 {
848         struct hw_aq_atl_utils_fw_rpc *prpc = NULL;
849         unsigned int rpc_size = 0U;
850         int err = 0;
851
852         err = hw_atl_utils_fw_rpc_wait(self, &prpc);
853         if (err < 0)
854                 goto err_exit;
855
856         memset(prpc, 0, sizeof(*prpc));
857
858         if (wol_enabled) {
859                 rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_wol);
860
861                 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD;
862                 prpc->msg_wol.priority = 0x10000000; /* normal priority */
863                 prpc->msg_wol.pattern_id = 1U;
864                 prpc->msg_wol.wol_packet_type = 2U; /* Magic Packet */
865
866                 ether_addr_copy((struct ether_addr *)mac,
867                         (struct ether_addr *)&prpc->msg_wol.wol_pattern);
868         } else {
869                 rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_del_id);
870
871                 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL;
872                 prpc->msg_wol.pattern_id = 1U;
873         }
874
875         err = hw_atl_utils_fw_rpc_call(self, rpc_size);
876
877 err_exit:
878         return err;
879 }
880
881 static
882 int aq_fw1x_set_power(struct aq_hw_s *self,
883                       unsigned int power_state __rte_unused,
884                       u8 *mac)
885 {
886         struct hw_aq_atl_utils_fw_rpc *prpc = NULL;
887         unsigned int rpc_size = 0U;
888         int err = 0;
889         if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) {
890                 err = aq_fw1x_set_wol(self, 1, mac);
891
892                 if (err < 0)
893                         goto err_exit;
894
895                 rpc_size = sizeof(prpc->msg_id) +
896                                 sizeof(prpc->msg_enable_wakeup);
897
898                 err = hw_atl_utils_fw_rpc_wait(self, &prpc);
899
900                 if (err < 0)
901                         goto err_exit;
902
903                 memset(prpc, 0, rpc_size);
904
905                 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_ENABLE_WAKEUP;
906                 prpc->msg_enable_wakeup.pattern_mask = 0x00000002;
907
908                 err = hw_atl_utils_fw_rpc_call(self, rpc_size);
909                 if (err < 0)
910                         goto err_exit;
911         }
912
913         hw_atl_utils_mpi_set_speed(self, 0);
914         hw_atl_utils_mpi_set_state(self, MPI_POWER);
915 err_exit:
916         return err;
917 }
918
919
920
921 const struct aq_fw_ops aq_fw_1x_ops = {
922         .init = hw_atl_utils_mpi_create,
923         .deinit = hw_atl_fw1x_deinit,
924         .reset = NULL,
925         .get_mac_permanent = hw_atl_utils_get_mac_permanent,
926         .set_link_speed = hw_atl_utils_mpi_set_speed,
927         .set_state = hw_atl_utils_mpi_set_state,
928         .update_link_status = hw_atl_utils_mpi_get_link_status,
929         .update_stats = hw_atl_utils_update_stats,
930         .set_power = aq_fw1x_set_power,
931         .get_temp = NULL,
932         .get_cable_len = NULL,
933         .set_eee_rate = NULL,
934         .get_eee_rate = NULL,
935         .set_flow_control = NULL,
936         .led_control = NULL,
937         .get_eeprom = NULL,
938         .set_eeprom = NULL,
939 };