summaryrefslogtreecommitdiffstats
path: root/Documentation/driver-api/fpga
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/driver-api/fpga')
-rw-r--r--Documentation/driver-api/fpga/fpga-bridge.rst22
-rw-r--r--Documentation/driver-api/fpga/fpga-mgr.rst162
-rw-r--r--Documentation/driver-api/fpga/fpga-programming.rst107
-rw-r--r--Documentation/driver-api/fpga/fpga-region.rst109
-rw-r--r--Documentation/driver-api/fpga/index.rst15
-rw-r--r--Documentation/driver-api/fpga/intro.rst54
6 files changed, 469 insertions, 0 deletions
diff --git a/Documentation/driver-api/fpga/fpga-bridge.rst b/Documentation/driver-api/fpga/fpga-bridge.rst
new file mode 100644
index 0000000000..6042085340
--- /dev/null
+++ b/Documentation/driver-api/fpga/fpga-bridge.rst
@@ -0,0 +1,22 @@
+FPGA Bridge
+===========
+
+API to implement a new FPGA bridge
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* struct fpga_bridge - The FPGA Bridge structure
+* struct fpga_bridge_ops - Low level Bridge driver ops
+* fpga_bridge_register() - Create and register a bridge
+* fpga_bridge_unregister() - Unregister a bridge
+
+.. kernel-doc:: include/linux/fpga/fpga-bridge.h
+ :functions: fpga_bridge
+
+.. kernel-doc:: include/linux/fpga/fpga-bridge.h
+ :functions: fpga_bridge_ops
+
+.. kernel-doc:: drivers/fpga/fpga-bridge.c
+ :functions: fpga_bridge_register
+
+.. kernel-doc:: drivers/fpga/fpga-bridge.c
+ :functions: fpga_bridge_unregister
diff --git a/Documentation/driver-api/fpga/fpga-mgr.rst b/Documentation/driver-api/fpga/fpga-mgr.rst
new file mode 100644
index 0000000000..49c0a95126
--- /dev/null
+++ b/Documentation/driver-api/fpga/fpga-mgr.rst
@@ -0,0 +1,162 @@
+FPGA Manager
+============
+
+Overview
+--------
+
+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
+hidden away in a low level driver which registers a set of ops with the core.
+The FPGA image data itself is very manufacturer specific, but for our purposes
+it's just binary data. The FPGA manager core won't parse it.
+
+The FPGA image to be programmed can be in a scatter gather list, a single
+contiguous buffer, or a firmware file. Because allocating contiguous kernel
+memory for the buffer should be avoided, users are encouraged to use a scatter
+gather list instead if possible.
+
+The particulars for programming the image are presented in a structure (struct
+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
+built for full or partial reconfiguration.
+
+How to support a new FPGA device
+--------------------------------
+
+To add another FPGA manager, write a driver that implements a set of ops. The
+probe function calls fpga_mgr_register() or fpga_mgr_register_full(), 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);
+ if (!priv)
+ return -ENOMEM;
+
+ /*
+ * do ioremaps, get interrupts, etc. and save
+ * them in priv
+ */
+
+ mgr = fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager",
+ &socfpga_fpga_ops, priv);
+ if (IS_ERR(mgr))
+ return PTR_ERR(mgr);
+
+ platform_set_drvdata(pdev, mgr);
+
+ return 0;
+ }
+
+ static int socfpga_fpga_remove(struct platform_device *pdev)
+ {
+ struct fpga_manager *mgr = platform_get_drvdata(pdev);
+
+ fpga_mgr_unregister(mgr);
+
+ return 0;
+ }
+
+Alternatively, the probe function could call one of the resource managed
+register functions, devm_fpga_mgr_register() or devm_fpga_mgr_register_full().
+When these functions are used, the parameter syntax is the same, but the call
+to fpga_mgr_unregister() should be removed. In the above example, the
+socfpga_fpga_remove() function would not be required.
+
+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.
+
+The programming sequence is::
+ 1. .parse_header (optional, may be called once or multiple times)
+ 2. .write_init
+ 3. .write or .write_sg (may be called once or multiple times)
+ 4. .write_complete
+
+The .parse_header function will set header_size and data_size to
+struct fpga_image_info. Before parse_header call, header_size is initialized
+with initial_header_size. If flag skip_header of fpga_manager_ops is true,
+.write function will get image buffer starting at header_size offset from the
+beginning. If data_size is set, .write function will get data_size bytes of
+the image buffer, otherwise .write will get data up to the end of image buffer.
+This will not affect .write_sg, .write_sg will still get whole image in
+sg_table form. If FPGA image is already mapped as a single contiguous buffer,
+whole buffer will be passed into .parse_header. If image is in scatter-gather
+form, core code will buffer up at least .initial_header_size before the first
+call of .parse_header, if it is not enough, .parse_header should set desired
+size into info->header_size and return -EAGAIN, then it will be called again
+with greater part of image buffer on the input.
+
+The .write_init function will prepare the FPGA to receive the image data. The
+buffer passed into .write_init will be at least info->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.
+
+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.
+
+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.
+
+The .write_complete function is called after all the image has been written
+to put the FPGA into operating mode.
+
+The ops include a .state function which will determine the state the FPGA is in
+and return a code of type enum fpga_mgr_states. It doesn't result in a change
+in state.
+
+API for implementing a new FPGA Manager driver
+----------------------------------------------
+
+* ``fpga_mgr_states`` - Values for :c:expr:`fpga_manager->state`.
+* struct fpga_manager - the FPGA manager struct
+* struct fpga_manager_ops - Low level FPGA manager driver ops
+* struct fpga_manager_info - Parameter structure for fpga_mgr_register_full()
+* fpga_mgr_register_full() - Create and register an FPGA manager using the
+ fpga_mgr_info structure to provide the full flexibility of options
+* fpga_mgr_register() - Create and register an FPGA manager using standard
+ arguments
+* devm_fpga_mgr_register_full() - Resource managed version of
+ fpga_mgr_register_full()
+* devm_fpga_mgr_register() - Resource managed version of fpga_mgr_register()
+* fpga_mgr_unregister() - Unregister an FPGA manager
+
+.. kernel-doc:: include/linux/fpga/fpga-mgr.h
+ :functions: fpga_mgr_states
+
+.. kernel-doc:: include/linux/fpga/fpga-mgr.h
+ :functions: fpga_manager
+
+.. kernel-doc:: include/linux/fpga/fpga-mgr.h
+ :functions: fpga_manager_ops
+
+.. kernel-doc:: include/linux/fpga/fpga-mgr.h
+ :functions: fpga_manager_info
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: fpga_mgr_register_full
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: fpga_mgr_register
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: devm_fpga_mgr_register_full
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: devm_fpga_mgr_register
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: fpga_mgr_unregister
diff --git a/Documentation/driver-api/fpga/fpga-programming.rst b/Documentation/driver-api/fpga/fpga-programming.rst
new file mode 100644
index 0000000000..fb4da4240e
--- /dev/null
+++ b/Documentation/driver-api/fpga/fpga-programming.rst
@@ -0,0 +1,107 @@
+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 fpga_region_program_fpga().
+
+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:expr:`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 fpga_image_info_alloc() and freed with
+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
+---------------------------
+
+* fpga_region_program_fpga() - Program an FPGA
+* fpga_image_info() - Specifies what FPGA image to program
+* fpga_image_info_alloc() - Allocate an FPGA image info struct
+* 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
diff --git a/Documentation/driver-api/fpga/fpga-region.rst b/Documentation/driver-api/fpga/fpga-region.rst
new file mode 100644
index 0000000000..dc55d60a0b
--- /dev/null
+++ b/Documentation/driver-api/fpga/fpga-region.rst
@@ -0,0 +1,109 @@
+FPGA Region
+===========
+
+Overview
+--------
+
+This document is meant to be a brief overview of the FPGA region API usage. A
+more conceptual look at regions can be found in the Device Tree binding
+document [#f1]_.
+
+For the purposes of this API document, let's just say that a region associates
+an FPGA Manager and a bridge (or bridges) with a reprogrammable region of an
+FPGA or the whole FPGA. The API provides a way to register a region and to
+program a region.
+
+Currently the only layer above fpga-region.c in the kernel is the Device Tree
+support (of-fpga-region.c) described in [#f1]_. The DT support layer uses regions
+to program the FPGA and then DT to handle enumeration. The common region code
+is intended to be used by other schemes that have other ways of accomplishing
+enumeration after programming.
+
+An fpga-region can be set up to know the following things:
+
+ * which FPGA manager to use to do the programming
+
+ * which bridges to disable before programming and enable afterwards.
+
+Additional info needed to program the FPGA image is passed in the struct
+fpga_image_info including:
+
+ * pointers to the image as either a scatter-gather buffer, a contiguous
+ buffer, or the name of firmware file
+
+ * flags indicating specifics such as whether the image is for partial
+ reconfiguration.
+
+How to add a new FPGA region
+----------------------------
+
+An example of usage can be seen in the probe function of [#f2]_.
+
+.. [#f1] ../devicetree/bindings/fpga/fpga-region.txt
+.. [#f2] ../../drivers/fpga/of-fpga-region.c
+
+API to add a new FPGA region
+----------------------------
+
+* struct fpga_region - The FPGA region struct
+* struct fpga_region_info - Parameter structure for fpga_region_register_full()
+* fpga_region_register_full() - Create and register an FPGA region using the
+ fpga_region_info structure to provide the full flexibility of options
+* fpga_region_register() - Create and register an FPGA region using standard
+ arguments
+* fpga_region_unregister() - Unregister an FPGA region
+
+The FPGA region's probe function will need to get a reference to the FPGA
+Manager it will be using to do the programming. This usually would happen
+during the region's probe function.
+
+* fpga_mgr_get() - Get a reference to an FPGA manager, raise ref count
+* of_fpga_mgr_get() - Get a reference to an FPGA manager, raise ref count,
+ given a device node.
+* fpga_mgr_put() - Put an FPGA manager
+
+The FPGA region will need to specify which bridges to control while programming
+the FPGA. The region driver can build a list of bridges during probe time
+(:c:expr:`fpga_region->bridge_list`) or it can have a function that creates
+the list of bridges to program just before programming
+(:c:expr:`fpga_region->get_bridges`). The FPGA bridge framework supplies the
+following APIs to handle building or tearing down that list.
+
+* fpga_bridge_get_to_list() - Get a ref of an FPGA bridge, add it to a
+ list
+* of_fpga_bridge_get_to_list() - Get a ref of an FPGA bridge, add it to a
+ list, given a device node
+* fpga_bridges_put() - Given a list of bridges, put them
+
+.. kernel-doc:: include/linux/fpga/fpga-region.h
+ :functions: fpga_region
+
+.. kernel-doc:: include/linux/fpga/fpga-region.h
+ :functions: fpga_region_info
+
+.. kernel-doc:: drivers/fpga/fpga-region.c
+ :functions: fpga_region_register_full
+
+.. kernel-doc:: drivers/fpga/fpga-region.c
+ :functions: fpga_region_register
+
+.. kernel-doc:: drivers/fpga/fpga-region.c
+ :functions: fpga_region_unregister
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: fpga_mgr_get
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: of_fpga_mgr_get
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: fpga_mgr_put
+
+.. kernel-doc:: drivers/fpga/fpga-bridge.c
+ :functions: fpga_bridge_get_to_list
+
+.. kernel-doc:: drivers/fpga/fpga-bridge.c
+ :functions: of_fpga_bridge_get_to_list
+
+.. kernel-doc:: drivers/fpga/fpga-bridge.c
+ :functions: fpga_bridges_put
diff --git a/Documentation/driver-api/fpga/index.rst b/Documentation/driver-api/fpga/index.rst
new file mode 100644
index 0000000000..31a4773bd2
--- /dev/null
+++ b/Documentation/driver-api/fpga/index.rst
@@ -0,0 +1,15 @@
+==============
+FPGA Subsystem
+==============
+
+:Author: Alan Tull
+
+.. toctree::
+ :maxdepth: 2
+
+ intro
+ fpga-mgr
+ fpga-bridge
+ fpga-region
+ fpga-programming
+
diff --git a/Documentation/driver-api/fpga/intro.rst b/Documentation/driver-api/fpga/intro.rst
new file mode 100644
index 0000000000..f54c7dabcc
--- /dev/null
+++ b/Documentation/driver-api/fpga/intro.rst
@@ -0,0 +1,54 @@
+Introduction
+============
+
+The FPGA subsystem supports reprogramming FPGAs dynamically under
+Linux. Some of the core intentions of the FPGA subsystems are:
+
+* The FPGA subsystem is vendor agnostic.
+
+* The FPGA subsystem separates upper layers (userspace interfaces and
+ enumeration) from lower layers that know how to program a specific
+ FPGA.
+
+* Code should not be shared between upper and lower layers. This
+ should go without saying. If that seems necessary, there's probably
+ framework functionality that can be added that will benefit
+ other users. Write the linux-fpga mailing list and maintainers and
+ seek out a solution that expands the framework for broad reuse.
+
+* Generally, when adding code, think of the future. Plan for reuse.
+
+The framework in the kernel is divided into:
+
+FPGA Manager
+------------
+
+If you are adding a new FPGA or a new method of programming an FPGA,
+this is the subsystem for you. Low level FPGA manager drivers contain
+the knowledge of how to program a specific device. This subsystem
+includes the framework in fpga-mgr.c and the low level drivers that
+are registered with it.
+
+FPGA Bridge
+-----------
+
+FPGA Bridges prevent spurious signals from going out of an FPGA or a
+region of an FPGA during programming. They are disabled before
+programming begins and re-enabled afterwards. An FPGA bridge may be
+actual hard hardware that gates a bus to a CPU or a soft ("freeze")
+bridge in FPGA fabric that surrounds a partial reconfiguration region
+of an FPGA. This subsystem includes fpga-bridge.c and the low level
+drivers that are registered with it.
+
+FPGA Region
+-----------
+
+If you are adding a new interface to the FPGA framework, add it on top
+of an FPGA region.
+
+The FPGA Region framework (fpga-region.c) associates managers and
+bridges as reconfigurable regions. A region may refer to the whole
+FPGA in full reconfiguration or to a partial reconfiguration region.
+
+The Device Tree FPGA Region support (of-fpga-region.c) handles
+reprogramming FPGAs when device tree overlays are applied.