cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hw_atl2_utils.c (3193B)


      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}