diff mbox series

[v1,1/5] firmware: microchip: support writing bitstream info to flash

Message ID 20240410-shabby-fineness-6e8662cf44e2@spud (mailing list archive)
State Accepted
Delegated to: Conor Dooley
Headers show
Series PolarFire SoC Auto Update design info support | expand

Checks

Context Check Description
conchuod/vmtest-fixes-PR fail merge-conflict

Commit Message

Conor Dooley April 10, 2024, 11:58 a.m. UTC
From: Conor Dooley <conor.dooley@microchip.com>

Updating the FPGA image might bring with it changes visible to Linux,
so it is helpful to also co-locate dt-overlays that describe the new
image contents. If these are packaged in a specific format [1] (detected
by first 4 bytes being MCHP, since FPGA images have no magic), load
the file to the reserved 1 MiB region immediately after the directory in
flash. The Beagle-V Fire's "gateware" already creates these files and
puts them in flash [2].

Link: exists on confluence, needs to be made public
Link: https://openbeagle.org/beaglev-fire/gateware/-/blob/main/gateware_scripts/generate_gateware_overlays.py?ref_type=heads [2]
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
 drivers/firmware/microchip/mpfs-auto-update.c | 47 +++++++++++++++----
 1 file changed, 39 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/drivers/firmware/microchip/mpfs-auto-update.c b/drivers/firmware/microchip/mpfs-auto-update.c
index 32394c24b37d..33343e83373c 100644
--- a/drivers/firmware/microchip/mpfs-auto-update.c
+++ b/drivers/firmware/microchip/mpfs-auto-update.c
@@ -71,8 +71,9 @@ 
 #define AUTO_UPDATE_UPGRADE_DIRECTORY	(AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_UPGRADE_INDEX)
 #define AUTO_UPDATE_BLANK_DIRECTORY	(AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_BLANK_INDEX)
 #define AUTO_UPDATE_DIRECTORY_SIZE	SZ_1K
-#define AUTO_UPDATE_RESERVED_SIZE	SZ_1M
-#define AUTO_UPDATE_BITSTREAM_BASE	(AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_RESERVED_SIZE)
+#define AUTO_UPDATE_INFO_BASE		AUTO_UPDATE_DIRECTORY_SIZE
+#define AUTO_UPDATE_INFO_SIZE		SZ_1M
+#define AUTO_UPDATE_BITSTREAM_BASE	(AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_INFO_SIZE)
 
 #define AUTO_UPDATE_TIMEOUT_MS		60000
 
@@ -86,6 +87,17 @@  struct mpfs_auto_update_priv {
 	bool cancel_request;
 };
 
+static bool mpfs_auto_update_is_bitstream_info(const u8 *data, u32 size)
+{
+	if (size < 4)
+		return false;
+
+	if (data[0] == 0x4d && data[1] == 0x43 && data[2] == 0x48 && data[3] == 0x50)
+		return true;
+
+	return false;
+}
+
 static enum fw_upload_err mpfs_auto_update_prepare(struct fw_upload *fw_uploader, const u8 *data,
 						   u32 size)
 {
@@ -287,22 +299,37 @@  static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
 	loff_t directory_address = AUTO_UPDATE_UPGRADE_DIRECTORY;
 	size_t erase_size = AUTO_UPDATE_DIRECTORY_SIZE;
 	size_t bytes_written = 0;
+	bool is_info = mpfs_auto_update_is_bitstream_info(data, size);
 	u32 image_address;
 	int ret;
 
 	erase_size = round_up(erase_size, (u64)priv->flash->erasesize);
 
-	image_address = AUTO_UPDATE_BITSTREAM_BASE +
-		AUTO_UPDATE_UPGRADE_INDEX * priv->size_per_bitstream;
+	if (is_info)
+		image_address = AUTO_UPDATE_INFO_BASE;
+	else
+		image_address = AUTO_UPDATE_BITSTREAM_BASE +
+				AUTO_UPDATE_UPGRADE_INDEX * priv->size_per_bitstream;
 
 	buffer = devm_kzalloc(priv->dev, erase_size, GFP_KERNEL);
 	if (!buffer)
 		return -ENOMEM;
 
-	ret = mpfs_auto_update_set_image_address(priv, buffer, image_address, directory_address);
-	if (ret) {
-		dev_err(priv->dev, "failed to set image address in the SPI directory: %d\n", ret);
-		goto out;
+	/*
+	 * For bitstream info, the descriptor is written to a fixed offset,
+	 * so there is no need to set the image address.
+	 */
+	if (!is_info) {
+		ret = mpfs_auto_update_set_image_address(priv, buffer, image_address, directory_address);
+		if (ret) {
+			dev_err(priv->dev, "failed to set image address in the SPI directory: %d\n", ret);
+			return ret;
+		}
+	} else {
+		if (size > AUTO_UPDATE_INFO_SIZE) {
+			dev_err(priv->dev, "bitstream info exceeds permitted size\n");
+			return -ENOSPC;
+		}
 	}
 
 	/*
@@ -334,6 +361,7 @@  static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
 	}
 
 	*written = bytes_written;
+	dev_info(priv->dev, "Wrote 0x%zx bytes to the flash\n", bytes_written);
 
 out:
 	devm_kfree(priv->dev, buffer);
@@ -360,6 +388,9 @@  static enum fw_upload_err mpfs_auto_update_write(struct fw_upload *fw_uploader,
 		goto out;
 	}
 
+	if (mpfs_auto_update_is_bitstream_info(data, size))
+		goto out;
+
 	ret = mpfs_auto_update_verify_image(fw_uploader);
 	if (ret)
 		err = FW_UPLOAD_ERR_FW_INVALID;