1
2
3
4
5
6
7
8
9
10
11
12
13
14#include "../aq_nic.h"
15#include "../aq_hw_utils.h"
16#include "hw_atl_utils.h"
17#include "hw_atl_llh.h"
18#include "hw_atl_llh_internal.h"
19
20#include <linux/random.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
51static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
52static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
53 enum hal_atl_utils_fw_state_e state);
54
55int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
56{
57 int err = 0;
58
59 err = hw_atl_utils_soft_reset(self);
60 if (err)
61 return err;
62
63 hw_atl_utils_hw_chip_features_init(self,
64 &self->chip_features);
65
66 hw_atl_utils_get_fw_version(self, &self->fw_ver_actual);
67
68 if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
69 self->fw_ver_actual) == 0) {
70 *fw_ops = &aq_fw_1x_ops;
71 } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X,
72 self->fw_ver_actual) == 0) {
73 *fw_ops = &aq_fw_2x_ops;
74 } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X,
75 self->fw_ver_actual) == 0) {
76 *fw_ops = &aq_fw_2x_ops;
77 } else {
78 aq_pr_err("Bad FW version detected: %x\n",
79 self->fw_ver_actual);
80 return -EOPNOTSUPP;
81 }
82 self->aq_fw_ops = *fw_ops;
83 err = self->aq_fw_ops->init(self);
84 return err;
85}
86
87static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self)
88{
89 u32 gsr, val;
90 int k = 0;
91
92 aq_hw_write_reg(self, 0x404, 0x40e1);
93 AQ_HW_SLEEP(50);
94
95
96 val = aq_hw_read_reg(self, 0x53C);
97 aq_hw_write_reg(self, 0x53C, val | 0x10);
98
99 gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
100 aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
101
102
103 aq_hw_write_reg(self, 0x404, 0x80e0);
104 aq_hw_write_reg(self, 0x32a8, 0x0);
105 aq_hw_write_reg(self, 0x520, 0x1);
106
107
108 val = aq_hw_read_reg(self, 0x53C);
109 aq_hw_write_reg(self, 0x53C, val | 0x10);
110 AQ_HW_SLEEP(10);
111
112 aq_hw_write_reg(self, 0x53C, val & ~0x10);
113
114 aq_hw_write_reg(self, 0x404, 0x180e0);
115
116 for (k = 0; k < 1000; k++) {
117 u32 flb_status = aq_hw_read_reg(self,
118 HW_ATL_MPI_DAISY_CHAIN_STATUS);
119
120 flb_status = flb_status & 0x10;
121 if (flb_status)
122 break;
123 AQ_HW_SLEEP(10);
124 }
125 if (k == 1000) {
126 aq_pr_err("MAC kickstart failed\n");
127 return -EIO;
128 }
129
130
131 aq_hw_write_reg(self, 0x404, 0x80e0);
132 AQ_HW_SLEEP(50);
133 aq_hw_write_reg(self, 0x3a0, 0x1);
134
135
136
137
138 hw_atl_rx_rx_reg_res_dis_set(self, 0U);
139 hw_atl_tx_tx_reg_res_dis_set(self, 0U);
140 aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
141 BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
142 HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
143 gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
144 aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
145
146 for (k = 0; k < 1000; k++) {
147 u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
148
149 if (fw_state)
150 break;
151 AQ_HW_SLEEP(10);
152 }
153 if (k == 1000) {
154 aq_pr_err("FW kickstart failed\n");
155 return -EIO;
156 }
157
158 AQ_HW_SLEEP(15);
159
160 return 0;
161}
162
163static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self)
164{
165 u32 gsr, val, rbl_status;
166 int k;
167
168 aq_hw_write_reg(self, 0x404, 0x40e1);
169 aq_hw_write_reg(self, 0x3a0, 0x1);
170 aq_hw_write_reg(self, 0x32a8, 0x0);
171
172
173 aq_hw_write_reg(self, 0x388, 0xDEAD);
174
175
176 val = aq_hw_read_reg(self, 0x53C);
177 aq_hw_write_reg(self, 0x53C, val | 0x10);
178
179
180 hw_atl_rx_rx_reg_res_dis_set(self, 0U);
181 hw_atl_tx_tx_reg_res_dis_set(self, 0U);
182 aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
183 BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
184 HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
185 gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
186 aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR,
187 (gsr & 0xFFFFBFFF) | 0x8000);
188
189 if (FORCE_FLASHLESS)
190 aq_hw_write_reg(self, 0x534, 0x0);
191
192 aq_hw_write_reg(self, 0x404, 0x40e0);
193
194
195 for (k = 0; k < 1000; k++) {
196 rbl_status = aq_hw_read_reg(self, 0x388) & 0xFFFF;
197 if (rbl_status && rbl_status != 0xDEAD)
198 break;
199 AQ_HW_SLEEP(10);
200 }
201 if (!rbl_status || rbl_status == 0xDEAD) {
202 aq_pr_err("RBL Restart failed");
203 return -EIO;
204 }
205
206
207 if (FORCE_FLASHLESS)
208 aq_hw_write_reg(self, 0x534, 0xA0);
209
210 if (rbl_status == 0xF1A7) {
211 aq_pr_err("No FW detected. Dynamic FW load not implemented\n");
212 return -ENOTSUPP;
213 }
214
215 for (k = 0; k < 1000; k++) {
216 u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
217
218 if (fw_state)
219 break;
220 AQ_HW_SLEEP(10);
221 }
222 if (k == 1000) {
223 aq_pr_err("FW kickstart failed\n");
224 return -EIO;
225 }
226
227 AQ_HW_SLEEP(15);
228
229 return 0;
230}
231
232int hw_atl_utils_soft_reset(struct aq_hw_s *self)
233{
234 int k;
235 u32 boot_exit_code = 0;
236
237 for (k = 0; k < 1000; ++k) {
238 u32 flb_status = aq_hw_read_reg(self,
239 HW_ATL_MPI_DAISY_CHAIN_STATUS);
240 boot_exit_code = aq_hw_read_reg(self,
241 HW_ATL_MPI_BOOT_EXIT_CODE);
242 if (flb_status != 0x06000000 || boot_exit_code != 0)
243 break;
244 }
245
246 if (k == 1000) {
247 aq_pr_err("Neither RBL nor FLB firmware started\n");
248 return -EOPNOTSUPP;
249 }
250
251 self->rbl_enabled = (boot_exit_code != 0);
252
253
254
255
256 if (!hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
257 aq_hw_read_reg(self,
258 HW_ATL_MPI_FW_VERSION))) {
259 int err = 0;
260
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 return hw_atl_utils_soft_reset_rbl(self);
269 else
270 return hw_atl_utils_soft_reset_flb(self);
271}
272
273int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
274 u32 *p, u32 cnt)
275{
276 int err = 0;
277
278 AQ_HW_WAIT_FOR(hw_atl_reg_glb_cpu_sem_get(self,
279 HW_ATL_FW_SM_RAM) == 1U,
280 1U, 10000U);
281
282 if (err < 0) {
283 bool is_locked;
284
285 hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
286 is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
287 if (!is_locked) {
288 err = -ETIME;
289 goto err_exit;
290 }
291 }
292
293 aq_hw_write_reg(self, HW_ATL_MIF_ADDR, a);
294
295 for (++cnt; --cnt && !err;) {
296 aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U);
297
298 if (IS_CHIP_FEATURE(REVISION_B1))
299 AQ_HW_WAIT_FOR(a != aq_hw_read_reg(self,
300 HW_ATL_MIF_ADDR),
301 1, 1000U);
302 else
303 AQ_HW_WAIT_FOR(!(0x100 & aq_hw_read_reg(self,
304 HW_ATL_MIF_CMD)),
305 1, 1000U);
306
307 *(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL);
308 a += 4;
309 }
310
311 hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
312
313err_exit:
314 return err;
315}
316
317static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
318 u32 cnt)
319{
320 int err = 0;
321 bool is_locked;
322
323 is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
324 if (!is_locked) {
325 err = -ETIME;
326 goto err_exit;
327 }
328 if (IS_CHIP_FEATURE(REVISION_B1)) {
329 u32 offset = 0;
330
331 for (; offset < cnt; ++offset) {
332 aq_hw_write_reg(self, 0x328, p[offset]);
333 aq_hw_write_reg(self, 0x32C,
334 (0x80000000 | (0xFFFF & (offset * 4))));
335 hw_atl_mcp_up_force_intr_set(self, 1);
336
337 AQ_HW_WAIT_FOR((aq_hw_read_reg(self,
338 0x32C) & 0xF0000000) !=
339 0x80000000,
340 10, 1000);
341 }
342 } else {
343 u32 offset = 0;
344
345 aq_hw_write_reg(self, 0x208, a);
346
347 for (; offset < cnt; ++offset) {
348 aq_hw_write_reg(self, 0x20C, p[offset]);
349 aq_hw_write_reg(self, 0x200, 0xC000);
350
351 AQ_HW_WAIT_FOR((aq_hw_read_reg(self, 0x200U) &
352 0x100) == 0, 10, 1000);
353 }
354 }
355
356 hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
357
358err_exit:
359 return err;
360}
361
362static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
363{
364 int err = 0;
365 const u32 dw_major_mask = 0xff000000U;
366 const u32 dw_minor_mask = 0x00ffffffU;
367
368 err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0;
369 if (err < 0)
370 goto err_exit;
371 err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
372 -EOPNOTSUPP : 0;
373err_exit:
374 return err;
375}
376
377static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
378 const struct aq_hw_caps_s *aq_hw_caps)
379{
380 int err = 0;
381
382 if (!aq_hw_read_reg(self, 0x370U)) {
383 unsigned int rnd = 0U;
384 unsigned int ucp_0x370 = 0U;
385
386 get_random_bytes(&rnd, sizeof(unsigned int));
387
388 ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd);
389 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
390 }
391
392 hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U);
393
394
395 AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
396 aq_hw_read_reg(self, 0x360U)), 1000U, 10U);
397
398 return err;
399}
400
401#define HW_ATL_RPC_CONTROL_ADR 0x0338U
402#define HW_ATL_RPC_STATE_ADR 0x033CU
403
404struct 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
416int 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
436err_exit:
437 return err;
438}
439
440int 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
485err_exit:
486 return err;
487}
488
489static 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, self->aq_nic_cfg->aq_hw_caps);
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
501err_exit:
502 return err;
503}
504
505int 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
514void 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 = self->aq_nic_cfg ?
528 self->aq_nic_cfg->mtu : 1514U;
529 pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
530 pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
531 pmbox->stats.dpc = atomic_read(&self->dpc);
532 } else {
533 pmbox->stats.dpc = hw_atl_reg_rx_dma_stat_counter7get(self);
534 }
535
536err_exit:;
537}
538
539static int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
540{
541 u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
542
543 val = val & ~HW_ATL_MPI_SPEED_MSK;
544 val |= speed << HW_ATL_MPI_SPEED_SHIFT;
545 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
546
547 return 0;
548}
549
550static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
551 enum hal_atl_utils_fw_state_e state)
552{
553 int err = 0;
554 u32 transaction_id = 0;
555 struct hw_aq_atl_utils_mbox_header mbox;
556 u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
557
558 if (state == MPI_RESET) {
559 hw_atl_utils_mpi_read_mbox(self, &mbox);
560
561 transaction_id = mbox.transaction_id;
562
563 AQ_HW_WAIT_FOR(transaction_id !=
564 (hw_atl_utils_mpi_read_mbox(self, &mbox),
565 mbox.transaction_id),
566 1000U, 100U);
567 if (err < 0)
568 goto err_exit;
569 }
570
571
572
573 if (state == MPI_DEINIT || state == MPI_POWER)
574 val |= HW_ATL_MPI_DIRTY_WAKE_MSK;
575 else
576 val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK;
577
578
579 val = val & ~HW_ATL_MPI_STATE_MSK;
580 val |= state & HW_ATL_MPI_STATE_MSK;
581
582 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
583err_exit:
584 return err;
585}
586
587int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
588{
589 u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
590 u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
591 struct aq_hw_link_status_s *link_status = &self->aq_link_status;
592
593 if (!link_speed_mask) {
594 link_status->mbps = 0U;
595 } else {
596 switch (link_speed_mask) {
597 case HAL_ATLANTIC_RATE_10G:
598 link_status->mbps = 10000U;
599 break;
600
601 case HAL_ATLANTIC_RATE_5G:
602 case HAL_ATLANTIC_RATE_5GSR:
603 link_status->mbps = 5000U;
604 break;
605
606 case HAL_ATLANTIC_RATE_2GS:
607 link_status->mbps = 2500U;
608 break;
609
610 case HAL_ATLANTIC_RATE_1G:
611 link_status->mbps = 1000U;
612 break;
613
614 case HAL_ATLANTIC_RATE_100M:
615 link_status->mbps = 100U;
616 break;
617
618 default:
619 return -EBUSY;
620 }
621 }
622
623 return 0;
624}
625
626int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
627 u8 *mac)
628{
629 int err = 0;
630 u32 h = 0U;
631 u32 l = 0U;
632 u32 mac_addr[2];
633
634 if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
635 unsigned int rnd = 0;
636 unsigned int ucp_0x370 = 0;
637
638 get_random_bytes(&rnd, sizeof(unsigned int));
639
640 ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
641 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
642 }
643
644 err = hw_atl_utils_fw_downld_dwords(self,
645 aq_hw_read_reg(self, 0x00000374U) +
646 (40U * 4U),
647 mac_addr,
648 ARRAY_SIZE(mac_addr));
649 if (err < 0) {
650 mac_addr[0] = 0U;
651 mac_addr[1] = 0U;
652 err = 0;
653 } else {
654 mac_addr[0] = __swab32(mac_addr[0]);
655 mac_addr[1] = __swab32(mac_addr[1]);
656 }
657
658 ether_addr_copy(mac, (u8 *)mac_addr);
659
660 if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
661
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
682unsigned 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
713void 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
740static 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
747int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
748 unsigned int power_state)
749{
750 hw_atl_utils_mpi_set_speed(self, 0);
751 hw_atl_utils_mpi_set_state(self, MPI_POWER);
752 return 0;
753}
754
755int hw_atl_utils_update_stats(struct aq_hw_s *self)
756{
757 struct hw_aq_atl_utils_mbox mbox;
758
759 hw_atl_utils_mpi_read_stats(self, &mbox);
760
761#define AQ_SDELTA(_N_) (self->curr_stats._N_ += \
762 mbox.stats._N_ - self->last_stats._N_)
763
764 if (self->aq_link_status.mbps) {
765 AQ_SDELTA(uprc);
766 AQ_SDELTA(mprc);
767 AQ_SDELTA(bprc);
768 AQ_SDELTA(erpt);
769
770 AQ_SDELTA(uptc);
771 AQ_SDELTA(mptc);
772 AQ_SDELTA(bptc);
773 AQ_SDELTA(erpr);
774
775 AQ_SDELTA(ubrc);
776 AQ_SDELTA(ubtc);
777 AQ_SDELTA(mbrc);
778 AQ_SDELTA(mbtc);
779 AQ_SDELTA(bbrc);
780 AQ_SDELTA(bbtc);
781 AQ_SDELTA(dpc);
782 }
783#undef AQ_SDELTA
784 self->curr_stats.dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counterlsw_get(self);
785 self->curr_stats.dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counterlsw_get(self);
786 self->curr_stats.dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counterlsw_get(self);
787 self->curr_stats.dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counterlsw_get(self);
788
789 memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
790
791 return 0;
792}
793
794struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self)
795{
796 return &self->curr_stats;
797}
798
799static const u32 hw_atl_utils_hw_mac_regs[] = {
800 0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
801 0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
802 0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
803 0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
804 0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
805 0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
806 0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
807 0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
808 0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
809 0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
810 0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
811 0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
812 0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
813 0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
814 0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
815 0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
816 0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
817 0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
818 0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
819 0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
820 0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
821 0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
822};
823
824int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
825 const struct aq_hw_caps_s *aq_hw_caps,
826 u32 *regs_buff)
827{
828 unsigned int i = 0U;
829
830 for (i = 0; i < aq_hw_caps->mac_regs_count; i++)
831 regs_buff[i] = aq_hw_read_reg(self,
832 hw_atl_utils_hw_mac_regs[i]);
833 return 0;
834}
835
836int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
837{
838 *fw_version = aq_hw_read_reg(self, 0x18U);
839 return 0;
840}
841
842const struct aq_fw_ops aq_fw_1x_ops = {
843 .init = hw_atl_utils_mpi_create,
844 .deinit = hw_atl_fw1x_deinit,
845 .reset = NULL,
846 .get_mac_permanent = hw_atl_utils_get_mac_permanent,
847 .set_link_speed = hw_atl_utils_mpi_set_speed,
848 .set_state = hw_atl_utils_mpi_set_state,
849 .update_link_status = hw_atl_utils_mpi_get_link_status,
850 .update_stats = hw_atl_utils_update_stats,
851 .set_flow_control = NULL,
852};
853