18c2ecf20Sopenharmony_ciIn-kernel API for FPGA Programming
28c2ecf20Sopenharmony_ci==================================
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ciOverview
58c2ecf20Sopenharmony_ci--------
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ciThe in-kernel API for FPGA programming is a combination of APIs from
88c2ecf20Sopenharmony_ciFPGA manager, bridge, and regions.  The actual function used to
98c2ecf20Sopenharmony_citrigger FPGA programming is fpga_region_program_fpga().
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cifpga_region_program_fpga() uses functionality supplied by
128c2ecf20Sopenharmony_cithe FPGA manager and bridges.  It will:
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci * lock the region's mutex
158c2ecf20Sopenharmony_ci * lock the mutex of the region's FPGA manager
168c2ecf20Sopenharmony_ci * build a list of FPGA bridges if a method has been specified to do so
178c2ecf20Sopenharmony_ci * disable the bridges
188c2ecf20Sopenharmony_ci * program the FPGA using info passed in :c:expr:`fpga_region->info`.
198c2ecf20Sopenharmony_ci * re-enable the bridges
208c2ecf20Sopenharmony_ci * release the locks
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ciThe struct fpga_image_info specifies what FPGA image to program.  It is
238c2ecf20Sopenharmony_ciallocated/freed by fpga_image_info_alloc() and freed with
248c2ecf20Sopenharmony_cifpga_image_info_free()
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ciHow to program an FPGA using a region
278c2ecf20Sopenharmony_ci-------------------------------------
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ciWhen the FPGA region driver probed, it was given a pointer to an FPGA manager
308c2ecf20Sopenharmony_cidriver so it knows which manager to use.  The region also either has a list of
318c2ecf20Sopenharmony_cibridges to control during programming or it has a pointer to a function that
328c2ecf20Sopenharmony_ciwill generate that list.  Here's some sample code of what to do next::
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	#include <linux/fpga/fpga-mgr.h>
358c2ecf20Sopenharmony_ci	#include <linux/fpga/fpga-region.h>
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	struct fpga_image_info *info;
388c2ecf20Sopenharmony_ci	int ret;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	/*
418c2ecf20Sopenharmony_ci	 * First, alloc the struct with information about the FPGA image to
428c2ecf20Sopenharmony_ci	 * program.
438c2ecf20Sopenharmony_ci	 */
448c2ecf20Sopenharmony_ci	info = fpga_image_info_alloc(dev);
458c2ecf20Sopenharmony_ci	if (!info)
468c2ecf20Sopenharmony_ci		return -ENOMEM;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	/* Set flags as needed, such as: */
498c2ecf20Sopenharmony_ci	info->flags = FPGA_MGR_PARTIAL_RECONFIG;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	/*
528c2ecf20Sopenharmony_ci	 * Indicate where the FPGA image is. This is pseudo-code; you're
538c2ecf20Sopenharmony_ci	 * going to use one of these three.
548c2ecf20Sopenharmony_ci	 */
558c2ecf20Sopenharmony_ci	if (image is in a scatter gather table) {
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci		info->sgt = [your scatter gather table]
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	} else if (image is in a buffer) {
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci		info->buf = [your image buffer]
628c2ecf20Sopenharmony_ci		info->count = [image buffer size]
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	} else if (image is in a firmware file) {
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci		info->firmware_name = devm_kstrdup(dev, firmware_name,
678c2ecf20Sopenharmony_ci						   GFP_KERNEL);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	/* Add info to region and do the programming */
728c2ecf20Sopenharmony_ci	region->info = info;
738c2ecf20Sopenharmony_ci	ret = fpga_region_program_fpga(region);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	/* Deallocate the image info if you're done with it */
768c2ecf20Sopenharmony_ci	region->info = NULL;
778c2ecf20Sopenharmony_ci	fpga_image_info_free(info);
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	if (ret)
808c2ecf20Sopenharmony_ci		return ret;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	/* Now enumerate whatever hardware has appeared in the FPGA. */
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ciAPI for programming an FPGA
858c2ecf20Sopenharmony_ci---------------------------
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci* fpga_region_program_fpga() —  Program an FPGA
888c2ecf20Sopenharmony_ci* fpga_image_info() —  Specifies what FPGA image to program
898c2ecf20Sopenharmony_ci* fpga_image_info_alloc() —  Allocate an FPGA image info struct
908c2ecf20Sopenharmony_ci* fpga_image_info_free() —  Free an FPGA image info struct
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci.. kernel-doc:: drivers/fpga/fpga-region.c
938c2ecf20Sopenharmony_ci   :functions: fpga_region_program_fpga
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ciFPGA Manager flags
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci.. kernel-doc:: include/linux/fpga/fpga-mgr.h
988c2ecf20Sopenharmony_ci   :doc: FPGA Manager flags
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci.. kernel-doc:: include/linux/fpga/fpga-mgr.h
1018c2ecf20Sopenharmony_ci   :functions: fpga_image_info
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci.. kernel-doc:: drivers/fpga/fpga-mgr.c
1048c2ecf20Sopenharmony_ci   :functions: fpga_image_info_alloc
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci.. kernel-doc:: drivers/fpga/fpga-mgr.c
1078c2ecf20Sopenharmony_ci   :functions: fpga_image_info_free
108