| In-kernel API for FPGA Programming |
| ================================== |
| |
| Overview |
| -------- |
| |
| The in-kernel API for FPGA programming is a combination of APIs from |
| FPGA manager, bridge, and regions. The actual function used to |
| trigger FPGA programming is :c:func:`fpga_region_program_fpga()`. |
| |
| :c:func:`fpga_region_program_fpga()` uses functionality supplied by |
| the FPGA manager and bridges. It will: |
| |
| * lock the region's mutex |
| * lock the mutex of the region's FPGA manager |
| * build a list of FPGA bridges if a method has been specified to do so |
| * disable the bridges |
| * program the FPGA using info passed in :c:member:`fpga_region->info`. |
| * re-enable the bridges |
| * release the locks |
| |
| The struct fpga_image_info specifies what FPGA image to program. It is |
| allocated/freed by :c:func:`fpga_image_info_alloc()` and freed with |
| :c:func:`fpga_image_info_free()` |
| |
| How to program an FPGA using a region |
| ------------------------------------- |
| |
| When the FPGA region driver probed, it was given a pointer to an FPGA manager |
| driver so it knows which manager to use. The region also either has a list of |
| bridges to control during programming or it has a pointer to a function that |
| will generate that list. Here's some sample code of what to do next:: |
| |
| #include <linux/fpga/fpga-mgr.h> |
| #include <linux/fpga/fpga-region.h> |
| |
| struct fpga_image_info *info; |
| int ret; |
| |
| /* |
| * First, alloc the struct with information about the FPGA image to |
| * program. |
| */ |
| info = fpga_image_info_alloc(dev); |
| if (!info) |
| return -ENOMEM; |
| |
| /* Set flags as needed, such as: */ |
| info->flags = FPGA_MGR_PARTIAL_RECONFIG; |
| |
| /* |
| * Indicate where the FPGA image is. This is pseudo-code; you're |
| * going to use one of these three. |
| */ |
| if (image is in a scatter gather table) { |
| |
| info->sgt = [your scatter gather table] |
| |
| } else if (image is in a buffer) { |
| |
| info->buf = [your image buffer] |
| info->count = [image buffer size] |
| |
| } else if (image is in a firmware file) { |
| |
| info->firmware_name = devm_kstrdup(dev, firmware_name, |
| GFP_KERNEL); |
| |
| } |
| |
| /* Add info to region and do the programming */ |
| region->info = info; |
| ret = fpga_region_program_fpga(region); |
| |
| /* Deallocate the image info if you're done with it */ |
| region->info = NULL; |
| fpga_image_info_free(info); |
| |
| if (ret) |
| return ret; |
| |
| /* Now enumerate whatever hardware has appeared in the FPGA. */ |
| |
| API for programming an FPGA |
| --------------------------- |
| |
| * :c:func:`fpga_region_program_fpga` — Program an FPGA |
| * :c:type:`fpga_image_info` — Specifies what FPGA image to program |
| * :c:func:`fpga_image_info_alloc()` — Allocate an FPGA image info struct |
| * :c:func:`fpga_image_info_free()` — Free an FPGA image info struct |
| |
| .. kernel-doc:: drivers/fpga/fpga-region.c |
| :functions: fpga_region_program_fpga |
| |
| FPGA Manager flags |
| |
| .. kernel-doc:: include/linux/fpga/fpga-mgr.h |
| :doc: FPGA Manager flags |
| |
| .. kernel-doc:: include/linux/fpga/fpga-mgr.h |
| :functions: fpga_image_info |
| |
| .. kernel-doc:: drivers/fpga/fpga-mgr.c |
| :functions: fpga_image_info_alloc |
| |
| .. kernel-doc:: drivers/fpga/fpga-mgr.c |
| :functions: fpga_image_info_free |