File Index
Files and directories
Sign in
FILE

hw_atl2_utils.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.c C
  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
 33int 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, self->fw_ver_actual)) {
 40		*fw_ops = &aq_a2_fw_ops;
 41	} else {
 42		aq_pr_err("Bad FW version detected: %x, but continue\n",
 43			  self->fw_ver_actual);
 44		*fw_ops = &aq_a2_fw_ops;
 45	}
 46	aq_pr_trace("Detect ATL2FW %x\n", self->fw_ver_actual);
 47	self->aq_fw_ops = *fw_ops;
 48	err = self->aq_fw_ops->init(self);
 49
 50	self->chip_features |= ATL_HW_CHIP_ANTIGUA;
 51
 52	return err;
 53}
 54
 55static bool hw_atl2_mcp_boot_complete(struct aq_hw_s *self)
 56{
 57	u32 rbl_status;
 58
 59	rbl_status = hw_atl2_mif_mcp_boot_reg_get(self);
 60	if (rbl_status & AQ_A2_FW_BOOT_COMPLETE_MASK)
 61		return true;
 62
 63	/* Host boot requested */
 64	if (hw_atl2_mif_host_req_int_get(self) & HW_ATL2_MCP_HOST_REQ_INT_READY)
 65		return true;
 66
 67	return false;
 68}
 69
 70int hw_atl2_utils_soft_reset(struct aq_hw_s *self)
 71{
 72	bool rbl_complete = false;
 73	u32 rbl_status = 0;
 74	u32 rbl_request;
 75	int err;
 76
 77	hw_atl2_mif_host_req_int_clr(self, 0x01);
 78	rbl_request = AQ_A2_FW_BOOT_REQ_REBOOT;
 79#ifdef AQ_CFG_FAST_START
 80	rbl_request |= AQ_A2_FW_BOOT_REQ_MAC_FAST_BOOT;
 81#endif
 82	hw_atl2_mif_mcp_boot_reg_set(self, rbl_request);
 83
 84	/* Wait for RBL boot */
 85	err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_boot_reg_get, self,
 86				rbl_status,
 87				((rbl_status & AQ_A2_BOOT_STARTED) &&
 88				 (rbl_status != 0xFFFFFFFFu)),
 89				10, 200000);
 90	if (err) {
 91		aq_pr_err("Boot code hanged");
 92		goto err_exit;
 93	}
 94
 95	err = readx_poll_timeout_atomic(hw_atl2_mcp_boot_complete, self,
 96					rbl_complete,
 97					rbl_complete,
 98					10, 2000000);
 99
100	if (err) {
101		aq_pr_err("FW Restart timed out");
102		goto err_exit;
103	}
104
105	rbl_status = hw_atl2_mif_mcp_boot_reg_get(self);
106
107	if (rbl_status & AQ_A2_FW_BOOT_FAILED_MASK) {
108		err = -EIO;
109		aq_pr_err("FW Restart failed");
110		goto err_exit;
111	}
112
113	if (hw_atl2_mif_host_req_int_get(self) &
114	    HW_ATL2_MCP_HOST_REQ_INT_READY) {
115		err = -EIO;
116		aq_pr_err("No FW detected. Dynamic FW load not implemented");
117		goto err_exit;
118	}
119
120	if (self->aq_fw_ops) {
121		err = self->aq_fw_ops->init(self);
122		if (err) {
123			aq_pr_err("FW Init failed");
124			goto err_exit;
125		}
126	}
127
128err_exit:
129	return err;
130}
~/ Read-only file preview.