2 * aQuantia Corporation Network Driver
3 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
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.
10 /* File hw_atl_utils.c: Definition of common functions for Atlantic hardware
15 #include "../aq_hw_utils.h"
16 #include "../aq_pci_func.h"
17 #include "../aq_ring.h"
18 #include "../aq_vec.h"
19 #include "hw_atl_utils.h"
20 #include "hw_atl_llh.h"
22 #include <linux/random.h>
24 #define HW_ATL_UCP_0X370_REG 0x0370U
26 #define HW_ATL_FW_SM_RAM 0x2U
27 #define HW_ATL_MPI_CONTROL_ADR 0x0368U
28 #define HW_ATL_MPI_STATE_ADR 0x036CU
30 #define HW_ATL_MPI_STATE_MSK 0x00FFU
31 #define HW_ATL_MPI_STATE_SHIFT 0U
32 #define HW_ATL_MPI_SPEED_MSK 0xFFFFU
33 #define HW_ATL_MPI_SPEED_SHIFT 16U
35 static int hw_atl_utils_fw_downld_dwords(struct aq_hw_s
*self
, u32 a
,
40 AQ_HW_WAIT_FOR(reg_glb_cpu_sem_get(self
,
41 HW_ATL_FW_SM_RAM
) == 1U,
47 reg_glb_cpu_sem_set(self
, 1U, HW_ATL_FW_SM_RAM
);
48 is_locked
= reg_glb_cpu_sem_get(self
, HW_ATL_FW_SM_RAM
);
55 aq_hw_write_reg(self
, 0x00000208U
, a
);
60 aq_hw_write_reg(self
, 0x00000200U
, 0x00008000U
);
63 (0x100U
& aq_hw_read_reg(self
, 0x00000200U
)) && --i
;) {
66 *(p
++) = aq_hw_read_reg(self
, 0x0000020CU
);
69 reg_glb_cpu_sem_set(self
, 1U, HW_ATL_FW_SM_RAM
);
75 static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s
*self
, u32 a
, u32
*p
,
81 is_locked
= reg_glb_cpu_sem_get(self
, HW_ATL_FW_SM_RAM
);
87 aq_hw_write_reg(self
, 0x00000208U
, a
);
92 aq_hw_write_reg(self
, 0x0000020CU
, *(p
++));
93 aq_hw_write_reg(self
, 0x00000200U
, 0xC000U
);
96 (0x100U
& aq_hw_read_reg(self
, 0x00000200U
)) && --i
;) {
100 reg_glb_cpu_sem_set(self
, 1U, HW_ATL_FW_SM_RAM
);
106 static int hw_atl_utils_ver_match(u32 ver_expected
, u32 ver_actual
)
109 const u32 dw_major_mask
= 0xff000000U
;
110 const u32 dw_minor_mask
= 0x00ffffffU
;
112 err
= (dw_major_mask
& (ver_expected
^ ver_actual
)) ? -EOPNOTSUPP
: 0;
115 err
= ((dw_minor_mask
& ver_expected
) > (dw_minor_mask
& ver_actual
)) ?
121 static int hw_atl_utils_init_ucp(struct aq_hw_s
*self
,
122 struct aq_hw_caps_s
*aq_hw_caps
)
126 if (!aq_hw_read_reg(self
, 0x370U
)) {
127 unsigned int rnd
= 0U;
128 unsigned int ucp_0x370
= 0U;
130 get_random_bytes(&rnd
, sizeof(unsigned int));
132 ucp_0x370
= 0x02020202U
| (0xFEFEFEFEU
& rnd
);
133 aq_hw_write_reg(self
, HW_ATL_UCP_0X370_REG
, ucp_0x370
);
136 reg_glb_cpu_scratch_scp_set(self
, 0x00000000U
, 25U);
138 /* check 10 times by 1ms */
139 AQ_HW_WAIT_FOR(0U != (PHAL_ATLANTIC_A0
->mbox_addr
=
140 aq_hw_read_reg(self
, 0x360U
)), 1000U, 10U);
142 err
= hw_atl_utils_ver_match(aq_hw_caps
->fw_ver_expected
,
143 aq_hw_read_reg(self
, 0x18U
));
146 pr_err("%s: Bad FW version detected: expected=%x, actual=%x\n",
148 aq_hw_caps
->fw_ver_expected
,
149 aq_hw_read_reg(self
, 0x18U
));
153 #define HW_ATL_RPC_CONTROL_ADR 0x0338U
154 #define HW_ATL_RPC_STATE_ADR 0x033CU
156 struct aq_hw_atl_utils_fw_rpc_tid_s
{
166 #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
168 static int hw_atl_utils_fw_rpc_call(struct aq_hw_s
*self
, unsigned int rpc_size
)
171 struct aq_hw_atl_utils_fw_rpc_tid_s sw
;
173 if (!IS_CHIP_FEATURE(MIPS
)) {
177 err
= hw_atl_utils_fw_upload_dwords(self
, PHAL_ATLANTIC
->rpc_addr
,
178 (u32
*)(void *)&PHAL_ATLANTIC
->rpc
,
179 (rpc_size
+ sizeof(u32
) -
180 sizeof(u8
)) / sizeof(u32
));
184 sw
.tid
= 0xFFFFU
& (++PHAL_ATLANTIC
->rpc_tid
);
185 sw
.len
= (u16
)rpc_size
;
186 aq_hw_write_reg(self
, HW_ATL_RPC_CONTROL_ADR
, sw
.val
);
192 static int hw_atl_utils_fw_rpc_wait(struct aq_hw_s
*self
,
193 struct hw_aq_atl_utils_fw_rpc
**rpc
)
196 struct aq_hw_atl_utils_fw_rpc_tid_s sw
;
197 struct aq_hw_atl_utils_fw_rpc_tid_s fw
;
200 sw
.val
= aq_hw_read_reg(self
, HW_ATL_RPC_CONTROL_ADR
);
202 PHAL_ATLANTIC
->rpc_tid
= sw
.tid
;
204 AQ_HW_WAIT_FOR(sw
.tid
==
206 aq_hw_read_reg(self
, HW_ATL_RPC_STATE_ADR
),
207 fw
.tid
), 1000U, 100U);
211 if (fw
.len
== 0xFFFFU
) {
212 err
= hw_atl_utils_fw_rpc_call(self
, sw
.len
);
216 } while (sw
.tid
!= fw
.tid
|| 0xFFFFU
== fw
.len
);
223 hw_atl_utils_fw_downld_dwords(self
,
224 PHAL_ATLANTIC
->rpc_addr
,
227 (fw
.len
+ sizeof(u32
) -
234 *rpc
= &PHAL_ATLANTIC
->rpc
;
241 static int hw_atl_utils_mpi_create(struct aq_hw_s
*self
,
242 struct aq_hw_caps_s
*aq_hw_caps
)
246 err
= hw_atl_utils_init_ucp(self
, aq_hw_caps
);
250 err
= hw_atl_utils_fw_rpc_init(self
);
258 int hw_atl_utils_mpi_read_mbox(struct aq_hw_s
*self
,
259 struct hw_aq_atl_utils_mbox_header
*pmbox
)
261 return hw_atl_utils_fw_downld_dwords(self
,
262 PHAL_ATLANTIC
->mbox_addr
,
263 (u32
*)(void *)pmbox
,
264 sizeof(*pmbox
) / sizeof(u32
));
267 void hw_atl_utils_mpi_read_stats(struct aq_hw_s
*self
,
268 struct hw_aq_atl_utils_mbox
*pmbox
)
272 err
= hw_atl_utils_fw_downld_dwords(self
,
273 PHAL_ATLANTIC
->mbox_addr
,
274 (u32
*)(void *)pmbox
,
275 sizeof(*pmbox
) / sizeof(u32
));
279 if (IS_CHIP_FEATURE(REVISION_A0
)) {
280 unsigned int mtu
= self
->aq_nic_cfg
?
281 self
->aq_nic_cfg
->mtu
: 1514U;
282 pmbox
->stats
.ubrc
= pmbox
->stats
.uprc
* mtu
;
283 pmbox
->stats
.ubtc
= pmbox
->stats
.uptc
* mtu
;
284 pmbox
->stats
.dpc
= atomic_read(&PHAL_ATLANTIC_A0
->dpc
);
286 pmbox
->stats
.dpc
= reg_rx_dma_stat_counter7get(self
);
292 int hw_atl_utils_mpi_set_speed(struct aq_hw_s
*self
, u32 speed
,
293 enum hal_atl_utils_fw_state_e state
)
297 ucp_0x368
= (speed
<< HW_ATL_MPI_SPEED_SHIFT
) | state
;
298 aq_hw_write_reg(self
, HW_ATL_MPI_CONTROL_ADR
, ucp_0x368
);
303 void hw_atl_utils_mpi_set(struct aq_hw_s
*self
,
304 enum hal_atl_utils_fw_state_e state
, u32 speed
)
307 u32 transaction_id
= 0;
308 struct hw_aq_atl_utils_mbox_header mbox
;
310 if (state
== MPI_RESET
) {
311 hw_atl_utils_mpi_read_mbox(self
, &mbox
);
313 transaction_id
= mbox
.transaction_id
;
315 AQ_HW_WAIT_FOR(transaction_id
!=
316 (hw_atl_utils_mpi_read_mbox(self
, &mbox
),
317 mbox
.transaction_id
),
323 err
= hw_atl_utils_mpi_set_speed(self
, speed
, state
);
328 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s
*self
)
330 u32 cp0x036C
= aq_hw_read_reg(self
, HW_ATL_MPI_STATE_ADR
);
331 u32 link_speed_mask
= cp0x036C
>> HW_ATL_MPI_SPEED_SHIFT
;
332 struct aq_hw_link_status_s
*link_status
= &self
->aq_link_status
;
334 if (!link_speed_mask
) {
335 link_status
->mbps
= 0U;
337 switch (link_speed_mask
) {
338 case HAL_ATLANTIC_RATE_10G
:
339 link_status
->mbps
= 10000U;
342 case HAL_ATLANTIC_RATE_5G
:
343 case HAL_ATLANTIC_RATE_5GSR
:
344 link_status
->mbps
= 5000U;
347 case HAL_ATLANTIC_RATE_2GS
:
348 link_status
->mbps
= 2500U;
351 case HAL_ATLANTIC_RATE_1G
:
352 link_status
->mbps
= 1000U;
355 case HAL_ATLANTIC_RATE_100M
:
356 link_status
->mbps
= 100U;
367 int hw_atl_utils_get_mac_permanent(struct aq_hw_s
*self
,
368 struct aq_hw_caps_s
*aq_hw_caps
,
376 self
->mmio
= aq_pci_func_get_mmio(self
->aq_pci_func
);
378 hw_atl_utils_hw_chip_features_init(self
,
379 &PHAL_ATLANTIC_A0
->chip_features
);
381 err
= hw_atl_utils_mpi_create(self
, aq_hw_caps
);
385 if (!aq_hw_read_reg(self
, HW_ATL_UCP_0X370_REG
)) {
386 unsigned int rnd
= 0;
387 unsigned int ucp_0x370
= 0;
389 get_random_bytes(&rnd
, sizeof(unsigned int));
391 ucp_0x370
= 0x02020202 | (0xFEFEFEFE & rnd
);
392 aq_hw_write_reg(self
, HW_ATL_UCP_0X370_REG
, ucp_0x370
);
395 err
= hw_atl_utils_fw_downld_dwords(self
,
396 aq_hw_read_reg(self
, 0x00000374U
) +
405 mac_addr
[0] = __swab32(mac_addr
[0]);
406 mac_addr
[1] = __swab32(mac_addr
[1]);
409 ether_addr_copy(mac
, (u8
*)mac_addr
);
411 if ((mac
[0] & 0x01U
) || ((mac
[0] | mac
[1] | mac
[2]) == 0x00U
)) {
414 | (0xFFFFU
& aq_hw_read_reg(self
, HW_ATL_UCP_0X370_REG
))
418 mac
[5] = (u8
)(0xFFU
& l
);
420 mac
[4] = (u8
)(0xFFU
& l
);
422 mac
[3] = (u8
)(0xFFU
& l
);
424 mac
[2] = (u8
)(0xFFU
& l
);
425 mac
[1] = (u8
)(0xFFU
& h
);
427 mac
[0] = (u8
)(0xFFU
& h
);
434 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps
)
436 unsigned int ret
= 0U;
465 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s
*self
, u32
*p
)
467 u32 chip_features
= 0U;
468 u32 val
= reg_glb_mif_id_get(self
);
469 u32 mif_rev
= val
& 0xFFU
;
471 if ((3U & mif_rev
) == 1U) {
473 HAL_ATLANTIC_UTILS_CHIP_REVISION_A0
|
474 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ
|
475 HAL_ATLANTIC_UTILS_CHIP_MIPS
;
476 } else if ((3U & mif_rev
) == 2U) {
478 HAL_ATLANTIC_UTILS_CHIP_REVISION_B0
|
479 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ
|
480 HAL_ATLANTIC_UTILS_CHIP_MIPS
|
481 HAL_ATLANTIC_UTILS_CHIP_TPO2
|
482 HAL_ATLANTIC_UTILS_CHIP_RPF2
;
488 int hw_atl_utils_hw_deinit(struct aq_hw_s
*self
)
490 hw_atl_utils_mpi_set(self
, MPI_DEINIT
, 0x0U
);
494 int hw_atl_utils_hw_set_power(struct aq_hw_s
*self
,
495 unsigned int power_state
)
497 hw_atl_utils_mpi_set(self
, MPI_POWER
, 0x0U
);
501 int hw_atl_utils_update_stats(struct aq_hw_s
*self
)
503 struct hw_atl_s
*hw_self
= PHAL_ATLANTIC
;
504 struct hw_aq_atl_utils_mbox mbox
;
506 if (!self
->aq_link_status
.mbps
)
509 hw_atl_utils_mpi_read_stats(self
, &mbox
);
511 #define AQ_SDELTA(_N_) (hw_self->curr_stats._N_ += \
512 mbox.stats._N_ - hw_self->last_stats._N_)
534 memcpy(&hw_self
->last_stats
, &mbox
.stats
, sizeof(mbox
.stats
));
539 int hw_atl_utils_get_hw_stats(struct aq_hw_s
*self
,
540 u64
*data
, unsigned int *p_count
)
542 struct hw_atl_s
*hw_self
= PHAL_ATLANTIC
;
543 struct hw_atl_stats_s
*stats
= &hw_self
->curr_stats
;
546 data
[i
] = stats
->uprc
+ stats
->mprc
+ stats
->bprc
;
547 data
[++i
] = stats
->uprc
;
548 data
[++i
] = stats
->mprc
;
549 data
[++i
] = stats
->bprc
;
550 data
[++i
] = stats
->erpt
;
551 data
[++i
] = stats
->uptc
+ stats
->mptc
+ stats
->bptc
;
552 data
[++i
] = stats
->uptc
;
553 data
[++i
] = stats
->mptc
;
554 data
[++i
] = stats
->bptc
;
555 data
[++i
] = stats
->ubrc
;
556 data
[++i
] = stats
->ubtc
;
557 data
[++i
] = stats
->mbrc
;
558 data
[++i
] = stats
->mbtc
;
559 data
[++i
] = stats
->bbrc
;
560 data
[++i
] = stats
->bbtc
;
561 data
[++i
] = stats
->ubrc
+ stats
->mbrc
+ stats
->bbrc
;
562 data
[++i
] = stats
->ubtc
+ stats
->mbtc
+ stats
->bbtc
;
563 data
[++i
] = stats_rx_dma_good_pkt_counterlsw_get(self
);
564 data
[++i
] = stats_tx_dma_good_pkt_counterlsw_get(self
);
565 data
[++i
] = stats_rx_dma_good_octet_counterlsw_get(self
);
566 data
[++i
] = stats_tx_dma_good_octet_counterlsw_get(self
);
567 data
[++i
] = stats
->dpc
;
575 static const u32 hw_atl_utils_hw_mac_regs
[] = {
576 0x00005580U
, 0x00005590U
, 0x000055B0U
, 0x000055B4U
,
577 0x000055C0U
, 0x00005B00U
, 0x00005B04U
, 0x00005B08U
,
578 0x00005B0CU
, 0x00005B10U
, 0x00005B14U
, 0x00005B18U
,
579 0x00005B1CU
, 0x00005B20U
, 0x00005B24U
, 0x00005B28U
,
580 0x00005B2CU
, 0x00005B30U
, 0x00005B34U
, 0x00005B38U
,
581 0x00005B3CU
, 0x00005B40U
, 0x00005B44U
, 0x00005B48U
,
582 0x00005B4CU
, 0x00005B50U
, 0x00005B54U
, 0x00005B58U
,
583 0x00005B5CU
, 0x00005B60U
, 0x00005B64U
, 0x00005B68U
,
584 0x00005B6CU
, 0x00005B70U
, 0x00005B74U
, 0x00005B78U
,
585 0x00005B7CU
, 0x00007C00U
, 0x00007C04U
, 0x00007C08U
,
586 0x00007C0CU
, 0x00007C10U
, 0x00007C14U
, 0x00007C18U
,
587 0x00007C1CU
, 0x00007C20U
, 0x00007C40U
, 0x00007C44U
,
588 0x00007C48U
, 0x00007C4CU
, 0x00007C50U
, 0x00007C54U
,
589 0x00007C58U
, 0x00007C5CU
, 0x00007C60U
, 0x00007C80U
,
590 0x00007C84U
, 0x00007C88U
, 0x00007C8CU
, 0x00007C90U
,
591 0x00007C94U
, 0x00007C98U
, 0x00007C9CU
, 0x00007CA0U
,
592 0x00007CC0U
, 0x00007CC4U
, 0x00007CC8U
, 0x00007CCCU
,
593 0x00007CD0U
, 0x00007CD4U
, 0x00007CD8U
, 0x00007CDCU
,
594 0x00007CE0U
, 0x00000300U
, 0x00000304U
, 0x00000308U
,
595 0x0000030cU
, 0x00000310U
, 0x00000314U
, 0x00000318U
,
596 0x0000031cU
, 0x00000360U
, 0x00000364U
, 0x00000368U
,
597 0x0000036cU
, 0x00000370U
, 0x00000374U
, 0x00006900U
,
600 int hw_atl_utils_hw_get_regs(struct aq_hw_s
*self
,
601 struct aq_hw_caps_s
*aq_hw_caps
,
606 for (i
= 0; i
< aq_hw_caps
->mac_regs_count
; i
++)
607 regs_buff
[i
] = aq_hw_read_reg(self
,
608 hw_atl_utils_hw_mac_regs
[i
]);
612 int hw_atl_utils_get_fw_version(struct aq_hw_s
*self
, u32
*fw_version
)
614 *fw_version
= aq_hw_read_reg(self
, 0x18U
);