diff options
author | Conor Dooley <conor.dooley@microchip.com> | 2024-04-10 12:58:04 +0100 |
---|---|---|
committer | Conor Dooley <conor.dooley@microchip.com> | 2024-06-05 19:35:21 +0100 |
commit | a2bf9dfe00905c2426893229b593487fe5abf152 (patch) | |
tree | 11a56421531b5f3d45ef75d5659c8361ff15e973 | |
parent | 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0 (diff) | |
download | lwn-a2bf9dfe00905c2426893229b593487fe5abf152.tar.gz lwn-a2bf9dfe00905c2426893229b593487fe5abf152.zip |
firmware: microchip: support writing bitstream info to flash
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: https://github.com/polarfire-soc/polarfire-soc-documentation/blob/master/how-to/re-programming-the-fpga-from-linux.md#main-header-format
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>
-rw-r--r-- | drivers/firmware/microchip/mpfs-auto-update.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/drivers/firmware/microchip/mpfs-auto-update.c b/drivers/firmware/microchip/mpfs-auto-update.c index 835a19a7a3a0..4711856f465a 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) { @@ -289,22 +301,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; + } } /* @@ -336,6 +363,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); @@ -362,6 +390,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; |