Skip to content
Snippets Groups Projects
Commit 547b822c authored by Alan Tull's avatar Alan Tull Committed by Greg Kroah-Hartman
Browse files

documentation: fpga: move fpga-mgr.txt to driver-api


Move Documentation/fpga/fpga-mgr.txt to driver-api/fpga/fpga-mgr.rst
and:
 - Add to driver-api/fpga/index.rst
 - Format changes so documentation builds cleanly.
 - Minor rewrites that make the doc flow better as ReST documentation.
   - Such as moving API reference to end of doc
 - Change API reference section to refer to kernel-doc documentation in
   fpga-mgr.c driver code rather than statically defining each function.

Signed-off-by: default avatarAlan Tull <atull@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 66c472cd
No related branches found
No related tags found
No related merge requests found
FPGA Manager Core FPGA Manager
============
Alan Tull 2015
Overview Overview
======== --------
The FPGA manager core exports a set of functions for programming an FPGA with The FPGA manager core exports a set of functions for programming an FPGA with
an image. The API is manufacturer agnostic. All manufacturer specifics are an image. The API is manufacturer agnostic. All manufacturer specifics are
...@@ -21,198 +20,201 @@ fpga_image_info). This struct contains parameters such as pointers to the ...@@ -21,198 +20,201 @@ fpga_image_info). This struct contains parameters such as pointers to the
FPGA image as well as image-specific particulars such as whether the image was FPGA image as well as image-specific particulars such as whether the image was
built for full or partial reconfiguration. built for full or partial reconfiguration.
API Functions: How to support a new FPGA device
============== --------------------------------
To program the FPGA: To add another FPGA manager, write a driver that implements a set of ops. The
-------------------- probe function calls fpga_mgr_register(), such as::
int fpga_mgr_load(struct fpga_manager *mgr, static const struct fpga_manager_ops socfpga_fpga_ops = {
struct fpga_image_info *info); .write_init = socfpga_fpga_ops_configure_init,
.write = socfpga_fpga_ops_configure_write,
.write_complete = socfpga_fpga_ops_configure_complete,
.state = socfpga_fpga_ops_state,
};
Load the FPGA from an image which is indicated in the info. If successful, static int socfpga_fpga_probe(struct platform_device *pdev)
the FPGA ends up in operating mode. Return 0 on success or a negative error {
code. struct device *dev = &pdev->dev;
struct socfpga_fpga_priv *priv;
struct fpga_manager *mgr;
int ret;
To allocate or free a struct fpga_image_info: priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
--------------------------------------------- if (!priv)
return -ENOMEM;
struct fpga_image_info *fpga_image_info_alloc(struct device *dev); /*
* do ioremaps, get interrupts, etc. and save
* them in priv
*/
void fpga_image_info_free(struct fpga_image_info *info); mgr = fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager",
&socfpga_fpga_ops, priv);
if (!mgr)
return -ENOMEM;
To get/put a reference to a FPGA manager: platform_set_drvdata(pdev, mgr);
-----------------------------------------
struct fpga_manager *of_fpga_mgr_get(struct device_node *node); ret = fpga_mgr_register(mgr);
struct fpga_manager *fpga_mgr_get(struct device *dev); if (ret)
void fpga_mgr_put(struct fpga_manager *mgr); fpga_mgr_free(mgr);
Given a DT node or device, get a reference to a FPGA manager. This pointer return ret;
can be saved until you are ready to program the FPGA. fpga_mgr_put releases }
the reference.
static int socfpga_fpga_remove(struct platform_device *pdev)
{
struct fpga_manager *mgr = platform_get_drvdata(pdev);
To get exclusive control of a FPGA manager: fpga_mgr_unregister(mgr);
-------------------------------------------
int fpga_mgr_lock(struct fpga_manager *mgr); return 0;
void fpga_mgr_unlock(struct fpga_manager *mgr); }
The user should call fpga_mgr_lock and verify that it returns 0 before
attempting to program the FPGA. Likewise, the user should call
fpga_mgr_unlock when done programming the FPGA.
To alloc/free a FPGA manager struct: The ops will implement whatever device specific register writes are needed to
------------------------------------ do the programming sequence for this particular FPGA. These ops return 0 for
success or negative error codes otherwise.
struct fpga_manager *fpga_mgr_create(struct device *dev, The programming sequence is::
const char *name, 1. .write_init
const struct fpga_manager_ops *mops, 2. .write or .write_sg (may be called once or multiple times)
void *priv); 3. .write_complete
void fpga_mgr_free(struct fpga_manager *mgr);
To register or unregister the low level FPGA-specific driver: The .write_init function will prepare the FPGA to receive the image data. The
------------------------------------------------------------- buffer passed into .write_init will be atmost .initial_header_size bytes long,
if the whole bitstream is not immediately available then the core code will
buffer up at least this much before starting.
int fpga_mgr_register(struct fpga_manager *mgr); The .write function writes a buffer to the FPGA. The buffer may be contain the
whole FPGA image or may be a smaller chunk of an FPGA image. In the latter
case, this function is called multiple times for successive chunks. This interface
is suitable for drivers which use PIO.
void fpga_mgr_unregister(struct fpga_manager *mgr); The .write_sg version behaves the same as .write except the input is a sg_table
scatter list. This interface is suitable for drivers which use DMA.
Use of these functions is described below in "How To Support a new FPGA The .write_complete function is called after all the image has been written
device." to put the FPGA into operating mode.
The ops include a .state function which will read the hardware FPGA manager and
return a code of type enum fpga_mgr_states. It doesn't result in a change in
hardware state.
How to write an image buffer to a supported FPGA How to write an image buffer to a supported FPGA
================================================ ------------------------------------------------
#include <linux/fpga/fpga-mgr.h>
struct fpga_manager *mgr; Some sample code::
struct fpga_image_info *info;
int ret;
/* #include <linux/fpga/fpga-mgr.h>
* Get a reference to FPGA manager. The manager is not locked, so you can
* hold onto this reference without it preventing programming.
*
* This example uses the device node of the manager. Alternatively, use
* fpga_mgr_get(dev) instead if you have the device.
*/
mgr = of_fpga_mgr_get(mgr_node);
/* struct with information about the FPGA image to program. */ struct fpga_manager *mgr;
info = fpga_image_info_alloc(dev); struct fpga_image_info *info;
int ret;
/* flags indicates whether to do full or partial reconfiguration */ /*
info->flags = FPGA_MGR_PARTIAL_RECONFIG; * Get a reference to FPGA manager. The manager is not locked, so you can
* hold onto this reference without it preventing programming.
*
* This example uses the device node of the manager. Alternatively, use
* fpga_mgr_get(dev) instead if you have the device.
*/
mgr = of_fpga_mgr_get(mgr_node);
/* /* struct with information about the FPGA image to program. */
* At this point, indicate where the image is. This is pseudo-code; you're info = fpga_image_info_alloc(dev);
* going to use one of these three.
*/
if (image is in a scatter gather table) {
info->sgt = [your scatter gather table] /* flags indicates whether to do full or partial reconfiguration */
info->flags = FPGA_MGR_PARTIAL_RECONFIG;
} else if (image is in a buffer) { /*
* At this point, indicate where the image is. This is pseudo-code; you're
* going to use one of these three.
*/
if (image is in a scatter gather table) {
info->buf = [your image buffer] info->sgt = [your scatter gather table]
info->count = [image buffer size]
} else if (image is in a firmware file) { } else if (image is in a buffer) {
info->firmware_name = devm_kstrdup(dev, firmware_name, GFP_KERNEL); info->buf = [your image buffer]
info->count = [image buffer size]
} } else if (image is in a firmware file) {
/* Get exclusive control of FPGA manager */ info->firmware_name = devm_kstrdup(dev, firmware_name, GFP_KERNEL);
ret = fpga_mgr_lock(mgr);
/* Load the buffer to the FPGA */ }
ret = fpga_mgr_buf_load(mgr, &info, buf, count);
/* Release the FPGA manager */ /* Get exclusive control of FPGA manager */
fpga_mgr_unlock(mgr); ret = fpga_mgr_lock(mgr);
fpga_mgr_put(mgr);
/* Deallocate the image info if you're done with it */ /* Load the buffer to the FPGA */
fpga_image_info_free(info); ret = fpga_mgr_buf_load(mgr, &info, buf, count);
How to support a new FPGA device /* Release the FPGA manager */
================================ fpga_mgr_unlock(mgr);
To add another FPGA manager, write a driver that implements a set of ops. The fpga_mgr_put(mgr);
probe function calls fpga_mgr_register(), such as:
static const struct fpga_manager_ops socfpga_fpga_ops = {
.write_init = socfpga_fpga_ops_configure_init,
.write = socfpga_fpga_ops_configure_write,
.write_complete = socfpga_fpga_ops_configure_complete,
.state = socfpga_fpga_ops_state,
};
static int socfpga_fpga_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct socfpga_fpga_priv *priv;
struct fpga_manager *mgr;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); /* Deallocate the image info if you're done with it */
if (!priv) fpga_image_info_free(info);
return -ENOMEM;
/* ... do ioremaps, get interrupts, etc. and save API for implementing a new FPGA Manager driver
them in priv... */ ----------------------------------------------
mgr = fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager", .. kernel-doc:: include/linux/fpga/fpga-mgr.h
&socfpga_fpga_ops, priv); :functions: fpga_manager
if (!mgr)
return -ENOMEM;
platform_set_drvdata(pdev, mgr); .. kernel-doc:: include/linux/fpga/fpga-mgr.h
:functions: fpga_manager_ops
ret = fpga_mgr_register(mgr); .. kernel-doc:: drivers/fpga/fpga-mgr.c
if (ret) :functions: fpga_mgr_create
fpga_mgr_free(mgr);
return ret; .. kernel-doc:: drivers/fpga/fpga-mgr.c
} :functions: fpga_mgr_free
static int socfpga_fpga_remove(struct platform_device *pdev) .. kernel-doc:: drivers/fpga/fpga-mgr.c
{ :functions: fpga_mgr_register
struct fpga_manager *mgr = platform_get_drvdata(pdev);
fpga_mgr_unregister(mgr); .. kernel-doc:: drivers/fpga/fpga-mgr.c
:functions: fpga_mgr_unregister
return 0; API for programming a FPGA
} --------------------------
.. kernel-doc:: include/linux/fpga/fpga-mgr.h
:functions: fpga_image_info
The ops will implement whatever device specific register writes are needed to .. kernel-doc:: include/linux/fpga/fpga-mgr.h
do the programming sequence for this particular FPGA. These ops return 0 for :functions: fpga_mgr_states
success or negative error codes otherwise.
The programming sequence is: .. kernel-doc:: drivers/fpga/fpga-mgr.c
1. .write_init :functions: fpga_image_info_alloc
2. .write or .write_sg (may be called once or multiple times)
3. .write_complete
The .write_init function will prepare the FPGA to receive the image data. The .. kernel-doc:: drivers/fpga/fpga-mgr.c
buffer passed into .write_init will be atmost .initial_header_size bytes long, :functions: fpga_image_info_free
if the whole bitstream is not immediately available then the core code will
buffer up at least this much before starting.
The .write function writes a buffer to the FPGA. The buffer may be contain the .. kernel-doc:: drivers/fpga/fpga-mgr.c
whole FPGA image or may be a smaller chunk of an FPGA image. In the latter :functions: of_fpga_mgr_get
case, this function is called multiple times for successive chunks. This interface
is suitable for drivers which use PIO.
The .write_sg version behaves the same as .write except the input is a sg_table .. kernel-doc:: drivers/fpga/fpga-mgr.c
scatter list. This interface is suitable for drivers which use DMA. :functions: fpga_mgr_get
The .write_complete function is called after all the image has been written .. kernel-doc:: drivers/fpga/fpga-mgr.c
to put the FPGA into operating mode. :functions: fpga_mgr_put
The ops include a .state function which will read the hardware FPGA manager and .. kernel-doc:: drivers/fpga/fpga-mgr.c
return a code of type enum fpga_mgr_states. It doesn't result in a change in :functions: fpga_mgr_lock
hardware state.
.. kernel-doc:: drivers/fpga/fpga-mgr.c
:functions: fpga_mgr_unlock
.. kernel-doc:: include/linux/fpga/fpga-mgr.h
:functions: fpga_mgr_states
Note - use :c:func:`fpga_region_program_fpga()` instead of :c:func:`fpga_mgr_load()`
.. kernel-doc:: drivers/fpga/fpga-mgr.c
:functions: fpga_mgr_load
...@@ -8,3 +8,4 @@ FPGA Subsystem ...@@ -8,3 +8,4 @@ FPGA Subsystem
:maxdepth: 2 :maxdepth: 2
intro intro
fpga-mgr
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment