/******************************************************************************
|
*
|
* Copyright(c) 2019 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 "efuse.h"
|
#include "mac_priv.h"
|
|
static struct efuse_info_item offset_pcie = {
|
0x400, /* mac_addr */
|
0, /* pid */
|
0x408, /* did */
|
0x406, /* vid */
|
0x40A, /* svid */
|
0x40C, /* smid */
|
};
|
|
static struct efuse_info_item offset_usb_8852a = {
|
0x438, /* mac_addr */
|
0x432, /* pid */
|
0, /* did */
|
0x430, /* vid */
|
0, /* svid */
|
0, /* smid */
|
};
|
|
static struct efuse_info_item offset_usb_8852b = {
|
0x488, /* mac_addr */
|
0x482, /* pid */
|
0, /* did */
|
0x480, /* vid */
|
0, /* svid */
|
0, /* smid */
|
};
|
|
static struct efuse_info_item offset_usb_8851b = {
|
0x488, /* mac_addr */
|
0x482, /* pid */
|
0, /* did */
|
0x480, /* vid */
|
0, /* svid */
|
0, /* smid */
|
};
|
|
static struct efuse_info_item offset_usb_8852bt = {
|
0x488, /* mac_addr */
|
0x482, /* pid */
|
0, /* did */
|
0x480, /* vid */
|
0, /* svid */
|
0, /* smid */
|
};
|
|
static struct efuse_info_item offset_sdio = {
|
0x41A, /* mac_addr */
|
0, /* pid */
|
0, /* did */
|
0, /* vid */
|
0, /* svid */
|
0, /* smid */
|
};
|
|
static struct efuse_info_item def_val_pcie = {
|
0x0, /* mac_addr */
|
0, /* pid */
|
0x52, /* did */
|
0xEC, /* vid */
|
0xEC, /* svid */
|
0x52, /* smid */
|
};
|
|
static struct efuse_info_item def_val_usb_8852a = {
|
0x0, /* mac_addr */
|
0x5A, /* pid */
|
0, /* did */
|
0xDA, /* vid */
|
0, /* svid */
|
0, /* smid */
|
};
|
|
static struct efuse_info_item def_val_usb_8852b = {
|
0x0, /* mac_addr */
|
0x5B, /* pid */
|
0, /* did */
|
0xDA, /* vid */
|
0, /* svid */
|
0, /* smid */
|
};
|
|
static struct efuse_info_item def_val_usb_8851b = {
|
0x0, /* mac_addr */
|
0x5B, /* pid */
|
0, /* did */
|
0xDA, /* vid */
|
0, /* svid */
|
0, /* smid */
|
};
|
|
static struct efuse_info_item def_val_usb_8852bt = {
|
0x0, /* mac_addr */
|
0x5B, /* pid */
|
0, /* did */
|
0xDA, /* vid */
|
0, /* svid */
|
0, /* smid */
|
};
|
|
static struct efuse_info_item def_val_sdio = {
|
0x0, /* mac_addr */
|
0, /* pid */
|
0, /* did */
|
0, /* vid */
|
0, /* svid */
|
0, /* smid */
|
};
|
|
static struct efuse_info_item len_pcie = {
|
6, /* mac_addr */
|
0, /* pid */
|
2, /* did */
|
2, /* vid */
|
2, /* svid */
|
2, /* smid */
|
};
|
|
static struct efuse_info_item len_usb = {
|
6, /* mac_addr */
|
2, /* pid */
|
0, /* did */
|
2, /* vid */
|
0, /* svid */
|
0, /* smid */
|
};
|
|
static struct efuse_info_item len_sdio = {
|
6, /* mac_addr */
|
0, /* pid */
|
0, /* did */
|
0, /* vid */
|
0, /* svid */
|
0, /* smid */
|
};
|
|
static struct efuse_info efuse_info_pcie = {
|
&offset_pcie, /* offset */
|
&def_val_pcie, /* def_val */
|
&len_pcie, /* len */
|
};
|
|
static struct efuse_info efuse_info_usb_8852a = {
|
&offset_usb_8852a, /* offset */
|
&def_val_usb_8852a, /* def_val */
|
&len_usb, /* len */
|
};
|
|
static struct efuse_info efuse_info_usb_8852b = {
|
&offset_usb_8852b, /* offset */
|
&def_val_usb_8852b, /* def_val */
|
&len_usb, /* len */
|
};
|
|
static struct efuse_info efuse_info_usb_8851b = {
|
&offset_usb_8851b, /* offset */
|
&def_val_usb_8851b, /* def_val */
|
&len_usb, /* len */
|
};
|
|
static struct efuse_info efuse_info_usb_8852bt = {
|
&offset_usb_8852bt, /* offset */
|
&def_val_usb_8852bt, /* def_val */
|
&len_usb, /* len */
|
};
|
|
static struct efuse_info efuse_info_sdio = {
|
&offset_sdio, /* offset */
|
&def_val_sdio, /* def_val */
|
&len_sdio, /* len */
|
};
|
|
static u32 efuse_map_init(struct mac_ax_adapter *adapter,
|
enum efuse_map_sel map_sel);
|
static u32 efuse_fwcmd_ck(struct mac_ax_adapter *adapter);
|
static u32 efuse_proc_ck(struct mac_ax_adapter *adapter);
|
static u32 cnv_efuse_state(struct mac_ax_adapter *adapter, u8 dest_state);
|
static u32 proc_dump_efuse(struct mac_ax_adapter *adapter,
|
enum mac_ax_efuse_read_cfg cfg);
|
static u32 read_hw_efuse(struct mac_ax_adapter *adapter, u32 offset, u32 size,
|
u8 *map);
|
static u32 write_hw_efuse(struct mac_ax_adapter *adapter, u32 offset, u8 value);
|
static u32 cmp_hw_efuse(struct mac_ax_adapter *adapter, u32 offset, u16 val);
|
static u32 eeprom_parser(struct mac_ax_adapter *adapter, u8 *phy_map,
|
u8 *log_map, enum mac_ax_efuse_parser_cfg cfg);
|
static u32 read_log_efuse_map(struct mac_ax_adapter *adapter, u8 *map,
|
u32 log_efuse_size);
|
static u32 proc_pg_efuse_by_map(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info,
|
enum mac_ax_efuse_read_cfg cfg);
|
static u32 dump_efuse_drv(struct mac_ax_adapter *adapter);
|
static u32 dump_efuse_fw(struct mac_ax_adapter *adapter);
|
static u32 proc_write_log_efuse(struct mac_ax_adapter *adapter, u32 offset,
|
u8 value);
|
static u32 read_efuse(struct mac_ax_adapter *adapter, u32 offset, u32 size,
|
u8 *map);
|
static u32 update_eeprom_mask(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info,
|
u8 *updated_mask, bool pg_sim);
|
static u32 check_efuse_enough(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info,
|
u8 *updated_mask);
|
static u32 proc_pg_efuse(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info, u8 word_en,
|
u8 pre_word_en, u32 eeprom_offset, bool pg_sim);
|
static u32 program_efuse(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info, u8 *updated_mask,
|
bool pg_sim);
|
static void mask_eeprom(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info);
|
static u32 query_status_map(struct mac_ax_adapter *adapter,
|
enum mac_ax_efuse_feature_id feature_id,
|
u8 *map, bool is_limit);
|
static u32 adjust_mask(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info);
|
static u32 compare_info_length(struct efuse_info *info,
|
enum rtw_efuse_info id, u32 length);
|
static u32 set_check_sum_val(struct mac_ax_adapter *adapter,
|
u8 *map, u16 value);
|
static void cal_check_sum(struct mac_ax_adapter *adapter,
|
u16 *chksum);
|
static u32 compare_version(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info, u32 ver_len);
|
static u32 read_hw_efuse_dav(struct mac_ax_adapter *adapter, u32 offset, u32 size,
|
u8 *map);
|
static u32 write_hw_efuse_dav(struct mac_ax_adapter *adapter, u32 offset,
|
u8 value);
|
static void switch_dv(struct mac_ax_adapter *adapter, enum rtw_dv_sel);
|
static void free_map_mask(struct mac_ax_adapter *adapter, u32 ver_len,
|
struct mac_ax_pg_efuse_info *info_DAV,
|
struct mac_ax_pg_efuse_info *info_DDV);
|
static u32 proc_dump_hidden(struct mac_ax_adapter *adapter);
|
|
u32 mac_dump_efuse_map_wl_plus(struct mac_ax_adapter *adapter,
|
enum mac_ax_efuse_read_cfg cfg, u8 *efuse_map)
|
{
|
u32 ret = 0;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
u8 chip_id = hw_info->chip_id;
|
bool dav_exist = (hw_info->dav_full_efuse_size == 0) ? false : true;
|
|
switch (chip_id) {
|
case MAC_AX_CHIP_ID_8852A:
|
ret = mac_dump_efuse_map_wl(adapter, cfg, efuse_map);
|
break;
|
default:
|
ret = mac_dump_efuse_map_wl(adapter, cfg, efuse_map);
|
if (ret)
|
return ret;
|
if (dav_exist) {
|
switch_dv(adapter, DAV);
|
ret = mac_dump_efuse_map_wl(adapter, cfg, efuse_map + hw_info->efuse_size);
|
switch_dv(adapter, DDV);
|
}
|
break;
|
}
|
|
if (ret)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_dump_efuse_map_wl(struct mac_ax_adapter *adapter,
|
enum mac_ax_efuse_read_cfg cfg, u8 *efuse_map)
|
{
|
u32 ret, stat;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
enum rtw_dv_sel dv_sel = adapter->efuse_param.dv_sel;
|
|
if (cfg == MAC_AX_EFUSE_R_FW && adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
PLTFM_MSG_TRACE("[TRACE]cfg = %d\n", cfg);
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_PHY);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
if (dv_sel == DAV)
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_DAV);
|
else
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_WL);
|
if (ret != 0)
|
return ret;
|
|
ret = proc_dump_efuse(adapter, cfg);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]dump efuse!!\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
query_status_map(adapter, MAC_AX_DUMP_PHYSICAL_EFUSE, efuse_map, 0);
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != 0)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_dump_efuse_map_bt(struct mac_ax_adapter *adapter,
|
enum mac_ax_efuse_read_cfg cfg, u8 *efuse_map)
|
{
|
u32 ret, stat;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
|
if (cfg == MAC_AX_EFUSE_R_FW && adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
PLTFM_MSG_TRACE("[TRACE]cfg = %d\n", cfg);
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_PHY);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_BT);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_BT);
|
if (ret != 0)
|
return ret;
|
|
ret = proc_dump_efuse(adapter, cfg);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]dump efuse!!\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
query_status_map(adapter, MAC_AX_DUMP_PHYSICAL_EFUSE, efuse_map, 0);
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != 0)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_write_efuse_plus(struct mac_ax_adapter *adapter, u32 addr, u8 val,
|
enum mac_ax_efuse_bank bank)
|
{
|
u32 ret = 0;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
u8 chip_id = hw_info->chip_id;
|
u32 efuse_size = hw_info->wl_efuse_size;
|
bool dav_exist = (hw_info->dav_full_efuse_size == 0) ? false : true;
|
|
switch (bank) {
|
case MAC_AX_EFUSE_BANK_WIFI:
|
if (chip_id == MAC_AX_CHIP_ID_8852A) {
|
ret = mac_write_efuse(adapter, addr, val, bank);
|
} else {
|
if (addr < efuse_size) {
|
ret = mac_write_efuse(adapter, addr, val, bank);
|
} else {
|
if (dav_exist) {
|
switch_dv(adapter, DAV);
|
ret = mac_write_efuse(adapter, addr -
|
efuse_size, val, bank);
|
switch_dv(adapter, DDV);
|
}
|
}
|
}
|
break;
|
case MAC_AX_EFUSE_BANK_BT:
|
ret = mac_write_efuse(adapter, addr, val, bank);
|
break;
|
default:
|
break;
|
}
|
if (ret)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_write_efuse(struct mac_ax_adapter *adapter, u32 addr, u8 val,
|
enum mac_ax_efuse_bank bank)
|
{
|
u32 ret, stat, efuse_size = 0;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
bool OTP_test = adapter->efuse_param.OTP_test;
|
|
if (bank == MAC_AX_EFUSE_BANK_WIFI) {
|
if (OTP_test)
|
efuse_size = OTP_PHY_SIZE;
|
else
|
efuse_size = adapter->hw_info->wl_efuse_size;
|
} else if (bank == MAC_AX_EFUSE_BANK_BT) {
|
efuse_size = adapter->hw_info->bt_efuse_size;
|
} else {
|
return MACEFUSEBANK;
|
}
|
|
if (addr >= efuse_size) {
|
PLTFM_MSG_ERR("[ERR]Offset is too large\n");
|
return MACEFUSESIZE;
|
}
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_PHY);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, bank);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
p_ops->enable_efuse_sw_pwr_cut(adapter, 1);
|
ret = write_hw_efuse(adapter, addr, val);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]write physical efuse\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
p_ops->disable_efuse_sw_pwr_cut(adapter, 1);
|
|
if (bank == MAC_AX_EFUSE_BANK_BT) {
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
}
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != 0)
|
return ret;
|
|
return ret;
|
}
|
|
u32 mac_read_efuse_plus(struct mac_ax_adapter *adapter, u32 addr, u32 size,
|
u8 *val, enum mac_ax_efuse_bank bank)
|
{
|
u32 ret = 0;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
u8 chip_id = hw_info->chip_id;
|
u32 efuse_size = hw_info->wl_efuse_size;
|
u32 size1, size2;
|
bool dav_exist = (hw_info->dav_full_efuse_size == 0) ? false : true;
|
|
switch (bank) {
|
case MAC_AX_EFUSE_BANK_WIFI:
|
if (chip_id == MAC_AX_CHIP_ID_8852A) {
|
ret = mac_read_efuse(adapter, addr, size, val, bank);
|
} else {
|
if (addr < efuse_size && addr + size <= efuse_size) {
|
ret = mac_read_efuse(adapter, addr, size,
|
val, bank);
|
} else if (addr >= efuse_size) {
|
if (dav_exist) {
|
switch_dv(adapter, DAV);
|
ret = mac_read_efuse(adapter, addr - efuse_size,
|
size, val, bank);
|
switch_dv(adapter, DDV);
|
}
|
} else if (addr < efuse_size &&
|
addr + size > efuse_size) {
|
size1 = efuse_size - addr;
|
size2 = addr + size - efuse_size;
|
|
ret = mac_read_efuse(adapter, addr, size1,
|
val, bank);
|
if (ret)
|
return ret;
|
if (dav_exist) {
|
switch_dv(adapter, DAV);
|
ret = mac_read_efuse(adapter, 0, size2,
|
val + size1, bank);
|
switch_dv(adapter, DDV);
|
}
|
}
|
}
|
break;
|
case MAC_AX_EFUSE_BANK_BT:
|
ret = mac_read_efuse(adapter, addr, size, val, bank);
|
break;
|
default:
|
break;
|
}
|
if (ret)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_read_efuse(struct mac_ax_adapter *adapter, u32 addr, u32 size, u8 *val,
|
enum mac_ax_efuse_bank bank)
|
{
|
u32 ret, stat, efuse_size = 0;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
bool OTP_test = adapter->efuse_param.OTP_test;
|
|
if (bank == MAC_AX_EFUSE_BANK_WIFI) {
|
if (OTP_test)
|
efuse_size = OTP_PHY_SIZE;
|
else
|
efuse_size = adapter->hw_info->wl_efuse_size;
|
} else if (bank == MAC_AX_EFUSE_BANK_BT) {
|
efuse_size = adapter->hw_info->bt_efuse_size;
|
} else {
|
return MACEFUSEBANK;
|
}
|
|
if (addr >= efuse_size || addr + size > efuse_size) {
|
PLTFM_MSG_ERR("[ERR] Wrong efuse index\n");
|
return MACEFUSESIZE;
|
}
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_PHY);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, bank);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = read_hw_efuse(adapter, addr, size, val);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]read hw efuse\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
if (bank == MAC_AX_EFUSE_BANK_BT) {
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
}
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != 0)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_read_hidden_efuse(struct mac_ax_adapter *adapter, u32 addr, u32 size,
|
u8 *val, enum mac_ax_efuse_hidden_cfg hidden_cfg)
|
{
|
u32 ret, stat;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
u32 log_sec_size = hw_info->efuse_size + hw_info->sec_data_efuse_size;
|
|
switch (hidden_cfg) {
|
case MAC_AX_EFUSE_HIDDEN_RF:
|
if (addr < log_sec_size || addr + size >
|
log_sec_size + hw_info->hidden_efuse_rf_size) {
|
PLTFM_MSG_ERR("[ERR] Wrong hidden rf index\n");
|
return MACEFUSESIZE;
|
}
|
break;
|
default:
|
PLTFM_MSG_ERR("[ERR] Hidden config invalid\n");
|
return MACNOITEM;
|
}
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_PHY);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_HIDDEN_RF);
|
if (ret != 0)
|
return ret;
|
|
ret = proc_dump_hidden(adapter);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]dump hidden!!\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
PLTFM_MEMCPY(val, adapter->efuse_param.hidden_rf_map +
|
(addr - log_sec_size), size);
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != 0)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
static u32 proc_dump_hidden(struct mac_ax_adapter *adapter)
|
{
|
u8 *map = NULL;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
u32 efuse_size = hw_info->efuse_size;
|
u32 sec_data_efuse_size = hw_info->sec_data_efuse_size;
|
u32 hidden_efuse_rf_size = hw_info->hidden_efuse_rf_size;
|
u8 hidden_rf_map_valid = adapter->efuse_param.hidden_rf_map_valid;
|
u32 ret;
|
|
if (hidden_rf_map_valid == 0) {
|
map = (u8 *)PLTFM_MALLOC(hidden_efuse_rf_size);
|
if (!map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
|
ret = read_hw_efuse(adapter, efuse_size + sec_data_efuse_size,
|
hidden_efuse_rf_size, map);
|
if (ret != 0) {
|
PLTFM_FREE(map, hidden_efuse_rf_size);
|
return ret;
|
}
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_MEMCPY(adapter->efuse_param.hidden_rf_map, map, hidden_efuse_rf_size);
|
adapter->efuse_param.hidden_rf_map_valid = 1;
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_FREE(map, hidden_efuse_rf_size);
|
}
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_get_efuse_avl_size(struct mac_ax_adapter *adapter, u32 *size)
|
{
|
u32 ret;
|
u8 *map;
|
u32 efuse_size = adapter->hw_info->log_efuse_size;
|
struct mac_ax_efuse_param *efuse_param = &adapter->efuse_param;
|
|
PLTFM_MSG_ERR("[TRACE]%s\n", __func__);
|
|
map = (u8 *)PLTFM_MALLOC(efuse_size);
|
if (!map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
|
ret = mac_dump_log_efuse(adapter, MAC_AX_EFUSE_PARSER_MAP,
|
MAC_AX_EFUSE_R_AUTO, map, 0);
|
|
PLTFM_FREE(map, efuse_size);
|
|
if (ret != 0)
|
return ret;
|
|
*size = adapter->hw_info->efuse_size - efuse_param->efuse_end;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_get_efuse_avl_size_bt(struct mac_ax_adapter *adapter, u32 *size)
|
{
|
u32 ret;
|
u8 *map;
|
u32 efuse_size = adapter->hw_info->bt_log_efuse_size;
|
struct mac_ax_efuse_param *efuse_param = &adapter->efuse_param;
|
|
map = (u8 *)PLTFM_MALLOC(efuse_size);
|
if (!map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
|
ret = mac_dump_log_efuse_bt(adapter, MAC_AX_EFUSE_PARSER_MAP,
|
MAC_AX_EFUSE_R_DRV, map);
|
|
PLTFM_FREE(map, efuse_size);
|
|
if (ret != 0)
|
return ret;
|
|
*size = adapter->hw_info->bt_efuse_size - efuse_param->bt_efuse_end;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_dump_log_efuse_plus(struct mac_ax_adapter *adapter,
|
enum mac_ax_efuse_parser_cfg parser_cfg,
|
enum mac_ax_efuse_read_cfg cfg,
|
u8 *efuse_map, bool is_limit)
|
{
|
u32 ret = 0;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
u8 chip_id = hw_info->chip_id;
|
enum mac_ax_intf intf = adapter->hw_info->intf;
|
u32 map_size = hw_info->log_efuse_size;
|
bool dav_exist = (hw_info->dav_full_efuse_size == 0) ? false : true;
|
|
if (chip_id == MAC_AX_CHIP_ID_8852A) {
|
ret = mac_dump_log_efuse(adapter, parser_cfg, cfg,
|
efuse_map, is_limit);
|
} else {
|
ret = mac_dump_log_efuse(adapter, parser_cfg, cfg,
|
efuse_map, is_limit);
|
if (ret)
|
return ret;
|
|
if (dav_exist) {
|
switch_dv(adapter, DAV);
|
if (is_limit) {
|
switch (intf) {
|
case MAC_AX_INTF_PCIE:
|
map_size = hw_info->limit_efuse_size_pcie;
|
break;
|
case MAC_AX_INTF_USB:
|
map_size = hw_info->limit_efuse_size_usb;
|
break;
|
case MAC_AX_INTF_SDIO:
|
map_size = hw_info->limit_efuse_size_sdio;
|
break;
|
default:
|
break;
|
}
|
}
|
|
ret = mac_dump_log_efuse(adapter, parser_cfg, cfg,
|
efuse_map + map_size, 0);
|
|
switch_dv(adapter, DDV);
|
}
|
}
|
|
if (ret)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_dump_log_efuse(struct mac_ax_adapter *adapter,
|
enum mac_ax_efuse_parser_cfg parser_cfg,
|
enum mac_ax_efuse_read_cfg cfg,
|
u8 *efuse_map, bool is_limit)
|
{
|
u8 *map = NULL;
|
u32 ret, stat;
|
u32 efuse_size;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
enum rtw_dv_sel dv_sel = adapter->efuse_param.dv_sel;
|
|
if (cfg == MAC_AX_EFUSE_R_FW &&
|
adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
PLTFM_MSG_TRACE("[TRACE]cfg = %d\n", cfg);
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_LOG_MAP);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
efuse_size = *bank_efuse_info->log_map_size;
|
|
if (dv_sel == DAV) {
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_DAV);
|
if (ret != 0)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG_DAV);
|
} else {
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG);
|
if (ret != 0)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_WL);
|
}
|
if (ret)
|
return ret;
|
|
if (*bank_efuse_info->log_map_valid == 0) {
|
ret = proc_dump_efuse(adapter, cfg);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]dump efuse\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
if (*bank_efuse_info->phy_map_valid == 1) {
|
map = (u8 *)PLTFM_MALLOC(efuse_size);
|
if (!map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
stat = cnv_efuse_state(adapter,
|
MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return MACBUFALLOC;
|
}
|
|
ret = eeprom_parser(adapter, *bank_efuse_info->phy_map,
|
map, parser_cfg);
|
if (ret != 0) {
|
PLTFM_FREE(map, efuse_size);
|
stat = cnv_efuse_state(adapter,
|
MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_MEMCPY(*bank_efuse_info->log_map, map,
|
efuse_size);
|
*bank_efuse_info->log_map_valid = 1;
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_FREE(map, efuse_size);
|
}
|
}
|
|
query_status_map(adapter, MAC_AX_DUMP_LOGICAL_EFUSE,
|
efuse_map, is_limit);
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != 0)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_read_log_efuse_plus(struct mac_ax_adapter *adapter, u32 addr, u32 size,
|
u8 *val)
|
{
|
u32 ret = 0;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
u8 chip_id = hw_info->chip_id;
|
u32 efuse_size = hw_info->log_efuse_size;
|
u32 size1, size2;
|
bool dav_exist = (hw_info->dav_full_efuse_size == 0) ? false : true;
|
|
if (chip_id == MAC_AX_CHIP_ID_8852A) {
|
ret = mac_read_log_efuse(adapter, addr, size, val);
|
} else {
|
if (addr < efuse_size && addr + size <= efuse_size) {
|
ret = mac_read_log_efuse(adapter, addr, size, val);
|
} else if (addr >= efuse_size) {
|
if (dav_exist) {
|
switch_dv(adapter, DAV);
|
ret = mac_read_log_efuse(adapter, addr - efuse_size,
|
size, val);
|
switch_dv(adapter, DDV);
|
}
|
} else if (addr < efuse_size && addr + size > efuse_size) {
|
size1 = efuse_size - addr;
|
size2 = addr + size - efuse_size;
|
|
ret = mac_read_log_efuse(adapter, addr, size1, val);
|
if (ret)
|
return ret;
|
|
if (dav_exist) {
|
switch_dv(adapter, DAV);
|
ret = mac_read_log_efuse(adapter, 0, size2,
|
val + size1);
|
switch_dv(adapter, DDV);
|
}
|
}
|
}
|
|
if (ret)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_read_log_efuse(struct mac_ax_adapter *adapter, u32 addr, u32 size,
|
u8 *val)
|
{
|
u8 *map = NULL;
|
u32 ret = 0, stat;
|
u32 efuse_size;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
enum rtw_dv_sel dv_sel = adapter->efuse_param.dv_sel;
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_LOG_MAP);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
efuse_size = *bank_efuse_info->log_map_size;
|
|
if (addr >= efuse_size || addr + size > efuse_size) {
|
PLTFM_MSG_ERR("[ERR] Wrong efuse index\n");
|
return MACEFUSESIZE;
|
}
|
|
if (dv_sel == DAV) {
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_DAV);
|
if (ret)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG_DAV);
|
} else {
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_WL);
|
if (ret)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG);
|
}
|
if (ret)
|
return ret;
|
|
map = (u8 *)PLTFM_MALLOC(efuse_size);
|
if (!map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return MACBUFALLOC;
|
}
|
|
ret = read_log_efuse_map(adapter, map, efuse_size);
|
if (ret != 0) {
|
PLTFM_FREE(map, efuse_size);
|
PLTFM_MSG_ERR("[ERR]read logical efuse\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_MEMCPY(val, map + addr, size);
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_FREE(map, efuse_size);
|
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_write_log_efuse_plus(struct mac_ax_adapter *adapter, u32 addr, u8 val)
|
{
|
u32 ret = 0;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
u8 chip_id = hw_info->chip_id;
|
u32 efuse_size = hw_info->log_efuse_size;
|
bool dav_exist = (hw_info->dav_full_efuse_size == 0) ? false : true;
|
|
if (chip_id == MAC_AX_CHIP_ID_8852A) {
|
ret = mac_write_log_efuse(adapter, addr, val);
|
} else {
|
if (addr < efuse_size) {
|
ret = mac_write_log_efuse(adapter, addr, val);
|
} else {
|
if (dav_exist) {
|
switch_dv(adapter, DAV);
|
ret = mac_write_log_efuse(adapter,
|
addr - efuse_size, val);
|
switch_dv(adapter, DDV);
|
}
|
}
|
}
|
|
if (ret)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_write_log_efuse(struct mac_ax_adapter *adapter, u32 addr, u8 val)
|
{
|
u32 ret, stat;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
enum rtw_dv_sel dv_sel = adapter->efuse_param.dv_sel;
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_LOG_MAP);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
if (addr >= *bank_efuse_info->log_map_size) {
|
PLTFM_MSG_ERR("[ERR]addr is too large\n");
|
return MACEFUSESIZE;
|
}
|
|
if (dv_sel == DAV) {
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_DAV);
|
if (ret)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG_DAV);
|
} else {
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_WL);
|
if (ret)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG);
|
}
|
if (ret)
|
return ret;
|
|
ret = proc_write_log_efuse(adapter, addr, val);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]write logical efuse\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != 0)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_dump_log_efuse_bt(struct mac_ax_adapter *adapter,
|
enum mac_ax_efuse_parser_cfg parser_cfg,
|
enum mac_ax_efuse_read_cfg cfg,
|
u8 *efuse_map)
|
{
|
u8 *map = NULL;
|
u32 ret, stat;
|
u32 efuse_size = adapter->hw_info->bt_log_efuse_size;
|
struct mac_ax_efuse_param *efuse_param = &adapter->efuse_param;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
|
if (cfg == MAC_AX_EFUSE_R_FW &&
|
adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
PLTFM_MSG_TRACE("[TRACE]cfg = %d\n", cfg);
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_LOG_MAP);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_BT);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG_BT);
|
if (ret != 0)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_BT);
|
if (ret != 0)
|
return ret;
|
|
if (efuse_param->bt_log_efuse_map_valid == 0) {
|
ret = proc_dump_efuse(adapter, cfg);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]dump efuse\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
if (efuse_param->bt_efuse_map_valid == 1) {
|
map = (u8 *)PLTFM_MALLOC(efuse_size);
|
if (!map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
stat = cnv_efuse_state(adapter,
|
MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return MACBUFALLOC;
|
}
|
|
ret = eeprom_parser(adapter, efuse_param->bt_efuse_map,
|
map, parser_cfg);
|
if (ret != 0) {
|
PLTFM_FREE(map, efuse_size);
|
stat = cnv_efuse_state(adapter,
|
MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_MEMCPY(efuse_param->bt_log_efuse_map, map,
|
efuse_size);
|
efuse_param->bt_log_efuse_map_valid = 1;
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_FREE(map, efuse_size);
|
}
|
}
|
|
query_status_map(adapter, MAC_AX_DUMP_LOGICAL_EFUSE, efuse_map, 0);
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != 0)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_read_log_efuse_bt(struct mac_ax_adapter *adapter, u32 addr, u32 size,
|
u8 *val)
|
{
|
u8 *map = NULL;
|
u32 ret, stat;
|
u32 efuse_size = adapter->hw_info->bt_log_efuse_size;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
|
if (addr >= efuse_size || addr + size > efuse_size) {
|
PLTFM_MSG_ERR("[ERR] Wrong efuse index\n");
|
return MACEFUSESIZE;
|
}
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_LOG_MAP);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_BT);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_BT);
|
if (ret)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG_BT);
|
if (ret)
|
return ret;
|
|
map = (u8 *)PLTFM_MALLOC(efuse_size);
|
if (!map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return MACBUFALLOC;
|
}
|
PLTFM_MEMSET(map, 0xFF, efuse_size);
|
|
ret = read_log_efuse_map(adapter, map, efuse_size);
|
if (ret != 0) {
|
PLTFM_FREE(map, efuse_size);
|
PLTFM_MSG_ERR("[ERR]read logical efuse\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_MEMCPY(val, map + addr, size);
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_FREE(map, efuse_size);
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_write_log_efuse_bt(struct mac_ax_adapter *adapter, u32 addr, u8 val)
|
{
|
u32 ret, stat;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
|
if (addr >= adapter->hw_info->log_efuse_size) {
|
PLTFM_MSG_ERR("[ERR]addr is too large\n");
|
return MACEFUSESIZE;
|
}
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_LOG_MAP);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_BT);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_BT);
|
if (ret)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG_BT);
|
if (ret)
|
return ret;
|
|
ret = proc_write_log_efuse(adapter, addr, val);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]write logical efuse\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != 0)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_pg_efuse_by_map_plus(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info,
|
enum mac_ax_efuse_read_cfg cfg,
|
bool part, bool is_limit)
|
{
|
u8 chip_id = adapter->hw_info->chip_id;
|
u32 ret;
|
struct mac_ax_pg_efuse_info info_DAV = {0};
|
struct mac_ax_pg_efuse_info info_DDV = {0};
|
u32 ver_len = 0;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
enum mac_ax_intf intf = adapter->hw_info->intf;
|
u32 map_size = adapter->hw_info->log_efuse_size;
|
bool dav_exist = (hw_info->dav_full_efuse_size == 0) ? false : true;
|
|
ret = mac_get_hw_value(adapter,
|
MAC_AX_HW_GET_EFUSE_VERSION_SIZE, &ver_len);
|
if (ret)
|
return ret;
|
|
if (chip_id == MAC_AX_CHIP_ID_8852A) {
|
ret = mac_pg_efuse_by_map(adapter, info, cfg, part, is_limit);
|
if (ret)
|
return ret;
|
} else {
|
if (is_limit) {
|
switch (intf) {
|
case MAC_AX_INTF_PCIE:
|
map_size = hw_info->limit_efuse_size_pcie;
|
break;
|
case MAC_AX_INTF_USB:
|
map_size = hw_info->limit_efuse_size_usb;
|
break;
|
case MAC_AX_INTF_SDIO:
|
map_size = hw_info->limit_efuse_size_sdio;
|
break;
|
default:
|
break;
|
}
|
}
|
|
/* a-die */
|
info_DAV.efuse_map_size = hw_info->dav_log_efuse_size;
|
info_DAV.efuse_mask_size = hw_info->dav_log_efuse_size >> 4;
|
|
info_DAV.efuse_map =
|
(u8 *)PLTFM_MALLOC(info_DAV.efuse_map_size + ver_len);
|
if (!info_DAV.efuse_map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
info_DAV.efuse_mask =
|
(u8 *)PLTFM_MALLOC(info_DAV.efuse_mask_size + ver_len);
|
if (!info_DAV.efuse_mask) {
|
free_map_mask(adapter, ver_len, &info_DAV, &info_DDV);
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
|
PLTFM_MEMCPY(info_DAV.efuse_map, info->efuse_map + map_size,
|
info_DAV.efuse_map_size + ver_len);
|
PLTFM_MEMCPY(info_DAV.efuse_mask,
|
info->efuse_mask + (map_size >> 4),
|
info_DAV.efuse_mask_size + ver_len);
|
|
/* d-die */
|
info_DDV.efuse_map_size =
|
info->efuse_map_size - info_DAV.efuse_map_size;
|
info_DDV.efuse_mask_size =
|
info->efuse_mask_size - info_DAV.efuse_mask_size;
|
|
info_DDV.efuse_map =
|
(u8 *)PLTFM_MALLOC(info_DDV.efuse_map_size + ver_len);
|
if (!info_DDV.efuse_map) {
|
free_map_mask(adapter, ver_len, &info_DAV, &info_DDV);
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
info_DDV.efuse_mask =
|
(u8 *)PLTFM_MALLOC(info_DDV.efuse_mask_size + ver_len);
|
if (!info_DDV.efuse_mask) {
|
free_map_mask(adapter, ver_len, &info_DAV, &info_DDV);
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
|
PLTFM_MEMCPY(info_DDV.efuse_map, info->efuse_map,
|
info_DDV.efuse_map_size);
|
PLTFM_MEMCPY(info_DDV.efuse_map + info_DDV.efuse_map_size,
|
info->efuse_map + info->efuse_map_size, ver_len);
|
|
PLTFM_MEMCPY(info_DDV.efuse_mask, info->efuse_mask,
|
info_DDV.efuse_mask_size);
|
PLTFM_MEMCPY(info_DDV.efuse_mask + info_DDV.efuse_mask_size,
|
info->efuse_mask + info->efuse_mask_size, ver_len);
|
|
ret = mac_pg_efuse_by_map(adapter,
|
&info_DDV, cfg, part, is_limit);
|
if (ret) {
|
free_map_mask(adapter, ver_len, &info_DAV, &info_DDV);
|
return ret;
|
}
|
|
if (dav_exist) {
|
switch_dv(adapter, DAV);
|
ret = mac_pg_efuse_by_map(adapter,
|
&info_DAV, cfg, part, 0);
|
if (ret) {
|
free_map_mask(adapter, ver_len, &info_DAV, &info_DDV);
|
return ret;
|
}
|
switch_dv(adapter, DDV);
|
}
|
}
|
|
free_map_mask(adapter, ver_len, &info_DAV, &info_DDV);
|
return MACSUCCESS;
|
}
|
|
static void free_map_mask(struct mac_ax_adapter *adapter, u32 ver_len,
|
struct mac_ax_pg_efuse_info *info_DAV,
|
struct mac_ax_pg_efuse_info *info_DDV)
|
{
|
if (info_DAV->efuse_map)
|
PLTFM_FREE(info_DAV->efuse_map,
|
info_DAV->efuse_map_size + ver_len);
|
if (info_DAV->efuse_mask)
|
PLTFM_FREE(info_DAV->efuse_mask,
|
info_DAV->efuse_mask_size + ver_len);
|
if (info_DDV->efuse_map)
|
PLTFM_FREE(info_DDV->efuse_map,
|
info_DDV->efuse_map_size + ver_len);
|
if (info_DDV->efuse_mask)
|
PLTFM_FREE(info_DDV->efuse_mask,
|
info_DDV->efuse_mask_size + ver_len);
|
}
|
|
u32 mac_pg_efuse_by_map(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info,
|
enum mac_ax_efuse_read_cfg cfg,
|
bool part, bool is_limit)
|
{
|
u32 ret, stat;
|
enum mac_ax_intf intf = adapter->hw_info->intf;
|
u32 map_size = adapter->hw_info->log_efuse_size;
|
u32 ver_len = 0;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
enum rtw_dv_sel dv_sel = adapter->efuse_param.dv_sel;
|
|
if (is_limit) {
|
switch (intf) {
|
case MAC_AX_INTF_PCIE:
|
map_size = adapter->hw_info->limit_efuse_size_pcie;
|
break;
|
case MAC_AX_INTF_USB:
|
map_size = adapter->hw_info->limit_efuse_size_usb;
|
break;
|
case MAC_AX_INTF_SDIO:
|
map_size = adapter->hw_info->limit_efuse_size_sdio;
|
break;
|
default:
|
break;
|
}
|
}
|
|
if (dv_sel == DAV)
|
map_size = adapter->hw_info->dav_log_efuse_size;
|
|
if (info->efuse_map_size != map_size) {
|
PLTFM_MSG_ERR("[ERR]map size error\n");
|
return MACEFUSESIZE;
|
}
|
|
if ((info->efuse_map_size & 0xF) > 0) {
|
PLTFM_MSG_ERR("[ERR]not multiple of 16\n");
|
return MACEFUSESIZE;
|
}
|
|
if (info->efuse_mask_size != info->efuse_map_size >> 4) {
|
PLTFM_MSG_ERR("[ERR]mask size error\n");
|
return MACEFUSESIZE;
|
}
|
|
if (!info->efuse_map) {
|
PLTFM_MSG_ERR("[ERR]map is NULL\n");
|
return MACNPTR;
|
}
|
|
if (!info->efuse_mask) {
|
PLTFM_MSG_ERR("[ERR]mask is NULL\n");
|
return MACNPTR;
|
}
|
|
ret = mac_get_hw_value(adapter,
|
MAC_AX_HW_GET_EFUSE_VERSION_SIZE, &ver_len);
|
if (ret)
|
return ret;
|
ret = compare_version(adapter, info, ver_len);
|
if (ret != 0)
|
return ret;
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_PHY);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
if (dv_sel == DAV) {
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_DAV);
|
if (ret)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG_DAV);
|
} else {
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_WL);
|
if (ret)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG);
|
}
|
if (ret)
|
return ret;
|
|
if (part)
|
ret = adjust_mask(adapter, info);
|
if (ret != 0) {
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = proc_pg_efuse_by_map(adapter, info, cfg);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]pg efuse\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != 0)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_pg_efuse_by_map_bt(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info,
|
enum mac_ax_efuse_read_cfg cfg)
|
{
|
u32 ret, stat;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
|
if (info->efuse_map_size != adapter->hw_info->bt_log_efuse_size) {
|
PLTFM_MSG_ERR("[ERR]map size error\n");
|
return MACEFUSESIZE;
|
}
|
|
if ((info->efuse_map_size & 0xF) > 0) {
|
PLTFM_MSG_ERR("[ERR]not multiple of 16\n");
|
return MACEFUSESIZE;
|
}
|
|
if (info->efuse_mask_size != info->efuse_map_size >> 4) {
|
PLTFM_MSG_ERR("[ERR]mask size error\n");
|
return MACEFUSESIZE;
|
}
|
|
if (!info->efuse_map) {
|
PLTFM_MSG_ERR("[ERR]map is NULL\n");
|
return MACNPTR;
|
}
|
|
if (!info->efuse_mask) {
|
PLTFM_MSG_ERR("[ERR]mask is NULL\n");
|
return MACNPTR;
|
}
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_PHY);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_BT);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_BT);
|
if (ret)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG_BT);
|
if (ret)
|
return ret;
|
|
ret = proc_pg_efuse_by_map(adapter, info, cfg);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]pg efuse\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != 0)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_mask_log_efuse(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info)
|
{
|
if (info->efuse_map_size != adapter->hw_info->log_efuse_size) {
|
PLTFM_MSG_ERR("[ERR]map size error\n");
|
return MACEFUSESIZE;
|
}
|
|
if ((info->efuse_map_size & 0xF) > 0) {
|
PLTFM_MSG_ERR("[ERR]not multiple of 16\n");
|
return MACEFUSESIZE;
|
}
|
|
if (info->efuse_mask_size != info->efuse_map_size >> 4) {
|
PLTFM_MSG_ERR("[ERR]mask size error\n");
|
return MACEFUSESIZE;
|
}
|
|
if (!info->efuse_map) {
|
PLTFM_MSG_ERR("[ERR]map is NULL\n");
|
return MACNPTR;
|
}
|
|
if (!info->efuse_mask) {
|
PLTFM_MSG_ERR("[ERR]mask is NULL\n");
|
return MACNPTR;
|
}
|
|
mask_eeprom(adapter, info);
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_pg_sec_data_by_map(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info)
|
{
|
u32 ret, stat;
|
u32 addr, efuse_size, sec_data_size;
|
u8 *map_pg;
|
u32 mac_addr_size = 6;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
|
/*Soar TBD add MAC address PG*/
|
|
map_pg = info->efuse_map;
|
efuse_size = adapter->hw_info->efuse_size;
|
sec_data_size = adapter->hw_info->sec_data_efuse_size;
|
|
if (info->efuse_map_size != adapter->hw_info->sec_data_efuse_size) {
|
PLTFM_MSG_ERR("[ERR]map size error\n");
|
return MACEFUSESIZE;
|
}
|
|
if (!info->efuse_map) {
|
PLTFM_MSG_ERR("[ERR]map is NULL\n");
|
return MACNPTR;
|
}
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_PHY);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
p_ops->enable_efuse_sw_pwr_cut(adapter, 1);
|
for (addr = mac_addr_size; addr < sec_data_size; addr++) {
|
ret = write_hw_efuse(adapter, addr + efuse_size,
|
*(map_pg + addr));
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]write physical efuse\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
}
|
p_ops->disable_efuse_sw_pwr_cut(adapter, 1);
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != 0)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_cmp_sec_data_by_map(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info)
|
{
|
u32 ret, stat;
|
u32 addr, start_addr, sec_data_size;
|
u16 val16;
|
u8 *map_pg;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
|
map_pg = info->efuse_map;
|
start_addr = adapter->hw_info->efuse_size;
|
sec_data_size = adapter->hw_info->sec_data_efuse_size;
|
|
if (info->efuse_map_size != adapter->hw_info->sec_data_efuse_size) {
|
PLTFM_MSG_ERR("[ERR]map size error\n");
|
return MACEFUSESIZE;
|
}
|
|
if (!info->efuse_map) {
|
PLTFM_MSG_ERR("[ERR]map is NULL\n");
|
return MACNPTR;
|
}
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != 0)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_PHY);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
return ret;
|
}
|
|
for (addr = 0;
|
addr < sec_data_size; addr += 2) {
|
val16 = *(map_pg + addr) | (*(map_pg + addr + 1) << 8);
|
ret = cmp_hw_efuse(adapter, addr + start_addr, val16);
|
if (ret == MACEFUSECMP) {
|
*(map_pg + addr) = 0xFF;
|
*(map_pg + addr + 1) = 0xFF;
|
} else if (ret == MACEFUSEREAD) {
|
PLTFM_MSG_ERR("[ERR]compare hw efuse\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != 0)
|
return stat;
|
} else if (ret == 0) {
|
*(map_pg + addr) = 0x00;
|
*(map_pg + addr + 1) = 0x00;
|
}
|
}
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != 0)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_get_efuse_info(struct mac_ax_adapter *adapter, u8 *efuse_map,
|
enum rtw_efuse_info id, void *value, u32 length,
|
u8 *autoload_status)
|
{
|
u32 offset, def_val;
|
u32 ret;
|
enum mac_ax_intf intf = adapter->hw_info->intf;
|
struct efuse_info info;
|
|
switch (intf) {
|
case MAC_AX_INTF_USB:
|
if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852A))
|
info = efuse_info_usb_8852a;
|
else if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852B))
|
info = efuse_info_usb_8852b;
|
else if (is_chip_id(adapter, MAC_AX_CHIP_ID_8851B))
|
info = efuse_info_usb_8851b;
|
else if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852BT))
|
info = efuse_info_usb_8852bt;
|
else
|
info = efuse_info_usb_8852b;
|
break;
|
case MAC_AX_INTF_PCIE:
|
info = efuse_info_pcie;
|
break;
|
case MAC_AX_INTF_SDIO:
|
info = efuse_info_sdio;
|
break;
|
default:
|
return MACINTF;
|
}
|
|
ret = compare_info_length(&info, id, length);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
switch (id) {
|
case EFUSE_INFO_MAC_ADDR:
|
offset = info.offset->mac_addr;
|
def_val = info.def_val->mac_addr;
|
break;
|
case EFUSE_INFO_MAC_PID:
|
offset = info.offset->pid;
|
def_val = info.def_val->pid;
|
break;
|
case EFUSE_INFO_MAC_DID:
|
offset = info.offset->did;
|
def_val = info.def_val->did;
|
break;
|
case EFUSE_INFO_MAC_VID:
|
offset = info.offset->vid;
|
def_val = info.def_val->vid;
|
break;
|
case EFUSE_INFO_MAC_SVID:
|
offset = info.offset->svid;
|
def_val = info.def_val->svid;
|
break;
|
case EFUSE_INFO_MAC_SMID:
|
offset = info.offset->smid;
|
def_val = info.def_val->smid;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
|
if (*autoload_status == 0)
|
PLTFM_MEMCPY(value, &def_val, 1);
|
else
|
PLTFM_MEMCPY(value, efuse_map + offset, length);
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_set_efuse_info(struct mac_ax_adapter *adapter, u8 *efuse_map,
|
enum rtw_efuse_info id, void *value, u32 length)
|
{
|
u32 offset;
|
u32 ret;
|
enum mac_ax_intf intf = adapter->hw_info->intf;
|
struct efuse_info info;
|
|
switch (intf) {
|
case MAC_AX_INTF_USB:
|
if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852A))
|
info = efuse_info_usb_8852a;
|
else if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852B))
|
info = efuse_info_usb_8852b;
|
else if (is_chip_id(adapter, MAC_AX_CHIP_ID_8851B))
|
info = efuse_info_usb_8851b;
|
else if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852BT))
|
info = efuse_info_usb_8852bt;
|
else
|
info = efuse_info_usb_8852b;
|
break;
|
case MAC_AX_INTF_PCIE:
|
info = efuse_info_pcie;
|
break;
|
case MAC_AX_INTF_SDIO:
|
info = efuse_info_sdio;
|
break;
|
default:
|
return MACINTF;
|
}
|
|
ret = compare_info_length(&info, id, length);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
switch (id) {
|
case EFUSE_INFO_MAC_ADDR:
|
offset = info.offset->mac_addr;
|
break;
|
case EFUSE_INFO_MAC_PID:
|
offset = info.offset->pid;
|
break;
|
case EFUSE_INFO_MAC_DID:
|
offset = info.offset->did;
|
break;
|
case EFUSE_INFO_MAC_VID:
|
offset = info.offset->vid;
|
break;
|
case EFUSE_INFO_MAC_SVID:
|
offset = info.offset->svid;
|
break;
|
case EFUSE_INFO_MAC_SMID:
|
offset = info.offset->smid;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
|
PLTFM_MEMCPY(efuse_map + offset, value, length);
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_read_hidden_rpt(struct mac_ax_adapter *adapter,
|
struct mac_defeature_value *rpt)
|
{
|
#if 0
|
return MACNOITEM;
|
#else
|
u32 ret, stat;
|
struct mac_ax_h2creg_info h2c;
|
struct mac_ax_c2hreg_poll c2h;
|
struct fwcmd_c2hreg *c2h_content;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
|
ret = efuse_proc_ck(adapter);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_PHY);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat != MACSUCCESS)
|
return stat;
|
return ret;
|
}
|
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_WL);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
h2c.id = FWCMD_H2CREG_FUNC_HIDDEN_GET;
|
h2c.content_len = sizeof(struct mac_efuse_hidden_h2creg);
|
|
c2h.polling_id = FWCMD_C2HREG_FUNC_EFUSE_HIDDEN;
|
c2h.retry_cnt = EFUSE_C2HREG_WAIT_CNT;
|
c2h.retry_wait_us = EFUSE_C2HREG_RETRY_WAIT_US;
|
|
ret = proc_msg_reg(adapter, &h2c, &c2h);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]read hidden rpt proc msg reg %d\n", ret);
|
stat = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (stat)
|
return stat;
|
return ret;
|
}
|
|
c2h_content = &c2h.c2hreg_cont.c2h_content;
|
|
rpt->rx_spatial_stream = GET_FIELD(c2h_content->dword0, FWCMD_C2HREG_EFUSE_HIDDEN_RX_NSS);
|
rpt->bandwidth = GET_FIELD(c2h_content->dword0, FWCMD_C2HREG_EFUSE_HIDDEN_BW);
|
rpt->tx_spatial_stream = GET_FIELD(c2h_content->dword1, FWCMD_C2HREG_EFUSE_HIDDEN_TX_NSS);
|
rpt->protocol_80211 = GET_FIELD(c2h_content->dword1, FWCMD_C2HREG_EFUSE_HIDDEN_PROT80211);
|
rpt->NIC_router = GET_FIELD(c2h_content->dword1, FWCMD_C2HREG_EFUSE_HIDDEN_NIC_ROUTER);
|
rpt->wl_func_support =
|
GET_FIELD(c2h_content->dword1, FWCMD_C2HREG_EFUSE_HIDDEN_WL_FUNC_SUPPORT);
|
rpt->hw_special_type =
|
GET_FIELD(c2h_content->dword2, FWCMD_C2HREG_EFUSE_HIDDEN_HW_SPECIAL_TYPE);
|
rpt->uuid =
|
GET_FIELD(c2h_content->dword3, FWCMD_C2HREG_EFUSE_HIDDEN_UUID_BYTE_3) << 24 |
|
GET_FIELD(c2h_content->dword2, FWCMD_C2HREG_EFUSE_HIDDEN_UUID_BYTE_2) << 16 |
|
GET_FIELD(c2h_content->dword2, FWCMD_C2HREG_EFUSE_HIDDEN_UUID_BYTE_1) << 8 |
|
GET_FIELD(c2h_content->dword2, FWCMD_C2HREG_EFUSE_HIDDEN_UUID_BYTE_0);
|
rpt->tx_path_num = GET_FIELD(c2h_content->dword3, FWCMD_C2HREG_EFUSE_HIDDEN_TX_PATH_NUM);
|
rpt->rx_path_num = GET_FIELD(c2h_content->dword3, FWCMD_C2HREG_EFUSE_HIDDEN_RX_PATH_NUM);
|
rpt->band_sel = GET_FIELD(c2h_content->dword3, FWCMD_C2HREG_EFUSE_HIDDEN_BAND_SEL);
|
|
ret = cnv_efuse_state(adapter, MAC_AX_EFUSE_IDLE);
|
if (ret != MACSUCCESS)
|
return ret;
|
|
return MACSUCCESS;
|
#endif
|
}
|
|
u32 mac_check_efuse_autoload(struct mac_ax_adapter *adapter,
|
u8 *autoload_status)
|
{
|
#define AUTOLOAD_SUS 1
|
#define AUTOLOAD_FAIL 0
|
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
if (MAC_REG_R16(R_AX_SYS_WL_EFUSE_CTRL) & B_AX_AUTOLOAD_SUS)
|
*autoload_status = AUTOLOAD_SUS;
|
else
|
*autoload_status = AUTOLOAD_FAIL;
|
|
return MACSUCCESS;
|
|
#undef AUTOLOAD_SUS
|
#undef AUTOLOAD_FAIL
|
}
|
|
u32 mac_pg_simulator_plus(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info, u8 *phy_map)
|
{
|
u8 chip_id = adapter->hw_info->chip_id;
|
u32 ret;
|
struct mac_ax_pg_efuse_info info_dav;
|
u32 ver_len = 0;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
u32 map_size = hw_info->log_efuse_size;
|
bool dav_exist = (hw_info->dav_full_efuse_size == 0) ? false : true;
|
|
ret = mac_get_hw_value(adapter,
|
MAC_AX_HW_GET_EFUSE_VERSION_SIZE, &ver_len);
|
if (ret)
|
return ret;
|
|
if (chip_id == MAC_AX_CHIP_ID_8852A) {
|
ret = mac_pg_simulator(adapter, info, phy_map);
|
} else {
|
info_dav.efuse_map_size = hw_info->dav_log_efuse_size;
|
info_dav.efuse_mask_size = hw_info->dav_log_efuse_size >> 4;
|
|
info_dav.efuse_map =
|
(u8 *)PLTFM_MALLOC(info_dav.efuse_map_size + ver_len);
|
if (!info_dav.efuse_map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
info_dav.efuse_mask =
|
(u8 *)PLTFM_MALLOC(info_dav.efuse_mask_size +
|
ver_len);
|
if (!info_dav.efuse_mask) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
|
PLTFM_MEMCPY(info_dav.efuse_map, info->efuse_map + map_size,
|
info_dav.efuse_map_size + ver_len);
|
PLTFM_MEMCPY(info_dav.efuse_mask,
|
info->efuse_mask + (map_size >> 4),
|
info_dav.efuse_mask_size + ver_len);
|
|
info->efuse_map_size -= info_dav.efuse_map_size;
|
info->efuse_mask_size -= info_dav.efuse_mask_size;
|
|
PLTFM_MEMCPY(info->efuse_map + map_size, info->efuse_map +
|
map_size + info_dav.efuse_map_size, ver_len);
|
PLTFM_MEMCPY(info->efuse_mask + (map_size >> 4),
|
info->efuse_mask + (map_size >> 4) +
|
info_dav.efuse_mask_size, ver_len);
|
|
ret = mac_pg_simulator(adapter, info, phy_map);
|
if (ret)
|
return ret;
|
|
if (dav_exist) {
|
switch_dv(adapter, DAV);
|
ret = mac_pg_simulator(adapter, &info_dav,
|
phy_map + hw_info->wl_efuse_size);
|
switch_dv(adapter, DDV);
|
PLTFM_MEMCPY(info->efuse_map + map_size, info_dav.efuse_map,
|
info_dav.efuse_map_size + ver_len);
|
}
|
}
|
|
if (ret)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_pg_simulator(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info, u8 *phy_map)
|
{
|
u8 *updated_mask;
|
u32 ret;
|
u32 mask_size;
|
u8 *log_efuse_map = NULL;
|
enum mac_ax_intf intf = adapter->hw_info->intf;
|
u32 map_size = adapter->hw_info->log_efuse_size;
|
u32 ver_len = 0;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
enum rtw_dv_sel dv_sel = adapter->efuse_param.dv_sel;
|
|
if (info->efuse_map_size != adapter->hw_info->log_efuse_size) {
|
switch (intf) {
|
case MAC_AX_INTF_PCIE:
|
map_size = adapter->hw_info->limit_efuse_size_pcie;
|
break;
|
case MAC_AX_INTF_USB:
|
map_size = adapter->hw_info->limit_efuse_size_usb;
|
break;
|
case MAC_AX_INTF_SDIO:
|
map_size = adapter->hw_info->limit_efuse_size_sdio;
|
break;
|
default:
|
break;
|
}
|
}
|
|
if (dv_sel == DAV)
|
map_size = adapter->hw_info->dav_log_efuse_size;
|
|
if (info->efuse_map_size != map_size) {
|
PLTFM_MSG_ERR("[ERR]map size error\n");
|
return MACEFUSESIZE;
|
}
|
|
mask_size = map_size >> 4;
|
|
ret = mac_get_hw_value(adapter,
|
MAC_AX_HW_GET_EFUSE_VERSION_SIZE, &ver_len);
|
if (ret)
|
return ret;
|
|
ret = compare_version(adapter, info, ver_len);
|
if (ret != 0)
|
return ret;
|
|
ret = p_ops->switch_efuse_bank(adapter, MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
|
return ret;
|
}
|
|
if (dv_sel == DAV) {
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_DAV);
|
if (ret)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG_DAV);
|
} else {
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_PHY_WL);
|
if (ret)
|
return ret;
|
ret = efuse_map_init(adapter, EFUSE_MAP_SEL_LOG);
|
}
|
if (ret)
|
return ret;
|
|
ret = eeprom_parser(adapter, phy_map, *bank_efuse_info->log_map,
|
MAC_AX_EFUSE_PARSER_MAP);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]logical map parser\n");
|
return ret;
|
}
|
PLTFM_MEMCPY(*bank_efuse_info->phy_map, phy_map,
|
*bank_efuse_info->phy_map_size);
|
|
updated_mask = (u8 *)PLTFM_MALLOC(mask_size);
|
if (!updated_mask) {
|
PLTFM_MSG_ERR("[ERR]malloc updated mask\n");
|
return MACBUFALLOC;
|
}
|
PLTFM_MEMSET(updated_mask, 0x00, mask_size);
|
|
ret = update_eeprom_mask(adapter, info, updated_mask, 1);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]update eeprom mask\n");
|
goto error;
|
}
|
|
ret = check_efuse_enough(adapter, info, updated_mask);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]chk efuse enough\n");
|
goto error;
|
}
|
|
ret = program_efuse(adapter, info, updated_mask, 1);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]pg efuse\n");
|
goto error;
|
}
|
|
PLTFM_FREE(updated_mask, mask_size);
|
|
PLTFM_MEMCPY(phy_map, *bank_efuse_info->phy_map,
|
*bank_efuse_info->phy_map_size);
|
ret = eeprom_parser(adapter, phy_map, info->efuse_map,
|
MAC_AX_EFUSE_PARSER_MAP);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]parser error\n");
|
PLTFM_FREE(log_efuse_map, map_size);
|
return ret;
|
}
|
|
/* For subsequent dump */
|
*bank_efuse_info->log_map_valid = 0;
|
*bank_efuse_info->phy_map_valid = 0;
|
|
return MACSUCCESS;
|
|
error:
|
PLTFM_FREE(updated_mask, mask_size);
|
return ret;
|
}
|
|
u32 mac_checksum_update(struct mac_ax_adapter *adapter)
|
{
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
u32 log_efuse_size = hw_info->log_efuse_size;
|
u8 *map;
|
u16 chksum;
|
u32 ret;
|
|
map = (u8 *)PLTFM_MALLOC(log_efuse_size);
|
if (!map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
PLTFM_MEMSET(map, 0xFF, log_efuse_size);
|
|
ret = mac_dump_log_efuse(adapter, MAC_AX_EFUSE_PARSER_MAP,
|
MAC_AX_EFUSE_R_AUTO, map, 0);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]Dump log map\n");
|
goto error;
|
}
|
|
cal_check_sum(adapter, &chksum);
|
|
ret = set_check_sum_val(adapter, map, chksum);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]write check sum\n");
|
goto error;
|
}
|
|
PLTFM_FREE(map, log_efuse_size);
|
return MACSUCCESS;
|
error:
|
PLTFM_FREE(map, log_efuse_size);
|
return ret;
|
}
|
|
u32 mac_checksum_rpt(struct mac_ax_adapter *adapter, u16 *chksum)
|
{
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
u32 log_efuse_size = hw_info->log_efuse_size;
|
u8 *tmp;
|
u32 ret;
|
u16 real_chksum = 0;
|
|
/* Read chksum val */
|
tmp = (u8 *)PLTFM_MALLOC(sizeof(real_chksum));
|
if (!tmp) {
|
PLTFM_MSG_ERR("[ERR]malloc tmp\n");
|
return MACBUFALLOC;
|
}
|
ret = mac_read_log_efuse(adapter, chksum_offset_1, sizeof(real_chksum),
|
tmp);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]read log efuse\n");
|
PLTFM_FREE(tmp, sizeof(real_chksum));
|
return ret;
|
}
|
|
real_chksum = *(u16 *)tmp;
|
PLTFM_FREE(tmp, sizeof(real_chksum));
|
|
if (real_chksum == 0xFFFF)
|
return MACCHKSUMEMPTY;
|
|
/* Read log map*/
|
tmp = (u8 *)PLTFM_MALLOC(log_efuse_size);
|
if (!tmp) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
PLTFM_MEMSET(tmp, 0xFF, log_efuse_size);
|
|
ret = mac_read_log_efuse(adapter, 0, log_efuse_size, tmp);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]read log efuse\n");
|
PLTFM_FREE(tmp, log_efuse_size);
|
return ret;
|
}
|
PLTFM_FREE(tmp, log_efuse_size);
|
|
cal_check_sum(adapter, chksum);
|
if (*chksum != real_chksum)
|
return MACCHKSUMFAIL;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_disable_rf_ofld_by_info(struct mac_ax_adapter *adapter,
|
struct mac_disable_rf_ofld_info info)
|
{
|
u32 ret;
|
struct h2c_info h2c_info = {0};
|
struct fwcmd_disable_rf *content;
|
|
if (adapter->sm.disable_rf != MAC_AX_OFLD_H2C_IDLE)
|
return MACPROCERR;
|
|
adapter->sm.disable_rf = MAC_AX_OFLD_H2C_SENDING;
|
|
h2c_info.agg_en = 0;
|
h2c_info.content_len = sizeof(struct fwcmd_disable_rf);
|
h2c_info.h2c_cat = FWCMD_H2C_CAT_MAC;
|
h2c_info.h2c_class = FWCMD_H2C_CL_FW_OFLD;
|
h2c_info.h2c_func = FWCMD_H2C_FUNC_DISABLE_RF;
|
h2c_info.rec_ack = 0;
|
h2c_info.done_ack = 0;
|
|
content = (struct fwcmd_disable_rf *)PLTFM_MALLOC(h2c_info.content_len);
|
if (!content)
|
return MACBUFALLOC;
|
|
content->dword0 =
|
cpu_to_le32(SET_WORD(info.func, FWCMD_H2C_DISABLE_RF_FUNC) |
|
SET_WORD(info.type, FWCMD_H2C_DISABLE_RF_NET_TYPE));
|
|
ret = mac_h2c_common(adapter, &h2c_info, (u32 *)content);
|
|
PLTFM_FREE(content, h2c_info.content_len);
|
|
if (adapter->sm.disable_rf != MAC_AX_OFLD_H2C_SENDING)
|
return MACPROCERR;
|
|
adapter->sm.disable_rf = MAC_AX_OFLD_H2C_IDLE;
|
|
return ret;
|
}
|
|
u32 _patch_otp_power_issue(struct mac_ax_adapter *adapter)
|
{
|
#define secure 1
|
u8 val8;
|
u32 ret, stat;
|
|
adapter->efuse_param.read_efuse_cnt = CHK_OTP_WAIT_CNT;
|
|
ret = mac_read_efuse_plus(adapter, CHK_OTP_ADDR, 1, &val8,
|
MAC_AX_EFUSE_BANK_WIFI);
|
if (ret != MACSUCCESS) {
|
adapter->efuse_param.read_efuse_cnt = EFUSE_WAIT_CNT;
|
stat = mac_set_efuse_ctrl(adapter, !secure);
|
if (stat != MACSUCCESS)
|
return stat;
|
return ret;
|
}
|
|
adapter->efuse_param.read_efuse_cnt = EFUSE_WAIT_CNT;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_set_efuse_ctrl(struct mac_ax_adapter *adapter, bool is_secure)
|
{
|
if (is_secure)
|
adapter->efuse_param.efuse_ctrl = R_AX_EFUSE_CTRL_S;
|
else
|
adapter->efuse_param.efuse_ctrl = R_AX_EFUSE_CTRL;
|
PLTFM_MSG_TRACE("[TRACE]is_secure= 0x%x, adapter->efuse_ctrl = 0x%x\n", is_secure,
|
adapter->efuse_param.efuse_ctrl);
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_otp_test(struct mac_ax_adapter *adapter, bool is_OTP_test)
|
{
|
if (is_OTP_test)
|
adapter->efuse_param.OTP_test = 1;
|
else
|
adapter->efuse_param.OTP_test = 0;
|
PLTFM_MSG_TRACE("[TRACE]is_OTP_test= 0x%x, adapter->OTP_test = 0x%x\n", is_OTP_test,
|
adapter->efuse_param.OTP_test);
|
|
return MACSUCCESS;
|
}
|
|
void cfg_efuse_auto_ck(struct mac_ax_adapter *adapter, u8 enable)
|
{
|
/*Soar TBD* move to set hw value */
|
|
#ifdef NEVER
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
adapter->efuse_param.auto_ck_en = enable;
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
#endif /* NEVER */
|
}
|
|
u32 get_fv_info(struct mac_ax_adapter *adapter)
|
{
|
u32 ret = MACCHIPID;
|
u8 efv = 0, ecv = 0;
|
struct mac_ax_ops *mac_ops = adapter_to_mac_ops(adapter);
|
|
#if (MAC_AX_8852A_SUPPORT || MAC_AX_8852B_SUPPORT || MAC_AX_8852C_SUPPORT || \
|
MAC_AX_8192XB_SUPPORT || MAC_AX_8851B_SUPPORT || MAC_AX_8851E_SUPPORT || \
|
MAC_AX_8852D_SUPPORT || MAC_AX_8852BT_SUPPORT)
|
if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852A) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8852B) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8852C) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8192XB) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8851B) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8851E) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8852D) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8852BT)) {
|
ret = mac_ops->read_efuse(adapter, EF_FV_OFSET_AX, 1, &efv,
|
MAC_AX_EFUSE_BANK_WIFI);
|
}
|
#endif
|
#if MAC_BE_1115E_SUPPORT
|
if (is_chip_id(adapter, MAC_BE_CHIP_ID_1115E))
|
ret = mac_ops->read_efuse(adapter, EF_FV_OFSET_BE, 1, &efv,
|
MAC_AX_EFUSE_BANK_WIFI);
|
#endif
|
#if (MAC_BE_8922A_SUPPORT || MAC_BE_8952A_SUPPORT)
|
if (is_chip_id(adapter, MAC_BE_CHIP_ID_8922A) ||
|
is_chip_id(adapter, MAC_BE_CHIP_ID_8952A)) {
|
ret = mac_ops->read_efuse(adapter, EF_FV_OFSET_BE_V1, 1, &efv,
|
MAC_AX_EFUSE_BANK_WIFI);
|
}
|
#endif
|
|
if (ret == MACSUCCESS && efv != 0) {
|
ecv = (efv >> EF_CV_OFSET) & EF_CV_MSK;
|
efv &= 0x0F;
|
|
if (ecv != 0xF)
|
adapter->hw_info->cv = ecv;
|
|
#if (MAC_AX_8852A_SUPPORT || MAC_AX_8852B_SUPPORT || MAC_AX_8852C_SUPPORT || \
|
MAC_AX_8851E_SUPPORT || MAC_AX_8852D_SUPPORT)
|
if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852A) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8852B) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8852C) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8851E) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8852D)) {
|
switch (efv) {
|
case FV_TYPE1:
|
adapter->hw_info->fv = FUV;
|
break;
|
case FV_TYPE2:
|
adapter->hw_info->fv = FSV;
|
break;
|
case FV_TYPE3:
|
adapter->hw_info->fv = FTV;
|
break;
|
//case FV_TYPE4:
|
//adapter->hw_info->fv = FTV;
|
//break;
|
default:
|
PLTFM_MSG_ERR("[ERR]Error efv = %x\n", efv);
|
ret = MACNOITEM;
|
}
|
}
|
#endif
|
#if MAC_AX_8851B_SUPPORT || MAC_AX_8192XB_SUPPORT || MAC_AX_8852BT_SUPPORT
|
if (is_chip_id(adapter, MAC_AX_CHIP_ID_8851B) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8192XB) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8852BT)) {
|
switch (efv) {
|
case FV_TYPE1:
|
adapter->hw_info->fv = FTV;
|
break;
|
case FV_TYPE2:
|
adapter->hw_info->fv = FSV;
|
break;
|
case FV_TYPE3:
|
adapter->hw_info->fv = FUV;
|
break;
|
//case FV_TYPE4:
|
//adapter->hw_info->fv = FTV;
|
//break;
|
default:
|
PLTFM_MSG_ERR("[ERR]Error efv = %x\n", efv);
|
ret = MACNOITEM;
|
}
|
}
|
#endif
|
#if (MAC_BE_1115E_SUPPORT || MAC_BE_8922A_SUPPORT || MAC_BE_8952A_SUPPORT)
|
if (is_chip_id(adapter, MAC_BE_CHIP_ID_1115E) ||
|
is_chip_id(adapter, MAC_BE_CHIP_ID_8922A) ||
|
is_chip_id(adapter, MAC_BE_CHIP_ID_8952A))
|
switch (efv) {
|
case FV_TYPE1:
|
adapter->hw_info->fv = FTV;
|
break;
|
case FV_TYPE2:
|
adapter->hw_info->fv = FSV;
|
break;
|
case FV_TYPE3:
|
adapter->hw_info->fv = FUV;
|
break;
|
//case FV_TYPE4:
|
//adapter->hw_info->fv = FTV;
|
//break;
|
default:
|
PLTFM_MSG_ERR("[ERR]Error efv = %x\n", efv);
|
ret = MACNOITEM;
|
}
|
#endif
|
}
|
PLTFM_MSG_ALWAYS("fv = %x, ecv = %x\n", adapter->hw_info->fv, ecv);
|
|
return ret;
|
}
|
|
u32 efuse_info_init(struct mac_ax_adapter *adapter)
|
{
|
PLTFM_MUTEX_INIT(&adapter->efuse_param.efuse_tbl.lock);
|
|
adapter->efuse_param.dv_sel = DDV;
|
adapter->efuse_param.efuse_ctrl = R_AX_EFUSE_CTRL;
|
adapter->efuse_param.read_efuse_cnt = EFUSE_WAIT_CNT;
|
|
return MACSUCCESS;
|
}
|
|
u32 efuse_info_exit(struct mac_ax_adapter *adapter)
|
{
|
struct mac_ax_efuse_param *efuse_param = &adapter->efuse_param;
|
struct mac_ax_efuse_ofld_info *efuse_ofld_info = &adapter->efuse_ofld_info;
|
|
PLTFM_MUTEX_DEINIT(&adapter->efuse_param.efuse_tbl.lock);
|
|
if (efuse_ofld_info->buf) {
|
PLTFM_FREE(efuse_ofld_info->buf, CMD_OFLD_MAX_LEN);
|
efuse_ofld_info->buf = NULL;
|
}
|
|
if (efuse_param->efuse_map) {
|
PLTFM_FREE(efuse_param->efuse_map,
|
adapter->hw_info->efuse_size);
|
efuse_param->efuse_map = (u8 *)NULL;
|
}
|
|
if (efuse_param->bt_efuse_map) {
|
PLTFM_FREE(efuse_param->bt_efuse_map,
|
adapter->hw_info->bt_efuse_size);
|
efuse_param->bt_efuse_map = (u8 *)NULL;
|
}
|
|
if (efuse_param->log_efuse_map) {
|
PLTFM_FREE(efuse_param->log_efuse_map,
|
adapter->hw_info->log_efuse_size);
|
efuse_param->log_efuse_map = (u8 *)NULL;
|
}
|
|
if (efuse_param->bt_log_efuse_map) {
|
PLTFM_FREE(efuse_param->bt_log_efuse_map,
|
adapter->hw_info->bt_log_efuse_size);
|
efuse_param->bt_log_efuse_map = (u8 *)NULL;
|
}
|
|
if (efuse_param->dav_efuse_map) {
|
PLTFM_FREE(efuse_param->dav_efuse_map,
|
adapter->hw_info->dav_efuse_size);
|
efuse_param->dav_efuse_map = (u8 *)NULL;
|
}
|
|
if (efuse_param->dav_log_efuse_map) {
|
PLTFM_FREE(efuse_param->dav_log_efuse_map,
|
adapter->hw_info->dav_log_efuse_size);
|
efuse_param->dav_log_efuse_map = (u8 *)NULL;
|
}
|
|
if (efuse_param->hidden_rf_map) {
|
PLTFM_FREE(efuse_param->hidden_rf_map,
|
adapter->hw_info->hidden_efuse_rf_size);
|
efuse_param->hidden_rf_map = (u8 *)NULL;
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 efuse_map_init(struct mac_ax_adapter *adapter,
|
enum efuse_map_sel map_sel)
|
{
|
u32 size;
|
struct mac_ax_efuse_param *efuse_param = &adapter->efuse_param;
|
|
switch (map_sel) {
|
case EFUSE_MAP_SEL_PHY_WL:
|
size = adapter->hw_info->efuse_size;
|
if (!efuse_param->efuse_map) {
|
efuse_param->efuse_map = (u8 *)PLTFM_MALLOC(size);
|
if (!efuse_param->efuse_map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
}
|
break;
|
case EFUSE_MAP_SEL_PHY_BT:
|
size = adapter->hw_info->bt_efuse_size;
|
if (!efuse_param->bt_efuse_map) {
|
efuse_param->bt_efuse_map = (u8 *)PLTFM_MALLOC(size);
|
if (!efuse_param->bt_efuse_map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
}
|
break;
|
case EFUSE_MAP_SEL_LOG:
|
size = adapter->hw_info->log_efuse_size;
|
if (!efuse_param->log_efuse_map) {
|
efuse_param->log_efuse_map = (u8 *)PLTFM_MALLOC(size);
|
if (!efuse_param->log_efuse_map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
}
|
break;
|
case EFUSE_MAP_SEL_LOG_BT:
|
size = adapter->hw_info->bt_log_efuse_size;
|
if (!efuse_param->bt_log_efuse_map) {
|
efuse_param->bt_log_efuse_map =
|
(u8 *)PLTFM_MALLOC(size);
|
if (!efuse_param->bt_log_efuse_map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
}
|
break;
|
case EFUSE_MAP_SEL_PHY_DAV:
|
size = adapter->hw_info->dav_efuse_size;
|
if (!efuse_param->dav_efuse_map) {
|
efuse_param->dav_efuse_map = (u8 *)PLTFM_MALLOC(size);
|
if (!efuse_param->dav_efuse_map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
}
|
break;
|
case EFUSE_MAP_SEL_LOG_DAV:
|
size = adapter->hw_info->dav_log_efuse_size;
|
if (!efuse_param->dav_log_efuse_map) {
|
efuse_param->dav_log_efuse_map =
|
(u8 *)PLTFM_MALLOC(size);
|
if (!efuse_param->dav_log_efuse_map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
}
|
break;
|
case EFUSE_MAP_SEL_HIDDEN_RF:
|
size = adapter->hw_info->hidden_efuse_rf_size;
|
if (!efuse_param->hidden_rf_map) {
|
efuse_param->hidden_rf_map = (u8 *)PLTFM_MALLOC(size);
|
if (!efuse_param->hidden_rf_map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
}
|
break;
|
default:
|
break;
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 efuse_fwcmd_ck(struct mac_ax_adapter *adapter)
|
{
|
/*Soar TBD*/
|
#ifdef NEVER
|
u32 ret;
|
|
ret = fwcmd_wq_idle(adapter,
|
SET_FWCMD_ID(FWCMD_TYPE_H2C,
|
FWCMD_H2C_CAT_MAC,
|
TBD,
|
TBD));
|
if (ret != 0) {
|
PLTFM_MSG_WARN("[WARN]H2C not idle(efuse)\n");
|
return ret;
|
}
|
#endif /* NEVER */
|
return MACSUCCESS;
|
}
|
|
static u32 efuse_proc_ck(struct mac_ax_adapter *adapter)
|
{
|
/*Soar TBD*/
|
#ifdef NEVER
|
u32 ret;
|
|
ret = efuse_fwcmd_ck(adapter);
|
if (ret != 0)
|
return ret;
|
#endif /* NEVER */
|
if (adapter->sm.efuse != MAC_AX_EFUSE_IDLE) {
|
PLTFM_MSG_WARN("[WARN]Proc not idle(efuse)\n");
|
return MACPROCBUSY;
|
}
|
|
if (adapter->sm.pwr != MAC_AX_PWR_ON)
|
PLTFM_MSG_ERR("[ERR]Access efuse in suspend\n");
|
|
return MACSUCCESS;
|
}
|
|
static u32 cnv_efuse_state(struct mac_ax_adapter *adapter, u8 dest_state)
|
{
|
#define BT_DISN_EN 1
|
#define BT_DISN_DIS 0
|
u8 cnt;
|
u32 val32, ret, bt_dis_state;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
|
if (adapter->sm.efuse >= MAC_AX_EFUSE_MAX)
|
return MACPROCERR;
|
|
if (adapter->sm.efuse == dest_state)
|
return MACPROCERR;
|
|
if (dest_state != MAC_AX_EFUSE_IDLE) {
|
if (adapter->sm.efuse != MAC_AX_EFUSE_IDLE)
|
return MACPROCERR;
|
}
|
|
adapter->sm.efuse = dest_state;
|
|
if (adapter->sm.efuse != MAC_AX_EFUSE_IDLE) {
|
bt_dis_state = mac_get_bt_dis(adapter);
|
if (bt_dis_state == BT_DISN_EN) {
|
ret = mac_set_bt_dis(adapter, BT_DISN_DIS);
|
if (ret != MACSUCCESS)
|
return ret;
|
}
|
|
cnt = BT_DIS_WAIT_CNT;
|
while (cnt) {
|
val32 = MAC_REG_R32(R_AX_IC_PWR_STATE);
|
val32 = GET_FIELD(val32, B_AX_WHOLE_SYS_PWR_STE);
|
if (val32 == MAC_AX_SYS_ACT)
|
break;
|
|
PLTFM_DELAY_US(BT_DIS_WAIT_US);
|
cnt--;
|
}
|
|
if (!cnt) {
|
PLTFM_MSG_ERR("[ERR]Whole system PWR state not ACT\n");
|
return MACSYSSTEERR;
|
}
|
} else {
|
bt_dis_state = mac_get_bt_dis(adapter);
|
if (bt_dis_state == BT_DISN_DIS) {
|
ret = mac_set_bt_dis(adapter, BT_DISN_EN);
|
if (ret != MACSUCCESS)
|
return ret;
|
}
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 proc_dump_efuse(struct mac_ax_adapter *adapter,
|
enum mac_ax_efuse_read_cfg cfg)
|
{
|
u32 ret;
|
struct rtw_phl_com_t *phl_com = (struct rtw_phl_com_t *)adapter->phl_adapter;
|
struct rtw_wcpu_cap_t *wcpu_cap = &phl_com->dev_cap.wcpu_cap;
|
bool cap_efuse_dump;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
bool is_bt = 0;
|
u32 log_efuse_size = *bank_efuse_info->log_map_size;
|
|
if (log_efuse_size == hw_info->bt_log_efuse_size)
|
is_bt = 1;
|
|
if (is_bt == 0) {
|
if (adapter->efuse_param.dv_sel == DAV)
|
cap_efuse_dump = (bool)(wcpu_cap->mac_ofld_cap.adie_efuse_dump_offload);
|
else
|
cap_efuse_dump = (bool)(wcpu_cap->mac_ofld_cap.efuse_dump_offload);
|
|
if (cfg == MAC_AX_EFUSE_R_AUTO) {
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY || cap_efuse_dump == false)
|
ret = dump_efuse_drv(adapter);
|
else
|
ret = dump_efuse_fw(adapter);
|
} else if (cfg == MAC_AX_EFUSE_R_FW) {
|
ret = dump_efuse_fw(adapter);
|
} else {
|
ret = dump_efuse_drv(adapter);
|
}
|
} else {
|
if (cfg == MAC_AX_EFUSE_R_FW)
|
ret = MACFWNOSUPPORT;
|
else
|
ret = dump_efuse_drv(adapter);
|
}
|
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]dump efsue drv/fw\n");
|
return ret;
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 read_hw_efuse(struct mac_ax_adapter *adapter, u32 offset, u32 size,
|
u8 *map)
|
{
|
u32 addr;
|
u32 tmp32 = 0;
|
u32 cnt;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
u32 efuse_start = *bank_efuse_info->efuse_start;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
enum rtw_dv_sel dv_sel = adapter->efuse_param.dv_sel;
|
u16 read_efuse_cnt = adapter->efuse_param.read_efuse_cnt;
|
u16 efuse_ctrl = adapter->efuse_param.efuse_ctrl;
|
|
offset += efuse_start;
|
|
if (dv_sel == DDV) {
|
p_ops->enable_efuse_sw_pwr_cut(adapter, 0);
|
|
for (addr = offset; addr < offset + size; addr++) {
|
MAC_REG_W32(efuse_ctrl,
|
((addr & B_AX_EF_ADDR_MSK) << B_AX_EF_ADDR_SH)
|
& ~B_AX_EF_RDY);
|
|
cnt = read_efuse_cnt;
|
if ((is_chip_id(adapter, MAC_AX_CHIP_ID_8852B) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8852C) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8851B) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8851E) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8852D) ||
|
is_chip_id(adapter, MAC_AX_CHIP_ID_8852BT)) &&
|
efuse_ctrl == R_AX_EFUSE_CTRL)
|
cnt = EFUSE_WAIT_CNT_PLUS;
|
|
while (--cnt) {
|
tmp32 = MAC_REG_R32(efuse_ctrl);
|
if (tmp32 & B_AX_EF_RDY)
|
break;
|
PLTFM_DELAY_US(1);
|
}
|
|
if (!cnt) {
|
PLTFM_MSG_ERR("[ERR]read efuse\n");
|
return MACEFUSEREAD;
|
}
|
|
*(map + addr - offset) = (u8)(tmp32 & 0xFF);
|
}
|
|
p_ops->disable_efuse_sw_pwr_cut(adapter, 0);
|
} else {
|
read_hw_efuse_dav(adapter, offset, size, map);
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 write_hw_efuse(struct mac_ax_adapter *adapter, u32 offset, u8 value)
|
{
|
//const u8 unlock_code = 0x69;
|
u8 value_read = 0;
|
u32 value32;
|
u32 cnt;
|
u32 ret;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
struct mac_ax_efuse_param *efuse_param = &adapter->efuse_param;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
u32 efuse_start = *bank_efuse_info->efuse_start;
|
enum rtw_dv_sel dv_sel = adapter->efuse_param.dv_sel;
|
u16 efuse_ctrl = adapter->efuse_param.efuse_ctrl;
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
*bank_efuse_info->phy_map_valid = 0;
|
*bank_efuse_info->log_map_valid = 0;
|
efuse_param->hidden_rf_map_valid = 0;
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
|
offset += efuse_start;
|
|
if (dv_sel == DDV) {
|
//MAC_REG_W8(R_AX_PMC_DBG_CTRL2 + 3, unlock_code);
|
|
value32 = value |
|
((offset & B_AX_EF_ADDR_MSK) << B_AX_EF_ADDR_SH);
|
value32 &= ~B_AX_EF_RDY;
|
MAC_REG_W32(efuse_ctrl,
|
value32 | (MODE_WRITE << B_AX_EF_MODE_SEL_SH));
|
|
cnt = EFUSE_WAIT_CNT;
|
while (--cnt) {
|
if (MAC_REG_R32(efuse_ctrl) & B_AX_EF_RDY)
|
break;
|
PLTFM_DELAY_US(1);
|
}
|
|
if (!cnt) {
|
PLTFM_MSG_ERR("[ERR]write efuse\n");
|
return MACEFUSEWRITE;
|
}
|
|
//MAC_REG_W8(R_AX_PMC_DBG_CTRL2 + 3, 0x00);
|
} else {
|
write_hw_efuse_dav(adapter, offset, value);
|
}
|
|
if (efuse_param->auto_ck_en == 1) {
|
ret = read_hw_efuse(adapter, offset, 1, &value_read);
|
if (ret != 0)
|
return ret;
|
|
if (value_read != value) {
|
PLTFM_MSG_ERR("[ERR]efuse compare\n");
|
return MACEFUSEWRITE;
|
}
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 cmp_hw_efuse(struct mac_ax_adapter *adapter, u32 offset, u16 val)
|
{
|
u32 val32;
|
u32 tmp32 = 0;
|
u32 cnt;
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
u16 efuse_ctrl = adapter->efuse_param.efuse_ctrl;
|
|
val32 = val | ((offset & B_AX_EF_ADDR_MSK) << B_AX_EF_ADDR_SH);
|
MAC_REG_W32(efuse_ctrl, val32 | (MODE_CMP << B_AX_EF_MODE_SEL_SH));
|
|
cnt = EFUSE_WAIT_CNT;
|
while (--cnt) {
|
tmp32 = MAC_REG_R32(efuse_ctrl);
|
if (tmp32 & B_AX_EF_RDY)
|
break;
|
PLTFM_DELAY_US(1);
|
}
|
|
if (!cnt) {
|
PLTFM_MSG_ERR("[ERR]compare efuse\n");
|
return MACEFUSEREAD;
|
}
|
|
if (0 == (tmp32 & B_AX_EF_COMP_RESULT))
|
return MACEFUSECMP;
|
|
return MACSUCCESS;
|
}
|
|
static u32 eeprom_parser(struct mac_ax_adapter *adapter, u8 *phy_map,
|
u8 *log_map, enum mac_ax_efuse_parser_cfg cfg)
|
{
|
u8 i;
|
u8 value8;
|
u8 blk_idx;
|
u8 word_en;
|
u8 valid;
|
u8 hdr = 0;
|
u8 hdr2 = 0;
|
u32 eeprom_idx;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
u32 sec_ctrl_size = hw_info->sec_ctrl_efuse_size;
|
u32 efuse_idx;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
u32 efuse_size = *bank_efuse_info->phy_map_size;
|
bool is_bt = 0;
|
u32 log_efuse_size = *bank_efuse_info->log_map_size;
|
|
PLTFM_MEMSET(log_map, 0xFF, log_efuse_size);
|
|
if (log_efuse_size == hw_info->bt_log_efuse_size) {
|
sec_ctrl_size = 0;
|
is_bt = 1;
|
}
|
efuse_idx = sec_ctrl_size;
|
|
do {
|
if (efuse_idx >= efuse_size) // secure zone
|
break;
|
|
value8 = *(phy_map + efuse_idx);
|
hdr = value8;
|
if (hdr == 0xff)
|
break;
|
efuse_idx++;
|
|
if (is_bt) {
|
if ((hdr & 0xF) != 0xF) {// 1byte entry
|
blk_idx = (hdr & 0xF0) >> 4;
|
word_en = hdr & 0x0F;
|
} else {// 2byte entry
|
value8 = *(phy_map + efuse_idx);
|
hdr2 = value8;
|
if (hdr2 == 0xff)
|
break;
|
|
blk_idx = (((hdr2 & 0xF0) >> 4) << 3) +
|
(((hdr & 0xF0) >> 4) >> 1); // offset
|
word_en = hdr2 & 0x0F;
|
|
efuse_idx++;
|
}
|
} else { // WLAN
|
value8 = *(phy_map + efuse_idx);
|
hdr2 = value8;
|
if (hdr2 == 0xff)
|
break;
|
|
blk_idx = ((hdr2 & 0xF0) >> 4) | ((hdr & 0x0F) << 4);
|
word_en = hdr2 & 0x0F;
|
|
efuse_idx++;
|
}
|
|
if (efuse_idx >= efuse_size - 1)
|
return MACEFUSEPARSE;
|
|
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) >
|
*bank_efuse_info->log_map_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]read hdr2:0x%X\n",
|
hdr2);
|
return MACEFUSEPARSE;
|
}
|
|
if (cfg == MAC_AX_EFUSE_PARSER_MAP) {
|
value8 = *(phy_map + efuse_idx);
|
*(log_map + eeprom_idx) = value8;
|
} else if (cfg == MAC_AX_EFUSE_PARSER_MASK) {
|
*(log_map + eeprom_idx) = 0x00;
|
}
|
|
eeprom_idx++;// 1 byte
|
efuse_idx++;
|
|
if (efuse_idx > efuse_size - 1)
|
return MACEFUSEPARSE;
|
|
if (cfg == MAC_AX_EFUSE_PARSER_MAP) {
|
value8 = *(phy_map + efuse_idx);
|
*(log_map + eeprom_idx) = value8;
|
} else if (cfg == MAC_AX_EFUSE_PARSER_MASK) {
|
*(log_map + eeprom_idx) = 0x00;
|
}
|
|
efuse_idx++;
|
|
if (efuse_idx > efuse_size)
|
return MACEFUSEPARSE;
|
}
|
}
|
} while (1);
|
|
*bank_efuse_info->efuse_end = efuse_idx;
|
|
return MACSUCCESS;
|
}
|
|
static u32 read_log_efuse_map(struct mac_ax_adapter *adapter, u8 *map,
|
u32 log_efuse_size)
|
{
|
u8 *local_map = NULL;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
u32 efuse_size = *bank_efuse_info->phy_map_size;
|
u32 ret;
|
|
if (!*bank_efuse_info->phy_map || !*bank_efuse_info->log_map) {
|
PLTFM_MSG_ERR("[ERR]malloc map: bank_efuse_info\n");
|
return MACBUFALLOC;
|
}
|
|
if (*bank_efuse_info->log_map_valid == 0) {
|
if (*bank_efuse_info->phy_map_valid == 0) {
|
local_map = (u8 *)PLTFM_MALLOC(efuse_size);
|
if (!local_map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
|
ret = read_efuse(adapter, 0, efuse_size, local_map);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]read efuse\n");
|
goto error;
|
}
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_MEMCPY(*bank_efuse_info->phy_map, local_map,
|
efuse_size);
|
*bank_efuse_info->phy_map_valid = 1;
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
|
PLTFM_FREE(local_map, efuse_size);
|
}
|
|
ret = eeprom_parser(adapter, *bank_efuse_info->phy_map, map,
|
MAC_AX_EFUSE_PARSER_MAP);
|
if (ret != 0)
|
return ret;
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_MEMCPY(*bank_efuse_info->log_map, map, log_efuse_size);
|
*bank_efuse_info->log_map_valid = 1;
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
} else {
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_MEMCPY(map, *bank_efuse_info->log_map, log_efuse_size);
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
}
|
|
return MACSUCCESS;
|
error:
|
PLTFM_FREE(local_map, efuse_size);
|
return ret;
|
}
|
|
static u32 proc_pg_efuse_by_map(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info,
|
enum mac_ax_efuse_read_cfg cfg)
|
{
|
u8 *updated_mask = NULL;
|
u32 ret;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
u32 log_efuse_size = *bank_efuse_info->log_map_size;
|
u32 mask_size = log_efuse_size >> 4;
|
|
updated_mask = (u8 *)PLTFM_MALLOC(mask_size);
|
if (!updated_mask) {
|
PLTFM_MSG_ERR("[ERR]malloc updated mask\n");
|
return MACBUFALLOC;
|
}
|
PLTFM_MEMSET(updated_mask, 0x00, mask_size);
|
|
ret = update_eeprom_mask(adapter, info, updated_mask, 0);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]update eeprom mask\n");
|
goto error;
|
}
|
|
ret = check_efuse_enough(adapter, info, updated_mask);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]chk efuse enough\n");
|
goto error;
|
}
|
|
ret = program_efuse(adapter, info, updated_mask, 0);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]pg efuse\n");
|
goto error;
|
}
|
|
PLTFM_FREE(updated_mask, mask_size);
|
return MACSUCCESS;
|
error:
|
PLTFM_FREE(updated_mask, mask_size);
|
return ret;
|
}
|
|
static u32 dump_efuse_drv(struct mac_ax_adapter *adapter)
|
{
|
u8 *map = NULL;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
u32 efuse_size = *bank_efuse_info->phy_map_size;
|
u32 ret;
|
|
PLTFM_MSG_TRACE("[TRACE]%s\n", __func__);
|
|
if (*bank_efuse_info->phy_map_valid == 0) {
|
map = (u8 *)PLTFM_MALLOC(efuse_size);
|
if (!map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
|
ret = read_hw_efuse(adapter, 0, efuse_size, map);
|
if (ret != 0) {
|
PLTFM_FREE(map, efuse_size);
|
return ret;
|
}
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_MEMCPY(*bank_efuse_info->phy_map, map, efuse_size);
|
*bank_efuse_info->phy_map_valid = 1;
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_FREE(map, efuse_size);
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 dump_efuse_fw(struct mac_ax_adapter *adapter)
|
{
|
u32 ret, cnt;
|
struct mac_ax_ops *ops = adapter->ops;
|
u8 *map = NULL;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
u32 efuse_size = *bank_efuse_info->phy_map_size;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
u8 ofld_type = 0;
|
|
PLTFM_MSG_TRACE("[TRACE]%s\n", __func__);
|
|
if (*bank_efuse_info->phy_map_valid == 0) {
|
if (bank_efuse_info->phy_map_size == &hw_info->dav_efuse_size)
|
ofld_type = DUMP_OFLD_TYPE_DAV;
|
|
/* H2C */
|
ret = ops->dump_efuse_ofld(adapter, efuse_size, ofld_type);
|
if (ret)
|
return ret;
|
|
/* Wait for C2H */
|
if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852A))
|
cnt = EFUSE_FW_DUMP_WAIT_CNT;
|
else
|
cnt = EFUSE_FW_DUMP_WAIT_CNT_V1;
|
|
while (--cnt) {
|
if (adapter->sm.efuse_ofld == MAC_AX_OFLD_H2C_DONE)
|
break;
|
PLTFM_DELAY_MS(1);
|
}
|
if (!cnt) {
|
PLTFM_MSG_ERR("[ERR]efuse C2H\n");
|
adapter->sm.efuse_ofld = MAC_AX_OFLD_H2C_IDLE;
|
return MACPROCERR;
|
}
|
|
/* cpy map */
|
map = (u8 *)PLTFM_MALLOC(efuse_size);
|
if (!map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
PLTFM_MEMSET(map, 0xFF, efuse_size);
|
|
ret = ops->efuse_ofld_map(adapter, map, efuse_size);
|
if (ret) {
|
PLTFM_FREE(map, efuse_size);
|
return ret;
|
}
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_MEMCPY(*bank_efuse_info->phy_map, map, efuse_size);
|
*bank_efuse_info->phy_map_valid = 1;
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_FREE(map, efuse_size);
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 proc_write_log_efuse(struct mac_ax_adapter *adapter, u32 offset,
|
u8 value)
|
{
|
u8 byte1;
|
u8 byte2;
|
u8 blk;
|
u8 blk_idx;
|
u8 hdr;
|
u8 hdr2 = 0;
|
u8 *map = NULL;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
u32 log_efuse_size = *bank_efuse_info->log_map_size;
|
u32 end, ret;
|
bool is_bt = 0;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
|
map = (u8 *)PLTFM_MALLOC(log_efuse_size);
|
if (!map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
|
if (*bank_efuse_info->log_map_valid == 0) {
|
ret = read_log_efuse_map(adapter, map, log_efuse_size);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]read logical efuse\n");
|
PLTFM_FREE(map, log_efuse_size);
|
return ret;
|
}
|
} else {
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
PLTFM_MEMCPY(map, *bank_efuse_info->log_map, log_efuse_size);
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
}
|
|
if (log_efuse_size == adapter->hw_info->bt_log_efuse_size)
|
is_bt = 1;
|
|
if (*(map + offset) != value) {
|
end = *bank_efuse_info->efuse_end;
|
|
if (is_bt) {
|
if (offset < BT_1B_ENTRY_SIZE) { // 1 byte entry
|
blk = (u8)(offset >> 3);
|
blk_idx = (u8)((offset & (8 - 1)) >> 1);//mod8
|
|
hdr = (u8)((blk << 4) +
|
((0x1 << blk_idx) ^ 0x0F));
|
} else { // 2 byte entry
|
blk = (u8)(offset >> 3 >> 3); // large section
|
blk_idx = (u8)(((offset >> 3) & (8 - 1)) << 1);
|
hdr = (u8)((blk_idx << 4) + 0xF);
|
|
blk_idx = (u8)((offset & (8 - 1)) >> 1);
|
hdr2 = (u8)((blk << 4) +
|
((0x1 << blk_idx) ^ 0x0F));
|
}
|
} else {
|
blk = (u8)(offset >> 3);// offset
|
blk_idx = (u8)((offset & (8 - 1)) >> 1); // mod8 0 1 2 3
|
|
hdr = ((blk & 0xF0) >> 4) | 0x30;
|
hdr2 = (u8)(((blk & 0x0F) << 4) +
|
((0x1 << blk_idx) ^ 0x0F));
|
}
|
|
if ((offset & 1) == 0) {
|
byte1 = value;
|
byte2 = *(map + offset + 1);
|
} else {
|
byte1 = *(map + offset - 1);
|
byte2 = value;
|
}
|
|
if (*bank_efuse_info->phy_map_size <= 4 + end) { // write 4 bytes
|
PLTFM_FREE(map, log_efuse_size);
|
return MACEFUSESIZE;
|
}
|
|
p_ops->enable_efuse_sw_pwr_cut(adapter, 1);
|
|
ret = write_hw_efuse(adapter, end, hdr);
|
if (ret != 0)
|
goto error;
|
|
if (!is_bt || offset >= BT_1B_ENTRY_SIZE) {
|
ret = write_hw_efuse(adapter, end + 1, hdr2);
|
if (ret != 0)
|
goto error;
|
end++;
|
}
|
|
ret = write_hw_efuse(adapter, end + 1, byte1);
|
if (ret != 0)
|
goto error;
|
|
ret = write_hw_efuse(adapter, end + 2, byte2);
|
if (ret != 0)
|
goto error;
|
|
p_ops->disable_efuse_sw_pwr_cut(adapter, 1);
|
}
|
|
PLTFM_FREE(map, log_efuse_size);
|
return MACSUCCESS;
|
error:
|
PLTFM_FREE(map, log_efuse_size);
|
return ret;
|
}
|
|
static u32 read_efuse(struct mac_ax_adapter *adapter, u32 offset, u32 size,
|
u8 *map)
|
{
|
u32 ret;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
|
if (!map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
|
if (*bank_efuse_info->phy_map_valid == 1) {
|
PLTFM_MEMCPY(map, *bank_efuse_info->phy_map + offset, size);
|
} else {
|
ret = read_hw_efuse(adapter, offset, size, map);
|
if (ret != 0)
|
return ret;
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 update_eeprom_mask(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info,
|
u8 *updated_mask, bool pg_sim)
|
{
|
u8 *map = NULL;
|
u8 *mask_map = NULL;
|
u8 clr_bit = 0;
|
u8 *map_pg;
|
u8 *efuse_mask;
|
u32 i;
|
u16 j;
|
u16 map_offset;
|
u16 mask_offset;
|
u32 ret;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
u32 log_efuse_size = *bank_efuse_info->log_map_size;
|
|
map = (u8 *)PLTFM_MALLOC(log_efuse_size);
|
if (!map) {
|
PLTFM_MSG_ERR("[ERR]malloc map\n");
|
return MACBUFALLOC;
|
}
|
PLTFM_MEMSET(map, 0xFF, log_efuse_size); // default: 0xFF
|
|
if (pg_sim) { //WL
|
PLTFM_MEMCPY(map, *bank_efuse_info->log_map, log_efuse_size);
|
} else {
|
ret = read_log_efuse_map(adapter, map, log_efuse_size);
|
if (ret != 0)
|
goto error;
|
}
|
|
/*log mask*/
|
mask_map = (u8 *)PLTFM_MALLOC(log_efuse_size);
|
if (!mask_map) {
|
PLTFM_MSG_ERR("[ERR]malloc mask map\n");
|
PLTFM_FREE(map, log_efuse_size);
|
return MACBUFALLOC;
|
}
|
PLTFM_MEMSET(mask_map, 0xFF, log_efuse_size);// default: 0xFF
|
|
ret = eeprom_parser(adapter, *bank_efuse_info->phy_map,
|
mask_map, MAC_AX_EFUSE_PARSER_MASK);
|
if (ret != 0) {
|
PLTFM_FREE(mask_map, log_efuse_size);
|
goto error;
|
}
|
|
map_pg = info->efuse_map;
|
efuse_mask = info->efuse_mask;
|
|
PLTFM_MEMCPY(updated_mask, efuse_mask, info->efuse_mask_size);
|
|
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) &&
|
*(mask_map + map_offset) == 0x00) {
|
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, log_efuse_size);
|
PLTFM_FREE(mask_map, log_efuse_size);
|
return MACSUCCESS;
|
error:
|
PLTFM_FREE(map, log_efuse_size);
|
return ret;
|
}
|
|
static u32 check_efuse_enough(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info,
|
u8 *updated_mask)
|
{
|
u8 pre_word_en;
|
u32 i;
|
u16 j;
|
u32 eeprom_offset;
|
u32 pg_num = 0;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
|
for (i = 0; i < info->efuse_map_size; i += 8) {
|
eeprom_offset = i;
|
|
if ((eeprom_offset & 0xF) > 0)
|
pre_word_en = (*(updated_mask + (i >> 4)) & 0x0F);
|
else
|
pre_word_en = (*(updated_mask + (i >> 4)) >> 4);
|
|
if (pre_word_en > 0) { // msk ==1 -> write
|
pg_num += 2;
|
for (j = 0; j < 4; j++) {
|
if (((pre_word_en >> j) & 0x1) > 0)
|
pg_num += 2;
|
}
|
}
|
}
|
|
if (*bank_efuse_info->phy_map_size
|
< (pg_num + *bank_efuse_info->efuse_end))
|
return MACEFUSESIZE;
|
|
return MACSUCCESS;
|
}
|
|
static u32 proc_pg_efuse(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info, u8 word_en,
|
u8 pre_word_en, u32 eeprom_offset, bool pg_sim)
|
{
|
u8 blk, blk_idx;
|
u8 hdr;
|
u8 hdr2 = 0xFF;
|
u8 i;
|
u32 efuse_end, ret;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
u8 *efuse_map = *bank_efuse_info->phy_map;
|
bool is_bt = 0;
|
|
if (info->efuse_map_size == adapter->hw_info->bt_log_efuse_size)
|
is_bt = 1;
|
|
efuse_end = *bank_efuse_info->efuse_end;
|
|
if (is_bt) {
|
if (eeprom_offset < BT_1B_ENTRY_SIZE) {
|
blk = (u8)(eeprom_offset >> 3);
|
hdr = (u8)((blk << 4) + word_en);
|
} else {
|
blk = (u8)(eeprom_offset >> 3 >> 3);
|
blk_idx = (u8)(((eeprom_offset >> 3) & (8 - 1)) << 1);
|
hdr = (u8)((blk_idx << 4) | 0xF);
|
hdr2 = (u8)((blk << 4) + word_en);
|
}
|
} else {
|
blk = (u8)(eeprom_offset >> 3);
|
hdr = ((blk & 0xF0) >> 4) | 0x30;
|
hdr2 = (u8)(((blk & 0x0F) << 4) + word_en);
|
}
|
|
if (pg_sim) { //WL
|
*(efuse_map + efuse_end) = hdr;
|
*(efuse_map + efuse_end + 1) = hdr2;
|
|
efuse_end += 2;
|
|
for (i = 0; i < 4; i++) {
|
if (((pre_word_en >> i) & 0x1) > 0) {
|
*(efuse_map + efuse_end) = *(info->efuse_map +
|
eeprom_offset + (i << 1));
|
efuse_end++;
|
|
*(efuse_map + efuse_end) = *(info->efuse_map +
|
eeprom_offset + (i << 1) + 1);
|
efuse_end++;
|
}
|
}
|
} else {
|
ret = write_hw_efuse(adapter, efuse_end, hdr);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]write efuse\n");
|
return ret;
|
}
|
|
if (is_bt == 0 || eeprom_offset >= BT_1B_ENTRY_SIZE) {
|
ret = write_hw_efuse(adapter, efuse_end + 1, hdr2);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]write efuse(+1)\n");
|
return ret;
|
}
|
efuse_end++;
|
}
|
|
efuse_end++;
|
for (i = 0; i < 4; i++) {
|
if (((pre_word_en >> i) & 0x1) > 0) {
|
ret = write_hw_efuse(adapter, efuse_end,
|
*(info->efuse_map +
|
eeprom_offset + (i << 1)));
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]write efuse\n");
|
return ret;
|
}
|
|
ret = write_hw_efuse(adapter, efuse_end + 1,
|
*(info->efuse_map +
|
eeprom_offset +
|
(i << 1) + 1));
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]write efuse+1\n");
|
return ret;
|
}
|
efuse_end = efuse_end + 2;
|
}
|
}
|
}
|
*bank_efuse_info->efuse_end = efuse_end;
|
return MACSUCCESS;
|
}
|
|
static u32 program_efuse(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info, u8 *updated_mask,
|
bool pg_sim)
|
{
|
u8 pre_word_en;
|
u8 word_en;
|
u32 i;
|
u32 eeprom_offset, ret;
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
|
p_ops->enable_efuse_sw_pwr_cut(adapter, 1);
|
|
for (i = 0; i < info->efuse_map_size; 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) {
|
ret = proc_pg_efuse(adapter, info, word_en, pre_word_en,
|
eeprom_offset, pg_sim);
|
if (ret != 0) {
|
PLTFM_MSG_ERR("[ERR]pg efuse");
|
return ret;
|
}
|
}
|
}
|
|
p_ops->disable_efuse_sw_pwr_cut(adapter, 1);
|
|
return MACSUCCESS;
|
}
|
|
static void mask_eeprom(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info)
|
{
|
u8 pre_word_en;
|
u8 *updated_mask;
|
u8 *efuse_map;
|
u32 i;
|
u16 j;
|
u32 offset;
|
|
updated_mask = info->efuse_mask;
|
efuse_map = info->efuse_map;
|
|
for (i = 0; i < info->efuse_map_size; 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;
|
}
|
}
|
}
|
}
|
|
static u32 query_status_map(struct mac_ax_adapter *adapter,
|
enum mac_ax_efuse_feature_id feature_id,
|
u8 *map, bool is_limit)
|
{
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
enum mac_ax_intf intf = adapter->hw_info->intf;
|
u32 map_size = 0;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
switch (feature_id) {
|
case MAC_AX_DUMP_PHYSICAL_EFUSE:
|
map_size = *bank_efuse_info->phy_map_size;
|
PLTFM_MEMCPY(map, *bank_efuse_info->phy_map, map_size);
|
break;
|
case MAC_AX_DUMP_LOGICAL_EFUSE:
|
if (!is_limit) {
|
map_size = *bank_efuse_info->log_map_size;
|
} else {// WL
|
switch (intf) {
|
case MAC_AX_INTF_PCIE:
|
map_size = hw_info->limit_efuse_size_pcie;
|
break;
|
case MAC_AX_INTF_USB:
|
map_size = hw_info->limit_efuse_size_usb;
|
break;
|
case MAC_AX_INTF_SDIO:
|
map_size = hw_info->limit_efuse_size_sdio;
|
break;
|
default:
|
break;
|
}
|
}
|
PLTFM_MEMCPY(map, *bank_efuse_info->log_map, map_size);
|
break;
|
default:
|
return MACFUNCINPUT;
|
}
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
|
return MACSUCCESS;
|
}
|
|
static u32 adjust_mask(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info)
|
{
|
u8 *efuse_mask = info->efuse_mask;
|
u8 *efuse_map = info->efuse_map;
|
u32 i = 0;
|
u16 j = 0;
|
u16 map_offset;
|
u16 mask_offset;
|
u8 adj_bit = 0;
|
|
PLTFM_MEMSET(efuse_mask, 0xFF, info->efuse_mask_size);
|
|
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 *)(efuse_map + map_offset) == 0xFFFF) {
|
switch (j) {
|
case 0:
|
adj_bit = BIT(4);
|
break;
|
case 2:
|
adj_bit = BIT(5);
|
break;
|
case 4:
|
adj_bit = BIT(6);
|
break;
|
case 6:
|
adj_bit = BIT(7);
|
break;
|
case 8:
|
adj_bit = BIT(0);
|
break;
|
case 10:
|
adj_bit = BIT(1);
|
break;
|
case 12:
|
adj_bit = BIT(2);
|
break;
|
case 14:
|
adj_bit = BIT(3);
|
break;
|
}
|
*(efuse_mask + mask_offset) &= ~adj_bit;
|
}
|
}
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 compare_info_length(struct efuse_info *info,
|
enum rtw_efuse_info id, u32 length)
|
{
|
u32 idle_len;
|
|
switch (id) {
|
case EFUSE_INFO_MAC_ADDR:
|
idle_len = info->len->mac_addr;
|
break;
|
case EFUSE_INFO_MAC_PID:
|
idle_len = info->len->pid;
|
break;
|
case EFUSE_INFO_MAC_DID:
|
idle_len = info->len->did;
|
break;
|
case EFUSE_INFO_MAC_VID:
|
idle_len = info->len->vid;
|
break;
|
case EFUSE_INFO_MAC_SVID:
|
idle_len = info->len->svid;
|
break;
|
case EFUSE_INFO_MAC_SMID:
|
idle_len = info->len->smid;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
|
if (length != idle_len || idle_len == 0)
|
return MACLENCMP;
|
|
return MACSUCCESS;
|
}
|
|
static u32 set_check_sum_val(struct mac_ax_adapter *adapter,
|
u8 *map, u16 value)
|
{
|
u8 byte1;
|
u8 byte2;
|
u8 blk;
|
u8 blk_idx;
|
u8 hdr;
|
u8 hdr2;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
u32 end = *bank_efuse_info->efuse_end, ret;
|
u32 offset = chksum_offset_1;
|
u8 i = 0;
|
u8 value8 = (u8)(value & 0xFF);
|
struct mac_ax_priv_ops *p_ops = adapter_to_priv_ops(adapter);
|
|
p_ops->enable_efuse_sw_pwr_cut(adapter, 1);
|
|
for (i = 0; i < 2; i++) {
|
blk = (u8)(offset >> 3);
|
blk_idx = (u8)((offset & (8 - 1)) >> 1);
|
|
hdr = ((blk & 0xF0) >> 4) | 0x30;
|
hdr2 = (u8)(((blk & 0x0F) << 4) + ((0x1 << blk_idx) ^ 0x0F));
|
|
if ((offset & 1) == 0) {
|
byte1 = value8;
|
byte2 = *(map + offset + 1);
|
} else {
|
byte1 = (u8)(value & 0xFF);
|
byte2 = value8;
|
}
|
|
if (*bank_efuse_info->phy_map_size <= 4 + end)
|
return MACEFUSESIZE;
|
|
ret = write_hw_efuse(adapter, end, hdr);
|
if (ret != 0)
|
return ret;
|
|
ret = write_hw_efuse(adapter, end + 1, hdr2);
|
if (ret != 0)
|
return ret;
|
|
ret = write_hw_efuse(adapter, end + 2, byte1);
|
if (ret != 0)
|
return ret;
|
|
ret = write_hw_efuse(adapter, end + 3, byte2);
|
if (ret != 0)
|
return ret;
|
|
offset = chksum_offset_2;
|
value8 = (u8)((value & 0xFF00) >> 8);
|
end += 4;
|
}
|
|
p_ops->disable_efuse_sw_pwr_cut(adapter, 1);
|
|
return MACSUCCESS;
|
}
|
|
static void cal_check_sum(struct mac_ax_adapter *adapter, u16 *chksum)
|
{
|
u32 i = 0;
|
struct mac_ax_hw_info *hw_info = adapter->hw_info;
|
struct mac_ax_efuse_param *efuse_param = &adapter->efuse_param;
|
u8 *map = efuse_param->log_efuse_map;
|
u16 *data;
|
|
data = (u16 *)map;
|
|
*chksum = 0x0000;
|
for (i = 0; i < hw_info->log_efuse_size >> 2; i++) {
|
if (i == chksum_offset_1 >> 2)
|
*chksum ^= 0x0000 ^ *(data + (2 * i + 1));
|
else
|
*chksum ^= *(data + 2 * i) ^ *(data + (2 * i + 1));
|
}
|
}
|
|
static u32 compare_version(struct mac_ax_adapter *adapter,
|
struct mac_ax_pg_efuse_info *info, u32 ver_len)
|
{
|
u8 *map = info->efuse_map;
|
u8 *mask = info->efuse_mask;
|
u32 map_size = info->efuse_map_size;
|
u32 i = 0;
|
|
for (i = 0; i < ver_len; i++) {
|
if (*(map + map_size + i) != *(mask + (map_size >> 4) + i))
|
return MACVERERR;
|
}
|
return MACSUCCESS;
|
}
|
|
u32 enable_efuse_pwr_cut_dav(struct mac_ax_adapter *adapter,
|
bool is_write)
|
{
|
u32 ret;
|
u8 chip_id = adapter->hw_info->chip_id;
|
|
if (!(is_write))
|
return MACSUCCESS;
|
|
if (chip_id == MAC_AX_CHIP_ID_8852A) {
|
return MACSUCCESS;
|
} else {
|
ret = mac_write_xtal_si(adapter, XTAL_SI_PWR_CUT,
|
XTAL_SI_SMALL_PWR_CUT,
|
XTAL_SI_SMALL_PWR_CUT);
|
if (ret)
|
return ret;
|
|
ret = mac_write_xtal_si(adapter, XTAL_SI_PWR_CUT,
|
XTAL_SI_BIG_PWR_CUT,
|
XTAL_SI_BIG_PWR_CUT);
|
if (ret)
|
return ret;
|
}
|
|
return MACSUCCESS;
|
}
|
|
u32 disable_efuse_pwr_cut_dav(struct mac_ax_adapter *adapter,
|
bool is_write)
|
{
|
u32 ret;
|
u8 chip_id = adapter->hw_info->chip_id;
|
|
if (!(is_write))
|
return MACSUCCESS;
|
|
if (chip_id == MAC_AX_CHIP_ID_8852A) {
|
return MACSUCCESS;
|
} else {
|
ret = mac_write_xtal_si(adapter, XTAL_SI_PWR_CUT, 0,
|
XTAL_SI_BIG_PWR_CUT);
|
if (ret)
|
return ret;
|
|
ret = mac_write_xtal_si(adapter, XTAL_SI_PWR_CUT, 0,
|
XTAL_SI_SMALL_PWR_CUT);
|
if (ret)
|
return ret;
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 read_hw_efuse_dav(struct mac_ax_adapter *adapter, u32 offset, u32 size,
|
u8 *map)
|
{
|
u32 addr;
|
u8 tmp8;
|
u32 cnt;
|
u32 ret;
|
|
ret = enable_efuse_pwr_cut_dav(adapter, 0);
|
if (ret)
|
return ret;
|
|
for (addr = offset; addr < offset + size; addr++) {
|
/* clear ready bit*/
|
ret = mac_write_xtal_si(adapter, XTAL_SI_CTRL, 0x40, FULL_BIT_MASK);
|
if (ret)
|
return ret;
|
/* set addr */
|
ret = mac_write_xtal_si(adapter, XTAL_SI_LOW_ADDR,
|
(addr & 0xff) << XTAL_SI_LOW_ADDR_SH,
|
XTAL_SI_LOW_ADDR_MSK);
|
if (ret)
|
return ret;
|
ret = mac_write_xtal_si(adapter, XTAL_SI_CTRL, (addr >> 8)
|
<< XTAL_SI_HIGH_ADDR_SH,
|
XTAL_SI_HIGH_ADDR_MSK
|
<< XTAL_SI_HIGH_ADDR_SH);
|
if (ret)
|
return ret;
|
/* set ctrl mode sel */
|
ret = mac_write_xtal_si(adapter, XTAL_SI_CTRL, 0,
|
XTAL_SI_MODE_SEL_MSK
|
<< XTAL_SI_MODE_SEL_SH);
|
if (ret)
|
return ret;
|
|
/* polling */
|
cnt = EFUSE_WAIT_CNT;
|
while (--cnt) {
|
ret = mac_read_xtal_si(adapter, XTAL_SI_CTRL, &tmp8);
|
if (ret)
|
return ret;
|
if (tmp8 & XTAL_SI_RDY)
|
break;
|
PLTFM_DELAY_US(1);
|
}
|
if (!cnt) {
|
PLTFM_MSG_ERR("[ERR]read efuse\n");
|
return MACEFUSEREAD;
|
}
|
|
ret = mac_read_xtal_si(adapter, XTAL_SI_READ_VAL, &tmp8);
|
if (ret)
|
return ret;
|
*(map + addr - offset) = tmp8;
|
}
|
|
ret = disable_efuse_pwr_cut_dav(adapter, 0);
|
if (ret)
|
return ret;
|
|
return MACSUCCESS;
|
}
|
|
static u32 write_hw_efuse_dav(struct mac_ax_adapter *adapter, u32 offset,
|
u8 value)
|
{
|
u32 cnt;
|
u32 ret;
|
u8 tmp8;
|
struct mac_bank_efuse_info *bank_efuse_info = &adapter->efuse_param.bank_efuse_info;
|
|
PLTFM_MUTEX_LOCK(&adapter->efuse_param.efuse_tbl.lock);
|
*bank_efuse_info->phy_map_valid = 0;
|
*bank_efuse_info->log_map_valid = 0;
|
PLTFM_MUTEX_UNLOCK(&adapter->efuse_param.efuse_tbl.lock);
|
|
/* clear ready bit*/
|
ret = mac_write_xtal_si(adapter, XTAL_SI_CTRL, 0x40, FULL_BIT_MASK);
|
if (ret)
|
return ret;
|
/* set val */
|
ret = mac_write_xtal_si(adapter, XTAL_SI_WRITE_VAL, value <<
|
XTAL_SI_WRITE_DATA_SH, XTAL_SI_WRITE_DATA_MSK <<
|
XTAL_SI_WRITE_DATA_SH);
|
if (ret)
|
return ret;
|
/* set addr */
|
ret = mac_write_xtal_si(adapter, XTAL_SI_LOW_ADDR, (offset & 0xff)
|
<< XTAL_SI_LOW_ADDR_SH,
|
XTAL_SI_LOW_ADDR_MSK << XTAL_SI_LOW_ADDR_SH);
|
if (ret)
|
return ret;
|
ret = mac_write_xtal_si(adapter, XTAL_SI_CTRL, (offset >> 8)
|
<< XTAL_SI_HIGH_ADDR_SH,
|
XTAL_SI_HIGH_ADDR_MSK << XTAL_SI_HIGH_ADDR_SH);
|
if (ret)
|
return ret;
|
/* set ctrl mode sel */
|
ret = mac_write_xtal_si(adapter, XTAL_SI_CTRL, 0x2
|
<< XTAL_SI_MODE_SEL_SH,
|
XTAL_SI_MODE_SEL_MSK << XTAL_SI_MODE_SEL_SH);
|
if (ret)
|
return ret;
|
|
/* polling */
|
cnt = EFUSE_WAIT_CNT;
|
while (--cnt) {
|
ret = mac_read_xtal_si(adapter, XTAL_SI_CTRL, &tmp8);
|
if (ret)
|
return ret;
|
if (tmp8 & XTAL_SI_RDY)
|
break;
|
PLTFM_DELAY_US(1);
|
}
|
if (!cnt) {
|
PLTFM_MSG_ERR("[ERR]write efuse\n");
|
return MACEFUSEREAD;
|
}
|
|
return MACSUCCESS;
|
}
|
|
static void switch_dv(struct mac_ax_adapter *adapter, enum rtw_dv_sel sel)
|
{
|
adapter->efuse_param.dv_sel = sel;
|
PLTFM_MSG_TRACE("[TRACE]dv_sel= 0x%x, adapter->dv_sel = 0x%x\n",
|
sel, adapter->efuse_param.dv_sel);
|
}
|