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 <dbogdanov@marvell.com> Co-developed-by: Igor Russkikh <irusskikh@marvell.com> Signed-off-by: Igor Russkikh <irusskikh@marvell.com> Signed-off-by: Mark Starovoytov <mstarovoitov@marvell.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ec7629e0c2
commit
c1be0bf092
|
@ -26,6 +26,7 @@ atlantic-objs := aq_main.o \
|
|||
hw_atl/hw_atl_utils_fw2x.o \
|
||||
hw_atl/hw_atl_llh.o \
|
||||
hw_atl2/hw_atl2.o \
|
||||
hw_atl2/hw_atl2_utils.o \
|
||||
hw_atl2/hw_atl2_utils_fw.o \
|
||||
hw_atl2/hw_atl2_llh.o \
|
||||
macsec/macsec_api.o
|
||||
|
|
|
@ -53,7 +53,6 @@ enum mcp_area {
|
|||
MCP_AREA_SETTINGS = 0x20000000,
|
||||
};
|
||||
|
||||
static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
|
||||
static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
|
||||
enum hal_atl_utils_fw_state_e state);
|
||||
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,
|
|||
p, cnt, MCP_AREA_SETTINGS);
|
||||
}
|
||||
|
||||
static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
|
||||
int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
|
||||
{
|
||||
const u32 dw_major_mask = 0xff000000U;
|
||||
const u32 dw_minor_mask = 0x00ffffffU;
|
||||
|
|
|
@ -634,6 +634,8 @@ int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size);
|
|||
int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
|
||||
struct hw_atl_utils_fw_rpc **rpc);
|
||||
|
||||
int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
|
||||
|
||||
extern const struct aq_fw_ops aq_fw_1x_ops;
|
||||
extern const struct aq_fw_ops aq_fw_2x_ops;
|
||||
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Atlantic Network Driver
|
||||
* Copyright (C) 2020 Marvell International Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
#include "aq_hw_utils.h"
|
||||
#include "hw_atl/hw_atl_utils.h"
|
||||
#include "hw_atl2_utils.h"
|
||||
#include "hw_atl2_llh.h"
|
||||
#include "hw_atl2_llh_internal.h"
|
||||
|
||||
#define HW_ATL2_FW_VER_1X 0x01000000U
|
||||
|
||||
#define AQ_A2_BOOT_STARTED BIT(0x18)
|
||||
#define AQ_A2_CRASH_INIT BIT(0x1B)
|
||||
#define AQ_A2_BOOT_CODE_FAILED BIT(0x1C)
|
||||
#define AQ_A2_FW_INIT_FAILED BIT(0x1D)
|
||||
#define AQ_A2_FW_INIT_COMP_SUCCESS BIT(0x1F)
|
||||
|
||||
#define AQ_A2_FW_BOOT_FAILED_MASK (AQ_A2_CRASH_INIT | \
|
||||
AQ_A2_BOOT_CODE_FAILED | \
|
||||
AQ_A2_FW_INIT_FAILED)
|
||||
#define AQ_A2_FW_BOOT_COMPLETE_MASK (AQ_A2_FW_BOOT_FAILED_MASK | \
|
||||
AQ_A2_FW_INIT_COMP_SUCCESS)
|
||||
|
||||
#define AQ_A2_FW_BOOT_REQ_REBOOT BIT(0x0)
|
||||
#define AQ_A2_FW_BOOT_REQ_HOST_BOOT BIT(0x8)
|
||||
#define AQ_A2_FW_BOOT_REQ_MAC_FAST_BOOT BIT(0xA)
|
||||
#define AQ_A2_FW_BOOT_REQ_PHY_FAST_BOOT BIT(0xB)
|
||||
|
||||
int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
|
||||
{
|
||||
int err;
|
||||
|
||||
self->fw_ver_actual = hw_atl2_utils_get_fw_version(self);
|
||||
|
||||
if (hw_atl_utils_ver_match(HW_ATL2_FW_VER_1X,
|
||||
self->fw_ver_actual) == 0) {
|
||||
*fw_ops = &aq_a2_fw_ops;
|
||||
} else {
|
||||
aq_pr_err("Bad FW version detected: %x, but continue\n",
|
||||
self->fw_ver_actual);
|
||||
*fw_ops = &aq_a2_fw_ops;
|
||||
}
|
||||
aq_pr_trace("Detect ATL2FW %x\n", self->fw_ver_actual);
|
||||
self->aq_fw_ops = *fw_ops;
|
||||
err = self->aq_fw_ops->init(self);
|
||||
|
||||
self->chip_features |= ATL_HW_CHIP_ANTIGUA;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool hw_atl2_mcp_boot_complete(struct aq_hw_s *self)
|
||||
{
|
||||
u32 rbl_status;
|
||||
|
||||
rbl_status = hw_atl2_mif_mcp_boot_reg_get(self);
|
||||
if (rbl_status & AQ_A2_FW_BOOT_COMPLETE_MASK)
|
||||
return true;
|
||||
|
||||
/* Host boot requested */
|
||||
if (hw_atl2_mif_host_req_int_get(self) & HW_ATL2_MCP_HOST_REQ_INT_READY)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int hw_atl2_utils_soft_reset(struct aq_hw_s *self)
|
||||
{
|
||||
bool rbl_complete = false;
|
||||
u32 rbl_status = 0;
|
||||
u32 rbl_request;
|
||||
int err;
|
||||
|
||||
err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_boot_reg_get, self,
|
||||
rbl_status,
|
||||
((rbl_status & AQ_A2_BOOT_STARTED) &&
|
||||
(rbl_status != 0xFFFFFFFFu)),
|
||||
10, 500000);
|
||||
if (err)
|
||||
aq_pr_trace("Boot code probably hanged, reboot anyway");
|
||||
|
||||
hw_atl2_mif_host_req_int_clr(self, 0x01);
|
||||
rbl_request = AQ_A2_FW_BOOT_REQ_REBOOT;
|
||||
#ifdef AQ_CFG_FAST_START
|
||||
rbl_request |= AQ_A2_FW_BOOT_REQ_MAC_FAST_BOOT;
|
||||
#endif
|
||||
hw_atl2_mif_mcp_boot_reg_set(self, rbl_request);
|
||||
|
||||
/* Wait for RBL boot */
|
||||
err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_boot_reg_get, self,
|
||||
rbl_status,
|
||||
((rbl_status & AQ_A2_BOOT_STARTED) &&
|
||||
(rbl_status != 0xFFFFFFFFu)),
|
||||
10, 200000);
|
||||
if (err) {
|
||||
aq_pr_err("Boot code hanged");
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
err = readx_poll_timeout_atomic(hw_atl2_mcp_boot_complete, self,
|
||||
rbl_complete,
|
||||
rbl_complete,
|
||||
10, 2000000);
|
||||
|
||||
if (err) {
|
||||
aq_pr_err("FW Restart timed out");
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
rbl_status = hw_atl2_mif_mcp_boot_reg_get(self);
|
||||
|
||||
if (rbl_status & AQ_A2_FW_BOOT_FAILED_MASK) {
|
||||
err = -EIO;
|
||||
aq_pr_err("FW Restart failed");
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
if (hw_atl2_mif_host_req_int_get(self) &
|
||||
HW_ATL2_MCP_HOST_REQ_INT_READY) {
|
||||
err = -EIO;
|
||||
aq_pr_err("No FW detected. Dynamic FW load not implemented");
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
if (self->aq_fw_ops) {
|
||||
err = self->aq_fw_ops->init(self);
|
||||
if (err) {
|
||||
aq_pr_err("FW Init failed");
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
|
||||
err_exit:
|
||||
return err;
|
||||
}
|
|
@ -6,6 +6,8 @@
|
|||
#ifndef HW_ATL2_UTILS_H
|
||||
#define HW_ATL2_UTILS_H
|
||||
|
||||
#include "aq_hw.h"
|
||||
|
||||
/* F W A P I */
|
||||
|
||||
struct link_options_s {
|
||||
|
@ -590,6 +592,12 @@ struct fw_interface_out {
|
|||
#define AQ_HOST_MODE_LOW_POWER 3U
|
||||
#define AQ_HOST_MODE_SHUTDOWN 4U
|
||||
|
||||
int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops);
|
||||
|
||||
int hw_atl2_utils_soft_reset(struct aq_hw_s *self);
|
||||
|
||||
u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self);
|
||||
|
||||
int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self,
|
||||
u8 *base_index, u8 *count);
|
||||
|
||||
|
|
|
@ -301,6 +301,18 @@ static int aq_a2_fw_renegotiate(struct aq_hw_s *self)
|
|||
return err;
|
||||
}
|
||||
|
||||
u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self)
|
||||
{
|
||||
struct version_s version;
|
||||
|
||||
hw_atl2_shared_buffer_read_safe(self, version, &version);
|
||||
|
||||
/* A2 FW version is stored in reverse order */
|
||||
return version.mac.major << 24 |
|
||||
version.mac.minor << 16 |
|
||||
version.mac.build;
|
||||
}
|
||||
|
||||
int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self,
|
||||
u8 *base_index, u8 *count)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue