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