1 // SPDX-License-Identifier: GPL-2.0-only
3 * aQuantia Corporation Network Driver
4 * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
7 /* File hw_atl_utils.c: Definition of common functions for Atlantic hardware
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"
17 #include <linux/random.h>
19 #define HW_ATL_UCP_0X370_REG 0x0370U
21 #define HW_ATL_MIF_CMD 0x0200U
22 #define HW_ATL_MIF_ADDR 0x0208U
23 #define HW_ATL_MIF_VAL 0x020CU
25 #define HW_ATL_MPI_RPC_ADDR 0x0334U
26 #define HW_ATL_RPC_CONTROL_ADR 0x0338U
27 #define HW_ATL_RPC_STATE_ADR 0x033CU
29 #define HW_ATL_MPI_FW_VERSION 0x18
30 #define HW_ATL_MPI_CONTROL_ADR 0x0368U
31 #define HW_ATL_MPI_STATE_ADR 0x036CU
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
39 #define HW_ATL_MPI_DAISY_CHAIN_STATUS 0x704
40 #define HW_ATL_MPI_BOOT_EXIT_CODE 0x388
42 #define HW_ATL_MAC_PHY_CONTROL 0x4000
43 #define HW_ATL_MAC_PHY_MPI_RESET_BIT 0x1D
45 #define HW_ATL_FW_VER_1X 0x01050006U
46 #define HW_ATL_FW_VER_2X 0x02000000U
47 #define HW_ATL_FW_VER_3X 0x03000000U
49 #define FORCE_FLASHLESS 0
52 MCP_AREA_CONFIG
= 0x80000000,
53 MCP_AREA_SETTINGS
= 0x20000000,
56 static int hw_atl_utils_ver_match(u32 ver_expected
, u32 ver_actual
);
57 static int hw_atl_utils_mpi_set_state(struct aq_hw_s
*self
,
58 enum hal_atl_utils_fw_state_e state
);
59 static u32
hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s
*self
);
60 static u32
hw_atl_utils_mpi_get_state(struct aq_hw_s
*self
);
61 static u32
hw_atl_utils_mif_cmd_get(struct aq_hw_s
*self
);
62 static u32
hw_atl_utils_mif_addr_get(struct aq_hw_s
*self
);
63 static u32
hw_atl_utils_rpc_state_get(struct aq_hw_s
*self
);
64 static u32
aq_fw1x_rpc_get(struct aq_hw_s
*self
);
66 int hw_atl_utils_initfw(struct aq_hw_s
*self
, const struct aq_fw_ops
**fw_ops
)
70 err
= hw_atl_utils_soft_reset(self
);
74 hw_atl_utils_hw_chip_features_init(self
,
75 &self
->chip_features
);
77 hw_atl_utils_get_fw_version(self
, &self
->fw_ver_actual
);
79 if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X
,
80 self
->fw_ver_actual
) == 0) {
81 *fw_ops
= &aq_fw_1x_ops
;
82 } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X
,
83 self
->fw_ver_actual
) == 0) {
84 *fw_ops
= &aq_fw_2x_ops
;
85 } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X
,
86 self
->fw_ver_actual
) == 0) {
87 *fw_ops
= &aq_fw_2x_ops
;
89 aq_pr_err("Bad FW version detected: %x\n",
93 self
->aq_fw_ops
= *fw_ops
;
94 err
= self
->aq_fw_ops
->init(self
);
99 static int hw_atl_utils_soft_reset_flb(struct aq_hw_s
*self
)
104 aq_hw_write_reg(self
, 0x404, 0x40e1);
108 val
= aq_hw_read_reg(self
, 0x53C);
109 aq_hw_write_reg(self
, 0x53C, val
| 0x10);
111 gsr
= aq_hw_read_reg(self
, HW_ATL_GLB_SOFT_RES_ADR
);
112 aq_hw_write_reg(self
, HW_ATL_GLB_SOFT_RES_ADR
, (gsr
& 0xBFFF) | 0x8000);
115 aq_hw_write_reg(self
, 0x404, 0x80e0);
116 aq_hw_write_reg(self
, 0x32a8, 0x0);
117 aq_hw_write_reg(self
, 0x520, 0x1);
119 /* Reset SPI again because of possible interrupted SPI burst */
120 val
= aq_hw_read_reg(self
, 0x53C);
121 aq_hw_write_reg(self
, 0x53C, val
| 0x10);
123 /* Clear SPI reset state */
124 aq_hw_write_reg(self
, 0x53C, val
& ~0x10);
126 aq_hw_write_reg(self
, 0x404, 0x180e0);
128 for (k
= 0; k
< 1000; k
++) {
129 u32 flb_status
= aq_hw_read_reg(self
,
130 HW_ATL_MPI_DAISY_CHAIN_STATUS
);
132 flb_status
= flb_status
& 0x10;
138 aq_pr_err("MAC kickstart failed\n");
143 aq_hw_write_reg(self
, 0x404, 0x80e0);
145 aq_hw_write_reg(self
, 0x3a0, 0x1);
147 /* Kickstart PHY - skipped */
149 /* Global software reset*/
150 hw_atl_rx_rx_reg_res_dis_set(self
, 0U);
151 hw_atl_tx_tx_reg_res_dis_set(self
, 0U);
152 aq_hw_write_reg_bit(self
, HW_ATL_MAC_PHY_CONTROL
,
153 BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT
),
154 HW_ATL_MAC_PHY_MPI_RESET_BIT
, 0x0);
155 gsr
= aq_hw_read_reg(self
, HW_ATL_GLB_SOFT_RES_ADR
);
156 aq_hw_write_reg(self
, HW_ATL_GLB_SOFT_RES_ADR
, (gsr
& 0xBFFF) | 0x8000);
158 for (k
= 0; k
< 1000; k
++) {
159 u32 fw_state
= aq_hw_read_reg(self
, HW_ATL_MPI_FW_VERSION
);
166 aq_pr_err("FW kickstart failed\n");
169 /* Old FW requires fixed delay after init */
175 static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s
*self
)
177 u32 gsr
, val
, rbl_status
;
180 aq_hw_write_reg(self
, 0x404, 0x40e1);
181 aq_hw_write_reg(self
, 0x3a0, 0x1);
182 aq_hw_write_reg(self
, 0x32a8, 0x0);
184 /* Alter RBL status */
185 aq_hw_write_reg(self
, 0x388, 0xDEAD);
188 val
= aq_hw_read_reg(self
, 0x53C);
189 aq_hw_write_reg(self
, 0x53C, val
| 0x10);
191 /* Global software reset*/
192 hw_atl_rx_rx_reg_res_dis_set(self
, 0U);
193 hw_atl_tx_tx_reg_res_dis_set(self
, 0U);
194 aq_hw_write_reg_bit(self
, HW_ATL_MAC_PHY_CONTROL
,
195 BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT
),
196 HW_ATL_MAC_PHY_MPI_RESET_BIT
, 0x0);
197 gsr
= aq_hw_read_reg(self
, HW_ATL_GLB_SOFT_RES_ADR
);
198 aq_hw_write_reg(self
, HW_ATL_GLB_SOFT_RES_ADR
,
199 (gsr
& 0xFFFFBFFF) | 0x8000);
202 aq_hw_write_reg(self
, 0x534, 0x0);
204 aq_hw_write_reg(self
, 0x404, 0x40e0);
206 /* Wait for RBL boot */
207 for (k
= 0; k
< 1000; k
++) {
208 rbl_status
= aq_hw_read_reg(self
, 0x388) & 0xFFFF;
209 if (rbl_status
&& rbl_status
!= 0xDEAD)
213 if (!rbl_status
|| rbl_status
== 0xDEAD) {
214 aq_pr_err("RBL Restart failed");
220 aq_hw_write_reg(self
, 0x534, 0xA0);
222 if (rbl_status
== 0xF1A7) {
223 aq_pr_err("No FW detected. Dynamic FW load not implemented\n");
227 for (k
= 0; k
< 1000; k
++) {
228 u32 fw_state
= aq_hw_read_reg(self
, HW_ATL_MPI_FW_VERSION
);
235 aq_pr_err("FW kickstart failed\n");
238 /* Old FW requires fixed delay after init */
244 int hw_atl_utils_soft_reset(struct aq_hw_s
*self
)
246 u32 boot_exit_code
= 0;
250 for (k
= 0; k
< 1000; ++k
) {
251 u32 flb_status
= aq_hw_read_reg(self
,
252 HW_ATL_MPI_DAISY_CHAIN_STATUS
);
253 boot_exit_code
= aq_hw_read_reg(self
,
254 HW_ATL_MPI_BOOT_EXIT_CODE
);
255 if (flb_status
!= 0x06000000 || boot_exit_code
!= 0)
260 aq_pr_err("Neither RBL nor FLB firmware started\n");
264 self
->rbl_enabled
= (boot_exit_code
!= 0);
266 /* FW 1.x may bootup in an invalid POWER state (WOL feature).
267 * We should work around this by forcing its state back to DEINIT
269 if (!hw_atl_utils_ver_match(HW_ATL_FW_VER_1X
,
271 HW_ATL_MPI_FW_VERSION
))) {
274 hw_atl_utils_mpi_set_state(self
, MPI_DEINIT
);
275 err
= readx_poll_timeout_atomic(hw_atl_utils_mpi_get_state
,
277 (val
& HW_ATL_MPI_STATE_MSK
) ==
284 if (self
->rbl_enabled
)
285 return hw_atl_utils_soft_reset_rbl(self
);
287 return hw_atl_utils_soft_reset_flb(self
);
290 int hw_atl_utils_fw_downld_dwords(struct aq_hw_s
*self
, u32 a
,
296 err
= readx_poll_timeout_atomic(hw_atl_sem_ram_get
,
297 self
, val
, val
== 1U,
303 hw_atl_reg_glb_cpu_sem_set(self
, 1U, HW_ATL_FW_SM_RAM
);
304 is_locked
= hw_atl_sem_ram_get(self
);
311 aq_hw_write_reg(self
, HW_ATL_MIF_ADDR
, a
);
313 for (++cnt
; --cnt
&& !err
;) {
314 aq_hw_write_reg(self
, HW_ATL_MIF_CMD
, 0x00008000U
);
316 if (IS_CHIP_FEATURE(REVISION_B1
))
317 err
= readx_poll_timeout_atomic(hw_atl_utils_mif_addr_get
,
321 err
= readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get
,
326 *(p
++) = aq_hw_read_reg(self
, HW_ATL_MIF_VAL
);
330 hw_atl_reg_glb_cpu_sem_set(self
, 1U, HW_ATL_FW_SM_RAM
);
336 static int hw_atl_utils_write_b1_mbox(struct aq_hw_s
*self
, u32 addr
,
337 u32
*p
, u32 cnt
, enum mcp_area area
)
345 case MCP_AREA_CONFIG
:
346 offset
-= self
->rpc_addr
;
349 case MCP_AREA_SETTINGS
:
350 offset
-= self
->settings_addr
;
354 offset
= offset
/ sizeof(u32
);
356 for (; data_offset
< cnt
; ++data_offset
, ++offset
) {
357 aq_hw_write_reg(self
, 0x328, p
[data_offset
]);
358 aq_hw_write_reg(self
, 0x32C,
359 (area
| (0xFFFF & (offset
* 4))));
360 hw_atl_mcp_up_force_intr_set(self
, 1);
361 /* 1000 times by 10us = 10ms */
362 err
= readx_poll_timeout_atomic(hw_atl_scrpad12_get
,
364 (val
& 0xF0000000) !=
375 static int hw_atl_utils_write_b0_mbox(struct aq_hw_s
*self
, u32 addr
,
382 aq_hw_write_reg(self
, 0x208, addr
);
384 for (; offset
< cnt
; ++offset
) {
385 aq_hw_write_reg(self
, 0x20C, p
[offset
]);
386 aq_hw_write_reg(self
, 0x200, 0xC000);
388 err
= readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get
,
400 static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s
*self
, u32 addr
, u32
*p
,
401 u32 cnt
, enum mcp_area area
)
406 err
= readx_poll_timeout_atomic(hw_atl_sem_ram_get
, self
,
412 if (IS_CHIP_FEATURE(REVISION_B1
))
413 err
= hw_atl_utils_write_b1_mbox(self
, addr
, p
, cnt
, area
);
415 err
= hw_atl_utils_write_b0_mbox(self
, addr
, p
, cnt
);
417 hw_atl_reg_glb_cpu_sem_set(self
, 1U, HW_ATL_FW_SM_RAM
);
422 err
= aq_hw_err_from_flags(self
);
428 int hw_atl_write_fwcfg_dwords(struct aq_hw_s
*self
, u32
*p
, u32 cnt
)
430 return hw_atl_utils_fw_upload_dwords(self
, self
->rpc_addr
, p
,
431 cnt
, MCP_AREA_CONFIG
);
434 int hw_atl_write_fwsettings_dwords(struct aq_hw_s
*self
, u32 offset
, u32
*p
,
437 return hw_atl_utils_fw_upload_dwords(self
, self
->settings_addr
+ offset
,
438 p
, cnt
, MCP_AREA_SETTINGS
);
441 static int hw_atl_utils_ver_match(u32 ver_expected
, u32 ver_actual
)
443 const u32 dw_major_mask
= 0xff000000U
;
444 const u32 dw_minor_mask
= 0x00ffffffU
;
447 err
= (dw_major_mask
& (ver_expected
^ ver_actual
)) ? -EOPNOTSUPP
: 0;
450 err
= ((dw_minor_mask
& ver_expected
) > (dw_minor_mask
& ver_actual
)) ?
457 static int hw_atl_utils_init_ucp(struct aq_hw_s
*self
,
458 const struct aq_hw_caps_s
*aq_hw_caps
)
462 if (!aq_hw_read_reg(self
, 0x370U
)) {
463 unsigned int rnd
= 0U;
464 unsigned int ucp_0x370
= 0U;
466 get_random_bytes(&rnd
, sizeof(unsigned int));
468 ucp_0x370
= 0x02020202U
| (0xFEFEFEFEU
& rnd
);
469 aq_hw_write_reg(self
, HW_ATL_UCP_0X370_REG
, ucp_0x370
);
472 hw_atl_reg_glb_cpu_scratch_scp_set(self
, 0x00000000U
, 25U);
474 /* check 10 times by 1ms */
475 err
= readx_poll_timeout_atomic(hw_atl_scrpad25_get
,
476 self
, self
->mbox_addr
,
477 self
->mbox_addr
!= 0U,
479 err
= readx_poll_timeout_atomic(aq_fw1x_rpc_get
, self
,
481 self
->rpc_addr
!= 0U,
487 struct aq_hw_atl_utils_fw_rpc_tid_s
{
497 #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
499 int hw_atl_utils_fw_rpc_call(struct aq_hw_s
*self
, unsigned int rpc_size
)
501 struct aq_hw_atl_utils_fw_rpc_tid_s sw
;
504 if (!IS_CHIP_FEATURE(MIPS
)) {
508 err
= hw_atl_write_fwcfg_dwords(self
, (u32
*)(void *)&self
->rpc
,
509 (rpc_size
+ sizeof(u32
) -
510 sizeof(u8
)) / sizeof(u32
));
514 sw
.tid
= 0xFFFFU
& (++self
->rpc_tid
);
515 sw
.len
= (u16
)rpc_size
;
516 aq_hw_write_reg(self
, HW_ATL_RPC_CONTROL_ADR
, sw
.val
);
522 int hw_atl_utils_fw_rpc_wait(struct aq_hw_s
*self
,
523 struct hw_atl_utils_fw_rpc
**rpc
)
525 struct aq_hw_atl_utils_fw_rpc_tid_s sw
;
526 struct aq_hw_atl_utils_fw_rpc_tid_s fw
;
530 sw
.val
= aq_hw_read_reg(self
, HW_ATL_RPC_CONTROL_ADR
);
532 self
->rpc_tid
= sw
.tid
;
534 err
= readx_poll_timeout_atomic(hw_atl_utils_rpc_state_get
,
541 err
= aq_hw_err_from_flags(self
);
545 if (fw
.len
== 0xFFFFU
) {
546 err
= hw_atl_utils_fw_rpc_call(self
, sw
.len
);
550 } while (sw
.tid
!= fw
.tid
|| 0xFFFFU
== fw
.len
);
555 hw_atl_utils_fw_downld_dwords(self
,
559 (fw
.len
+ sizeof(u32
) -
573 static int hw_atl_utils_mpi_create(struct aq_hw_s
*self
)
577 err
= hw_atl_utils_init_ucp(self
, self
->aq_nic_cfg
->aq_hw_caps
);
581 err
= hw_atl_utils_fw_rpc_init(self
);
589 int hw_atl_utils_mpi_read_mbox(struct aq_hw_s
*self
,
590 struct hw_atl_utils_mbox_header
*pmbox
)
592 return hw_atl_utils_fw_downld_dwords(self
,
594 (u32
*)(void *)pmbox
,
595 sizeof(*pmbox
) / sizeof(u32
));
598 void hw_atl_utils_mpi_read_stats(struct aq_hw_s
*self
,
599 struct hw_atl_utils_mbox
*pmbox
)
603 err
= hw_atl_utils_fw_downld_dwords(self
,
605 (u32
*)(void *)pmbox
,
606 sizeof(*pmbox
) / sizeof(u32
));
610 if (IS_CHIP_FEATURE(REVISION_A0
)) {
611 unsigned int mtu
= self
->aq_nic_cfg
?
612 self
->aq_nic_cfg
->mtu
: 1514U;
613 pmbox
->stats
.ubrc
= pmbox
->stats
.uprc
* mtu
;
614 pmbox
->stats
.ubtc
= pmbox
->stats
.uptc
* mtu
;
615 pmbox
->stats
.dpc
= atomic_read(&self
->dpc
);
617 pmbox
->stats
.dpc
= hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self
);
623 static int hw_atl_utils_mpi_set_speed(struct aq_hw_s
*self
, u32 speed
)
625 u32 val
= aq_hw_read_reg(self
, HW_ATL_MPI_CONTROL_ADR
);
627 val
= val
& ~HW_ATL_MPI_SPEED_MSK
;
628 val
|= speed
<< HW_ATL_MPI_SPEED_SHIFT
;
629 aq_hw_write_reg(self
, HW_ATL_MPI_CONTROL_ADR
, val
);
634 static int hw_atl_utils_mpi_set_state(struct aq_hw_s
*self
,
635 enum hal_atl_utils_fw_state_e state
)
637 u32 val
= aq_hw_read_reg(self
, HW_ATL_MPI_CONTROL_ADR
);
638 struct hw_atl_utils_mbox_header mbox
;
639 u32 transaction_id
= 0;
642 if (state
== MPI_RESET
) {
643 hw_atl_utils_mpi_read_mbox(self
, &mbox
);
645 transaction_id
= mbox
.transaction_id
;
647 err
= readx_poll_timeout_atomic(hw_atl_utils_get_mpi_mbox_tid
,
648 self
, mbox
.transaction_id
,
655 /* On interface DEINIT we disable DW (raise bit)
656 * Otherwise enable DW (clear bit)
658 if (state
== MPI_DEINIT
|| state
== MPI_POWER
)
659 val
|= HW_ATL_MPI_DIRTY_WAKE_MSK
;
661 val
&= ~HW_ATL_MPI_DIRTY_WAKE_MSK
;
663 /* Set new state bits */
664 val
= val
& ~HW_ATL_MPI_STATE_MSK
;
665 val
|= state
& HW_ATL_MPI_STATE_MSK
;
667 aq_hw_write_reg(self
, HW_ATL_MPI_CONTROL_ADR
, val
);
673 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s
*self
)
675 struct aq_hw_link_status_s
*link_status
= &self
->aq_link_status
;
679 mpi_state
= hw_atl_utils_mpi_get_state(self
);
680 speed
= mpi_state
>> HW_ATL_MPI_SPEED_SHIFT
;
683 link_status
->mbps
= 0U;
686 case HAL_ATLANTIC_RATE_10G
:
687 link_status
->mbps
= 10000U;
690 case HAL_ATLANTIC_RATE_5G
:
691 case HAL_ATLANTIC_RATE_5GSR
:
692 link_status
->mbps
= 5000U;
695 case HAL_ATLANTIC_RATE_2GS
:
696 link_status
->mbps
= 2500U;
699 case HAL_ATLANTIC_RATE_1G
:
700 link_status
->mbps
= 1000U;
703 case HAL_ATLANTIC_RATE_100M
:
704 link_status
->mbps
= 100U;
715 int hw_atl_utils_get_mac_permanent(struct aq_hw_s
*self
,
724 if (!aq_hw_read_reg(self
, HW_ATL_UCP_0X370_REG
)) {
725 unsigned int ucp_0x370
= 0;
726 unsigned int rnd
= 0;
728 get_random_bytes(&rnd
, sizeof(unsigned int));
730 ucp_0x370
= 0x02020202 | (0xFEFEFEFE & rnd
);
731 aq_hw_write_reg(self
, HW_ATL_UCP_0X370_REG
, ucp_0x370
);
734 efuse_addr
= aq_hw_read_reg(self
, 0x00000374U
);
736 err
= hw_atl_utils_fw_downld_dwords(self
, efuse_addr
+ (40U * 4U),
737 mac_addr
, ARRAY_SIZE(mac_addr
));
743 mac_addr
[0] = __swab32(mac_addr
[0]);
744 mac_addr
[1] = __swab32(mac_addr
[1]);
747 ether_addr_copy(mac
, (u8
*)mac_addr
);
749 if ((mac
[0] & 0x01U
) || ((mac
[0] | mac
[1] | mac
[2]) == 0x00U
)) {
752 (0xFFFFU
& aq_hw_read_reg(self
, HW_ATL_UCP_0X370_REG
)) |
756 mac
[5] = (u8
)(0xFFU
& l
);
758 mac
[4] = (u8
)(0xFFU
& l
);
760 mac
[3] = (u8
)(0xFFU
& l
);
762 mac
[2] = (u8
)(0xFFU
& l
);
763 mac
[1] = (u8
)(0xFFU
& h
);
765 mac
[0] = (u8
)(0xFFU
& h
);
771 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps
)
773 unsigned int ret
= 0U;
803 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s
*self
, u32
*p
)
805 u32 val
= hw_atl_reg_glb_mif_id_get(self
);
806 u32 mif_rev
= val
& 0xFFU
;
807 u32 chip_features
= 0U;
809 if ((0xFU
& mif_rev
) == 1U) {
810 chip_features
|= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0
|
811 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ
|
812 HAL_ATLANTIC_UTILS_CHIP_MIPS
;
813 } else if ((0xFU
& mif_rev
) == 2U) {
814 chip_features
|= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0
|
815 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ
|
816 HAL_ATLANTIC_UTILS_CHIP_MIPS
|
817 HAL_ATLANTIC_UTILS_CHIP_TPO2
|
818 HAL_ATLANTIC_UTILS_CHIP_RPF2
;
819 } else if ((0xFU
& mif_rev
) == 0xAU
) {
820 chip_features
|= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1
|
821 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ
|
822 HAL_ATLANTIC_UTILS_CHIP_MIPS
|
823 HAL_ATLANTIC_UTILS_CHIP_TPO2
|
824 HAL_ATLANTIC_UTILS_CHIP_RPF2
;
830 static int hw_atl_fw1x_deinit(struct aq_hw_s
*self
)
832 hw_atl_utils_mpi_set_speed(self
, 0);
833 hw_atl_utils_mpi_set_state(self
, MPI_DEINIT
);
838 int hw_atl_utils_update_stats(struct aq_hw_s
*self
)
840 struct aq_stats_s
*cs
= &self
->curr_stats
;
841 struct hw_atl_utils_mbox mbox
;
843 hw_atl_utils_mpi_read_stats(self
, &mbox
);
845 #define AQ_SDELTA(_N_) (self->curr_stats._N_ += \
846 mbox.stats._N_ - self->last_stats._N_)
848 if (self
->aq_link_status
.mbps
) {
869 cs
->dma_pkt_rc
= hw_atl_stats_rx_dma_good_pkt_counter_get(self
);
870 cs
->dma_pkt_tc
= hw_atl_stats_tx_dma_good_pkt_counter_get(self
);
871 cs
->dma_oct_rc
= hw_atl_stats_rx_dma_good_octet_counter_get(self
);
872 cs
->dma_oct_tc
= hw_atl_stats_tx_dma_good_octet_counter_get(self
);
874 memcpy(&self
->last_stats
, &mbox
.stats
, sizeof(mbox
.stats
));
879 struct aq_stats_s
*hw_atl_utils_get_hw_stats(struct aq_hw_s
*self
)
881 return &self
->curr_stats
;
884 static const u32 hw_atl_utils_hw_mac_regs
[] = {
885 0x00005580U
, 0x00005590U
, 0x000055B0U
, 0x000055B4U
,
886 0x000055C0U
, 0x00005B00U
, 0x00005B04U
, 0x00005B08U
,
887 0x00005B0CU
, 0x00005B10U
, 0x00005B14U
, 0x00005B18U
,
888 0x00005B1CU
, 0x00005B20U
, 0x00005B24U
, 0x00005B28U
,
889 0x00005B2CU
, 0x00005B30U
, 0x00005B34U
, 0x00005B38U
,
890 0x00005B3CU
, 0x00005B40U
, 0x00005B44U
, 0x00005B48U
,
891 0x00005B4CU
, 0x00005B50U
, 0x00005B54U
, 0x00005B58U
,
892 0x00005B5CU
, 0x00005B60U
, 0x00005B64U
, 0x00005B68U
,
893 0x00005B6CU
, 0x00005B70U
, 0x00005B74U
, 0x00005B78U
,
894 0x00005B7CU
, 0x00007C00U
, 0x00007C04U
, 0x00007C08U
,
895 0x00007C0CU
, 0x00007C10U
, 0x00007C14U
, 0x00007C18U
,
896 0x00007C1CU
, 0x00007C20U
, 0x00007C40U
, 0x00007C44U
,
897 0x00007C48U
, 0x00007C4CU
, 0x00007C50U
, 0x00007C54U
,
898 0x00007C58U
, 0x00007C5CU
, 0x00007C60U
, 0x00007C80U
,
899 0x00007C84U
, 0x00007C88U
, 0x00007C8CU
, 0x00007C90U
,
900 0x00007C94U
, 0x00007C98U
, 0x00007C9CU
, 0x00007CA0U
,
901 0x00007CC0U
, 0x00007CC4U
, 0x00007CC8U
, 0x00007CCCU
,
902 0x00007CD0U
, 0x00007CD4U
, 0x00007CD8U
, 0x00007CDCU
,
903 0x00007CE0U
, 0x00000300U
, 0x00000304U
, 0x00000308U
,
904 0x0000030cU
, 0x00000310U
, 0x00000314U
, 0x00000318U
,
905 0x0000031cU
, 0x00000360U
, 0x00000364U
, 0x00000368U
,
906 0x0000036cU
, 0x00000370U
, 0x00000374U
, 0x00006900U
,
909 int hw_atl_utils_hw_get_regs(struct aq_hw_s
*self
,
910 const struct aq_hw_caps_s
*aq_hw_caps
,
915 for (i
= 0; i
< aq_hw_caps
->mac_regs_count
; i
++)
916 regs_buff
[i
] = aq_hw_read_reg(self
,
917 hw_atl_utils_hw_mac_regs
[i
]);
922 int hw_atl_utils_get_fw_version(struct aq_hw_s
*self
, u32
*fw_version
)
924 *fw_version
= aq_hw_read_reg(self
, 0x18U
);
929 static int aq_fw1x_set_wake_magic(struct aq_hw_s
*self
, bool wol_enabled
,
932 struct hw_atl_utils_fw_rpc
*prpc
= NULL
;
933 unsigned int rpc_size
= 0U;
936 err
= hw_atl_utils_fw_rpc_wait(self
, &prpc
);
940 memset(prpc
, 0, sizeof(*prpc
));
943 rpc_size
= offsetof(struct hw_atl_utils_fw_rpc
, msg_wol_add
) +
944 sizeof(prpc
->msg_wol_add
);
947 prpc
->msg_id
= HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD
;
948 prpc
->msg_wol_add
.priority
=
949 HAL_ATLANTIC_UTILS_FW_MSG_WOL_PRIOR
;
950 prpc
->msg_wol_add
.pattern_id
=
951 HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN
;
952 prpc
->msg_wol_add
.packet_type
=
953 HAL_ATLANTIC_UTILS_FW_MSG_WOL_MAG_PKT
;
955 ether_addr_copy((u8
*)&prpc
->msg_wol_add
.magic_packet_pattern
,
958 rpc_size
= sizeof(prpc
->msg_wol_remove
) +
959 offsetof(struct hw_atl_utils_fw_rpc
, msg_wol_remove
);
961 prpc
->msg_id
= HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL
;
962 prpc
->msg_wol_add
.pattern_id
=
963 HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN
;
966 err
= hw_atl_utils_fw_rpc_call(self
, rpc_size
);
972 static int aq_fw1x_set_power(struct aq_hw_s
*self
, unsigned int power_state
,
975 struct hw_atl_utils_fw_rpc
*prpc
= NULL
;
976 unsigned int rpc_size
= 0U;
979 if (self
->aq_nic_cfg
->wol
& WAKE_MAGIC
) {
980 err
= aq_fw1x_set_wake_magic(self
, 1, mac
);
985 rpc_size
= sizeof(prpc
->msg_id
) +
986 sizeof(prpc
->msg_enable_wakeup
);
988 err
= hw_atl_utils_fw_rpc_wait(self
, &prpc
);
993 memset(prpc
, 0, rpc_size
);
995 prpc
->msg_id
= HAL_ATLANTIC_UTILS_FW_MSG_ENABLE_WAKEUP
;
996 prpc
->msg_enable_wakeup
.pattern_mask
= 0x00000002;
998 err
= hw_atl_utils_fw_rpc_call(self
, rpc_size
);
1002 hw_atl_utils_mpi_set_speed(self
, 0);
1003 hw_atl_utils_mpi_set_state(self
, MPI_POWER
);
1009 static u32
hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s
*self
)
1011 struct hw_atl_utils_mbox_header mbox
;
1013 hw_atl_utils_mpi_read_mbox(self
, &mbox
);
1015 return mbox
.transaction_id
;
1018 static u32
hw_atl_utils_mpi_get_state(struct aq_hw_s
*self
)
1020 return aq_hw_read_reg(self
, HW_ATL_MPI_STATE_ADR
);
1023 static u32
hw_atl_utils_mif_cmd_get(struct aq_hw_s
*self
)
1025 return aq_hw_read_reg(self
, HW_ATL_MIF_CMD
);
1028 static u32
hw_atl_utils_mif_addr_get(struct aq_hw_s
*self
)
1030 return aq_hw_read_reg(self
, HW_ATL_MIF_ADDR
);
1033 static u32
hw_atl_utils_rpc_state_get(struct aq_hw_s
*self
)
1035 return aq_hw_read_reg(self
, HW_ATL_RPC_STATE_ADR
);
1038 static u32
aq_fw1x_rpc_get(struct aq_hw_s
*self
)
1040 return aq_hw_read_reg(self
, HW_ATL_MPI_RPC_ADDR
);
1043 const struct aq_fw_ops aq_fw_1x_ops
= {
1044 .init
= hw_atl_utils_mpi_create
,
1045 .deinit
= hw_atl_fw1x_deinit
,
1047 .get_mac_permanent
= hw_atl_utils_get_mac_permanent
,
1048 .set_link_speed
= hw_atl_utils_mpi_set_speed
,
1049 .set_state
= hw_atl_utils_mpi_set_state
,
1050 .update_link_status
= hw_atl_utils_mpi_get_link_status
,
1051 .update_stats
= hw_atl_utils_update_stats
,
1052 .get_phy_temp
= NULL
,
1053 .set_power
= aq_fw1x_set_power
,
1054 .set_eee_rate
= NULL
,
1055 .get_eee_rate
= NULL
,
1056 .set_flow_control
= NULL
,
1057 .send_fw_request
= NULL
,
1059 .led_control
= NULL
,