mirror of
https://github.com/RinCat/RTL88x2BU-Linux-Driver.git
synced 2024-12-27 10:31:35 +00:00
1911 lines
49 KiB
C
1911 lines
49 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright(c) 2016 - 2018 Realtek Corporation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#include "halmac_efuse_88xx.h"
|
|
#include "halmac_88xx_cfg.h"
|
|
#include "halmac_common_88xx.h"
|
|
#include "halmac_init_88xx.h"
|
|
|
|
#if HALMAC_88XX_SUPPORT
|
|
|
|
#define RSVD_EFUSE_SIZE 16
|
|
#define RSVD_CS_EFUSE_SIZE 24
|
|
#define FEATURE_DUMP_PHY_EFUSE HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE
|
|
#define FEATURE_DUMP_LOG_EFUSE HALMAC_FEATURE_DUMP_LOGICAL_EFUSE
|
|
|
|
static enum halmac_cmd_construct_state
|
|
efuse_cmd_cnstr_state_88xx(struct halmac_adapter *adapter);
|
|
|
|
static enum halmac_ret_status
|
|
proc_dump_efuse_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_efuse_read_cfg cfg);
|
|
|
|
static enum halmac_ret_status
|
|
read_hw_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u32 size,
|
|
u8 *map);
|
|
|
|
static enum halmac_ret_status
|
|
read_log_efuse_map_88xx(struct halmac_adapter *adapter, u8 *map);
|
|
|
|
static enum halmac_ret_status
|
|
proc_pg_efuse_by_map_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info,
|
|
enum halmac_efuse_read_cfg cfg);
|
|
|
|
static enum halmac_ret_status
|
|
dump_efuse_fw_88xx(struct halmac_adapter *adapter);
|
|
|
|
static enum halmac_ret_status
|
|
dump_efuse_drv_88xx(struct halmac_adapter *adapter);
|
|
|
|
static enum halmac_ret_status
|
|
proc_write_log_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u8 value);
|
|
|
|
static enum halmac_ret_status
|
|
update_eeprom_mask_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info, u8 *updated_mask);
|
|
|
|
static enum halmac_ret_status
|
|
check_efuse_enough_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info, u8 *updated_mask);
|
|
|
|
static enum halmac_ret_status
|
|
pg_extend_efuse_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info, u8 word_en,
|
|
u8 pre_word_en, u32 eeprom_offset);
|
|
|
|
static enum halmac_ret_status
|
|
proc_pg_efuse_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info, u8 word_en,
|
|
u8 pre_word_en, u32 eeprom_offset);
|
|
|
|
static enum halmac_ret_status
|
|
program_efuse_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info, u8 *updated_mask);
|
|
|
|
static void
|
|
mask_eeprom_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info);
|
|
|
|
/**
|
|
* dump_efuse_map_88xx() - dump "physical" efuse map
|
|
* @adapter : the adapter of halmac
|
|
* @cfg : dump efuse method
|
|
* Author : Ivan Lin/KaiYuan Chang
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
dump_efuse_map_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_efuse_read_cfg cfg)
|
|
{
|
|
u8 *map = NULL;
|
|
u8 *efuse_map;
|
|
u32 efuse_size = adapter->hw_cfg_info.efuse_size;
|
|
u32 prtct_efuse_size = adapter->hw_cfg_info.prtct_efuse_size;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
|
|
proc_status = &adapter->halmac_state.efuse_state.proc_status;
|
|
|
|
if (cfg == HALMAC_EFUSE_R_FW &&
|
|
halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_NO_DLFW;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
PLTFM_MSG_TRACE("[TRACE]cfg = %d\n", cfg);
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_WARN("[WARN]Wait event(efuse)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
|
|
if (efuse_cmd_cnstr_state_88xx(adapter) != HALMAC_CMD_CNSTR_IDLE) {
|
|
PLTFM_MSG_WARN("[WARN]Not idle(efuse)\n");
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
if (adapter->halmac_state.mac_pwr == HALMAC_MAC_POWER_OFF)
|
|
PLTFM_MSG_ERR("[ERR]Dump efuse in suspend\n");
|
|
|
|
*proc_status = HALMAC_CMD_PROCESS_IDLE;
|
|
adapter->evnt.phy_efuse_map = 1;
|
|
|
|
status = switch_efuse_bank_88xx(adapter, HALMAC_EFUSE_BANK_WIFI);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
|
|
return status;
|
|
}
|
|
|
|
status = proc_dump_efuse_88xx(adapter, cfg);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]dump efuse!!\n");
|
|
return status;
|
|
}
|
|
|
|
if (adapter->efuse_map_valid == 1) {
|
|
*proc_status = HALMAC_CMD_PROCESS_DONE;
|
|
efuse_map = adapter->efuse_map;
|
|
|
|
map = (u8 *)PLTFM_MALLOC(efuse_size);
|
|
if (!map) {
|
|
PLTFM_MSG_ERR("[ERR]malloc!!\n");
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
PLTFM_MEMSET(map, 0xFF, efuse_size);
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_mutex);
|
|
#if HALMAC_PLATFORM_WINDOWS
|
|
PLTFM_MEMCPY(map, efuse_map, efuse_size);
|
|
#else
|
|
PLTFM_MEMCPY(map, efuse_map, efuse_size - prtct_efuse_size);
|
|
PLTFM_MEMCPY(map + efuse_size - prtct_efuse_size +
|
|
RSVD_CS_EFUSE_SIZE,
|
|
efuse_map + efuse_size - prtct_efuse_size +
|
|
RSVD_CS_EFUSE_SIZE,
|
|
prtct_efuse_size - RSVD_EFUSE_SIZE -
|
|
RSVD_CS_EFUSE_SIZE);
|
|
#endif
|
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_mutex);
|
|
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE,
|
|
*proc_status, map, efuse_size);
|
|
adapter->evnt.phy_efuse_map = 0;
|
|
|
|
PLTFM_FREE(map, efuse_size);
|
|
}
|
|
|
|
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* dump_efuse_map_bt_88xx() - dump "BT physical" efuse map
|
|
* @adapter : the adapter of halmac
|
|
* @bank : bt efuse bank
|
|
* @size : bt efuse map size. get from halmac_get_efuse_size API
|
|
* @map : bt efuse map
|
|
* Author : Soar / Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
dump_efuse_map_bt_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_efuse_bank bank, u32 size, u8 *map)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
|
|
proc_status = &adapter->halmac_state.efuse_state.proc_status;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (adapter->hw_cfg_info.bt_efuse_size != size)
|
|
return HALMAC_RET_EFUSE_SIZE_INCORRECT;
|
|
|
|
if (bank >= HALMAC_EFUSE_BANK_MAX || bank == HALMAC_EFUSE_BANK_WIFI) {
|
|
PLTFM_MSG_ERR("[ERR]Undefined BT bank\n");
|
|
return HALMAC_RET_EFUSE_BANK_INCORRECT;
|
|
}
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_WARN("[WARN]Wait event(efuse)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
|
|
if (efuse_cmd_cnstr_state_88xx(adapter) != HALMAC_CMD_CNSTR_IDLE) {
|
|
PLTFM_MSG_WARN("[WARN]Not idle(efuse)\n");
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
status = switch_efuse_bank_88xx(adapter, bank);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
|
|
return status;
|
|
}
|
|
|
|
status = read_hw_efuse_88xx(adapter, 0, size, map);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]read hw efuse\n");
|
|
return status;
|
|
}
|
|
|
|
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* write_efuse_bt_88xx() - write "BT physical" efuse offset
|
|
* @adapter : the adapter of halmac
|
|
* @offset : offset
|
|
* @value : Write value
|
|
* @map : bt efuse map
|
|
* Author : Soar
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
write_efuse_bt_88xx(struct halmac_adapter *adapter, u32 offset, u8 value,
|
|
enum halmac_efuse_bank bank)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
|
|
proc_status = &adapter->halmac_state.efuse_state.proc_status;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_WARN("[WARN]Wait event(efuse)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
|
|
if (efuse_cmd_cnstr_state_88xx(adapter) != HALMAC_CMD_CNSTR_IDLE) {
|
|
PLTFM_MSG_WARN("[WARN]Not idle(efuse)\n");
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
if (offset >= adapter->hw_cfg_info.efuse_size) {
|
|
PLTFM_MSG_ERR("[ERR]Offset is too large\n");
|
|
return HALMAC_RET_EFUSE_SIZE_INCORRECT;
|
|
}
|
|
|
|
if (bank > HALMAC_EFUSE_BANK_MAX || bank == HALMAC_EFUSE_BANK_WIFI) {
|
|
PLTFM_MSG_ERR("[ERR]Undefined BT bank\n");
|
|
return HALMAC_RET_EFUSE_BANK_INCORRECT;
|
|
}
|
|
|
|
status = switch_efuse_bank_88xx(adapter, bank);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
|
|
return status;
|
|
}
|
|
|
|
status = write_hw_efuse_88xx(adapter, offset, value);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]write efuse\n");
|
|
return status;
|
|
}
|
|
|
|
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* read_efuse_bt_88xx() - read "BT physical" efuse offset
|
|
* @adapter : the adapter of halmac
|
|
* @offset : offset
|
|
* @value : 1 byte efuse value
|
|
* @bank : efuse bank
|
|
* Author : Soar
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
read_efuse_bt_88xx(struct halmac_adapter *adapter, u32 offset, u8 *value,
|
|
enum halmac_efuse_bank bank)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
|
|
proc_status = &adapter->halmac_state.efuse_state.proc_status;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_WARN("[WARN]Wait event(efuse)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
|
|
if (efuse_cmd_cnstr_state_88xx(adapter) != HALMAC_CMD_CNSTR_IDLE) {
|
|
PLTFM_MSG_WARN("[WARN]Not idle(efuse)\n");
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
if (offset >= adapter->hw_cfg_info.efuse_size) {
|
|
PLTFM_MSG_ERR("[ERR]Offset is too large\n");
|
|
return HALMAC_RET_EFUSE_SIZE_INCORRECT;
|
|
}
|
|
|
|
if (bank > HALMAC_EFUSE_BANK_MAX || bank == HALMAC_EFUSE_BANK_WIFI) {
|
|
PLTFM_MSG_ERR("[ERR]Undefined BT bank\n");
|
|
return HALMAC_RET_EFUSE_BANK_INCORRECT;
|
|
}
|
|
|
|
status = switch_efuse_bank_88xx(adapter, bank);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
|
return status;
|
|
}
|
|
|
|
status = read_efuse_88xx(adapter, offset, 1, value);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]read efuse\n");
|
|
return status;
|
|
}
|
|
|
|
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* cfg_efuse_auto_check_88xx() - check efuse after writing it
|
|
* @adapter : the adapter of halmac
|
|
* @enable : 1, enable efuse auto check. others, disable
|
|
* Author : Soar
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
cfg_efuse_auto_check_88xx(struct halmac_adapter *adapter, u8 enable)
|
|
{
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
adapter->efuse_auto_check_en = enable;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* get_efuse_available_size_88xx() - get efuse available size
|
|
* @adapter : the adapter of halmac
|
|
* @size : physical efuse available size
|
|
* Author : Soar
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
get_efuse_available_size_88xx(struct halmac_adapter *adapter, u32 *size)
|
|
{
|
|
enum halmac_ret_status status;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
status = dump_log_efuse_map_88xx(adapter, HALMAC_EFUSE_R_DRV);
|
|
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
|
|
*size = adapter->hw_cfg_info.efuse_size -
|
|
adapter->hw_cfg_info.prtct_efuse_size - adapter->efuse_end;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* get_efuse_size_88xx() - get "physical" efuse size
|
|
* @adapter : the adapter of halmac
|
|
* @size : physical efuse size
|
|
* Author : Ivan Lin/KaiYuan Chang
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
get_efuse_size_88xx(struct halmac_adapter *adapter, u32 *size)
|
|
{
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
*size = adapter->hw_cfg_info.efuse_size;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* get_log_efuse_size_88xx() - get "logical" efuse size
|
|
* @adapter : the adapter of halmac
|
|
* @size : logical efuse size
|
|
* Author : Ivan Lin/KaiYuan Chang
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
get_log_efuse_size_88xx(struct halmac_adapter *adapter, u32 *size)
|
|
{
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
*size = adapter->hw_cfg_info.eeprom_size;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* dump_log_efuse_map_88xx() - dump "logical" efuse map
|
|
* @adapter : the adapter of halmac
|
|
* @cfg : dump efuse method
|
|
* Author : Soar
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
dump_log_efuse_map_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_efuse_read_cfg cfg)
|
|
{
|
|
u8 *map = NULL;
|
|
u32 size = adapter->hw_cfg_info.eeprom_size;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
|
|
proc_status = &adapter->halmac_state.efuse_state.proc_status;
|
|
|
|
if (cfg == HALMAC_EFUSE_R_FW &&
|
|
halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_NO_DLFW;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
PLTFM_MSG_TRACE("[TRACE]cfg = %d\n", cfg);
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_WARN("[WARN]Wait event(efuse)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
|
|
if (efuse_cmd_cnstr_state_88xx(adapter) != HALMAC_CMD_CNSTR_IDLE) {
|
|
PLTFM_MSG_WARN("[WARN]Not idle(efuse)\n");
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
if (adapter->halmac_state.mac_pwr == HALMAC_MAC_POWER_OFF)
|
|
PLTFM_MSG_ERR("[ERR]Dump efuse in suspend\n");
|
|
|
|
*proc_status = HALMAC_CMD_PROCESS_IDLE;
|
|
adapter->evnt.log_efuse_map = 1;
|
|
|
|
status = switch_efuse_bank_88xx(adapter, HALMAC_EFUSE_BANK_WIFI);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
|
return status;
|
|
}
|
|
|
|
status = proc_dump_efuse_88xx(adapter, cfg);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]dump efuse\n");
|
|
return status;
|
|
}
|
|
|
|
if (adapter->efuse_map_valid == 1) {
|
|
*proc_status = HALMAC_CMD_PROCESS_DONE;
|
|
|
|
map = (u8 *)PLTFM_MALLOC(size);
|
|
if (!map) {
|
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
PLTFM_MEMSET(map, 0xFF, size);
|
|
|
|
if (eeprom_parser_88xx(adapter, adapter->efuse_map, map) !=
|
|
HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(map, size);
|
|
return HALMAC_RET_EEPROM_PARSING_FAIL;
|
|
}
|
|
|
|
PLTFM_EVENT_SIG(HALMAC_FEATURE_DUMP_LOGICAL_EFUSE,
|
|
*proc_status, map, size);
|
|
adapter->evnt.log_efuse_map = 0;
|
|
|
|
PLTFM_FREE(map, size);
|
|
}
|
|
|
|
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* read_logical_efuse_88xx() - read logical efuse map 1 byte
|
|
* @adapter : the adapter of halmac
|
|
* @offset : offset
|
|
* @value : 1 byte efuse value
|
|
* Author : Soar
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
read_logical_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u8 *value)
|
|
{
|
|
u8 *map = NULL;
|
|
u32 size = adapter->hw_cfg_info.eeprom_size;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
|
|
proc_status = &adapter->halmac_state.efuse_state.proc_status;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (offset >= size) {
|
|
PLTFM_MSG_ERR("[ERR]Offset is too large\n");
|
|
return HALMAC_RET_EFUSE_SIZE_INCORRECT;
|
|
}
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_WARN("[WARN]Wait event(efuse)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
if (efuse_cmd_cnstr_state_88xx(adapter) != HALMAC_CMD_CNSTR_IDLE) {
|
|
PLTFM_MSG_WARN("[WARN]Not idle(efuse)\n");
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
status = switch_efuse_bank_88xx(adapter, HALMAC_EFUSE_BANK_WIFI);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
|
return status;
|
|
}
|
|
|
|
map = (u8 *)PLTFM_MALLOC(size);
|
|
if (!map) {
|
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
PLTFM_MEMSET(map, 0xFF, size);
|
|
|
|
status = read_log_efuse_map_88xx(adapter, map);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]read logical efuse\n");
|
|
PLTFM_FREE(map, size);
|
|
return status;
|
|
}
|
|
|
|
*value = *(map + offset);
|
|
|
|
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
|
|
HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(map, size);
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
PLTFM_FREE(map, size);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* write_log_efuse_88xx() - write "logical" efuse offset
|
|
* @adapter : the adapter of halmac
|
|
* @offset : offset
|
|
* @value : value
|
|
* Author : Soar
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
write_log_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u8 value)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
|
|
proc_status = &adapter->halmac_state.efuse_state.proc_status;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (offset >= adapter->hw_cfg_info.eeprom_size) {
|
|
PLTFM_MSG_ERR("[ERR]Offset is too large\n");
|
|
return HALMAC_RET_EFUSE_SIZE_INCORRECT;
|
|
}
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_WARN("[WARN]Wait event(efuse)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
|
|
if (efuse_cmd_cnstr_state_88xx(adapter) != HALMAC_CMD_CNSTR_IDLE) {
|
|
PLTFM_MSG_WARN("[WARN]Not idle(efuse)\n");
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
status = switch_efuse_bank_88xx(adapter, HALMAC_EFUSE_BANK_WIFI);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
|
return status;
|
|
}
|
|
|
|
status = proc_write_log_efuse_88xx(adapter, offset, value);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]write logical efuse\n");
|
|
return status;
|
|
}
|
|
|
|
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* pg_efuse_by_map_88xx() - pg logical efuse by map
|
|
* @adapter : the adapter of halmac
|
|
* @info : efuse map information
|
|
* @cfg : dump efuse method
|
|
* Author : Soar
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
pg_efuse_by_map_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info,
|
|
enum halmac_efuse_read_cfg cfg)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
|
|
proc_status = &adapter->halmac_state.efuse_state.proc_status;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (info->efuse_map_size != adapter->hw_cfg_info.eeprom_size) {
|
|
PLTFM_MSG_ERR("[ERR]map size error\n");
|
|
return HALMAC_RET_EFUSE_SIZE_INCORRECT;
|
|
}
|
|
|
|
if ((info->efuse_map_size & 0xF) > 0) {
|
|
PLTFM_MSG_ERR("[ERR]not multiple of 16\n");
|
|
return HALMAC_RET_EFUSE_SIZE_INCORRECT;
|
|
}
|
|
|
|
if (info->efuse_mask_size != info->efuse_map_size >> 4) {
|
|
PLTFM_MSG_ERR("[ERR]mask size error\n");
|
|
return HALMAC_RET_EFUSE_SIZE_INCORRECT;
|
|
}
|
|
|
|
if (!info->efuse_map) {
|
|
PLTFM_MSG_ERR("[ERR]map is NULL\n");
|
|
return HALMAC_RET_NULL_POINTER;
|
|
}
|
|
|
|
if (!info->efuse_mask) {
|
|
PLTFM_MSG_ERR("[ERR]mask is NULL\n");
|
|
return HALMAC_RET_NULL_POINTER;
|
|
}
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_WARN("[WARN]Wait event(efuse)\n");
|
|
return HALMAC_RET_BUSY_STATE;
|
|
}
|
|
|
|
if (efuse_cmd_cnstr_state_88xx(adapter) != HALMAC_CMD_CNSTR_IDLE) {
|
|
PLTFM_MSG_WARN("[WARN]Not idle(efuse)\n");
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
status = switch_efuse_bank_88xx(adapter, HALMAC_EFUSE_BANK_WIFI);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
|
return status;
|
|
}
|
|
|
|
status = proc_pg_efuse_by_map_88xx(adapter, info, cfg);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]pg efuse\n");
|
|
return status;
|
|
}
|
|
|
|
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* mask_log_efuse_88xx() - mask logical efuse
|
|
* @adapter : the adapter of halmac
|
|
* @info : efuse map information
|
|
* Author : Soar
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
mask_log_efuse_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info)
|
|
{
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (info->efuse_map_size != adapter->hw_cfg_info.eeprom_size) {
|
|
PLTFM_MSG_ERR("[ERR]map size error\n");
|
|
return HALMAC_RET_EFUSE_SIZE_INCORRECT;
|
|
}
|
|
|
|
if ((info->efuse_map_size & 0xF) > 0) {
|
|
PLTFM_MSG_ERR("[ERR]not multiple of 16\n");
|
|
return HALMAC_RET_EFUSE_SIZE_INCORRECT;
|
|
}
|
|
|
|
if (info->efuse_mask_size != info->efuse_map_size >> 4) {
|
|
PLTFM_MSG_ERR("[ERR]mask size error\n");
|
|
return HALMAC_RET_EFUSE_SIZE_INCORRECT;
|
|
}
|
|
|
|
if (!info->efuse_map) {
|
|
PLTFM_MSG_ERR("[ERR]map is NULL\n");
|
|
return HALMAC_RET_NULL_POINTER;
|
|
}
|
|
|
|
if (!info->efuse_mask) {
|
|
PLTFM_MSG_ERR("[ERR]mask is NULL\n");
|
|
return HALMAC_RET_NULL_POINTER;
|
|
}
|
|
|
|
mask_eeprom_88xx(adapter, info);
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_cmd_construct_state
|
|
efuse_cmd_cnstr_state_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
return adapter->halmac_state.efuse_state.cmd_cnstr_state;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
switch_efuse_bank_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_efuse_bank bank)
|
|
{
|
|
u8 reg_value;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_BUSY) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
reg_value = HALMAC_REG_R8(REG_LDO_EFUSE_CTRL + 1);
|
|
|
|
if (bank == (reg_value & (BIT(0) | BIT(1))))
|
|
return HALMAC_RET_SUCCESS;
|
|
|
|
reg_value &= ~(BIT(0) | BIT(1));
|
|
reg_value |= bank;
|
|
HALMAC_REG_W8(REG_LDO_EFUSE_CTRL + 1, reg_value);
|
|
|
|
reg_value = HALMAC_REG_R8(REG_LDO_EFUSE_CTRL + 1);
|
|
if ((reg_value & (BIT(0) | BIT(1))) != bank)
|
|
return HALMAC_RET_SWITCH_EFUSE_BANK_FAIL;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
proc_dump_efuse_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_efuse_read_cfg cfg)
|
|
{
|
|
u32 h2c_init;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
enum halmac_cmd_process_status *proc_status;
|
|
|
|
proc_status = &adapter->halmac_state.efuse_state.proc_status;
|
|
|
|
*proc_status = HALMAC_CMD_PROCESS_SENDING;
|
|
|
|
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_H2C_SENT) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
if (cfg == HALMAC_EFUSE_R_AUTO) {
|
|
h2c_init = HALMAC_REG_R32(REG_H2C_PKT_READADDR);
|
|
if (adapter->halmac_state.dlfw_state == HALMAC_DLFW_NONE ||
|
|
h2c_init == 0)
|
|
status = dump_efuse_drv_88xx(adapter);
|
|
else
|
|
status = dump_efuse_fw_88xx(adapter);
|
|
} else if (cfg == HALMAC_EFUSE_R_FW) {
|
|
status = dump_efuse_fw_88xx(adapter);
|
|
} else {
|
|
status = dump_efuse_drv_88xx(adapter);
|
|
}
|
|
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]dump efsue drv/fw\n");
|
|
return status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
cnv_efuse_state_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_construct_state dest_state)
|
|
{
|
|
struct halmac_efuse_state *state = &adapter->halmac_state.efuse_state;
|
|
|
|
if (state->cmd_cnstr_state != HALMAC_CMD_CNSTR_IDLE &&
|
|
state->cmd_cnstr_state != HALMAC_CMD_CNSTR_BUSY &&
|
|
state->cmd_cnstr_state != HALMAC_CMD_CNSTR_H2C_SENT)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
if (state->cmd_cnstr_state == dest_state)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
|
|
if (dest_state == HALMAC_CMD_CNSTR_BUSY) {
|
|
if (state->cmd_cnstr_state == HALMAC_CMD_CNSTR_H2C_SENT)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
} else if (dest_state == HALMAC_CMD_CNSTR_H2C_SENT) {
|
|
if (state->cmd_cnstr_state == HALMAC_CMD_CNSTR_IDLE)
|
|
return HALMAC_RET_ERROR_STATE;
|
|
}
|
|
|
|
state->cmd_cnstr_state = dest_state;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
read_hw_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u32 size,
|
|
u8 *map)
|
|
{
|
|
u8 enable;
|
|
u32 value32;
|
|
u32 addr;
|
|
u32 tmp32;
|
|
u32 cnt;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
/* Read efuse no need 2.5V LDO */
|
|
enable = 0;
|
|
status = api->halmac_set_hw_value(adapter, HALMAC_HW_LDO25_EN, &enable);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]dis ldo25\n");
|
|
return status;
|
|
}
|
|
value32 = HALMAC_REG_R32(REG_EFUSE_CTRL);
|
|
|
|
for (addr = offset; addr < offset + size; addr++) {
|
|
value32 &= ~(BIT_MASK_EF_DATA | BITS_EF_ADDR);
|
|
value32 |= ((addr & BIT_MASK_EF_ADDR) << BIT_SHIFT_EF_ADDR);
|
|
HALMAC_REG_W32(REG_EFUSE_CTRL, value32 & (~BIT_EF_FLAG));
|
|
|
|
cnt = 1000000;
|
|
do {
|
|
PLTFM_DELAY_US(1);
|
|
tmp32 = HALMAC_REG_R32(REG_EFUSE_CTRL);
|
|
cnt--;
|
|
if (cnt == 0) {
|
|
PLTFM_MSG_ERR("[ERR]read\n");
|
|
return HALMAC_RET_EFUSE_R_FAIL;
|
|
}
|
|
} while ((tmp32 & BIT_EF_FLAG) == 0);
|
|
|
|
*(map + addr - offset) = (u8)(tmp32 & BIT_MASK_EF_DATA);
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
write_hw_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u8 value)
|
|
{
|
|
const u8 unlock_code = 0x69;
|
|
u8 value_read = 0;
|
|
u8 enable;
|
|
u32 value32;
|
|
u32 tmp32;
|
|
u32 cnt;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_mutex);
|
|
adapter->efuse_map_valid = 0;
|
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_mutex);
|
|
|
|
HALMAC_REG_W8(REG_PMC_DBG_CTRL2 + 3, unlock_code);
|
|
|
|
/* Enable 2.5V LDO */
|
|
enable = 1;
|
|
status = api->halmac_set_hw_value(adapter, HALMAC_HW_LDO25_EN, &enable);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]en ldo25\n");
|
|
return status;
|
|
}
|
|
|
|
value32 = HALMAC_REG_R32(REG_EFUSE_CTRL);
|
|
value32 &= ~(BIT_MASK_EF_DATA | BITS_EF_ADDR);
|
|
value32 = value32 | ((offset & BIT_MASK_EF_ADDR) << BIT_SHIFT_EF_ADDR) |
|
|
(value & BIT_MASK_EF_DATA);
|
|
HALMAC_REG_W32(REG_EFUSE_CTRL, value32 | BIT_EF_FLAG);
|
|
|
|
cnt = 1000000;
|
|
do {
|
|
PLTFM_DELAY_US(1);
|
|
tmp32 = HALMAC_REG_R32(REG_EFUSE_CTRL);
|
|
cnt--;
|
|
if (cnt == 0) {
|
|
PLTFM_MSG_ERR("[ERR]write!!\n");
|
|
return HALMAC_RET_EFUSE_W_FAIL;
|
|
}
|
|
} while (BIT_EF_FLAG == (tmp32 & BIT_EF_FLAG));
|
|
|
|
HALMAC_REG_W8(REG_PMC_DBG_CTRL2 + 3, 0x00);
|
|
|
|
/* Disable 2.5V LDO */
|
|
enable = 0;
|
|
status = api->halmac_set_hw_value(adapter, HALMAC_HW_LDO25_EN, &enable);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]dis ldo25\n");
|
|
return status;
|
|
}
|
|
|
|
if (adapter->efuse_auto_check_en == 1) {
|
|
if (read_hw_efuse_88xx(adapter, offset, 1, &value_read) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_EFUSE_R_FAIL;
|
|
if (value_read != value) {
|
|
PLTFM_MSG_ERR("[ERR]efuse compare\n");
|
|
return HALMAC_RET_EFUSE_W_FAIL;
|
|
}
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
eeprom_parser_88xx(struct halmac_adapter *adapter, u8 *phy_map, u8 *log_map)
|
|
{
|
|
u8 i;
|
|
u8 value8;
|
|
u8 blk_idx;
|
|
u8 word_en;
|
|
u8 valid;
|
|
u8 hdr;
|
|
u8 hdr2 = 0;
|
|
u32 eeprom_idx;
|
|
u32 efuse_idx = 0;
|
|
u32 prtct_efuse_size = adapter->hw_cfg_info.prtct_efuse_size;
|
|
struct halmac_hw_cfg_info *hw_info = &adapter->hw_cfg_info;
|
|
|
|
PLTFM_MEMSET(log_map, 0xFF, hw_info->eeprom_size);
|
|
|
|
do {
|
|
value8 = *(phy_map + efuse_idx);
|
|
hdr = value8;
|
|
|
|
if ((hdr & 0x1f) == 0x0f) {
|
|
efuse_idx++;
|
|
value8 = *(phy_map + efuse_idx);
|
|
hdr2 = value8;
|
|
if (hdr2 == 0xff)
|
|
break;
|
|
blk_idx = ((hdr2 & 0xF0) >> 1) | ((hdr >> 5) & 0x07);
|
|
word_en = hdr2 & 0x0F;
|
|
} else {
|
|
blk_idx = (hdr & 0xF0) >> 4;
|
|
word_en = hdr & 0x0F;
|
|
}
|
|
|
|
if (hdr == 0xff)
|
|
break;
|
|
|
|
efuse_idx++;
|
|
|
|
if (efuse_idx >= hw_info->efuse_size - prtct_efuse_size - 1)
|
|
return HALMAC_RET_EEPROM_PARSING_FAIL;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
valid = (u8)((~(word_en >> i)) & BIT(0));
|
|
if (valid == 1) {
|
|
eeprom_idx = (blk_idx << 3) + (i << 1);
|
|
|
|
if ((eeprom_idx + 1) > hw_info->eeprom_size) {
|
|
PLTFM_MSG_ERR("[ERR]efuse idx:0x%X\n",
|
|
efuse_idx - 1);
|
|
|
|
PLTFM_MSG_ERR("[ERR]read hdr:0x%X\n",
|
|
hdr);
|
|
|
|
PLTFM_MSG_ERR("[ERR]rad hdr2:0x%X\n",
|
|
hdr2);
|
|
|
|
return HALMAC_RET_EEPROM_PARSING_FAIL;
|
|
}
|
|
|
|
value8 = *(phy_map + efuse_idx);
|
|
*(log_map + eeprom_idx) = value8;
|
|
|
|
eeprom_idx++;
|
|
efuse_idx++;
|
|
|
|
if (efuse_idx > hw_info->efuse_size -
|
|
prtct_efuse_size - 1)
|
|
return HALMAC_RET_EEPROM_PARSING_FAIL;
|
|
|
|
value8 = *(phy_map + efuse_idx);
|
|
*(log_map + eeprom_idx) = value8;
|
|
|
|
efuse_idx++;
|
|
|
|
if (efuse_idx > hw_info->efuse_size -
|
|
prtct_efuse_size)
|
|
return HALMAC_RET_EEPROM_PARSING_FAIL;
|
|
}
|
|
}
|
|
} while (1);
|
|
|
|
adapter->efuse_end = efuse_idx;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
read_log_efuse_map_88xx(struct halmac_adapter *adapter, u8 *map)
|
|
{
|
|
u8 *local_map = NULL;
|
|
u32 efuse_size;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
if (adapter->efuse_map_valid == 0) {
|
|
efuse_size = adapter->hw_cfg_info.efuse_size;
|
|
|
|
local_map = (u8 *)PLTFM_MALLOC(efuse_size);
|
|
if (!local_map) {
|
|
PLTFM_MSG_ERR("[ERR]local map\n");
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
|
|
status = read_efuse_88xx(adapter, 0, efuse_size, local_map);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]read efuse\n");
|
|
PLTFM_FREE(local_map, efuse_size);
|
|
return status;
|
|
}
|
|
|
|
if (!adapter->efuse_map) {
|
|
adapter->efuse_map = (u8 *)PLTFM_MALLOC(efuse_size);
|
|
if (!adapter->efuse_map) {
|
|
PLTFM_MSG_ERR("[ERR]malloc adapter map\n");
|
|
PLTFM_FREE(local_map, efuse_size);
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
}
|
|
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_mutex);
|
|
PLTFM_MEMCPY(adapter->efuse_map, local_map, efuse_size);
|
|
adapter->efuse_map_valid = 1;
|
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_mutex);
|
|
|
|
PLTFM_FREE(local_map, efuse_size);
|
|
}
|
|
|
|
if (eeprom_parser_88xx(adapter, adapter->efuse_map, map) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_EEPROM_PARSING_FAIL;
|
|
|
|
return status;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
proc_pg_efuse_by_map_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info,
|
|
enum halmac_efuse_read_cfg cfg)
|
|
{
|
|
u8 *updated_mask = NULL;
|
|
u32 mask_size = adapter->hw_cfg_info.eeprom_size >> 4;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
updated_mask = (u8 *)PLTFM_MALLOC(mask_size);
|
|
if (!updated_mask) {
|
|
PLTFM_MSG_ERR("[ERR]malloc updated mask\n");
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
PLTFM_MEMSET(updated_mask, 0x00, mask_size);
|
|
|
|
status = update_eeprom_mask_88xx(adapter, info, updated_mask);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]update eeprom mask\n");
|
|
PLTFM_FREE(updated_mask, mask_size);
|
|
return status;
|
|
}
|
|
|
|
status = check_efuse_enough_88xx(adapter, info, updated_mask);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]chk efuse enough\n");
|
|
PLTFM_FREE(updated_mask, mask_size);
|
|
return status;
|
|
}
|
|
|
|
status = program_efuse_88xx(adapter, info, updated_mask);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]pg efuse\n");
|
|
PLTFM_FREE(updated_mask, mask_size);
|
|
return status;
|
|
}
|
|
|
|
PLTFM_FREE(updated_mask, mask_size);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
dump_efuse_drv_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
u8 *map = NULL;
|
|
u32 efuse_size = adapter->hw_cfg_info.efuse_size;
|
|
|
|
if (!adapter->efuse_map) {
|
|
adapter->efuse_map = (u8 *)PLTFM_MALLOC(efuse_size);
|
|
if (!adapter->efuse_map) {
|
|
PLTFM_MSG_ERR("[ERR]malloc adapter map!!\n");
|
|
reset_ofld_feature_88xx(adapter,
|
|
FEATURE_DUMP_PHY_EFUSE);
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
}
|
|
|
|
if (adapter->efuse_map_valid == 0) {
|
|
map = (u8 *)PLTFM_MALLOC(efuse_size);
|
|
if (!map) {
|
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
|
|
if (read_hw_efuse_88xx(adapter, 0, efuse_size, map) !=
|
|
HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(map, efuse_size);
|
|
return HALMAC_RET_EFUSE_R_FAIL;
|
|
}
|
|
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_mutex);
|
|
PLTFM_MEMCPY(adapter->efuse_map, map, efuse_size);
|
|
adapter->efuse_map_valid = 1;
|
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_mutex);
|
|
|
|
PLTFM_FREE(map, efuse_size);
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
dump_efuse_fw_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
|
|
u16 seq_num = 0;
|
|
u32 efuse_size = adapter->hw_cfg_info.efuse_size;
|
|
struct halmac_h2c_header_info hdr_info;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
hdr_info.sub_cmd_id = SUB_CMD_ID_DUMP_PHYSICAL_EFUSE;
|
|
hdr_info.content_size = 0;
|
|
hdr_info.ack = 1;
|
|
set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
|
|
|
|
adapter->halmac_state.efuse_state.seq_num = seq_num;
|
|
|
|
if (!adapter->efuse_map) {
|
|
adapter->efuse_map = (u8 *)PLTFM_MALLOC(efuse_size);
|
|
if (!adapter->efuse_map) {
|
|
PLTFM_MSG_ERR("[ERR]malloc adapter map\n");
|
|
reset_ofld_feature_88xx(adapter,
|
|
FEATURE_DUMP_PHY_EFUSE);
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
}
|
|
|
|
if (adapter->efuse_map_valid == 0) {
|
|
status = send_h2c_pkt_88xx(adapter, h2c_buf);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]send h2c pkt\n");
|
|
reset_ofld_feature_88xx(adapter,
|
|
FEATURE_DUMP_PHY_EFUSE);
|
|
return status;
|
|
}
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
proc_write_log_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u8 value)
|
|
{
|
|
u8 byte1;
|
|
u8 byte2;
|
|
u8 blk;
|
|
u8 blk_idx;
|
|
u8 hdr;
|
|
u8 hdr2;
|
|
u8 *map = NULL;
|
|
u32 eeprom_size = adapter->hw_cfg_info.eeprom_size;
|
|
u32 prtct_efuse_size = adapter->hw_cfg_info.prtct_efuse_size;
|
|
u32 end;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
map = (u8 *)PLTFM_MALLOC(eeprom_size);
|
|
if (!map) {
|
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
PLTFM_MEMSET(map, 0xFF, eeprom_size);
|
|
|
|
status = read_log_efuse_map_88xx(adapter, map);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]read logical efuse\n");
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return status;
|
|
}
|
|
|
|
if (*(map + offset) != value) {
|
|
end = adapter->efuse_end;
|
|
blk = (u8)(offset >> 3);
|
|
blk_idx = (u8)((offset & (8 - 1)) >> 1);
|
|
|
|
if (offset > 0x7f) {
|
|
hdr = (((blk & 0x07) << 5) & 0xE0) | 0x0F;
|
|
hdr2 = (u8)(((blk & 0x78) << 1) +
|
|
((0x1 << blk_idx) ^ 0x0F));
|
|
} else {
|
|
hdr = (u8)((blk << 4) + ((0x01 << blk_idx) ^ 0x0F));
|
|
}
|
|
|
|
if ((offset & 1) == 0) {
|
|
byte1 = value;
|
|
byte2 = *(map + offset + 1);
|
|
} else {
|
|
byte1 = *(map + offset - 1);
|
|
byte2 = value;
|
|
}
|
|
|
|
if (offset > 0x7f) {
|
|
if (adapter->hw_cfg_info.efuse_size <=
|
|
4 + prtct_efuse_size + end) {
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return HALMAC_RET_EFUSE_NOT_ENOUGH;
|
|
}
|
|
|
|
status = write_hw_efuse_88xx(adapter, end, hdr);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return status;
|
|
}
|
|
|
|
status = write_hw_efuse_88xx(adapter, end + 1, hdr2);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return status;
|
|
}
|
|
|
|
status = write_hw_efuse_88xx(adapter, end + 2, byte1);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return status;
|
|
}
|
|
|
|
status = write_hw_efuse_88xx(adapter, end + 3, byte2);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return status;
|
|
}
|
|
} else {
|
|
if (adapter->hw_cfg_info.efuse_size <=
|
|
3 + prtct_efuse_size + end) {
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return HALMAC_RET_EFUSE_NOT_ENOUGH;
|
|
}
|
|
|
|
status = write_hw_efuse_88xx(adapter, end, hdr);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return status;
|
|
}
|
|
|
|
status = write_hw_efuse_88xx(adapter, end + 1, byte1);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return status;
|
|
}
|
|
|
|
status = write_hw_efuse_88xx(adapter, end + 2, byte2);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return status;
|
|
}
|
|
}
|
|
}
|
|
|
|
PLTFM_FREE(map, eeprom_size);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
read_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u32 size, u8 *map)
|
|
{
|
|
if (!map) {
|
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
|
return HALMAC_RET_NULL_POINTER;
|
|
}
|
|
|
|
if (adapter->efuse_map_valid == 1) {
|
|
PLTFM_MEMCPY(map, adapter->efuse_map + offset, size);
|
|
} else {
|
|
if (read_hw_efuse_88xx(adapter, offset, size, map) !=
|
|
HALMAC_RET_SUCCESS)
|
|
return HALMAC_RET_EFUSE_R_FAIL;
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
update_eeprom_mask_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info, u8 *updated_mask)
|
|
{
|
|
u8 *map = NULL;
|
|
u8 clr_bit = 0;
|
|
u32 eeprom_size = adapter->hw_cfg_info.eeprom_size;
|
|
u8 *map_pg;
|
|
u8 *efuse_mask;
|
|
u16 i;
|
|
u16 j;
|
|
u16 map_offset;
|
|
u16 mask_offset;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
map = (u8 *)PLTFM_MALLOC(eeprom_size);
|
|
if (!map) {
|
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
PLTFM_MEMSET(map, 0xFF, eeprom_size);
|
|
|
|
PLTFM_MEMSET(updated_mask, 0x00, info->efuse_mask_size);
|
|
|
|
status = read_log_efuse_map_88xx(adapter, map);
|
|
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return status;
|
|
}
|
|
|
|
map_pg = info->efuse_map;
|
|
efuse_mask = info->efuse_mask;
|
|
|
|
for (i = 0; i < info->efuse_mask_size; i++)
|
|
*(updated_mask + i) = *(efuse_mask + i);
|
|
|
|
for (i = 0; i < info->efuse_map_size; i += 16) {
|
|
for (j = 0; j < 16; j += 2) {
|
|
map_offset = i + j;
|
|
mask_offset = i >> 4;
|
|
if (*(u16 *)(map_pg + map_offset) ==
|
|
*(u16 *)(map + map_offset)) {
|
|
switch (j) {
|
|
case 0:
|
|
clr_bit = BIT(4);
|
|
break;
|
|
case 2:
|
|
clr_bit = BIT(5);
|
|
break;
|
|
case 4:
|
|
clr_bit = BIT(6);
|
|
break;
|
|
case 6:
|
|
clr_bit = BIT(7);
|
|
break;
|
|
case 8:
|
|
clr_bit = BIT(0);
|
|
break;
|
|
case 10:
|
|
clr_bit = BIT(1);
|
|
break;
|
|
case 12:
|
|
clr_bit = BIT(2);
|
|
break;
|
|
case 14:
|
|
clr_bit = BIT(3);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
*(updated_mask + mask_offset) &= ~clr_bit;
|
|
}
|
|
}
|
|
}
|
|
|
|
PLTFM_FREE(map, eeprom_size);
|
|
|
|
return status;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
check_efuse_enough_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info, u8 *updated_mask)
|
|
{
|
|
u8 pre_word_en;
|
|
u16 i;
|
|
u16 j;
|
|
u32 eeprom_offset;
|
|
u32 pg_num = 0;
|
|
|
|
for (i = 0; i < info->efuse_map_size; i = i + 8) {
|
|
eeprom_offset = i;
|
|
|
|
if ((eeprom_offset & 7) > 0)
|
|
pre_word_en = (*(updated_mask + (i >> 4)) & 0x0F);
|
|
else
|
|
pre_word_en = (*(updated_mask + (i >> 4)) >> 4);
|
|
|
|
if (pre_word_en > 0) {
|
|
if (eeprom_offset > 0x7f) {
|
|
pg_num += 2;
|
|
for (j = 0; j < 4; j++) {
|
|
if (((pre_word_en >> j) & 0x1) > 0)
|
|
pg_num += 2;
|
|
}
|
|
} else {
|
|
pg_num++;
|
|
for (j = 0; j < 4; j++) {
|
|
if (((pre_word_en >> j) & 0x1) > 0)
|
|
pg_num += 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (adapter->hw_cfg_info.efuse_size <=
|
|
(pg_num + adapter->hw_cfg_info.prtct_efuse_size +
|
|
adapter->efuse_end))
|
|
return HALMAC_RET_EFUSE_NOT_ENOUGH;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
pg_extend_efuse_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info, u8 word_en,
|
|
u8 pre_word_en, u32 eeprom_offset)
|
|
{
|
|
u8 blk;
|
|
u8 hdr;
|
|
u8 hdr2;
|
|
u16 i;
|
|
u32 efuse_end;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
efuse_end = adapter->efuse_end;
|
|
|
|
blk = (u8)(eeprom_offset >> 3);
|
|
hdr = (((blk & 0x07) << 5) & 0xE0) | 0x0F;
|
|
hdr2 = (u8)(((blk & 0x78) << 1) + word_en);
|
|
|
|
status = write_hw_efuse_88xx(adapter, efuse_end, hdr);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]write efuse\n");
|
|
return status;
|
|
}
|
|
|
|
status = write_hw_efuse_88xx(adapter, efuse_end + 1, hdr2);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]write efuse(+1)\n");
|
|
return status;
|
|
}
|
|
|
|
efuse_end = efuse_end + 2;
|
|
for (i = 0; i < 4; i++) {
|
|
if (((pre_word_en >> i) & 0x1) > 0) {
|
|
status = write_hw_efuse_88xx(adapter, efuse_end,
|
|
*(info->efuse_map +
|
|
eeprom_offset +
|
|
(i << 1)));
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]write efuse(<<1)\n");
|
|
return status;
|
|
}
|
|
|
|
status = write_hw_efuse_88xx(adapter, efuse_end + 1,
|
|
*(info->efuse_map +
|
|
eeprom_offset + (i << 1)
|
|
+ 1));
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]write efuse(<<1)+1\n");
|
|
return status;
|
|
}
|
|
efuse_end = efuse_end + 2;
|
|
}
|
|
}
|
|
adapter->efuse_end = efuse_end;
|
|
return status;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
proc_pg_efuse_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info, u8 word_en,
|
|
u8 pre_word_en, u32 eeprom_offset)
|
|
{
|
|
u8 blk;
|
|
u8 hdr;
|
|
u16 i;
|
|
u32 efuse_end;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
efuse_end = adapter->efuse_end;
|
|
|
|
blk = (u8)(eeprom_offset >> 3);
|
|
hdr = (u8)((blk << 4) + word_en);
|
|
|
|
status = write_hw_efuse_88xx(adapter, efuse_end, hdr);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]write efuse\n");
|
|
return status;
|
|
}
|
|
efuse_end = efuse_end + 1;
|
|
for (i = 0; i < 4; i++) {
|
|
if (((pre_word_en >> i) & 0x1) > 0) {
|
|
status = write_hw_efuse_88xx(adapter, efuse_end,
|
|
*(info->efuse_map +
|
|
eeprom_offset +
|
|
(i << 1)));
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]write efuse(<<1)\n");
|
|
return status;
|
|
}
|
|
status = write_hw_efuse_88xx(adapter, efuse_end + 1,
|
|
*(info->efuse_map +
|
|
eeprom_offset + (i << 1)
|
|
+ 1));
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]write efuse(<<1)+1\n");
|
|
return status;
|
|
}
|
|
efuse_end = efuse_end + 2;
|
|
}
|
|
}
|
|
adapter->efuse_end = efuse_end;
|
|
return status;
|
|
}
|
|
|
|
static enum halmac_ret_status
|
|
program_efuse_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info, u8 *updated_mask)
|
|
{
|
|
u8 pre_word_en;
|
|
u8 word_en;
|
|
u16 i;
|
|
u32 eeprom_offset;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
for (i = 0; i < info->efuse_map_size; i = i + 8) {
|
|
eeprom_offset = i;
|
|
|
|
if (((eeprom_offset >> 3) & 1) > 0) {
|
|
pre_word_en = (*(updated_mask + (i >> 4)) & 0x0F);
|
|
word_en = pre_word_en ^ 0x0F;
|
|
} else {
|
|
pre_word_en = (*(updated_mask + (i >> 4)) >> 4);
|
|
word_en = pre_word_en ^ 0x0F;
|
|
}
|
|
|
|
if (pre_word_en > 0) {
|
|
if (eeprom_offset > 0x7f) {
|
|
status = pg_extend_efuse_88xx(adapter, info,
|
|
word_en,
|
|
pre_word_en,
|
|
eeprom_offset);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]extend efuse\n");
|
|
return status;
|
|
}
|
|
} else {
|
|
status = proc_pg_efuse_88xx(adapter, info,
|
|
word_en,
|
|
pre_word_en,
|
|
eeprom_offset);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]extend efuse");
|
|
return status;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static void
|
|
mask_eeprom_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_pg_efuse_info *info)
|
|
{
|
|
u8 pre_word_en;
|
|
u8 *updated_mask;
|
|
u8 *efuse_map;
|
|
u16 i;
|
|
u16 j;
|
|
u32 offset;
|
|
|
|
updated_mask = info->efuse_mask;
|
|
efuse_map = info->efuse_map;
|
|
|
|
for (i = 0; i < info->efuse_map_size; i = i + 8) {
|
|
offset = i;
|
|
|
|
if (((offset >> 3) & 1) > 0)
|
|
pre_word_en = (*(updated_mask + (i >> 4)) & 0x0F);
|
|
else
|
|
pre_word_en = (*(updated_mask + (i >> 4)) >> 4);
|
|
|
|
for (j = 0; j < 4; j++) {
|
|
if (((pre_word_en >> j) & 0x1) == 0) {
|
|
*(efuse_map + offset + (j << 1)) = 0xFF;
|
|
*(efuse_map + offset + (j << 1) + 1) = 0xFF;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
get_efuse_data_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
u8 seg_id;
|
|
u8 seg_size;
|
|
u8 seq_num;
|
|
u8 fw_rc;
|
|
u8 *map = NULL;
|
|
u32 eeprom_size = adapter->hw_cfg_info.eeprom_size;
|
|
struct halmac_efuse_state *state = &adapter->halmac_state.efuse_state;
|
|
enum halmac_cmd_process_status proc_status;
|
|
|
|
seq_num = (u8)EFUSE_DATA_GET_H2C_SEQ(buf);
|
|
PLTFM_MSG_TRACE("[TRACE]Seq num : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
if (seq_num != state->seq_num) {
|
|
PLTFM_MSG_ERR("[ERR]Seq num mismatch : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_ERR("[ERR]not cmd sending\n");
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
seg_id = (u8)EFUSE_DATA_GET_SEGMENT_ID(buf);
|
|
seg_size = (u8)EFUSE_DATA_GET_SEGMENT_SIZE(buf);
|
|
if (seg_id == 0)
|
|
adapter->efuse_seg_size = seg_size;
|
|
|
|
map = (u8 *)PLTFM_MALLOC(eeprom_size);
|
|
if (!map) {
|
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
PLTFM_MEMSET(map, 0xFF, eeprom_size);
|
|
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_mutex);
|
|
PLTFM_MEMCPY(adapter->efuse_map + seg_id * adapter->efuse_seg_size,
|
|
buf + C2H_DATA_OFFSET_88XX, seg_size);
|
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_mutex);
|
|
|
|
if (EFUSE_DATA_GET_END_SEGMENT(buf) == 0) {
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
fw_rc = state->fw_rc;
|
|
|
|
if ((enum halmac_h2c_return_code)fw_rc == HALMAC_H2C_RETURN_SUCCESS) {
|
|
proc_status = HALMAC_CMD_PROCESS_DONE;
|
|
state->proc_status = proc_status;
|
|
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_mutex);
|
|
adapter->efuse_map_valid = 1;
|
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_mutex);
|
|
|
|
if (adapter->evnt.phy_efuse_map == 1) {
|
|
PLTFM_EVENT_SIG(FEATURE_DUMP_PHY_EFUSE,
|
|
proc_status, adapter->efuse_map,
|
|
adapter->hw_cfg_info.efuse_size);
|
|
adapter->evnt.phy_efuse_map = 0;
|
|
}
|
|
|
|
if (adapter->evnt.log_efuse_map == 1) {
|
|
if (eeprom_parser_88xx(adapter, adapter->efuse_map,
|
|
map) != HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return HALMAC_RET_EEPROM_PARSING_FAIL;
|
|
}
|
|
PLTFM_EVENT_SIG(FEATURE_DUMP_LOG_EFUSE, proc_status,
|
|
map, eeprom_size);
|
|
adapter->evnt.log_efuse_map = 0;
|
|
}
|
|
} else {
|
|
proc_status = HALMAC_CMD_PROCESS_ERROR;
|
|
state->proc_status = proc_status;
|
|
|
|
if (adapter->evnt.phy_efuse_map == 1) {
|
|
PLTFM_EVENT_SIG(FEATURE_DUMP_PHY_EFUSE, proc_status,
|
|
&state->fw_rc, 1);
|
|
adapter->evnt.phy_efuse_map = 0;
|
|
}
|
|
|
|
if (adapter->evnt.log_efuse_map == 1) {
|
|
PLTFM_EVENT_SIG(FEATURE_DUMP_LOG_EFUSE, proc_status,
|
|
&state->fw_rc, 1);
|
|
adapter->evnt.log_efuse_map = 0;
|
|
}
|
|
}
|
|
|
|
PLTFM_FREE(map, eeprom_size);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
get_dump_phy_efuse_status_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_process_status *proc_status,
|
|
u8 *data, u32 *size)
|
|
{
|
|
u8 *map = NULL;
|
|
u32 efuse_size = adapter->hw_cfg_info.efuse_size;
|
|
u32 prtct_efuse_size = adapter->hw_cfg_info.prtct_efuse_size;
|
|
struct halmac_efuse_state *state = &adapter->halmac_state.efuse_state;
|
|
|
|
*proc_status = state->proc_status;
|
|
|
|
if (!data)
|
|
return HALMAC_RET_NULL_POINTER;
|
|
|
|
if (!size)
|
|
return HALMAC_RET_NULL_POINTER;
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_DONE) {
|
|
if (*size < efuse_size) {
|
|
*size = efuse_size;
|
|
return HALMAC_RET_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
*size = efuse_size;
|
|
|
|
map = (u8 *)PLTFM_MALLOC(efuse_size);
|
|
if (!map) {
|
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
PLTFM_MEMSET(map, 0xFF, efuse_size);
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_mutex);
|
|
PLTFM_MEMCPY(map, adapter->efuse_map,
|
|
efuse_size - prtct_efuse_size);
|
|
PLTFM_MEMCPY(map + efuse_size - prtct_efuse_size +
|
|
RSVD_CS_EFUSE_SIZE,
|
|
adapter->efuse_map + efuse_size -
|
|
prtct_efuse_size + RSVD_CS_EFUSE_SIZE,
|
|
prtct_efuse_size - RSVD_EFUSE_SIZE -
|
|
RSVD_CS_EFUSE_SIZE);
|
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_mutex);
|
|
|
|
PLTFM_MEMCPY(data, map, *size);
|
|
|
|
PLTFM_FREE(map, efuse_size);
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
get_dump_log_efuse_status_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_cmd_process_status *proc_status,
|
|
u8 *data, u32 *size)
|
|
{
|
|
u8 *map = NULL;
|
|
u32 eeprom_size = adapter->hw_cfg_info.eeprom_size;
|
|
struct halmac_efuse_state *state = &adapter->halmac_state.efuse_state;
|
|
|
|
*proc_status = state->proc_status;
|
|
|
|
if (!data)
|
|
return HALMAC_RET_NULL_POINTER;
|
|
|
|
if (!size)
|
|
return HALMAC_RET_NULL_POINTER;
|
|
|
|
if (*proc_status == HALMAC_CMD_PROCESS_DONE) {
|
|
if (*size < eeprom_size) {
|
|
*size = eeprom_size;
|
|
return HALMAC_RET_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
*size = eeprom_size;
|
|
|
|
map = (u8 *)PLTFM_MALLOC(eeprom_size);
|
|
if (!map) {
|
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
|
return HALMAC_RET_MALLOC_FAIL;
|
|
}
|
|
PLTFM_MEMSET(map, 0xFF, eeprom_size);
|
|
|
|
if (eeprom_parser_88xx(adapter, adapter->efuse_map, map) !=
|
|
HALMAC_RET_SUCCESS) {
|
|
PLTFM_FREE(map, eeprom_size);
|
|
return HALMAC_RET_EEPROM_PARSING_FAIL;
|
|
}
|
|
|
|
PLTFM_MEMCPY(data, map, *size);
|
|
|
|
PLTFM_FREE(map, eeprom_size);
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
get_h2c_ack_phy_efuse_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
u8 seq_num = 0;
|
|
u8 fw_rc;
|
|
struct halmac_efuse_state *state = &adapter->halmac_state.efuse_state;
|
|
|
|
seq_num = (u8)H2C_ACK_HDR_GET_H2C_SEQ(buf);
|
|
PLTFM_MSG_TRACE("[TRACE]Seq num : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
if (seq_num != state->seq_num) {
|
|
PLTFM_MSG_ERR("[ERR]Seq num mismatch : h2c->%d c2h->%d\n",
|
|
state->seq_num, seq_num);
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
|
|
PLTFM_MSG_ERR("[ERR]not cmd sending\n");
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
|
|
state->fw_rc = fw_rc;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
u32
|
|
get_rsvd_efuse_size_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
return adapter->hw_cfg_info.prtct_efuse_size;
|
|
}
|
|
|
|
#endif /* HALMAC_88XX_SUPPORT */
|