162306a36Sopenharmony_ciIn-kernel API for FPGA Programming
262306a36Sopenharmony_ci==================================
362306a36Sopenharmony_ci
462306a36Sopenharmony_ciOverview
562306a36Sopenharmony_ci--------
662306a36Sopenharmony_ci
762306a36Sopenharmony_ciThe in-kernel API for FPGA programming is a combination of APIs from
862306a36Sopenharmony_ciFPGA manager, bridge, and regions.  The actual function used to
962306a36Sopenharmony_citrigger FPGA programming is fpga_region_program_fpga().
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cifpga_region_program_fpga() uses functionality supplied by
1262306a36Sopenharmony_cithe FPGA manager and bridges.  It will:
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci * lock the region's mutex
1562306a36Sopenharmony_ci * lock the mutex of the region's FPGA manager
1662306a36Sopenharmony_ci * build a list of FPGA bridges if a method has been specified to do so
1762306a36Sopenharmony_ci * disable the bridges
1862306a36Sopenharmony_ci * program the FPGA using info passed in :c:expr:`fpga_region->info`.
1962306a36Sopenharmony_ci * re-enable the bridges
2062306a36Sopenharmony_ci * release the locks
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ciThe struct fpga_image_info specifies what FPGA image to program.  It is
2362306a36Sopenharmony_ciallocated/freed by fpga_image_info_alloc() and freed with
2462306a36Sopenharmony_cifpga_image_info_free()
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ciHow to program an FPGA using a region
2762306a36Sopenharmony_ci-------------------------------------
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ciWhen the FPGA region driver probed, it was given a pointer to an FPGA manager
3062306a36Sopenharmony_cidriver so it knows which manager to use.  The region also either has a list of
3162306a36Sopenharmony_cibridges to control during programming or it has a pointer to a function that
3262306a36Sopenharmony_ciwill generate that list.  Here's some sample code of what to do next::
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	#include <linux/fpga/fpga-mgr.h>
3562306a36Sopenharmony_ci	#include <linux/fpga/fpga-region.h>
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	struct fpga_image_info *info;
3862306a36Sopenharmony_ci	int ret;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	/*
4162306a36Sopenharmony_ci	 * First, alloc the struct with information about the FPGA image to
4262306a36Sopenharmony_ci	 * program.
4362306a36Sopenharmony_ci	 */
4462306a36Sopenharmony_ci	info = fpga_image_info_alloc(dev);
4562306a36Sopenharmony_ci	if (!info)
4662306a36Sopenharmony_ci		return -ENOMEM;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	/* Set flags as needed, such as: */
4962306a36Sopenharmony_ci	info->flags = FPGA_MGR_PARTIAL_RECONFIG;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	/*
5262306a36Sopenharmony_ci	 * Indicate where the FPGA image is. This is pseudo-code; you're
5362306a36Sopenharmony_ci	 * going to use one of these three.
5462306a36Sopenharmony_ci	 */
5562306a36Sopenharmony_ci	if (image is in a scatter gather table) {
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci		info->sgt = [your scatter gather table]
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	} else if (image is in a buffer) {
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci		info->buf = [your image buffer]
6262306a36Sopenharmony_ci		info->count = [image buffer size]
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	} else if (image is in a firmware file) {
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci		info->firmware_name = devm_kstrdup(dev, firmware_name,
6762306a36Sopenharmony_ci						   GFP_KERNEL);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	/* Add info to region and do the programming */
7262306a36Sopenharmony_ci	region->info = info;
7362306a36Sopenharmony_ci	ret = fpga_region_program_fpga(region);
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	/* Deallocate the image info if you're done with it */
7662306a36Sopenharmony_ci	region->info = NULL;
7762306a36Sopenharmony_ci	fpga_image_info_free(info);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	if (ret)
8062306a36Sopenharmony_ci		return ret;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	/* Now enumerate whatever hardware has appeared in the FPGA. */
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ciAPI for programming an FPGA
8562306a36Sopenharmony_ci---------------------------
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci* fpga_region_program_fpga() -  Program an FPGA
8862306a36Sopenharmony_ci* fpga_image_info() -  Specifies what FPGA image to program
8962306a36Sopenharmony_ci* fpga_image_info_alloc() -  Allocate an FPGA image info struct
9062306a36Sopenharmony_ci* fpga_image_info_free() -  Free an FPGA image info struct
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci.. kernel-doc:: drivers/fpga/fpga-region.c
9362306a36Sopenharmony_ci   :functions: fpga_region_program_fpga
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ciFPGA Manager flags
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci.. kernel-doc:: include/linux/fpga/fpga-mgr.h
9862306a36Sopenharmony_ci   :doc: FPGA Manager flags
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci.. kernel-doc:: include/linux/fpga/fpga-mgr.h
10162306a36Sopenharmony_ci   :functions: fpga_image_info
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci.. kernel-doc:: drivers/fpga/fpga-mgr.c
10462306a36Sopenharmony_ci   :functions: fpga_image_info_alloc
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci.. kernel-doc:: drivers/fpga/fpga-mgr.c
10762306a36Sopenharmony_ci   :functions: fpga_image_info_free
108