Skip to contentSkip to conversation

Open source FPGA image header

RFC New Alan Tull 1 participant 6 messages Jul 24, 2017

Subsystems (2)
lore
Share & tools
lore

Alan Tull

author
#0 lore raw

cover Open source FPGA image header

This patch set adds open source FPGA image headers. This allows FPGA FPGA image specific information to be added to the images themselves. The header format is a simplified form of u-boot FIT images and can be expanded as real use cases are raised. As all the FPGA kernel frameworks are intended to be vendor agnostic, so also is the header. As libfdt's licensing is permissive, this header is also intended to be useful for OS's other than Linux.

In February, there was a conversation on the linux-fpga mailing list where Moritz and Jason suggested headers, so with their permission I'll be happy to add 'Suggested-by'.

An API function and a sysfs interface are added for applying FPGA images to regions.

Patches 1-2 are documentation

Patches 3-4 are small API changes and could be rolled into my "non-DT
support for FPGA regions" patchset.

Patch 5 is the bulk of it.

todo: I've been working on scatter gather table support for this. It's not done yet, so I pulled it out for now.

This patch applies on top of my "non-DT support for FPGA regions" v3 patchset.

Alan Tull

Alan Tull (5):
doc: fpga: add document for the fdt FPGA header
doc: fpga: add sysfs document for fpga region
fpga: add dev to fpga_image_info
fpga-region: new function fpga_region_free fpga-region support for fdt headers on fpga images

 Documentation/ABI/testing/sysfs-class-fpga-region |   7 +
 Documentation/fpga/fpga-header.txt                | 103 +++++
 drivers/fpga/Kconfig                              |   7 +
 drivers/fpga/fpga-mgr.c                           |  14 +-
 drivers/fpga/fpga-region.c                        | 460 ++++++++++++++++++++++
 drivers/fpga/of-fpga-region.c                     |  16 +-
 include/linux/fpga/fpga-mgr.h                     |  13 +-
 include/linux/fpga/fpga-region.h                  |   3 +
 8 files changed, 612 insertions(+), 11 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-fpga-region
 create mode 100644 Documentation/fpga/fpga-header.txt
Signature · 1 line
2.7.4
author
#1 lore raw

RFC 1/5 doc: fpga: add document for the fdt FPGA header

Add a document for the open source fdt FPGA header.

---
 Documentation/fpga/fpga-header.txt | 103 +++++++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)
 create mode 100644 Documentation/fpga/fpga-header.txt
Documentation/fpga/fpga-header.txt new file +103 -0
new file mode 100644
index 0000000..0045f63
@@ -0,0 +1,103 @@
+Open source FPGA image headers
+
+Alan Tull 2017
+
+CONTENTS
+- Introduction
+- Format
+- Example
+- Using mkimage
+
+Introduction
+============
+
+Open source FPGA image headers have been added to allow FPGA image specific
+information to be included with the image.  The header format is a simplified
+form of u-boot FIT images and can be expanded as real use cases are raised.
+As all the FPGA kernel frameworks are intended to be vendor agnostic, so also
+is the header.  As libfdt's licensing is permissive, this header is also
+intended to be useful for OS's other than Linux such that the FPGA image need
+not be rebuilt for use under another OS.
+
+Format
+======
+
+The format of the header is a reduced FIT-like header, so it can be built
+using mkimage.  The header is a FDT followed by two optional binary data
+sections: a Device Tree overlay and a raw FPGA image.  When the image is
+applied to a FPGA region, first the FPGA is programmed (if the raw image is
+present) and then the DT overlay, if present, is applied.  If the DT overlay
+is eliminated, this header format may be used on systems running without
+Device Tree.
+
+Example
+=======
+
+/dts-v1/;
+
+/ {
+	description = "Program FPGA image and apply DT overlay";
+	#address-cells = <1>;
+
+	images {
+		fdt@1 {
+			description = "Flattened Device Tree blob";
+			type = "flat_dt";
+			data = /incbin/("/some/path/persona0.dtb");
+		};
+		fpga@1 {
+			description = "FPGA image";
+			type = "fpga";
+			data = /incbin/("/some/path/persona0.rbf");
+			partial-fpga-config;
+			region-unfreeze-timeout-us = <4>;
+			region-freeze-timeout-us = <4>;
+			config-complete-timeout-us = <100>;
+		};
+	};
+};
+
+This format is compatible with FIT, but leaves out a few things that were not
+needed.  The compression property is left out (assuming none).  The
+'configurations' section is left out since there is only one possible
+configuration presented here.  If we see an actual use case for
+configurations in the future, we could expand to support it seamlessly.
+
+Any FPGA image info must be included in the FPGA image section.  FPGA image
+info properties are defined in the fpga-region.txt Device Tree binding
+document at ../devicetree/bindings/fpga/fpga-region.txt.
+
+The FPGA image section has to come last.
+
+Using mkimage
+=============
+
+If the above example is named persona0.its, it can be compiled by using
+mkimage as follows.  The output file is persona0.fit.
+
+ mkimage -f persona0.its persona0.fit
+
+Applying the image
+==================
+
+A sysfs attribute 'firmware_name' is added for each FPGA region.
+
+To apply the image:
+
+  echo persona.fit > /sys/class/fpga_region/region0/firmware_name
+
+To free up the region for reprogramming:
+
+  echo > /sys/class/fpga_region/region0/firmware_name
+
+FPGA Region API Function
+========================
+
+An API for FPGA region has been added:
+
+  int fpga_region_fdt_image_apply(struct fpga_region *region)
+
+This function will parse the header of a FPGA image and do the programming
+and apply the DT overlay.  The FPGA image is presented as a scatter gather
+table, a contiguous buffer, or name of a firmware file in the region's FPGA
+image info (region->info).
Signature · 1 line
2.7.4
author
#2 lore raw

RFC 2/5 doc: fpga: add sysfs document for fpga region

In reply to Alan Tull

Document the firmware_name attribute added for each region.

---
 Documentation/ABI/testing/sysfs-class-fpga-region | 7 +++++++
 1 file changed, 7 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-fpga-region
Documentation/ABI/testing/sysfs-class-fpga-region new file +7 -0
new file mode 100644
index 0000000..de47645
@@ -0,0 +1,7 @@
+What:		/sys/class/fpga_region/<fpga>/firmware_name
+Date:		July 2017
+KernelVersion:	4.15
+Contact:	Alan Tull <[email protected]>
+Description:	Write the name of FPGA image file on the firmware path to
+		program the FPGA region.  Write nothing to free up the
+		FPGA region for reprogramming.
Signature · 1 line
2.7.4
author
#3 lore raw

RFC 3/5 fpga: add dev to fpga_image_info

In reply to Alan Tull

This patch should be rolled into the next version of my "non-dt support for FPGA regions" patchset.

Add a pointer to the device that owns the fpga_image_info to fpga_image_info. That way the fpga_image_info_free can drop the 'dev' parameter and we are left with:

struct fpga_image_info *fpga_image_info_alloc(struct device *dev);

void fpga_image_info_free(struct fpga_image_info *info);

---
 drivers/fpga/fpga-mgr.c       | 14 ++++++++++----
 drivers/fpga/of-fpga-region.c |  6 +++---
 include/linux/fpga/fpga-mgr.h |  4 +++-
 3 files changed, 16 insertions(+), 8 deletions(-)
drivers/fpga/fpga-mgr.c +10 -4
index be13cce..af33310 100644
@@ -40,20 +40,26 @@ struct fpga_image_info *fpga_image_info_alloc(struct device *dev)
 	if (!info)
 		return ERR_PTR(-ENOMEM);
 
+	get_device(dev);
+	info->dev = dev;
+
 	return info;
 }
 EXPORT_SYMBOL_GPL(fpga_image_info_alloc);
 
-void fpga_image_info_free(struct device *dev,
-			  struct fpga_image_info *info)
+void fpga_image_info_free(struct fpga_image_info *info)
 {
+	struct device *dev;
+
 	if (!info)
 		return;
 
 	if (info->firmware_name)
-		devm_kfree(dev, info->firmware_name);
+		devm_kfree(info->dev, info->firmware_name);
 
-	devm_kfree(dev, info);
+	dev = info->dev;
+	devm_kfree(info->dev, info);
+	put_device(dev);
 }
 EXPORT_SYMBOL_GPL(fpga_image_info_free);
 
drivers/fpga/of-fpga-region.c +3 -3
index c2ea9b6..6bb5799 100644
@@ -273,7 +273,7 @@ static struct fpga_image_info *of_fpga_region_parse_ov(
 
 	return info;
 ret_no_info:
-	fpga_image_info_free(dev, info);
+	fpga_image_info_free(info);
 	return ERR_PTR(ret);
 }
 
@@ -314,7 +314,7 @@ static int of_fpga_region_notify_pre_apply(struct fpga_region *region,
 	ret = fpga_region_program_fpga(region);
 	if (ret) {
 		/* error; reject overlay */
-		fpga_image_info_free(dev, info);
+		fpga_image_info_free(info);
 		region->info = NULL;
 	}
 
@@ -335,7 +335,7 @@ static void of_fpga_region_notify_post_remove(struct fpga_region *region,
 {
 	fpga_bridges_disable(&region->bridge_list);
 	fpga_bridges_put(&region->bridge_list);
-	fpga_image_info_free(&region->dev, region->info);
+	fpga_image_info_free(region->info);
 	region->info = NULL;
 }
 
include/linux/fpga/fpga-mgr.h +3 -1
index 50954cb..ddc56c0 100644
@@ -79,6 +79,7 @@ enum fpga_mgr_states {
 
 /**
  * struct fpga_image_info - information specific to a FPGA image
+ * @dev: device that owns this info
  * @flags: boolean flags as defined above
  * @enable_timeout_us: maximum time to enable traffic through bridge (uSec)
  * @disable_timeout_us: maximum time to disable traffic through bridge (uSec)
@@ -91,6 +92,7 @@ enum fpga_mgr_states {
  * @overlay: Device Tree overlay
  */
 struct fpga_image_info {
+	struct device *dev;
 	u32 flags;
 	u32 enable_timeout_us;
 	u32 disable_timeout_us;
@@ -153,7 +155,7 @@ struct fpga_manager {
 
 struct fpga_image_info *fpga_image_info_alloc(struct device *dev);
 
-void fpga_image_info_free(struct device *dev, struct fpga_image_info *info);
+void fpga_image_info_free(struct fpga_image_info *info);
 
 int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info);
 
Signature · 1 line
2.7.4
author
#4 lore raw

RFC 4/5 fpga-region: new function fpga_region_free

In reply to Alan Tull

Add FPGA region API function fpga_region_free() that undoes some of what fpga_region_program_fpga() does to free up a region to be reprogrammed.

---
 drivers/fpga/fpga-region.c       | 20 ++++++++++++++++++++
 drivers/fpga/of-fpga-region.c    |  5 +----
 include/linux/fpga/fpga-region.h |  2 ++
 3 files changed, 23 insertions(+), 4 deletions(-)
drivers/fpga/fpga-region.c +20 -0
index afc6188..944d24a 100644
@@ -162,6 +162,26 @@ int fpga_region_program_fpga(struct fpga_region *region)
 }
 EXPORT_SYMBOL_GPL(fpga_region_program_fpga);
 
+/**
+ * fpga_region_free
+ * Undo some of what fpga_region_program_fpga() did to free up
+ * region to be reprogrammed.
+ * @region: FPGA region
+ */
+void fpga_region_free(struct fpga_region *region)
+{
+	if (!region->info)
+		return;
+
+	fpga_bridges_disable(&region->bridge_list);
+	if (region->get_bridges)
+		fpga_bridges_put(&region->bridge_list);
+
+	fpga_image_info_free(region->info);
+	region->info = NULL;
+}
+EXPORT_SYMBOL_GPL(fpga_region_free);
+
 int fpga_region_register(struct device *dev, struct fpga_region *region)
 {
 	int id, ret = 0;
drivers/fpga/of-fpga-region.c +1 -4
index 6bb5799..019ca37 100644
@@ -333,10 +333,7 @@ static int of_fpga_region_notify_pre_apply(struct fpga_region *region,
 static void of_fpga_region_notify_post_remove(struct fpga_region *region,
 					      struct of_overlay_notify_data *nd)
 {
-	fpga_bridges_disable(&region->bridge_list);
-	fpga_bridges_put(&region->bridge_list);
-	fpga_image_info_free(region->info);
-	region->info = NULL;
+	fpga_region_free(region);
 }
 
 /**
include/linux/fpga/fpga-region.h +2 -0
index f2eecdd..3b6f0b0 100644
@@ -32,6 +32,8 @@ struct fpga_region *fpga_region_class_find(
 	int (*match)(struct device *, const void *));
 
 int fpga_region_program_fpga(struct fpga_region *region);
+void fpga_region_free(struct fpga_region *region);
+
 int fpga_region_register(struct device *dev, struct fpga_region *region);
 int fpga_region_unregister(struct fpga_region *region);
 
Signature · 1 line
2.7.4
author
#5 lore raw

RFC 5/5 fpga-region support for fdt headers on fpga images

In reply to Alan Tull

Support a FDT header for FPGA images. Header format is a simplified FIT containing at most one FPGA image and one DT overlay.

The FPGA image section includes FPGA image info properties needed for programming.

If present, the DT overlay image is applied after the FPGA is programmed.

Both images are optional. If the DT overlay isn't present, this interface may be used on systems running without a live Device Tree.

todo: add scatter gather table support.

---
 drivers/fpga/Kconfig             |   7 +
 drivers/fpga/fpga-region.c       | 440 +++++++++++++++++++++++++++++++++++++++
 drivers/fpga/of-fpga-region.c    |   7 +
 include/linux/fpga/fpga-mgr.h    |   9 +
 include/linux/fpga/fpga-region.h |   1 +
 5 files changed, 464 insertions(+)
drivers/fpga/Kconfig +7 -0
index c349c42..f4b595b 100644
@@ -19,6 +19,13 @@ config FPGA_REGION
 	  and the FPGA Bridges associated with either a reconfigurable
 	  region of an FPGA or a whole FPGA.
 
+config FPGA_REGION_SYSFS
+       bool "FPGA Region Sysfs"
+	depends on FPGA_REGION
+	help
+	  FPGA Region sysfs interface.  This creates sysfs files under
+	  /sys/class/fpga_region/ to control programming FPGA regions.
+
 config OF_FPGA_REGION
 	tristate "FPGA Region Device Tree Overlay Support"
 	depends on OF && FPGA_REGION
drivers/fpga/fpga-region.c +440 -0

482 lines not on this page · raw message

drivers/fpga/of-fpga-region.c +7 -0
index 019ca37..034cd9d 100644
@@ -375,6 +375,13 @@ static int of_fpga_region_notify(struct notifier_block *nb,
 	if (!region)
 		return NOTIFY_OK;
 
+	/*
+	 * If notification is because bitstream had a fdt in the header,
+	 * silently ignore notification.
+	 */
+	if (region->info && region->info->fdt_blob)
+		return NOTIFY_OK;
+
 	ret = 0;
 	switch (action) {
 	case OF_OVERLAY_PRE_APPLY:
include/linux/fpga/fpga-mgr.h +9 -0
index ddc56c0..fb91154 100644
@@ -16,6 +16,7 @@
  * You should have received a copy of the GNU General Public License along with
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+#include <linux/firmware.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
 
@@ -86,10 +87,14 @@ enum fpga_mgr_states {
  * @config_complete_timeout_us: maximum time for FPGA to switch to operating
  *	   status in the write_complete op.
  * @firmware_name: name of FPGA image firmware file
+ * @fw: FPGA image firmware
  * @sgt: scatter/gather table containing FPGA image
  * @buf: contiguous buffer containing FPGA image
  * @count: size of buf
+ * @fdt_blob: fdt from FPGA image header
+ * @header: header
  * @overlay: Device Tree overlay
+ * @ov_id: id of applied overlay
  */
 struct fpga_image_info {
 	struct device *dev;
@@ -98,11 +103,15 @@ struct fpga_image_info {
 	u32 disable_timeout_us;
 	u32 config_complete_timeout_us;
 	char *firmware_name;
+	const struct firmware *fw;
 	struct sg_table *sgt;
 	const char *buf;
 	size_t count;
+	char *fdt_blob;
+	char *header;
 #ifdef CONFIG_OF
 	struct device_node *overlay;
+	int ov_id;
 #endif
 };
 
include/linux/fpga/fpga-region.h +1 -0
index 3b6f0b0..3839430 100644
@@ -33,6 +33,7 @@ struct fpga_region *fpga_region_class_find(
 
 int fpga_region_program_fpga(struct fpga_region *region);
 void fpga_region_free(struct fpga_region *region);
+int fpga_region_fdt_image_apply(struct fpga_region *region);
 
 int fpga_region_register(struct device *dev, struct fpga_region *region);
 int fpga_region_unregister(struct fpga_region *region);
Signature · 1 line
2.7.4