ath10k: select board data based on BMI chip id and board id

QCA99X0 uses radio specific board names based on chip id and
board id combinations. We get these IDs from the target using BMI after otp.bin
has been started.

This patch reorders the call to the function ath10k_core_fetch_board_file
so that we have OTP binary before requesting for boardid-chipid. We get this
OTP data after parsing firmware-N.bin.

[kvalo@qca.qualcomm.com: try BMI_PARAM_GET_EEPROM_BOARD_ID with
 all boards and detect if command is not supported]
Signed-off-by: Manikanta Pubbisetty <c_mpubbi@qti.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
Manikanta Pubbisetty 2015-10-09 11:55:59 +03:00 committed by Kalle Valo
parent 0a51b343ab
commit db0984e51a
4 changed files with 93 additions and 8 deletions
drivers/net/wireless/ath/ath10k

View File

@ -82,6 +82,16 @@ enum bmi_cmd_id {
#define BMI_NVRAM_SEG_NAME_SZ 16 #define BMI_NVRAM_SEG_NAME_SZ 16
#define BMI_PARAM_GET_EEPROM_BOARD_ID 0x10
#define ATH10K_BMI_BOARD_ID_FROM_OTP_MASK 0x7c00
#define ATH10K_BMI_BOARD_ID_FROM_OTP_LSB 10
#define ATH10K_BMI_CHIP_ID_FROM_OTP_MASK 0x18000
#define ATH10K_BMI_CHIP_ID_FROM_OTP_LSB 15
#define ATH10K_BMI_BOARD_ID_STATUS_MASK 0xff
struct bmi_cmd { struct bmi_cmd {
__le32 id; /* enum bmi_cmd_id */ __le32 id; /* enum bmi_cmd_id */
union { union {

View File

@ -448,6 +448,56 @@ out:
return ret; return ret;
} }
static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
{
u32 result, address;
u8 board_id, chip_id;
int ret;
address = ar->hw_params.patch_load_addr;
if (!ar->otp_data || !ar->otp_len) {
ath10k_warn(ar,
"failed to retrieve board id because of invalid otp\n");
return -ENODATA;
}
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot upload otp to 0x%x len %zd for board id\n",
address, ar->otp_len);
ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len);
if (ret) {
ath10k_err(ar, "could not write otp for board id check: %d\n",
ret);
return ret;
}
ret = ath10k_bmi_execute(ar, address, BMI_PARAM_GET_EEPROM_BOARD_ID,
&result);
if (ret) {
ath10k_err(ar, "could not execute otp for board id check: %d\n",
ret);
return ret;
}
board_id = MS(result, ATH10K_BMI_BOARD_ID_FROM_OTP);
chip_id = MS(result, ATH10K_BMI_CHIP_ID_FROM_OTP);
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot get otp board id result 0x%08x board_id %d chip_id %d\n",
result, board_id, chip_id);
if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0)
return -EOPNOTSUPP;
ar->id.bmi_ids_valid = true;
ar->id.bmi_board_id = board_id;
ar->id.bmi_chip_id = chip_id;
return 0;
}
static int ath10k_download_and_run_otp(struct ath10k *ar) static int ath10k_download_and_run_otp(struct ath10k *ar)
{ {
u32 result, address = ar->hw_params.patch_load_addr; u32 result, address = ar->hw_params.patch_load_addr;
@ -792,12 +842,22 @@ err:
static int ath10k_core_create_board_name(struct ath10k *ar, char *name, static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
size_t name_len) size_t name_len)
{ {
if (ar->id.bmi_ids_valid) {
scnprintf(name, name_len,
"bus=%s,bmi-chip-id=%d,bmi-board-id=%d",
ath10k_bus_str(ar->hif.bus),
ar->id.bmi_chip_id,
ar->id.bmi_board_id);
goto out;
}
scnprintf(name, name_len, scnprintf(name, name_len,
"bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x", "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x",
ath10k_bus_str(ar->hif.bus), ath10k_bus_str(ar->hif.bus),
ar->id.vendor, ar->id.device, ar->id.vendor, ar->id.device,
ar->id.subsystem_vendor, ar->id.subsystem_device); ar->id.subsystem_vendor, ar->id.subsystem_device);
out:
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name); ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name);
return 0; return 0;
@ -1060,12 +1120,6 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
/* calibration file is optional, don't check for any errors */ /* calibration file is optional, don't check for any errors */
ath10k_fetch_cal_file(ar); ath10k_fetch_cal_file(ar);
ret = ath10k_core_fetch_board_file(ar);
if (ret) {
ath10k_err(ar, "failed to fetch board file: %d\n", ret);
return ret;
}
ar->fw_api = 5; ar->fw_api = 5;
ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
@ -1675,6 +1729,19 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
goto err_power_down; goto err_power_down;
} }
ret = ath10k_core_get_board_id_from_otp(ar);
if (ret && ret != -EOPNOTSUPP) {
ath10k_err(ar, "failed to get board id from otp for qca99x0: %d\n",
ret);
return ret;
}
ret = ath10k_core_fetch_board_file(ar);
if (ret) {
ath10k_err(ar, "failed to fetch board file: %d\n", ret);
goto err_free_firmware_files;
}
ret = ath10k_core_init_firmware_features(ar); ret = ath10k_core_init_firmware_features(ar);
if (ret) { if (ret) {
ath10k_err(ar, "fatal problem with firmware features: %d\n", ath10k_err(ar, "fatal problem with firmware features: %d\n",

View File

@ -681,6 +681,10 @@ struct ath10k {
u32 device; u32 device;
u32 subsystem_vendor; u32 subsystem_vendor;
u32 subsystem_device; u32 subsystem_device;
bool bmi_ids_valid;
u8 bmi_board_id;
u8 bmi_chip_id;
} id; } id;
int fw_api; int fw_api;

View File

@ -129,8 +129,12 @@ void ath10k_print_driver_info(struct ath10k *ar)
ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features)); ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
scnprintf(boardinfo, sizeof(boardinfo), "sub %04x:%04x", if (ar->id.bmi_ids_valid)
ar->id.subsystem_vendor, ar->id.subsystem_device); scnprintf(boardinfo, sizeof(boardinfo), "bmi %d:%d",
ar->id.bmi_chip_id, ar->id.bmi_board_id);
else
scnprintf(boardinfo, sizeof(boardinfo), "sub %04x:%04x",
ar->id.subsystem_vendor, ar->id.subsystem_device);
ath10k_info(ar, "%s (0x%08x, 0x%08x %s) fw %s fwapi %d bdapi %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n", ath10k_info(ar, "%s (0x%08x, 0x%08x %s) fw %s fwapi %d bdapi %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n",
ar->hw_params.name, ar->hw_params.name,