Sfoglia il codice sorgente

qcacld-3.0: Add auto BDF Selection

qcacld-2.0 to qcacld-3.0 propagation

The board data file is selected based on the board id returned
by executing otp binary.

Based on the chip id and the board id, select the appropriate
board data file and download.

The board data file selection is as follows:
Mission mode: bdwlan<chip_id>.b<board_id>
Factory mode: utfbd<chip_id>.b<board_id>

If the auto board data files are not present in the filesystem,
then download the default board data file i.e bdwlan<chip_id>.bin

Change-Id: I26c3eb377513d2c4439eddc4e5dc75eba66c78f4
CRs-Fixed: 805800
Zhang Qian 7 anni fa
parent
commit
b17ee62d9b
2 ha cambiato i file con 147 aggiunte e 54 eliminazioni
  1. 2 0
      core/bmi/src/i_bmi.h
  2. 145 54
      core/bmi/src/ol_fw.c

+ 2 - 0
core/bmi/src/i_bmi.h

@@ -137,6 +137,7 @@ enum ATH_BIN_FILE {
  * @bmi_cmd_da - BMI Command Physical address
  * @bmi_rsp_da - BMI Response Physical address
  * @bmi_done - Flag to check if BMI Phase is complete
+ * @board_id - board ID
  * @fw_files - FW files
  *
  */
@@ -146,6 +147,7 @@ struct bmi_info {
 	dma_addr_t bmi_cmd_da;
 	dma_addr_t bmi_rsp_da;
 	bool bmi_done;
+	uint16_t board_id;
 	struct pld_fw_files fw_files;
 };
 

+ 145 - 54
core/bmi/src/ol_fw.c

@@ -140,6 +140,36 @@ end:
 }
 #endif
 
+/**
+ * ol_board_id_to_filename() - Auto BDF board_id to filename conversion
+ * @old_name: name of the default board data file
+ * @board_id: board ID
+ *
+ * The API return board filename based on the board_id and chip_id.
+ * eg: input = "bdwlan30.bin", board_id = 0x01, board_file = "bdwlan30.b01"
+ * Return: The buffer with the formated board filename.
+ */
+static char *ol_board_id_to_filename(const char *old_name,
+				     uint16_t board_id)
+{
+	int name_len;
+	char *new_name;
+
+	name_len = strlen(old_name);
+	new_name = qdf_mem_malloc(name_len + 1);
+
+	if (!new_name)
+		goto out;
+
+	if (board_id > 0xFF)
+		board_id = 0x0;
+
+	qdf_mem_copy(new_name, old_name, name_len);
+	snprintf(&new_name[name_len - 2], 3, "%.2x", board_id);
+out:
+	return new_name;
+}
+
 #ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT
 #define SIGNED_SPLIT_BINARY_VALUE true
 #else
@@ -164,13 +194,23 @@ __ol_transfer_bin_file(struct ol_context *ol_ctx, enum ATH_BIN_FILE file,
 	uint32_t target_type = tgt_info->target_type;
 	struct bmi_info *bmi_ctx = GET_BMI_CONTEXT(ol_ctx);
 	qdf_device_t qdf_dev = ol_ctx->qdf_dev;
-	int ret = 0;
+	int i;
+
+	/*
+	 * If there is no board data file bases on board id, the default
+	 * board data file should be used.
+	 * For factory mode, the sequence for file selection should be
+	 * utfbd.board_id -> utfbd.bin -> bd.board_id -> bd.bin. So we
+	 * need to cache 4 file names.
+	 */
+	uint32_t bd_files = 1;
+	char *bd_id_filename[2] = {NULL, NULL};
+	const char *bd_filename[2] = {NULL, NULL};
 
 	switch (file) {
 	default:
 		BMI_ERR("%s: Unknown file type", __func__);
-		ret = -1;
-		return ret;
+		return -EINVAL;
 	case ATH_OTP_FILE:
 		filename = bmi_ctx->fw_files.otp_data;
 		if (SIGNED_SPLIT_BINARY_VALUE)
@@ -208,6 +248,7 @@ __ol_transfer_bin_file(struct ol_context *ol_ctx, enum ATH_BIN_FILE file,
 		BMI_INFO("%s: no Patch file defined", __func__);
 		return 0;
 	case ATH_BOARD_DATA_FILE:
+		filename = bmi_ctx->fw_files.board_data;
 #ifdef QCA_WIFI_FTM
 		if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE) {
 			filename = bmi_ctx->fw_files.utf_board_data;
@@ -216,13 +257,37 @@ __ol_transfer_bin_file(struct ol_context *ol_ctx, enum ATH_BIN_FILE file,
 
 			BMI_INFO("%s: Loading board data file %s",
 						__func__, filename);
-			break;
+
+			/*
+			 * In FTM mode, if utf files do not exit.
+			 * bdwlan should be used.
+			 */
+			bd_files = 2;
 		}
 #endif /* QCA_WIFI_FTM */
-		filename = bmi_ctx->fw_files.board_data;
 		if (SIGNED_SPLIT_BINARY_VALUE)
 			bin_sign = false;
 
+		bd_filename[0] = filename;
+
+		/*
+		 * For factory mode, we should cache 2 group of file names.
+		 * For mission mode, bd_files==1, only one group of file names.
+		 */
+		bd_filename[bd_files - 1] =
+					bmi_ctx->fw_files.board_data;
+		for (i = 0; i < bd_files; i++) {
+			bd_id_filename[i] =
+				ol_board_id_to_filename(bd_filename[i],
+							bmi_ctx->board_id);
+			if (bd_id_filename[i]) {
+				BMI_INFO("%s: board data file is %s",
+					 __func__, bd_id_filename[i]);
+			} else {
+				BMI_ERR("%s: Fail to allocate board filename",
+					__func__);
+			}
+		}
 		break;
 	case ATH_SETUP_FILE:
 		if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE &&
@@ -230,8 +295,7 @@ __ol_transfer_bin_file(struct ol_context *ol_ctx, enum ATH_BIN_FILE file,
 			filename = bmi_ctx->fw_files.setup_file;
 			if (filename[0] == 0) {
 				BMI_INFO("%s: no Setup file defined", __func__);
-				ret = -1;
-				return ret;
+				return -EPERM;
 			}
 
 			if (SIGNED_SPLIT_BINARY_VALUE)
@@ -241,41 +305,44 @@ __ol_transfer_bin_file(struct ol_context *ol_ctx, enum ATH_BIN_FILE file,
 			       __func__, filename);
 		} else {
 			BMI_INFO("%s: no Setup file needed", __func__);
-			ret = -1;
-			return ret;
+			return -EPERM;
 		}
 		break;
 	}
 
-	if (request_firmware(&fw_entry, filename, qdf_dev->dev) != 0) {
-		BMI_ERR("%s: Failed to get %s", __func__, filename);
-
-		if (file == ATH_OTP_FILE)
-			return -ENOENT;
-
-#if defined(QCA_WIFI_FTM)
-		/* Try default board data file if FTM specific
-		 * board data file is not present.
-		 */
-		if (filename == bmi_ctx->fw_files.utf_board_data) {
-			filename = bmi_ctx->fw_files.board_data;
-			BMI_INFO("%s: Trying to load default %s",
-			       __func__, filename);
-			if (request_firmware(&fw_entry, filename,
-						qdf_dev->dev) != 0) {
-				BMI_ERR("%s: Failed to get %s",
-				       __func__, filename);
-				ret = -1;
-				return ret;
+	/* For FTM mode. bd.bin is used if there is no utf.bin */
+	if (file == ATH_BOARD_DATA_FILE) {
+		for (i = 0; i < bd_files; i++) {
+			if (bd_id_filename[i]) {
+				BMI_DBG("%s: Trying to load %s",
+					 __func__, bd_id_filename[i]);
+				status = request_firmware(&fw_entry,
+							  bd_id_filename[i],
+							  qdf_dev->dev);
+				if (!status)
+					break;
+				BMI_ERR("%s: Failed to get %s:%d",
+					__func__, bd_id_filename[i],
+					status);
 			}
-		} else {
-			ret = -1;
-			return ret;
+
+			/* bd.board_id not exits, using bd.bin */
+			BMI_DBG("%s: Trying to load default %s",
+				 __func__, bd_filename[i]);
+			status = request_firmware(&fw_entry, bd_filename[i],
+						  qdf_dev->dev);
+			if (!status)
+				break;
+			BMI_ERR("%s: Failed to get default %s:%d",
+				__func__, bd_filename[i], status);
 		}
-#else
-		ret = -1;
-		return ret;
-#endif
+	} else {
+		status = request_firmware(&fw_entry, filename, qdf_dev->dev);
+	}
+
+	if (status) {
+		BMI_ERR("%s: Failed to get %s", __func__, filename);
+		return -ENOENT;
 	}
 
 	if (!fw_entry || !fw_entry->data) {
@@ -303,8 +370,8 @@ __ol_transfer_bin_file(struct ol_context *ol_ctx, enum ATH_BIN_FILE file,
 		temp_eeprom = qdf_mem_malloc(fw_entry_size);
 		if (!temp_eeprom) {
 			BMI_ERR("%s: Memory allocation failed", __func__);
-			release_firmware(fw_entry);
-			return -ENOMEM;
+			status = -ENOMEM;
+			goto release_fw;
 		}
 
 		qdf_mem_copy(temp_eeprom, (uint8_t *) fw_entry->data,
@@ -435,6 +502,11 @@ release_fw:
 	if (fw_entry)
 		release_firmware(fw_entry);
 
+	for (i = 0; i < bd_files; i++) {
+		qdf_mem_free(bd_id_filename[i]);
+		bd_id_filename[i] = NULL;
+	}
+
 	if (status != EOK)
 		BMI_ERR("%s, BMI operation failed: %d", __func__, __LINE__);
 	else
@@ -1269,34 +1341,53 @@ QDF_STATUS ol_download_firmware(struct ol_context *ol_ctx)
 				hi_board_data_initialized)),
 				(uint8_t *) &param, 4, ol_ctx);
 	} else {
-		/* Flash is either not available or invalid */
-		if (ol_transfer_bin_file(ol_ctx, ATH_BOARD_DATA_FILE, address,
-							false) != EOK) {
-			return QDF_STATUS_E_FAILURE;
-		}
-
-		/* Record the fact that Board Data is initialized */
-		param = 1;
-		bmi_write_memory(
-			hif_hia_item_address(target_type,
-			offsetof(struct host_interest_s,
-				hi_board_data_initialized)),
-				(uint8_t *) &param, 4, ol_ctx);
-
 		/* Transfer One Time Programmable data */
 		address = BMI_SEGMENTED_WRITE_ADDR;
 		BMI_INFO("%s: Using 0x%x for the remainder of init",
 				__func__, address);
 
 		status = ol_transfer_bin_file(ol_ctx, ATH_OTP_FILE,
-						address, true);
+					      address, true);
 		/* Execute the OTP code only if entry found and downloaded */
 		if (status == EOK) {
-			param = 0;
+			uint16_t board_id = 0xffff;
+			/* get board id */
+			param = 0x10;
 			bmi_execute(address, &param, ol_ctx);
+			if (!(param & 0xff))
+				board_id = (param >> 8) & 0xffff;
+			BMI_INFO("%s: board ID is 0x%0x", __func__, board_id);
+			bmi_ctx->board_id = board_id;
 		} else if (status < 0) {
 			return status;
 		}
+
+		bmi_read_memory(hif_hia_item_address(target_type,
+				offsetof(struct host_interest_s,
+					hi_board_data)),
+				(uint8_t *)&address, 4, ol_ctx);
+
+		if (!address) {
+			address = AR6004_REV5_BOARD_DATA_ADDRESS;
+			pr_err("%s: Target address not known! Using 0x%x\n",
+			       __func__, address);
+		}
+
+		/* Flash is either not available or invalid */
+		if (ol_transfer_bin_file(ol_ctx, ATH_BOARD_DATA_FILE,
+					 address, false) != EOK) {
+			return QDF_STATUS_E_FAILURE;
+		}
+
+		/* Record the fact that Board Data is initialized */
+		param = 1;
+		bmi_write_memory(hif_hia_item_address(target_type,
+				 offsetof(struct host_interest_s,
+					  hi_board_data_initialized)),
+				 (uint8_t *) &param, 4, ol_ctx);
+		address = BMI_SEGMENTED_WRITE_ADDR;
+		param = 0;
+		bmi_execute(address, &param, ol_ctx);
 	}
 
 	if (ol_transfer_bin_file(ol_ctx, ATH_SETUP_FILE,