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}