1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * aQuantia Corporation Network Driver
4 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
5 */
6
7 /* File hw_atl_utils.c: Definition of common functions for Atlantic hardware
8 * abstraction layer.
9 */
10
11 #include "../aq_nic.h"
12 #include "../aq_hw_utils.h"
13 #include "hw_atl_utils.h"
14 #include "hw_atl_llh.h"
15 #include "hw_atl_llh_internal.h"
16
17 #include <linux/random.h>
18
19 #define HW_ATL_UCP_0X370_REG 0x0370U
20
21 #define HW_ATL_MIF_CMD 0x0200U
22 #define HW_ATL_MIF_ADDR 0x0208U
23 #define HW_ATL_MIF_VAL 0x020CU
24
25 #define HW_ATL_RPC_CONTROL_ADR 0x0338U
26 #define HW_ATL_RPC_STATE_ADR 0x033CU
27
28 #define HW_ATL_MPI_FW_VERSION 0x18
29 #define HW_ATL_MPI_CONTROL_ADR 0x0368U
30 #define HW_ATL_MPI_STATE_ADR 0x036CU
31
32 #define HW_ATL_MPI_STATE_MSK 0x00FFU
33 #define HW_ATL_MPI_STATE_SHIFT 0U
34 #define HW_ATL_MPI_SPEED_MSK 0x00FF0000U
35 #define HW_ATL_MPI_SPEED_SHIFT 16U
36 #define HW_ATL_MPI_DIRTY_WAKE_MSK 0x02000000U
37
38 #define HW_ATL_MPI_DAISY_CHAIN_STATUS 0x704
39 #define HW_ATL_MPI_BOOT_EXIT_CODE 0x388
40
41 #define HW_ATL_MAC_PHY_CONTROL 0x4000
42 #define HW_ATL_MAC_PHY_MPI_RESET_BIT 0x1D
43
44 #define HW_ATL_FW_VER_1X 0x01050006U
45 #define HW_ATL_FW_VER_2X 0x02000000U
46 #define HW_ATL_FW_VER_3X 0x03000000U
47
48 #define FORCE_FLASHLESS 0
49
50 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
51
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 static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self);
56 static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self);
57 static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self);
58 static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self);
59 static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self);
60
hw_atl_utils_initfw(struct aq_hw_s * self,const struct aq_fw_ops ** fw_ops)61 int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
62 {
63 int err = 0;
64
65 err = hw_atl_utils_soft_reset(self);
66 if (err)
67 return err;
68
69 hw_atl_utils_hw_chip_features_init(self,
70 &self->chip_features);
71
72 hw_atl_utils_get_fw_version(self, &self->fw_ver_actual);
73
74 if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
75 self->fw_ver_actual) == 0) {
76 *fw_ops = &aq_fw_1x_ops;
77 } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X,
78 self->fw_ver_actual) == 0) {
79 *fw_ops = &aq_fw_2x_ops;
80 } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X,
81 self->fw_ver_actual) == 0) {
82 *fw_ops = &aq_fw_2x_ops;
83 } else {
84 aq_pr_err("Bad FW version detected: %x\n",
85 self->fw_ver_actual);
86 return -EOPNOTSUPP;
87 }
88 self->aq_fw_ops = *fw_ops;
89 err = self->aq_fw_ops->init(self);
90 return err;
91 }
92
hw_atl_utils_soft_reset_flb(struct aq_hw_s * self)93 static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self)
94 {
95 u32 gsr, val;
96 int k = 0;
97
98 aq_hw_write_reg(self, 0x404, 0x40e1);
99 AQ_HW_SLEEP(50);
100
101 /* Cleanup SPI */
102 val = aq_hw_read_reg(self, 0x53C);
103 aq_hw_write_reg(self, 0x53C, val | 0x10);
104
105 gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
106 aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
107
108 /* Kickstart MAC */
109 aq_hw_write_reg(self, 0x404, 0x80e0);
110 aq_hw_write_reg(self, 0x32a8, 0x0);
111 aq_hw_write_reg(self, 0x520, 0x1);
112
113 /* Reset SPI again because of possible interrupted SPI burst */
114 val = aq_hw_read_reg(self, 0x53C);
115 aq_hw_write_reg(self, 0x53C, val | 0x10);
116 AQ_HW_SLEEP(10);
117 /* Clear SPI reset state */
118 aq_hw_write_reg(self, 0x53C, val & ~0x10);
119
120 aq_hw_write_reg(self, 0x404, 0x180e0);
121
122 for (k = 0; k < 1000; k++) {
123 u32 flb_status = aq_hw_read_reg(self,
124 HW_ATL_MPI_DAISY_CHAIN_STATUS);
125
126 flb_status = flb_status & 0x10;
127 if (flb_status)
128 break;
129 AQ_HW_SLEEP(10);
130 }
131 if (k == 1000) {
132 aq_pr_err("MAC kickstart failed\n");
133 return -EIO;
134 }
135
136 /* FW reset */
137 aq_hw_write_reg(self, 0x404, 0x80e0);
138 AQ_HW_SLEEP(50);
139 aq_hw_write_reg(self, 0x3a0, 0x1);
140
141 /* Kickstart PHY - skipped */
142
143 /* Global software reset*/
144 hw_atl_rx_rx_reg_res_dis_set(self, 0U);
145 hw_atl_tx_tx_reg_res_dis_set(self, 0U);
146 aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
147 BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
148 HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
149 gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
150 aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
151
152 for (k = 0; k < 1000; k++) {
153 u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
154
155 if (fw_state)
156 break;
157 AQ_HW_SLEEP(10);
158 }
159 if (k == 1000) {
160 aq_pr_err("FW kickstart failed\n");
161 return -EIO;
162 }
163 /* Old FW requires fixed delay after init */
164 AQ_HW_SLEEP(15);
165
166 return 0;
167 }
168
hw_atl_utils_soft_reset_rbl(struct aq_hw_s * self)169 static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self)
170 {
171 u32 gsr, val, rbl_status;
172 int k;
173
174 aq_hw_write_reg(self, 0x404, 0x40e1);
175 aq_hw_write_reg(self, 0x3a0, 0x1);
176 aq_hw_write_reg(self, 0x32a8, 0x0);
177
178 /* Alter RBL status */
179 aq_hw_write_reg(self, 0x388, 0xDEAD);
180
181 /* Cleanup SPI */
182 val = aq_hw_read_reg(self, 0x53C);
183 aq_hw_write_reg(self, 0x53C, val | 0x10);
184
185 /* Global software reset*/
186 hw_atl_rx_rx_reg_res_dis_set(self, 0U);
187 hw_atl_tx_tx_reg_res_dis_set(self, 0U);
188 aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
189 BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
190 HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
191 gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
192 aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR,
193 (gsr & 0xFFFFBFFF) | 0x8000);
194
195 if (FORCE_FLASHLESS)
196 aq_hw_write_reg(self, 0x534, 0x0);
197
198 aq_hw_write_reg(self, 0x404, 0x40e0);
199
200 /* Wait for RBL boot */
201 for (k = 0; k < 1000; k++) {
202 rbl_status = aq_hw_read_reg(self, 0x388) & 0xFFFF;
203 if (rbl_status && rbl_status != 0xDEAD)
204 break;
205 AQ_HW_SLEEP(10);
206 }
207 if (!rbl_status || rbl_status == 0xDEAD) {
208 aq_pr_err("RBL Restart failed");
209 return -EIO;
210 }
211
212 /* Restore NVR */
213 if (FORCE_FLASHLESS)
214 aq_hw_write_reg(self, 0x534, 0xA0);
215
216 if (rbl_status == 0xF1A7) {
217 aq_pr_err("No FW detected. Dynamic FW load not implemented\n");
218 return -ENOTSUPP;
219 }
220
221 for (k = 0; k < 1000; k++) {
222 u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
223
224 if (fw_state)
225 break;
226 AQ_HW_SLEEP(10);
227 }
228 if (k == 1000) {
229 aq_pr_err("FW kickstart failed\n");
230 return -EIO;
231 }
232 /* Old FW requires fixed delay after init */
233 AQ_HW_SLEEP(15);
234
235 return 0;
236 }
237
hw_atl_utils_soft_reset(struct aq_hw_s * self)238 int hw_atl_utils_soft_reset(struct aq_hw_s *self)
239 {
240 int k;
241 u32 boot_exit_code = 0;
242 u32 val;
243
244 for (k = 0; k < 1000; ++k) {
245 u32 flb_status = aq_hw_read_reg(self,
246 HW_ATL_MPI_DAISY_CHAIN_STATUS);
247 boot_exit_code = aq_hw_read_reg(self,
248 HW_ATL_MPI_BOOT_EXIT_CODE);
249 if (flb_status != 0x06000000 || boot_exit_code != 0)
250 break;
251 }
252
253 if (k == 1000) {
254 aq_pr_err("Neither RBL nor FLB firmware started\n");
255 return -EOPNOTSUPP;
256 }
257
258 self->rbl_enabled = (boot_exit_code != 0);
259
260 /* FW 1.x may bootup in an invalid POWER state (WOL feature).
261 * We should work around this by forcing its state back to DEINIT
262 */
263 if (!hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
264 aq_hw_read_reg(self,
265 HW_ATL_MPI_FW_VERSION))) {
266 int err = 0;
267
268 hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
269 err = readx_poll_timeout_atomic(hw_atl_utils_mpi_get_state,
270 self, val,
271 (val & HW_ATL_MPI_STATE_MSK) ==
272 MPI_DEINIT,
273 10, 10000U);
274 if (err)
275 return err;
276 }
277
278 if (self->rbl_enabled)
279 return hw_atl_utils_soft_reset_rbl(self);
280 else
281 return hw_atl_utils_soft_reset_flb(self);
282 }
283
hw_atl_utils_fw_downld_dwords(struct aq_hw_s * self,u32 a,u32 * p,u32 cnt)284 int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
285 u32 *p, u32 cnt)
286 {
287 int err = 0;
288 u32 val;
289
290 err = readx_poll_timeout_atomic(hw_atl_sem_ram_get,
291 self, val, val == 1U,
292 1U, 10000U);
293
294 if (err < 0) {
295 bool is_locked;
296
297 hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
298 is_locked = hw_atl_sem_ram_get(self);
299 if (!is_locked) {
300 err = -ETIME;
301 goto err_exit;
302 }
303 }
304
305 aq_hw_write_reg(self, HW_ATL_MIF_ADDR, a);
306
307 for (++cnt; --cnt && !err;) {
308 aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U);
309
310 if (IS_CHIP_FEATURE(REVISION_B1))
311 err = readx_poll_timeout_atomic(hw_atl_utils_mif_addr_get,
312 self, val, val != a,
313 1U, 1000U);
314 else
315 err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
316 self, val,
317 !(val & 0x100),
318 1U, 1000U);
319
320 *(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL);
321 a += 4;
322 }
323
324 hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
325
326 err_exit:
327 return err;
328 }
329
hw_atl_utils_fw_upload_dwords(struct aq_hw_s * self,u32 a,u32 * p,u32 cnt)330 static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
331 u32 cnt)
332 {
333 u32 val;
334 int err = 0;
335
336 err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, self,
337 val, val == 1U,
338 10U, 100000U);
339 if (err < 0)
340 goto err_exit;
341
342 if (IS_CHIP_FEATURE(REVISION_B1)) {
343 u32 offset = 0;
344
345 for (; offset < cnt; ++offset) {
346 aq_hw_write_reg(self, 0x328, p[offset]);
347 aq_hw_write_reg(self, 0x32C,
348 (0x80000000 | (0xFFFF & (offset * 4))));
349 hw_atl_mcp_up_force_intr_set(self, 1);
350 /* 1000 times by 10us = 10ms */
351 err = readx_poll_timeout_atomic(hw_atl_scrpad12_get,
352 self, val,
353 (val & 0xF0000000) !=
354 0x80000000,
355 10U, 10000U);
356 }
357 } else {
358 u32 offset = 0;
359
360 aq_hw_write_reg(self, 0x208, a);
361
362 for (; offset < cnt; ++offset) {
363 aq_hw_write_reg(self, 0x20C, p[offset]);
364 aq_hw_write_reg(self, 0x200, 0xC000);
365
366 err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
367 self, val,
368 (val & 0x100) == 0,
369 1000U, 10000U);
370 }
371 }
372
373 hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
374
375 err_exit:
376 return err;
377 }
378
hw_atl_utils_ver_match(u32 ver_expected,u32 ver_actual)379 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
380 {
381 int err = 0;
382 const u32 dw_major_mask = 0xff000000U;
383 const u32 dw_minor_mask = 0x00ffffffU;
384
385 err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0;
386 if (err < 0)
387 goto err_exit;
388 err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
389 -EOPNOTSUPP : 0;
390 err_exit:
391 return err;
392 }
393
hw_atl_utils_init_ucp(struct aq_hw_s * self,const struct aq_hw_caps_s * aq_hw_caps)394 static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
395 const struct aq_hw_caps_s *aq_hw_caps)
396 {
397 int err = 0;
398
399 if (!aq_hw_read_reg(self, 0x370U)) {
400 unsigned int rnd = 0U;
401 unsigned int ucp_0x370 = 0U;
402
403 get_random_bytes(&rnd, sizeof(unsigned int));
404
405 ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd);
406 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
407 }
408
409 hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U);
410
411 /* check 10 times by 1ms */
412 err = readx_poll_timeout_atomic(hw_atl_scrpad25_get,
413 self, self->mbox_addr,
414 self->mbox_addr != 0U,
415 1000U, 10000U);
416
417 return err;
418 }
419
420 struct aq_hw_atl_utils_fw_rpc_tid_s {
421 union {
422 u32 val;
423 struct {
424 u16 tid;
425 u16 len;
426 };
427 };
428 };
429
430 #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
431
hw_atl_utils_fw_rpc_call(struct aq_hw_s * self,unsigned int rpc_size)432 int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
433 {
434 int err = 0;
435 struct aq_hw_atl_utils_fw_rpc_tid_s sw;
436
437 if (!IS_CHIP_FEATURE(MIPS)) {
438 err = -1;
439 goto err_exit;
440 }
441 err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
442 (u32 *)(void *)&self->rpc,
443 (rpc_size + sizeof(u32) -
444 sizeof(u8)) / sizeof(u32));
445 if (err < 0)
446 goto err_exit;
447
448 sw.tid = 0xFFFFU & (++self->rpc_tid);
449 sw.len = (u16)rpc_size;
450 aq_hw_write_reg(self, HW_ATL_RPC_CONTROL_ADR, sw.val);
451
452 err_exit:
453 return err;
454 }
455
hw_atl_utils_fw_rpc_wait(struct aq_hw_s * self,struct hw_atl_utils_fw_rpc ** rpc)456 int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
457 struct hw_atl_utils_fw_rpc **rpc)
458 {
459 int err = 0;
460 struct aq_hw_atl_utils_fw_rpc_tid_s sw;
461 struct aq_hw_atl_utils_fw_rpc_tid_s fw;
462
463 do {
464 sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR);
465
466 self->rpc_tid = sw.tid;
467
468 err = readx_poll_timeout_atomic(hw_atl_utils_rpc_state_get,
469 self, fw.val,
470 sw.tid == fw.tid,
471 1000U, 100000U);
472
473 if (fw.len == 0xFFFFU) {
474 err = hw_atl_utils_fw_rpc_call(self, sw.len);
475 if (err < 0)
476 goto err_exit;
477 }
478 } while (sw.tid != fw.tid || 0xFFFFU == fw.len);
479
480 if (rpc) {
481 if (fw.len) {
482 err =
483 hw_atl_utils_fw_downld_dwords(self,
484 self->rpc_addr,
485 (u32 *)(void *)
486 &self->rpc,
487 (fw.len + sizeof(u32) -
488 sizeof(u8)) /
489 sizeof(u32));
490 if (err < 0)
491 goto err_exit;
492 }
493
494 *rpc = &self->rpc;
495 }
496
497 err_exit:
498 return err;
499 }
500
hw_atl_utils_mpi_create(struct aq_hw_s * self)501 static int hw_atl_utils_mpi_create(struct aq_hw_s *self)
502 {
503 int err = 0;
504
505 err = hw_atl_utils_init_ucp(self, self->aq_nic_cfg->aq_hw_caps);
506 if (err < 0)
507 goto err_exit;
508
509 err = hw_atl_utils_fw_rpc_init(self);
510 if (err < 0)
511 goto err_exit;
512
513 err_exit:
514 return err;
515 }
516
hw_atl_utils_mpi_read_mbox(struct aq_hw_s * self,struct hw_atl_utils_mbox_header * pmbox)517 int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
518 struct hw_atl_utils_mbox_header *pmbox)
519 {
520 return hw_atl_utils_fw_downld_dwords(self,
521 self->mbox_addr,
522 (u32 *)(void *)pmbox,
523 sizeof(*pmbox) / sizeof(u32));
524 }
525
hw_atl_utils_mpi_read_stats(struct aq_hw_s * self,struct hw_atl_utils_mbox * pmbox)526 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
527 struct hw_atl_utils_mbox *pmbox)
528 {
529 int err = 0;
530
531 err = hw_atl_utils_fw_downld_dwords(self,
532 self->mbox_addr,
533 (u32 *)(void *)pmbox,
534 sizeof(*pmbox) / sizeof(u32));
535 if (err < 0)
536 goto err_exit;
537
538 if (IS_CHIP_FEATURE(REVISION_A0)) {
539 unsigned int mtu = self->aq_nic_cfg ?
540 self->aq_nic_cfg->mtu : 1514U;
541 pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
542 pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
543 pmbox->stats.dpc = atomic_read(&self->dpc);
544 } else {
545 pmbox->stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
546 }
547
548 err_exit:;
549 }
550
hw_atl_utils_mpi_set_speed(struct aq_hw_s * self,u32 speed)551 static int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
552 {
553 u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
554
555 val = val & ~HW_ATL_MPI_SPEED_MSK;
556 val |= speed << HW_ATL_MPI_SPEED_SHIFT;
557 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
558
559 return 0;
560 }
561
hw_atl_utils_mpi_set_state(struct aq_hw_s * self,enum hal_atl_utils_fw_state_e state)562 static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
563 enum hal_atl_utils_fw_state_e state)
564 {
565 int err = 0;
566 u32 transaction_id = 0;
567 struct hw_atl_utils_mbox_header mbox;
568 u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
569
570 if (state == MPI_RESET) {
571 hw_atl_utils_mpi_read_mbox(self, &mbox);
572
573 transaction_id = mbox.transaction_id;
574
575 err = readx_poll_timeout_atomic(hw_atl_utils_get_mpi_mbox_tid,
576 self, mbox.transaction_id,
577 transaction_id !=
578 mbox.transaction_id,
579 1000U, 100000U);
580 if (err < 0)
581 goto err_exit;
582 }
583 /* On interface DEINIT we disable DW (raise bit)
584 * Otherwise enable DW (clear bit)
585 */
586 if (state == MPI_DEINIT || state == MPI_POWER)
587 val |= HW_ATL_MPI_DIRTY_WAKE_MSK;
588 else
589 val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK;
590
591 /* Set new state bits */
592 val = val & ~HW_ATL_MPI_STATE_MSK;
593 val |= state & HW_ATL_MPI_STATE_MSK;
594
595 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
596 err_exit:
597 return err;
598 }
599
hw_atl_utils_mpi_get_link_status(struct aq_hw_s * self)600 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
601 {
602 u32 cp0x036C = hw_atl_utils_mpi_get_state(self);
603 u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
604 struct aq_hw_link_status_s *link_status = &self->aq_link_status;
605
606 if (!link_speed_mask) {
607 link_status->mbps = 0U;
608 } else {
609 switch (link_speed_mask) {
610 case HAL_ATLANTIC_RATE_10G:
611 link_status->mbps = 10000U;
612 break;
613
614 case HAL_ATLANTIC_RATE_5G:
615 case HAL_ATLANTIC_RATE_5GSR:
616 link_status->mbps = 5000U;
617 break;
618
619 case HAL_ATLANTIC_RATE_2GS:
620 link_status->mbps = 2500U;
621 break;
622
623 case HAL_ATLANTIC_RATE_1G:
624 link_status->mbps = 1000U;
625 break;
626
627 case HAL_ATLANTIC_RATE_100M:
628 link_status->mbps = 100U;
629 break;
630
631 default:
632 return -EBUSY;
633 }
634 }
635
636 return 0;
637 }
638
hw_atl_utils_get_mac_permanent(struct aq_hw_s * self,u8 * mac)639 int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
640 u8 *mac)
641 {
642 int err = 0;
643 u32 h = 0U;
644 u32 l = 0U;
645 u32 mac_addr[2];
646
647 if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
648 unsigned int rnd = 0;
649 unsigned int ucp_0x370 = 0;
650
651 get_random_bytes(&rnd, sizeof(unsigned int));
652
653 ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
654 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
655 }
656
657 err = hw_atl_utils_fw_downld_dwords(self,
658 aq_hw_read_reg(self, 0x00000374U) +
659 (40U * 4U),
660 mac_addr,
661 ARRAY_SIZE(mac_addr));
662 if (err < 0) {
663 mac_addr[0] = 0U;
664 mac_addr[1] = 0U;
665 err = 0;
666 } else {
667 mac_addr[0] = __swab32(mac_addr[0]);
668 mac_addr[1] = __swab32(mac_addr[1]);
669 }
670
671 ether_addr_copy(mac, (u8 *)mac_addr);
672
673 if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
674 /* chip revision */
675 l = 0xE3000000U |
676 (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) |
677 (0x00 << 16);
678 h = 0x8001300EU;
679
680 mac[5] = (u8)(0xFFU & l);
681 l >>= 8;
682 mac[4] = (u8)(0xFFU & l);
683 l >>= 8;
684 mac[3] = (u8)(0xFFU & l);
685 l >>= 8;
686 mac[2] = (u8)(0xFFU & l);
687 mac[1] = (u8)(0xFFU & h);
688 h >>= 8;
689 mac[0] = (u8)(0xFFU & h);
690 }
691
692 return err;
693 }
694
hw_atl_utils_mbps_2_speed_index(unsigned int mbps)695 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
696 {
697 unsigned int ret = 0U;
698
699 switch (mbps) {
700 case 100U:
701 ret = 5U;
702 break;
703
704 case 1000U:
705 ret = 4U;
706 break;
707
708 case 2500U:
709 ret = 3U;
710 break;
711
712 case 5000U:
713 ret = 1U;
714 break;
715
716 case 10000U:
717 ret = 0U;
718 break;
719
720 default:
721 break;
722 }
723 return ret;
724 }
725
hw_atl_utils_hw_chip_features_init(struct aq_hw_s * self,u32 * p)726 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
727 {
728 u32 chip_features = 0U;
729 u32 val = hw_atl_reg_glb_mif_id_get(self);
730 u32 mif_rev = val & 0xFFU;
731
732 if ((0xFU & mif_rev) == 1U) {
733 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
734 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
735 HAL_ATLANTIC_UTILS_CHIP_MIPS;
736 } else if ((0xFU & mif_rev) == 2U) {
737 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
738 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
739 HAL_ATLANTIC_UTILS_CHIP_MIPS |
740 HAL_ATLANTIC_UTILS_CHIP_TPO2 |
741 HAL_ATLANTIC_UTILS_CHIP_RPF2;
742 } else if ((0xFU & mif_rev) == 0xAU) {
743 chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 |
744 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
745 HAL_ATLANTIC_UTILS_CHIP_MIPS |
746 HAL_ATLANTIC_UTILS_CHIP_TPO2 |
747 HAL_ATLANTIC_UTILS_CHIP_RPF2;
748 }
749
750 *p = chip_features;
751 }
752
hw_atl_fw1x_deinit(struct aq_hw_s * self)753 static int hw_atl_fw1x_deinit(struct aq_hw_s *self)
754 {
755 hw_atl_utils_mpi_set_speed(self, 0);
756 hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
757 return 0;
758 }
759
hw_atl_utils_update_stats(struct aq_hw_s * self)760 int hw_atl_utils_update_stats(struct aq_hw_s *self)
761 {
762 struct hw_atl_utils_mbox mbox;
763 struct aq_stats_s *cs = &self->curr_stats;
764
765 hw_atl_utils_mpi_read_stats(self, &mbox);
766
767 #define AQ_SDELTA(_N_) (self->curr_stats._N_ += \
768 mbox.stats._N_ - self->last_stats._N_)
769
770 if (self->aq_link_status.mbps) {
771 AQ_SDELTA(uprc);
772 AQ_SDELTA(mprc);
773 AQ_SDELTA(bprc);
774 AQ_SDELTA(erpt);
775
776 AQ_SDELTA(uptc);
777 AQ_SDELTA(mptc);
778 AQ_SDELTA(bptc);
779 AQ_SDELTA(erpr);
780
781 AQ_SDELTA(ubrc);
782 AQ_SDELTA(ubtc);
783 AQ_SDELTA(mbrc);
784 AQ_SDELTA(mbtc);
785 AQ_SDELTA(bbrc);
786 AQ_SDELTA(bbtc);
787 AQ_SDELTA(dpc);
788 }
789 #undef AQ_SDELTA
790
791 cs->dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counter_get(self);
792 cs->dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counter_get(self);
793 cs->dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counter_get(self);
794 cs->dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counter_get(self);
795
796 memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
797
798 return 0;
799 }
800
hw_atl_utils_get_hw_stats(struct aq_hw_s * self)801 struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self)
802 {
803 return &self->curr_stats;
804 }
805
806 static const u32 hw_atl_utils_hw_mac_regs[] = {
807 0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
808 0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
809 0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
810 0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
811 0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
812 0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
813 0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
814 0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
815 0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
816 0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
817 0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
818 0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
819 0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
820 0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
821 0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
822 0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
823 0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
824 0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
825 0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
826 0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
827 0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
828 0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
829 };
830
hw_atl_utils_hw_get_regs(struct aq_hw_s * self,const struct aq_hw_caps_s * aq_hw_caps,u32 * regs_buff)831 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
832 const struct aq_hw_caps_s *aq_hw_caps,
833 u32 *regs_buff)
834 {
835 unsigned int i = 0U;
836
837 for (i = 0; i < aq_hw_caps->mac_regs_count; i++)
838 regs_buff[i] = aq_hw_read_reg(self,
839 hw_atl_utils_hw_mac_regs[i]);
840 return 0;
841 }
842
hw_atl_utils_get_fw_version(struct aq_hw_s * self,u32 * fw_version)843 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
844 {
845 *fw_version = aq_hw_read_reg(self, 0x18U);
846 return 0;
847 }
848
aq_fw1x_set_wol(struct aq_hw_s * self,bool wol_enabled,u8 * mac)849 static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac)
850 {
851 struct hw_atl_utils_fw_rpc *prpc = NULL;
852 unsigned int rpc_size = 0U;
853 int err = 0;
854
855 err = hw_atl_utils_fw_rpc_wait(self, &prpc);
856 if (err < 0)
857 goto err_exit;
858
859 memset(prpc, 0, sizeof(*prpc));
860
861 if (wol_enabled) {
862 rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_wol);
863
864 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD;
865 prpc->msg_wol.priority =
866 HAL_ATLANTIC_UTILS_FW_MSG_WOL_PRIOR;
867 prpc->msg_wol.pattern_id =
868 HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN;
869 prpc->msg_wol.wol_packet_type =
870 HAL_ATLANTIC_UTILS_FW_MSG_WOL_MAG_PKT;
871
872 ether_addr_copy((u8 *)&prpc->msg_wol.wol_pattern, mac);
873 } else {
874 rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_del_id);
875
876 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL;
877 prpc->msg_wol.pattern_id =
878 HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN;
879 }
880
881 err = hw_atl_utils_fw_rpc_call(self, rpc_size);
882
883 err_exit:
884 return err;
885 }
886
aq_fw1x_set_power(struct aq_hw_s * self,unsigned int power_state,u8 * mac)887 static int aq_fw1x_set_power(struct aq_hw_s *self, unsigned int power_state,
888 u8 *mac)
889 {
890 struct hw_atl_utils_fw_rpc *prpc = NULL;
891 unsigned int rpc_size = 0U;
892 int err = 0;
893
894 if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) {
895 err = aq_fw1x_set_wol(self, 1, mac);
896
897 if (err < 0)
898 goto err_exit;
899
900 rpc_size = sizeof(prpc->msg_id) +
901 sizeof(prpc->msg_enable_wakeup);
902
903 err = hw_atl_utils_fw_rpc_wait(self, &prpc);
904
905 if (err < 0)
906 goto err_exit;
907
908 memset(prpc, 0, rpc_size);
909
910 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_ENABLE_WAKEUP;
911 prpc->msg_enable_wakeup.pattern_mask = 0x00000002;
912
913 err = hw_atl_utils_fw_rpc_call(self, rpc_size);
914 if (err < 0)
915 goto err_exit;
916 }
917 hw_atl_utils_mpi_set_speed(self, 0);
918 hw_atl_utils_mpi_set_state(self, MPI_POWER);
919
920 err_exit:
921 return err;
922 }
923
hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s * self)924 static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self)
925 {
926 struct hw_atl_utils_mbox_header mbox;
927
928 hw_atl_utils_mpi_read_mbox(self, &mbox);
929
930 return mbox.transaction_id;
931 }
932
hw_atl_utils_mpi_get_state(struct aq_hw_s * self)933 static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self)
934 {
935 return aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
936 }
937
hw_atl_utils_mif_cmd_get(struct aq_hw_s * self)938 static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self)
939 {
940 return aq_hw_read_reg(self, HW_ATL_MIF_CMD);
941 }
942
hw_atl_utils_mif_addr_get(struct aq_hw_s * self)943 static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self)
944 {
945 return aq_hw_read_reg(self, HW_ATL_MIF_ADDR);
946 }
947
hw_atl_utils_rpc_state_get(struct aq_hw_s * self)948 static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self)
949 {
950 return aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR);
951 }
952
953 const struct aq_fw_ops aq_fw_1x_ops = {
954 .init = hw_atl_utils_mpi_create,
955 .deinit = hw_atl_fw1x_deinit,
956 .reset = NULL,
957 .get_mac_permanent = hw_atl_utils_get_mac_permanent,
958 .set_link_speed = hw_atl_utils_mpi_set_speed,
959 .set_state = hw_atl_utils_mpi_set_state,
960 .update_link_status = hw_atl_utils_mpi_get_link_status,
961 .update_stats = hw_atl_utils_update_stats,
962 .get_phy_temp = NULL,
963 .set_power = aq_fw1x_set_power,
964 .set_eee_rate = NULL,
965 .get_eee_rate = NULL,
966 .set_flow_control = NULL,
967 };
968