1 /*
2 * aQuantia Corporation Network Driver
3 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 */
9
10 /* File hw_atl_utils.c: Definition of common functions for Atlantic hardware
11 * abstraction layer.
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
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
hw_atl_utils_initfw(struct aq_hw_s * self,const struct aq_fw_ops ** fw_ops)55 int 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
hw_atl_utils_soft_reset_flb(struct aq_hw_s * self)87 static 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 /* Cleanup SPI */
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 /* Kickstart MAC */
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 /* Reset SPI again because of possible interrupted SPI burst */
108 val = aq_hw_read_reg(self, 0x53C);
109 aq_hw_write_reg(self, 0x53C, val | 0x10);
110 AQ_HW_SLEEP(10);
111 /* Clear SPI reset state */
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 /* FW reset */
131 aq_hw_write_reg(self, 0x404, 0x80e0);
132 AQ_HW_SLEEP(50);
133 aq_hw_write_reg(self, 0x3a0, 0x1);
134
135 /* Kickstart PHY - skipped */
136
137 /* Global software reset*/
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 /* Old FW requires fixed delay after init */
158 AQ_HW_SLEEP(15);
159
160 return 0;
161 }
162
hw_atl_utils_soft_reset_rbl(struct aq_hw_s * self)163 static 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 /* Alter RBL status */
173 aq_hw_write_reg(self, 0x388, 0xDEAD);
174
175 /* Cleanup SPI */
176 val = aq_hw_read_reg(self, 0x53C);
177 aq_hw_write_reg(self, 0x53C, val | 0x10);
178
179 /* Global software reset*/
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 /* Wait for RBL boot */
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 /* Restore NVR */
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 /* Old FW requires fixed delay after init */
227 AQ_HW_SLEEP(15);
228
229 return 0;
230 }
231
hw_atl_utils_soft_reset(struct aq_hw_s * self)232 int 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 /* FW 1.x may bootup in an invalid POWER state (WOL feature).
254 * We should work around this by forcing its state back to DEINIT
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
hw_atl_utils_fw_downld_dwords(struct aq_hw_s * self,u32 a,u32 * p,u32 cnt)273 int 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
313 err_exit:
314 return err;
315 }
316
hw_atl_utils_fw_upload_dwords(struct aq_hw_s * self,u32 a,u32 * p,u32 cnt)317 static 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
329 aq_hw_write_reg(self, 0x00000208U, a);
330
331 for (++cnt; --cnt;) {
332 u32 i = 0U;
333
334 aq_hw_write_reg(self, 0x0000020CU, *(p++));
335 aq_hw_write_reg(self, 0x00000200U, 0xC000U);
336
337 for (i = 1024U;
338 (0x100U & aq_hw_read_reg(self, 0x00000200U)) && --i;) {
339 }
340 }
341
342 hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
343
344 err_exit:
345 return err;
346 }
347
hw_atl_utils_ver_match(u32 ver_expected,u32 ver_actual)348 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
349 {
350 int err = 0;
351 const u32 dw_major_mask = 0xff000000U;
352 const u32 dw_minor_mask = 0x00ffffffU;
353
354 err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0;
355 if (err < 0)
356 goto err_exit;
357 err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
358 -EOPNOTSUPP : 0;
359 err_exit:
360 return err;
361 }
362
hw_atl_utils_init_ucp(struct aq_hw_s * self,const struct aq_hw_caps_s * aq_hw_caps)363 static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
364 const struct aq_hw_caps_s *aq_hw_caps)
365 {
366 int err = 0;
367
368 if (!aq_hw_read_reg(self, 0x370U)) {
369 unsigned int rnd = 0U;
370 unsigned int ucp_0x370 = 0U;
371
372 get_random_bytes(&rnd, sizeof(unsigned int));
373
374 ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd);
375 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
376 }
377
378 hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U);
379
380 /* check 10 times by 1ms */
381 AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
382 aq_hw_read_reg(self, 0x360U)), 1000U, 10U);
383
384 return err;
385 }
386
387 #define HW_ATL_RPC_CONTROL_ADR 0x0338U
388 #define HW_ATL_RPC_STATE_ADR 0x033CU
389
390 struct aq_hw_atl_utils_fw_rpc_tid_s {
391 union {
392 u32 val;
393 struct {
394 u16 tid;
395 u16 len;
396 };
397 };
398 };
399
400 #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
401
hw_atl_utils_fw_rpc_call(struct aq_hw_s * self,unsigned int rpc_size)402 static int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
403 {
404 int err = 0;
405 struct aq_hw_atl_utils_fw_rpc_tid_s sw;
406
407 if (!IS_CHIP_FEATURE(MIPS)) {
408 err = -1;
409 goto err_exit;
410 }
411 err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
412 (u32 *)(void *)&self->rpc,
413 (rpc_size + sizeof(u32) -
414 sizeof(u8)) / sizeof(u32));
415 if (err < 0)
416 goto err_exit;
417
418 sw.tid = 0xFFFFU & (++self->rpc_tid);
419 sw.len = (u16)rpc_size;
420 aq_hw_write_reg(self, HW_ATL_RPC_CONTROL_ADR, sw.val);
421
422 err_exit:
423 return err;
424 }
425
hw_atl_utils_fw_rpc_wait(struct aq_hw_s * self,struct hw_aq_atl_utils_fw_rpc ** rpc)426 static int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
427 struct hw_aq_atl_utils_fw_rpc **rpc)
428 {
429 int err = 0;
430 struct aq_hw_atl_utils_fw_rpc_tid_s sw;
431 struct aq_hw_atl_utils_fw_rpc_tid_s fw;
432
433 do {
434 sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR);
435
436 self->rpc_tid = sw.tid;
437
438 AQ_HW_WAIT_FOR(sw.tid ==
439 (fw.val =
440 aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR),
441 fw.tid), 1000U, 100U);
442 if (err < 0)
443 goto err_exit;
444
445 if (fw.len == 0xFFFFU) {
446 err = hw_atl_utils_fw_rpc_call(self, sw.len);
447 if (err < 0)
448 goto err_exit;
449 }
450 } while (sw.tid != fw.tid || 0xFFFFU == fw.len);
451 if (err < 0)
452 goto err_exit;
453
454 if (rpc) {
455 if (fw.len) {
456 err =
457 hw_atl_utils_fw_downld_dwords(self,
458 self->rpc_addr,
459 (u32 *)(void *)
460 &self->rpc,
461 (fw.len + sizeof(u32) -
462 sizeof(u8)) /
463 sizeof(u32));
464 if (err < 0)
465 goto err_exit;
466 }
467
468 *rpc = &self->rpc;
469 }
470
471 err_exit:
472 return err;
473 }
474
hw_atl_utils_mpi_create(struct aq_hw_s * self)475 static int hw_atl_utils_mpi_create(struct aq_hw_s *self)
476 {
477 int err = 0;
478
479 err = hw_atl_utils_init_ucp(self, self->aq_nic_cfg->aq_hw_caps);
480 if (err < 0)
481 goto err_exit;
482
483 err = hw_atl_utils_fw_rpc_init(self);
484 if (err < 0)
485 goto err_exit;
486
487 err_exit:
488 return err;
489 }
490
hw_atl_utils_mpi_read_mbox(struct aq_hw_s * self,struct hw_aq_atl_utils_mbox_header * pmbox)491 int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
492 struct hw_aq_atl_utils_mbox_header *pmbox)
493 {
494 return hw_atl_utils_fw_downld_dwords(self,
495 self->mbox_addr,
496 (u32 *)(void *)pmbox,
497 sizeof(*pmbox) / sizeof(u32));
498 }
499
hw_atl_utils_mpi_read_stats(struct aq_hw_s * self,struct hw_aq_atl_utils_mbox * pmbox)500 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
501 struct hw_aq_atl_utils_mbox *pmbox)
502 {
503 int err = 0;
504
505 err = hw_atl_utils_fw_downld_dwords(self,
506 self->mbox_addr,
507 (u32 *)(void *)pmbox,
508 sizeof(*pmbox) / sizeof(u32));
509 if (err < 0)
510 goto err_exit;
511
512 if (IS_CHIP_FEATURE(REVISION_A0)) {
513 unsigned int mtu = self->aq_nic_cfg ?
514 self->aq_nic_cfg->mtu : 1514U;
515 pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
516 pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
517 pmbox->stats.dpc = atomic_read(&self->dpc);
518 } else {
519 pmbox->stats.dpc = hw_atl_reg_rx_dma_stat_counter7get(self);
520 }
521
522 err_exit:;
523 }
524
hw_atl_utils_mpi_set_speed(struct aq_hw_s * self,u32 speed)525 static int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
526 {
527 u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
528
529 val = val & ~HW_ATL_MPI_SPEED_MSK;
530 val |= speed << HW_ATL_MPI_SPEED_SHIFT;
531 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
532
533 return 0;
534 }
535
hw_atl_utils_mpi_set_state(struct aq_hw_s * self,enum hal_atl_utils_fw_state_e state)536 static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
537 enum hal_atl_utils_fw_state_e state)
538 {
539 int err = 0;
540 u32 transaction_id = 0;
541 struct hw_aq_atl_utils_mbox_header mbox;
542 u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
543
544 if (state == MPI_RESET) {
545 hw_atl_utils_mpi_read_mbox(self, &mbox);
546
547 transaction_id = mbox.transaction_id;
548
549 AQ_HW_WAIT_FOR(transaction_id !=
550 (hw_atl_utils_mpi_read_mbox(self, &mbox),
551 mbox.transaction_id),
552 1000U, 100U);
553 if (err < 0)
554 goto err_exit;
555 }
556 /* On interface DEINIT we disable DW (raise bit)
557 * Otherwise enable DW (clear bit)
558 */
559 if (state == MPI_DEINIT || state == MPI_POWER)
560 val |= HW_ATL_MPI_DIRTY_WAKE_MSK;
561 else
562 val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK;
563
564 /* Set new state bits */
565 val = val & ~HW_ATL_MPI_STATE_MSK;
566 val |= state & HW_ATL_MPI_STATE_MSK;
567
568 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
569 err_exit:
570 return err;
571 }
572
hw_atl_utils_mpi_get_link_status(struct aq_hw_s * self)573 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
574 {
575 u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
576 u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
577 struct aq_hw_link_status_s *link_status = &self->aq_link_status;
578
579 if (!link_speed_mask) {
580 link_status->mbps = 0U;
581 } else {
582 switch (link_speed_mask) {
583 case HAL_ATLANTIC_RATE_10G:
584 link_status->mbps = 10000U;
585 break;
586
587 case HAL_ATLANTIC_RATE_5G:
588 case HAL_ATLANTIC_RATE_5GSR:
589 link_status->mbps = 5000U;
590 break;
591
592 case HAL_ATLANTIC_RATE_2GS:
593 link_status->mbps = 2500U;
594 break;
595
596 case HAL_ATLANTIC_RATE_1G:
597 link_status->mbps = 1000U;
598 break;
599
600 case HAL_ATLANTIC_RATE_100M:
601 link_status->mbps = 100U;
602 break;
603
604 default:
605 return -EBUSY;
606 }
607 }
608
609 return 0;
610 }
611
hw_atl_utils_get_mac_permanent(struct aq_hw_s * self,u8 * mac)612 int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
613 u8 *mac)
614 {
615 int err = 0;
616 u32 h = 0U;
617 u32 l = 0U;
618 u32 mac_addr[2];
619
620 if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
621 unsigned int rnd = 0;
622 unsigned int ucp_0x370 = 0;
623
624 get_random_bytes(&rnd, sizeof(unsigned int));
625
626 ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
627 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
628 }
629
630 err = hw_atl_utils_fw_downld_dwords(self,
631 aq_hw_read_reg(self, 0x00000374U) +
632 (40U * 4U),
633 mac_addr,
634 ARRAY_SIZE(mac_addr));
635 if (err < 0) {
636 mac_addr[0] = 0U;
637 mac_addr[1] = 0U;
638 err = 0;
639 } else {
640 mac_addr[0] = __swab32(mac_addr[0]);
641 mac_addr[1] = __swab32(mac_addr[1]);
642 }
643
644 ether_addr_copy(mac, (u8 *)mac_addr);
645
646 if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
647 /* chip revision */
648 l = 0xE3000000U
649 | (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG))
650 | (0x00 << 16);
651 h = 0x8001300EU;
652
653 mac[5] = (u8)(0xFFU & l);
654 l >>= 8;
655 mac[4] = (u8)(0xFFU & l);
656 l >>= 8;
657 mac[3] = (u8)(0xFFU & l);
658 l >>= 8;
659 mac[2] = (u8)(0xFFU & l);
660 mac[1] = (u8)(0xFFU & h);
661 h >>= 8;
662 mac[0] = (u8)(0xFFU & h);
663 }
664
665 return err;
666 }
667
hw_atl_utils_mbps_2_speed_index(unsigned int mbps)668 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
669 {
670 unsigned int ret = 0U;
671
672 switch (mbps) {
673 case 100U:
674 ret = 5U;
675 break;
676
677 case 1000U:
678 ret = 4U;
679 break;
680
681 case 2500U:
682 ret = 3U;
683 break;
684
685 case 5000U:
686 ret = 1U;
687 break;
688
689 case 10000U:
690 ret = 0U;
691 break;
692
693 default:
694 break;
695 }
696 return ret;
697 }
698
hw_atl_utils_hw_chip_features_init(struct aq_hw_s * self,u32 * p)699 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
700 {
701 u32 chip_features = 0U;
702 u32 val = hw_atl_reg_glb_mif_id_get(self);
703 u32 mif_rev = val & 0xFFU;
704
705 if ((0xFU & mif_rev) == 1U) {
706 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
707 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
708 HAL_ATLANTIC_UTILS_CHIP_MIPS;
709 } else if ((0xFU & mif_rev) == 2U) {
710 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
711 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
712 HAL_ATLANTIC_UTILS_CHIP_MIPS |
713 HAL_ATLANTIC_UTILS_CHIP_TPO2 |
714 HAL_ATLANTIC_UTILS_CHIP_RPF2;
715 } else if ((0xFU & mif_rev) == 0xAU) {
716 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 |
717 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
718 HAL_ATLANTIC_UTILS_CHIP_MIPS |
719 HAL_ATLANTIC_UTILS_CHIP_TPO2 |
720 HAL_ATLANTIC_UTILS_CHIP_RPF2;
721 }
722
723 *p = chip_features;
724 }
725
hw_atl_fw1x_deinit(struct aq_hw_s * self)726 static int hw_atl_fw1x_deinit(struct aq_hw_s *self)
727 {
728 hw_atl_utils_mpi_set_speed(self, 0);
729 hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
730 return 0;
731 }
732
hw_atl_utils_hw_set_power(struct aq_hw_s * self,unsigned int power_state)733 int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
734 unsigned int power_state)
735 {
736 hw_atl_utils_mpi_set_speed(self, 0);
737 hw_atl_utils_mpi_set_state(self, MPI_POWER);
738 return 0;
739 }
740
hw_atl_utils_update_stats(struct aq_hw_s * self)741 int hw_atl_utils_update_stats(struct aq_hw_s *self)
742 {
743 struct hw_aq_atl_utils_mbox mbox;
744
745 hw_atl_utils_mpi_read_stats(self, &mbox);
746
747 #define AQ_SDELTA(_N_) (self->curr_stats._N_ += \
748 mbox.stats._N_ - self->last_stats._N_)
749
750 if (self->aq_link_status.mbps) {
751 AQ_SDELTA(uprc);
752 AQ_SDELTA(mprc);
753 AQ_SDELTA(bprc);
754 AQ_SDELTA(erpt);
755
756 AQ_SDELTA(uptc);
757 AQ_SDELTA(mptc);
758 AQ_SDELTA(bptc);
759 AQ_SDELTA(erpr);
760
761 AQ_SDELTA(ubrc);
762 AQ_SDELTA(ubtc);
763 AQ_SDELTA(mbrc);
764 AQ_SDELTA(mbtc);
765 AQ_SDELTA(bbrc);
766 AQ_SDELTA(bbtc);
767 AQ_SDELTA(dpc);
768 }
769 #undef AQ_SDELTA
770 self->curr_stats.dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counterlsw_get(self);
771 self->curr_stats.dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counterlsw_get(self);
772 self->curr_stats.dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counterlsw_get(self);
773 self->curr_stats.dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counterlsw_get(self);
774
775 memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
776
777 return 0;
778 }
779
hw_atl_utils_get_hw_stats(struct aq_hw_s * self)780 struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self)
781 {
782 return &self->curr_stats;
783 }
784
785 static const u32 hw_atl_utils_hw_mac_regs[] = {
786 0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
787 0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
788 0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
789 0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
790 0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
791 0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
792 0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
793 0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
794 0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
795 0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
796 0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
797 0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
798 0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
799 0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
800 0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
801 0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
802 0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
803 0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
804 0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
805 0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
806 0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
807 0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
808 };
809
hw_atl_utils_hw_get_regs(struct aq_hw_s * self,const struct aq_hw_caps_s * aq_hw_caps,u32 * regs_buff)810 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
811 const struct aq_hw_caps_s *aq_hw_caps,
812 u32 *regs_buff)
813 {
814 unsigned int i = 0U;
815
816 for (i = 0; i < aq_hw_caps->mac_regs_count; i++)
817 regs_buff[i] = aq_hw_read_reg(self,
818 hw_atl_utils_hw_mac_regs[i]);
819 return 0;
820 }
821
hw_atl_utils_get_fw_version(struct aq_hw_s * self,u32 * fw_version)822 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
823 {
824 *fw_version = aq_hw_read_reg(self, 0x18U);
825 return 0;
826 }
827
828 const struct aq_fw_ops aq_fw_1x_ops = {
829 .init = hw_atl_utils_mpi_create,
830 .deinit = hw_atl_fw1x_deinit,
831 .reset = NULL,
832 .get_mac_permanent = hw_atl_utils_get_mac_permanent,
833 .set_link_speed = hw_atl_utils_mpi_set_speed,
834 .set_state = hw_atl_utils_mpi_set_state,
835 .update_link_status = hw_atl_utils_mpi_get_link_status,
836 .update_stats = hw_atl_utils_update_stats,
837 .set_flow_control = NULL,
838 };
839