Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 36000479 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "UPSTREAM: ath10k: support extended board data download for dual-band QCA9984"

parents 267dd345 8c5aade5
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -84,18 +84,18 @@
		};

		wcnss_mem: wcnss@89300000 {
			reg = <0x0 0x89300000 0x0 0x600000>;
			reg = <0x0 0x89300000 0x0 0x700000>;
			no-map;
		};

		venus_mem: venus@89900000 {
			reg = <0x0 0x89900000 0x0 0x600000>;
			reg = <0x0 0x89A00000 0x0 0x600000>;
			no-map;
		};

		mba_mem: mba@8ea00000 {
			no-map;
			reg = <0 0x8ea00000 0 0x100000>;
			reg = <0 0x8A000000 0 0x100000>;
		};
	};

+5 −0
Original line number Diff line number Diff line
@@ -86,6 +86,10 @@ enum bmi_cmd_id {
#define BMI_PARAM_GET_FLASH_BOARD_ID 0x8000
#define BMI_PARAM_FLASH_SECTION_ALL 0x10000

/* Dual-band Extended Board ID */
#define BMI_PARAM_GET_EXT_BOARD_ID 0x40000
#define ATH10K_BMI_EXT_BOARD_ID_SUPPORT 0x40000

#define ATH10K_BMI_BOARD_ID_FROM_OTP_MASK   0x7c00
#define ATH10K_BMI_BOARD_ID_FROM_OTP_LSB    10

@@ -93,6 +97,7 @@ enum bmi_cmd_id {
#define ATH10K_BMI_CHIP_ID_FROM_OTP_LSB     15

#define ATH10K_BMI_BOARD_ID_STATUS_MASK 0xff
#define ATH10K_BMI_EBOARD_ID_STATUS_MASK 0xff

struct bmi_cmd {
	__le32 id; /* enum bmi_cmd_id */
+205 −41
Original line number Diff line number Diff line
@@ -294,8 +294,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
		.fw = {
			.dir = QCA9984_HW_1_0_FW_DIR,
			.board = QCA9984_HW_1_0_BOARD_DATA_FILE,
			.eboard = QCA9984_HW_1_0_EBOARD_DATA_FILE,
			.board_size = QCA99X0_BOARD_DATA_SZ,
			.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
			.ext_board_size = QCA99X0_EXT_BOARD_DATA_SZ,
		},
		.sw_decrypt_mcast_mgmt = true,
		.hw_ops = &qca99x0_ops,
@@ -697,6 +699,7 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
{
	u32 result, address;
	u8 board_id, chip_id;
	bool ext_bid_support;
	int ret, bmi_board_id_param;

	address = ar->hw_params.patch_load_addr;
@@ -736,10 +739,13 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)

	board_id = MS(result, ATH10K_BMI_BOARD_ID_FROM_OTP);
	chip_id = MS(result, ATH10K_BMI_CHIP_ID_FROM_OTP);
	ext_bid_support = (result & ATH10K_BMI_EXT_BOARD_ID_SUPPORT);

	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);
		   "boot get otp board id result 0x%08x board_id %d chip_id %d ext_bid_support %d\n",
		   result, board_id, chip_id, ext_bid_support);

	ar->id.ext_bid_supported = ext_bid_support;

	if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0 ||
	    (board_id == 0)) {
@@ -880,9 +886,15 @@ static void ath10k_core_free_board_files(struct ath10k *ar)
	if (!IS_ERR(ar->normal_mode_fw.board))
		release_firmware(ar->normal_mode_fw.board);

	if (!IS_ERR(ar->normal_mode_fw.ext_board))
		release_firmware(ar->normal_mode_fw.ext_board);

	ar->normal_mode_fw.board = NULL;
	ar->normal_mode_fw.board_data = NULL;
	ar->normal_mode_fw.board_len = 0;
	ar->normal_mode_fw.ext_board = NULL;
	ar->normal_mode_fw.ext_board_data = NULL;
	ar->normal_mode_fw.ext_board_len = 0;
}

static void ath10k_core_free_firmware_files(struct ath10k *ar)
@@ -936,8 +948,11 @@ static int ath10k_fetch_cal_file(struct ath10k *ar)
	return 0;
}

static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar)
static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
{
	const struct firmware *fw;

	if (bd_ie_type == ATH10K_BD_IE_BOARD) {
		if (!ar->hw_params.fw.board) {
			ath10k_err(ar, "failed to find board file fw entry\n");
			return -EINVAL;
@@ -951,13 +966,29 @@ static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar)

		ar->normal_mode_fw.board_data = ar->normal_mode_fw.board->data;
		ar->normal_mode_fw.board_len = ar->normal_mode_fw.board->size;
	} else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {
		if (!ar->hw_params.fw.eboard) {
			ath10k_err(ar, "failed to find eboard file fw entry\n");
			return -EINVAL;
		}

		fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
					  ar->hw_params.fw.eboard);
		ar->normal_mode_fw.ext_board = fw;
		if (IS_ERR(ar->normal_mode_fw.ext_board))
			return PTR_ERR(ar->normal_mode_fw.ext_board);

		ar->normal_mode_fw.ext_board_data = ar->normal_mode_fw.ext_board->data;
		ar->normal_mode_fw.ext_board_len = ar->normal_mode_fw.ext_board->size;
	}

	return 0;
}

static int ath10k_core_parse_bd_ie_board(struct ath10k *ar,
					 const void *buf, size_t buf_len,
					 const char *boardname)
					 const char *boardname,
					 int bd_ie_type)
{
	const struct ath10k_fw_ie *hdr;
	bool name_match_found;
@@ -1006,12 +1037,21 @@ static int ath10k_core_parse_bd_ie_board(struct ath10k *ar,
				/* no match found */
				break;

			if (bd_ie_type == ATH10K_BD_IE_BOARD) {
				ath10k_dbg(ar, ATH10K_DBG_BOOT,
					   "boot found board data for '%s'",
						boardname);

				ar->normal_mode_fw.board_data = board_ie_data;
				ar->normal_mode_fw.board_len = board_ie_len;
			} else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {
				ath10k_dbg(ar, ATH10K_DBG_BOOT,
					   "boot found eboard data for '%s'",
						boardname);

				ar->normal_mode_fw.ext_board_data = board_ie_data;
				ar->normal_mode_fw.ext_board_len = board_ie_len;
			}

			ret = 0;
			goto out;
@@ -1061,7 +1101,18 @@ static int ath10k_core_search_bd(struct ath10k *ar,
		switch (ie_id) {
		case ATH10K_BD_IE_BOARD:
			ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,
							    boardname);
							    boardname,
							    ATH10K_BD_IE_BOARD);
			if (ret == -ENOENT)
				/* no match found, continue */
				break;

			/* either found or error, so stop searching */
			goto out;
		case ATH10K_BD_IE_BOARD_EXT:
			ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,
							    boardname,
							    ATH10K_BD_IE_BOARD_EXT);
			if (ret == -ENOENT)
				/* no match found, continue */
				break;
@@ -1091,6 +1142,8 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
	const u8 *data;
	int ret;

	/* Skip if already fetched during board data download */
	if (!ar->normal_mode_fw.board)
		ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
								ar->hw_params.fw.dir,
								filename);
@@ -1189,11 +1242,29 @@ static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
	return 0;
}

static int ath10k_core_fetch_board_file(struct ath10k *ar)
static int ath10k_core_create_eboard_name(struct ath10k *ar, char *name,
					  size_t name_len)
{
	if (ar->id.bmi_ids_valid) {
		scnprintf(name, name_len,
			  "bus=%s,bmi-chip-id=%d,bmi-eboard-id=%d",
			  ath10k_bus_str(ar->hif.bus),
			  ar->id.bmi_chip_id,
			  ar->id.bmi_eboard_id);

		ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using eboard name '%s'\n", name);
		return 0;
	}
	/* Fallback if returned board id is zero */
	return -1;
}

static int ath10k_core_fetch_board_file(struct ath10k *ar, int bd_ie_type)
{
	char boardname[100], fallback_boardname[100];
	int ret;

	if (bd_ie_type == ATH10K_BD_IE_BOARD) {
		ret = ath10k_core_create_board_name(ar, boardname,
						    sizeof(boardname), true);
		if (ret) {
@@ -1207,6 +1278,14 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar)
			ath10k_err(ar, "failed to create fallback board name: %d", ret);
			return ret;
		}
	} else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {
		ret = ath10k_core_create_eboard_name(ar, boardname,
						     sizeof(boardname));
		if (ret) {
			ath10k_err(ar, "fallback to eboard.bin since board id 0");
			goto fallback;
		}
	}

	ar->bd_api = 2;
	ret = ath10k_core_fetch_board_data_api_n(ar, boardname,
@@ -1215,8 +1294,9 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar)
	if (!ret)
		goto success;

fallback:
	ar->bd_api = 1;
	ret = ath10k_core_fetch_board_data_api_1(ar);
	ret = ath10k_core_fetch_board_data_api_1(ar, bd_ie_type);
	if (ret) {
		ath10k_err(ar, "failed to fetch board-2.bin or board.bin from %s\n",
			   ar->hw_params.fw.dir);
@@ -1228,11 +1308,65 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar)
	return 0;
}

static int ath10k_core_get_ext_board_id_from_otp(struct ath10k *ar)
{
	u32 result, address;
	u8 ext_board_id;
	int ret;

	address = ar->hw_params.patch_load_addr;

	if (!ar->normal_mode_fw.fw_file.otp_data ||
	    !ar->normal_mode_fw.fw_file.otp_len) {
		ath10k_warn(ar,
			    "failed to retrieve extended board id due to otp binary missing\n");
		return -ENODATA;
	}

	ath10k_dbg(ar, ATH10K_DBG_BOOT,
		   "boot upload otp to 0x%x len %zd for ext board id\n",
		   address, ar->normal_mode_fw.fw_file.otp_len);

	ret = ath10k_bmi_fast_download(ar, address,
				       ar->normal_mode_fw.fw_file.otp_data,
				       ar->normal_mode_fw.fw_file.otp_len);
	if (ret) {
		ath10k_err(ar, "could not write otp for ext board id check: %d\n",
			   ret);
		return ret;
	}

	ret = ath10k_bmi_execute(ar, address, BMI_PARAM_GET_EXT_BOARD_ID, &result);
	if (ret) {
		ath10k_err(ar, "could not execute otp for ext board id check: %d\n",
			   ret);
		return ret;
	}

	if (!result) {
		ath10k_dbg(ar, ATH10K_DBG_BOOT,
			   "ext board id does not exist in otp, ignore it\n");
		return -EOPNOTSUPP;
	}

	ext_board_id = result & ATH10K_BMI_EBOARD_ID_STATUS_MASK;

	ath10k_dbg(ar, ATH10K_DBG_BOOT,
		   "boot get otp ext board id result 0x%08x ext_board_id %d\n",
		   result, ext_board_id);

	ar->id.bmi_eboard_id = ext_board_id;

	return 0;
}

static int ath10k_download_board_data(struct ath10k *ar, const void *data,
				      size_t data_len)
{
	u32 board_data_size = ar->hw_params.fw.board_size;
	u32 address;
	u32 eboard_data_size = ar->hw_params.fw.ext_board_size;
	u32 board_address;
	u32 ext_board_address;
	int ret;

	ret = ath10k_push_board_ext_data(ar, data, data_len);
@@ -1241,13 +1375,13 @@ static int ath10k_download_board_data(struct ath10k *ar, const void *data,
		goto exit;
	}

	ret = ath10k_bmi_read32(ar, hi_board_data, &address);
	ret = ath10k_bmi_read32(ar, hi_board_data, &board_address);
	if (ret) {
		ath10k_err(ar, "could not read board data addr (%d)\n", ret);
		goto exit;
	}

	ret = ath10k_bmi_write_memory(ar, address, data,
	ret = ath10k_bmi_write_memory(ar, board_address, data,
				      min_t(u32, board_data_size,
					    data_len));
	if (ret) {
@@ -1261,6 +1395,36 @@ static int ath10k_download_board_data(struct ath10k *ar, const void *data,
		goto exit;
	}

	if (!ar->id.ext_bid_supported)
		goto exit;

	/* Extended board data download */
	ret = ath10k_core_get_ext_board_id_from_otp(ar);
	if (ret == -EOPNOTSUPP) {
		/* Not fetching ext_board_data if ext board id is 0 */
		ath10k_dbg(ar, ATH10K_DBG_BOOT, "otp returned ext board id 0\n");
		return 0;
	} else if (ret) {
		ath10k_err(ar, "failed to get extended board id: %d\n", ret);
		goto exit;
	}

	ret = ath10k_core_fetch_board_file(ar, ATH10K_BD_IE_BOARD_EXT);
	if (ret)
		goto exit;

	if (ar->normal_mode_fw.ext_board_data) {
		ext_board_address = board_address + EXT_BOARD_ADDRESS_OFFSET;
		ath10k_dbg(ar, ATH10K_DBG_BOOT,
			   "boot writing ext board data to addr 0x%x",
			   ext_board_address);
		ret = ath10k_bmi_write_memory(ar, ext_board_address,
					      ar->normal_mode_fw.ext_board_data,
					      min_t(u32, eboard_data_size, data_len));
		if (ret)
			ath10k_err(ar, "failed to write ext board data: %d\n", ret);
	}

exit:
	return ret;
}
@@ -2526,7 +2690,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
		if (ret)
			ath10k_dbg(ar, ATH10K_DBG_BOOT, "DT bdf variant name not set.\n");

		ret = ath10k_core_fetch_board_file(ar);
		ret = ath10k_core_fetch_board_file(ar, ATH10K_BD_IE_BOARD);
		if (ret) {
			ath10k_err(ar, "failed to fetch board file: %d\n", ret);
			goto err_free_firmware_files;
+5 −0
Original line number Diff line number Diff line
@@ -750,6 +750,9 @@ struct ath10k_fw_components {
	const struct firmware *board;
	const void *board_data;
	size_t board_len;
	const struct firmware *ext_board;
	const void *ext_board_data;
	size_t ext_board_len;

	struct ath10k_fw_file fw_file;
};
@@ -849,7 +852,9 @@ struct ath10k {
		bool qmi_ids_valid;
		u32 qmi_board_id;
		u8 bmi_board_id;
		u8 bmi_eboard_id;
		u8 bmi_chip_id;
		bool ext_bid_supported;

		char bdf_ext[ATH10K_SMBIOS_BDF_EXT_STR_LENGTH];
	} id;
+4 −0
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ enum qca9377_chip_id_rev {
#define QCA9984_HW_1_0_CHIP_ID_REV	0x0
#define QCA9984_HW_1_0_FW_DIR		ATH10K_FW_DIR "/QCA9984/hw1.0"
#define QCA9984_HW_1_0_BOARD_DATA_FILE "board.bin"
#define QCA9984_HW_1_0_EBOARD_DATA_FILE "eboard.bin"
#define QCA9984_HW_1_0_PATCH_LOAD_ADDR	0x1234

/* QCA9888 2.0 defines */
@@ -219,6 +220,7 @@ enum ath10k_fw_htt_op_version {
enum ath10k_bd_ie_type {
	/* contains sub IEs of enum ath10k_bd_ie_board_type */
	ATH10K_BD_IE_BOARD = 0,
	ATH10K_BD_IE_BOARD_EXT = 1,
};

enum ath10k_bd_ie_board_type {
@@ -529,6 +531,8 @@ struct ath10k_hw_params {
		const char *dir;
		const char *board;
		size_t board_size;
		const char *eboard;
		size_t ext_board_size;
		size_t board_ext_size;
	} fw;

Loading