Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c1be0bf

Browse files
logostdavem330
authored andcommitted
net: atlantic: common functions needed for basic A2 init/deinit hw_ops
This patch adds common functions (mostly FW-related), which are needed for basic A2 HW initialization / deinitialization. Signed-off-by: Dmitry Bogdanov <[email protected]> Co-developed-by: Igor Russkikh <[email protected]> Signed-off-by: Igor Russkikh <[email protected]> Signed-off-by: Mark Starovoytov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ec7629e commit c1be0bf

File tree

6 files changed

+163
-2
lines changed

6 files changed

+163
-2
lines changed

drivers/net/ethernet/aquantia/atlantic/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ atlantic-objs := aq_main.o \
2626
hw_atl/hw_atl_utils_fw2x.o \
2727
hw_atl/hw_atl_llh.o \
2828
hw_atl2/hw_atl2.o \
29+
hw_atl2/hw_atl2_utils.o \
2930
hw_atl2/hw_atl2_utils_fw.o \
3031
hw_atl2/hw_atl2_llh.o \
3132
macsec/macsec_api.o

drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ enum mcp_area {
5353
MCP_AREA_SETTINGS = 0x20000000,
5454
};
5555

56-
static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
5756
static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
5857
enum hal_atl_utils_fw_state_e state);
5958
static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self);
@@ -434,7 +433,7 @@ int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p,
434433
p, cnt, MCP_AREA_SETTINGS);
435434
}
436435

437-
static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
436+
int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
438437
{
439438
const u32 dw_major_mask = 0xff000000U;
440439
const u32 dw_minor_mask = 0x00ffffffU;

drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,8 @@ int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size);
634634
int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
635635
struct hw_atl_utils_fw_rpc **rpc);
636636

637+
int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
638+
637639
extern const struct aq_fw_ops aq_fw_1x_ops;
638640
extern const struct aq_fw_ops aq_fw_2x_ops;
639641

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/* Atlantic Network Driver
3+
* Copyright (C) 2020 Marvell International Ltd.
4+
*/
5+
6+
#include <linux/iopoll.h>
7+
8+
#include "aq_hw_utils.h"
9+
#include "hw_atl/hw_atl_utils.h"
10+
#include "hw_atl2_utils.h"
11+
#include "hw_atl2_llh.h"
12+
#include "hw_atl2_llh_internal.h"
13+
14+
#define HW_ATL2_FW_VER_1X 0x01000000U
15+
16+
#define AQ_A2_BOOT_STARTED BIT(0x18)
17+
#define AQ_A2_CRASH_INIT BIT(0x1B)
18+
#define AQ_A2_BOOT_CODE_FAILED BIT(0x1C)
19+
#define AQ_A2_FW_INIT_FAILED BIT(0x1D)
20+
#define AQ_A2_FW_INIT_COMP_SUCCESS BIT(0x1F)
21+
22+
#define AQ_A2_FW_BOOT_FAILED_MASK (AQ_A2_CRASH_INIT | \
23+
AQ_A2_BOOT_CODE_FAILED | \
24+
AQ_A2_FW_INIT_FAILED)
25+
#define AQ_A2_FW_BOOT_COMPLETE_MASK (AQ_A2_FW_BOOT_FAILED_MASK | \
26+
AQ_A2_FW_INIT_COMP_SUCCESS)
27+
28+
#define AQ_A2_FW_BOOT_REQ_REBOOT BIT(0x0)
29+
#define AQ_A2_FW_BOOT_REQ_HOST_BOOT BIT(0x8)
30+
#define AQ_A2_FW_BOOT_REQ_MAC_FAST_BOOT BIT(0xA)
31+
#define AQ_A2_FW_BOOT_REQ_PHY_FAST_BOOT BIT(0xB)
32+
33+
int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
34+
{
35+
int err;
36+
37+
self->fw_ver_actual = hw_atl2_utils_get_fw_version(self);
38+
39+
if (hw_atl_utils_ver_match(HW_ATL2_FW_VER_1X,
40+
self->fw_ver_actual) == 0) {
41+
*fw_ops = &aq_a2_fw_ops;
42+
} else {
43+
aq_pr_err("Bad FW version detected: %x, but continue\n",
44+
self->fw_ver_actual);
45+
*fw_ops = &aq_a2_fw_ops;
46+
}
47+
aq_pr_trace("Detect ATL2FW %x\n", self->fw_ver_actual);
48+
self->aq_fw_ops = *fw_ops;
49+
err = self->aq_fw_ops->init(self);
50+
51+
self->chip_features |= ATL_HW_CHIP_ANTIGUA;
52+
53+
return err;
54+
}
55+
56+
static bool hw_atl2_mcp_boot_complete(struct aq_hw_s *self)
57+
{
58+
u32 rbl_status;
59+
60+
rbl_status = hw_atl2_mif_mcp_boot_reg_get(self);
61+
if (rbl_status & AQ_A2_FW_BOOT_COMPLETE_MASK)
62+
return true;
63+
64+
/* Host boot requested */
65+
if (hw_atl2_mif_host_req_int_get(self) & HW_ATL2_MCP_HOST_REQ_INT_READY)
66+
return true;
67+
68+
return false;
69+
}
70+
71+
int hw_atl2_utils_soft_reset(struct aq_hw_s *self)
72+
{
73+
bool rbl_complete = false;
74+
u32 rbl_status = 0;
75+
u32 rbl_request;
76+
int err;
77+
78+
err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_boot_reg_get, self,
79+
rbl_status,
80+
((rbl_status & AQ_A2_BOOT_STARTED) &&
81+
(rbl_status != 0xFFFFFFFFu)),
82+
10, 500000);
83+
if (err)
84+
aq_pr_trace("Boot code probably hanged, reboot anyway");
85+
86+
hw_atl2_mif_host_req_int_clr(self, 0x01);
87+
rbl_request = AQ_A2_FW_BOOT_REQ_REBOOT;
88+
#ifdef AQ_CFG_FAST_START
89+
rbl_request |= AQ_A2_FW_BOOT_REQ_MAC_FAST_BOOT;
90+
#endif
91+
hw_atl2_mif_mcp_boot_reg_set(self, rbl_request);
92+
93+
/* Wait for RBL boot */
94+
err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_boot_reg_get, self,
95+
rbl_status,
96+
((rbl_status & AQ_A2_BOOT_STARTED) &&
97+
(rbl_status != 0xFFFFFFFFu)),
98+
10, 200000);
99+
if (err) {
100+
aq_pr_err("Boot code hanged");
101+
goto err_exit;
102+
}
103+
104+
err = readx_poll_timeout_atomic(hw_atl2_mcp_boot_complete, self,
105+
rbl_complete,
106+
rbl_complete,
107+
10, 2000000);
108+
109+
if (err) {
110+
aq_pr_err("FW Restart timed out");
111+
goto err_exit;
112+
}
113+
114+
rbl_status = hw_atl2_mif_mcp_boot_reg_get(self);
115+
116+
if (rbl_status & AQ_A2_FW_BOOT_FAILED_MASK) {
117+
err = -EIO;
118+
aq_pr_err("FW Restart failed");
119+
goto err_exit;
120+
}
121+
122+
if (hw_atl2_mif_host_req_int_get(self) &
123+
HW_ATL2_MCP_HOST_REQ_INT_READY) {
124+
err = -EIO;
125+
aq_pr_err("No FW detected. Dynamic FW load not implemented");
126+
goto err_exit;
127+
}
128+
129+
if (self->aq_fw_ops) {
130+
err = self->aq_fw_ops->init(self);
131+
if (err) {
132+
aq_pr_err("FW Init failed");
133+
goto err_exit;
134+
}
135+
}
136+
137+
err_exit:
138+
return err;
139+
}

drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#ifndef HW_ATL2_UTILS_H
77
#define HW_ATL2_UTILS_H
88

9+
#include "aq_hw.h"
10+
911
/* F W A P I */
1012

1113
struct link_options_s {
@@ -590,6 +592,12 @@ struct fw_interface_out {
590592
#define AQ_HOST_MODE_LOW_POWER 3U
591593
#define AQ_HOST_MODE_SHUTDOWN 4U
592594

595+
int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops);
596+
597+
int hw_atl2_utils_soft_reset(struct aq_hw_s *self);
598+
599+
u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self);
600+
593601
int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self,
594602
u8 *base_index, u8 *count);
595603

drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,18 @@ static int aq_a2_fw_renegotiate(struct aq_hw_s *self)
301301
return err;
302302
}
303303

304+
u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self)
305+
{
306+
struct version_s version;
307+
308+
hw_atl2_shared_buffer_read_safe(self, version, &version);
309+
310+
/* A2 FW version is stored in reverse order */
311+
return version.mac.major << 24 |
312+
version.mac.minor << 16 |
313+
version.mac.build;
314+
}
315+
304316
int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self,
305317
u8 *base_index, u8 *count)
306318
{

0 commit comments

Comments
 (0)