mirror of https://gitee.com/openkylin/linux.git
108 lines
3.0 KiB
ReStructuredText
108 lines
3.0 KiB
ReStructuredText
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
|