linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v13 0/6] simple fpga bus and fpga bridge framework
@ 2015-11-03 17:10 atull
  2015-11-03 17:10 ` [PATCH v13 1/6] fpga: add usage documentation for simple fpga bus atull
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: atull @ 2015-11-03 17:10 UTC (permalink / raw)
  To: Rob Herring
  Cc: Moritz Fischer, Josh Cartwright, gregkh, monstr, michal.simek,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Jonathan Corbet, linux-kernel, devicetree, linux-doc,
	pantelis.antoniou, delicious.quinoa, dinguyen, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

These patches are too late for this merge window; I'm submitting
them for those who are reviewing, especially the bindings.

Changes since v12:
 Change DT property from "init-val" to "bridge-enable"
 Use proposed DT common property "firmware-name" instead of "fpga-firmware"
 Clean up cruft from simple-fpga-bus DT bindings example
 Support Simple FPGA Bus when FPGA Bridges are compiled out.
 Cleanup and nits

The Simple FPGA Bus provides a manufacturer-agnostic interface for
reprogramming FPGAs using Device Tree Overlays.  It uses the FPGA Bridge
Framework and the upstreamed FPGA Manager Framework.  In the case where
FPGA Bridges are not needed, they don't need to be specified in the DT
and can compiled out, if desired.

Alan Tull (6):
  fpga: add usage documentation for simple fpga bus
  fpga: add bindings document for simple fpga bus
  fpga: add simple-fpga-bus
  fpga: add fpga bridge framework
  ARM: socfpga: add bindings document for fpga bridge drivers
  ARM: socfpga: fpga bridge driver support

 .../bindings/fpga/altera-fpga2sdram-bridge.txt     |  15 +
 .../bindings/fpga/altera-hps2fpga-bridge.txt       |  31 ++
 .../devicetree/bindings/fpga/simple-fpga-bus.txt   |  74 +++++
 Documentation/fpga/simple-fpga-bus.txt             |  58 ++++
 drivers/fpga/Kconfig                               |  21 ++
 drivers/fpga/Makefile                              |   7 +
 drivers/fpga/altera-fpga2sdram.c                   | 185 ++++++++++++
 drivers/fpga/altera-hps2fpga.c                     | 233 +++++++++++++++
 drivers/fpga/fpga-bridge.c                         | 229 +++++++++++++++
 drivers/fpga/simple-fpga-bus.c                     | 323 +++++++++++++++++++++
 include/linux/fpga/fpga-bridge.h                   |  74 +++++
 11 files changed, 1250 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt
 create mode 100644 Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt
 create mode 100644 Documentation/devicetree/bindings/fpga/simple-fpga-bus.txt
 create mode 100644 Documentation/fpga/simple-fpga-bus.txt
 create mode 100644 drivers/fpga/altera-fpga2sdram.c
 create mode 100644 drivers/fpga/altera-hps2fpga.c
 create mode 100644 drivers/fpga/fpga-bridge.c
 create mode 100644 drivers/fpga/simple-fpga-bus.c
 create mode 100644 include/linux/fpga/fpga-bridge.h

-- 
1.9.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v13 1/6] fpga: add usage documentation for simple fpga bus
  2015-11-03 17:10 [PATCH v13 0/6] simple fpga bus and fpga bridge framework atull
@ 2015-11-03 17:10 ` atull
  2015-11-03 17:11 ` [PATCH v13 2/6] fpga: add bindings document " atull
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: atull @ 2015-11-03 17:10 UTC (permalink / raw)
  To: Rob Herring
  Cc: Moritz Fischer, Josh Cartwright, gregkh, monstr, michal.simek,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Jonathan Corbet, linux-kernel, devicetree, linux-doc,
	pantelis.antoniou, delicious.quinoa, dinguyen, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

Add a document spelling out usage of the simple fpga bus.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
Reviewed-by: Moritz Fischer <moritz.fischer@ettus.com>
---
v9:  Initial version of this patch in patchset
v10: s/fpga/FPGA/g
     improve formatting
     some rewriting
     move to staging/simple-fpga-bus
v11: No change in this patch for v11 of the patch set
v12: Moved out of staging
     Small changes due to using FPGA bridge framework and not
     representing the bridges as resets.
v13: Fix some nits
---
 Documentation/fpga/simple-fpga-bus.txt | 58 ++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)
 create mode 100644 Documentation/fpga/simple-fpga-bus.txt

diff --git a/Documentation/fpga/simple-fpga-bus.txt b/Documentation/fpga/simple-fpga-bus.txt
new file mode 100644
index 0000000..9b04826
--- /dev/null
+++ b/Documentation/fpga/simple-fpga-bus.txt
@@ -0,0 +1,58 @@
+Simple FPGA Bus
+
+Alan Tull 2015
+
+Overview
+========
+
+The simple FPGA bus adds device tree overlay support for FPGAs.  Loading a DT
+overlay will result in the FPGA getting programmed with an image, its bridges
+will be released, and the DT populated for nodes below the simple-fpga-bus.
+This results in drivers getting probed for the hardware that just got added.
+This is intended to support the FPGA usage where the FPGA has hardware that
+requires drivers.  Removing the overlay will result in the drivers getting
+removed and the bridges being disabled.
+
+The simple FPGA bus will need to disable and enable bridges that will only
+affect the child devices that are below the bus.  If partial reconfiguration
+is to be done, then bridges will need to be added within the FPGA design to
+protect the rest of the bus when one part of the FPGA design is being
+reconfigured.
+
+
+Sequence
+========
+
+Load the DT overlay.  One way to do that from user space is to use Pantelis'
+DT-Overlay configfs interface.
+
+This causes the simple FPGA bus to be probed and will do the following:
+ 1. Disable the FPGA bridges.
+ 2. Call the FPGA manager core to program the FPGA.
+ 3. Release the FPGA bridges.
+ 4. Call of_platform_populate resulting in device drivers getting probed.
+
+
+Requirements
+============
+
+ 1. An FPGA image that has a hardware block or blocks that use drivers that are
+    supported in the kernel.
+ 2. A device tree overlay (example is in the simple-fpga-bus bindings document).
+ 3. A FPGA manager driver supporting writing the FPGA.
+ 4. FPGA bridge drivers.
+
+The DT overlay includes bindings (documented in bindings/simple-fpga-bus.txt)
+that specify:
+ * Which FPGA manager to use.
+ * Which image file to load.
+ * Flags indicating whether this this image is for full reconfiguration or
+   partial.
+ * A list of FPGA bridges.
+ * Child nodes specifying the devices that will be added with appropriate
+   compatible strings, etc.
+
+Since this code uses the firmware interface to get the image and DT overlay,
+they currently have to be files on the file system.  It doesn't have to be that
+way forever as DT bindings could be added to point to other sources for the
+image.
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v13 2/6] fpga: add bindings document for simple fpga bus
  2015-11-03 17:10 [PATCH v13 0/6] simple fpga bus and fpga bridge framework atull
  2015-11-03 17:10 ` [PATCH v13 1/6] fpga: add usage documentation for simple fpga bus atull
@ 2015-11-03 17:11 ` atull
  2015-11-03 17:11 ` [PATCH v13 3/6] fpga: add simple-fpga-bus atull
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: atull @ 2015-11-03 17:11 UTC (permalink / raw)
  To: Rob Herring
  Cc: Moritz Fischer, Josh Cartwright, gregkh, monstr, michal.simek,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Jonathan Corbet, linux-kernel, devicetree, linux-doc,
	pantelis.antoniou, delicious.quinoa, dinguyen, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

New bindings document for simple fpga bus.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
---
v9:  initial version added to this patchset
v10: s/fpga/FPGA/g
     replace DT overlay example with slightly more complicated example
     move to staging/simple-fpga-bus
v11: No change in this patch for v11 of the patch set
v12: Moved out of staging.
     Changed to use FPGA bridges framework instead of resets
     for bridges.
v13: bridge@0xff20000 -> bridge@ff200000, etc
     Leave out directly talking about overlays
     Remove regs and clocks directly under simple-fpga-bus in example
     Use common "firmware-name" binding instead of "fpga-firmware"
---
 .../devicetree/bindings/fpga/simple-fpga-bus.txt   | 74 ++++++++++++++++++++++
 1 file changed, 74 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/fpga/simple-fpga-bus.txt

diff --git a/Documentation/devicetree/bindings/fpga/simple-fpga-bus.txt b/Documentation/devicetree/bindings/fpga/simple-fpga-bus.txt
new file mode 100644
index 0000000..9646c09
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/simple-fpga-bus.txt
@@ -0,0 +1,74 @@
+Simple FPGA Bus
+===============
+
+A Simple FPGA Bus is a bus that handles configuring an FPGA and its bridges
+before populating the devices below its node.
+
+Required properties:
+- compatible : should contain "simple-fpga-bus"
+- #address-cells, #size-cells, ranges: must be present to handle address space
+  mapping for children.
+
+Optional properties:
+- fpga-mgr : should contain a phandle to a FPGA manager.
+- fpga-firmware : should contain the name of a FPGA image file located on the
+  firmware search path.
+- partial-reconfig : boolean property should be defined if partial
+  reconfiguration of the FPGA is to be done, otherwise full reconfiguration
+  is done.
+- fpga-bridges : should contain a list of bridges that the bus will disable
+  before programming the FPGA and then enable after the FPGA has been
+  programmed.
+
+Example:
+
+/dts-v1/;
+/plugin/;
+/ {
+	fragment@0 {
+		target-path="/soc";
+		__overlay__ {
+			#address-cells = <1>;
+	                #size-cells = <1>;
+
+			bridge@ff200000 {
+				compatible = "simple-fpga-bus";
+
+				#address-cells = <0x2>;
+				#size-cells = <0x1>;
+
+				ranges = <0x00000000 0x00000000 0xc0000000 0x00010000>,
+					 <0x00000001 0x00020000 0xff220000 0x00000008>,
+					 <0x00000001 0x00010040 0xff210040 0x00000020>;
+
+				fpga-mgr = <&hps_0_fpgamgr>;
+				firmware-name = "soc_system.rbf";
+
+				fpga-bridges = <&hps_fpgabridge0>, <&hps_fpgabridge1>, <&hps_fpgabridge2>;
+
+				onchip_memory2_0: memory@000000000 {
+					device_type = "memory";
+					compatible = "ALTR,onchipmem-15.1";
+					reg = <0x00000000 0x00000000 0x00010000>;
+				};
+
+				jtag_uart: serial@100020000 {
+					compatible = "altr,juart-15.1", "altr,juart-1.0";
+					reg = <0x00000001 0x00020000 0x00000008>;
+					interrupt-parent = <&intc>;
+					interrupts = <0 42 4>;
+				};
+
+				led_pio: gpio@100010040 {
+					compatible = "altr,pio-15.1", "altr,pio-1.0";
+					reg = <0x00000001 0x00010040 0x00000020>;
+					altr,gpio-bank-width = <4>;
+					resetvalue = <0>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+			};
+		};
+	};
+};
+
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v13 3/6] fpga: add simple-fpga-bus
  2015-11-03 17:10 [PATCH v13 0/6] simple fpga bus and fpga bridge framework atull
  2015-11-03 17:10 ` [PATCH v13 1/6] fpga: add usage documentation for simple fpga bus atull
  2015-11-03 17:11 ` [PATCH v13 2/6] fpga: add bindings document " atull
@ 2015-11-03 17:11 ` atull
  2015-11-03 17:11 ` [PATCH v13 4/6] fpga: add fpga bridge framework atull
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: atull @ 2015-11-03 17:11 UTC (permalink / raw)
  To: Rob Herring
  Cc: Moritz Fischer, Josh Cartwright, gregkh, monstr, michal.simek,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Jonathan Corbet, linux-kernel, devicetree, linux-doc,
	pantelis.antoniou, delicious.quinoa, dinguyen, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

The Simple FPGA bus uses the FPGA Manager Framework and the
FPGA Bridge Framework to provide a manufactorer-agnostic
interface for reprogramming FPGAs that is Device Tree
Overlays-based.

When a Device Tree Overlay containing a Simple FPGA Bus is
applied, the Simple FPGA Bus will be probed and will:
 * Disable the FPGA bridges specified in the overlay
 * Reprogram a specified FPGA with a specified image file
 * Enable the specified FPGA bridges
 * Populate the child devices

Removing the Device Tree Overlay is also supported.

This supports fpga use where hardware blocks on a fpga will
need drivers.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
---
v9:  initial version (this patch added during rest of patchset's v9)
v10: request deferral if fpga mgr or bridges not available yet
     cleanup as fpga manager core goes into the real kernel
     Don't assume bridges are disabled before programming FPGA
     Don't hang onto reference for fpga manager
     Move to staging/simple-fpga-bus
v11: No change in this patch for v11 of the patch set
v12: Moved out of staging.
     Use fpga bridges framework.
v13: If no bridges are specified, assume we don't need any.
     Clean up debug messages
     Some dev_info -> dev_dbg
     Remove unneeded #include
     Fix size of array of pointers
     Don't need to specify .owner
     Use common binding: firmware-name
---
 drivers/fpga/Kconfig           |   7 +
 drivers/fpga/Makefile          |   3 +
 drivers/fpga/simple-fpga-bus.c | 323 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 333 insertions(+)
 create mode 100644 drivers/fpga/simple-fpga-bus.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index c9b9fdf..5fcf60a 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -13,6 +13,13 @@ config FPGA
 
 if FPGA
 
+config SIMPLE_FPGA_BUS
+       bool "Simple FPGA Bus"
+       depends on OF
+       help
+         Simple FPGA Bus allows loading FPGA images under control of
+	 Device Tree.
+
 config FPGA_MGR_SOCFPGA
 	tristate "Altera SOCFPGA FPGA Manager"
 	depends on ARCH_SOCFPGA
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 8d83fc6..9b55ae0 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -8,3 +8,6 @@ obj-$(CONFIG_FPGA)			+= fpga-mgr.o
 # FPGA Manager Drivers
 obj-$(CONFIG_FPGA_MGR_SOCFPGA)		+= socfpga.o
 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)	+= zynq-fpga.o
+
+# High Level Interfaces
+obj-$(CONFIG_SIMPLE_FPGA_BUS)		+= simple-fpga-bus.o
diff --git a/drivers/fpga/simple-fpga-bus.c b/drivers/fpga/simple-fpga-bus.c
new file mode 100644
index 0000000..abe95a0
--- /dev/null
+++ b/drivers/fpga/simple-fpga-bus.c
@@ -0,0 +1,323 @@
+/*
+ * Simple FPGA Bus
+ *
+ *  Copyright (C) 2013-2015 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/fpga/fpga-bridge.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+
+/**
+ * struct simple_fpga_bus - simple fpga bus private data
+ * @dev:	device from pdev
+ * @bridges:	FPGA bridges associated with this bus
+ * @num_bridges: size of the bridges array
+ */
+struct simple_fpga_bus {
+	struct device *dev;
+	struct fpga_bridge **bridges;
+	int num_bridges;
+};
+
+/**
+ * simple_fpga_bus_get_mgr - get associated fpga manager
+ * @priv: simple fpga bus private data
+ * pointer to fpga manager in priv->mgr on success
+ *
+ * Given a simple fpga bus, get a reference to its the fpga manager specified
+ * by its "fpga-mgr" device tree property.
+ *
+ * Return: 0 if the fpga manager is not specified.
+ *         pointer to struct fpga_manager if successful.
+ *         Negative error code otherwise.
+ */
+static struct fpga_manager *simple_fpga_bus_get_mgr(
+					struct simple_fpga_bus *priv)
+{
+	struct device *dev = priv->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *mgr_node;
+
+	/*
+	 * Return 0 (not an error) if fpga manager is not specified.
+	 * This supports the case where fpga was already configured.
+	 */
+	mgr_node = of_parse_phandle(np, "fpga-mgr", 0);
+	if (!mgr_node) {
+		dev_dbg(dev, "could not find fpga-mgr DT property\n");
+		return 0;
+	}
+
+	return of_fpga_mgr_get(mgr_node);
+}
+
+/**
+ * simple_fpga_bus_load_image - load an fpga image under device tree control
+ * @priv: simple fpga bus private data
+ *
+ * Given a simple fpga bus, load the fpga image specified in its device
+ * tree node.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+static int simple_fpga_bus_load_image(struct simple_fpga_bus *priv,
+				      struct fpga_manager *mgr)
+{
+	struct device *dev = priv->dev;
+	struct device_node *np = dev->of_node;
+	u32 flags = 0;
+	const char *path;
+
+	if (of_property_read_bool(np, "partial-reconfig"))
+		flags |= FPGA_MGR_PARTIAL_RECONFIG;
+
+	/* If firmware image is specified in the DT, load it */
+	if (!of_property_read_string(np, "firmware-name", &path))
+		return fpga_mgr_firmware_load(mgr, flags, path);
+
+	/*
+	 * Here we can add other methods of getting ahold of a fpga image
+	 * specified in the device tree and programming it.
+	 */
+
+	dev_dbg(dev, "No FPGA image to load.\n");
+
+	/* Status is that we have a fpga manager but no image specified. */
+	return -EINVAL;
+}
+
+/**
+ * simple_fpga_bus_bridge_enable - enable the fpga bridges
+ * @priv: simple fpga bus private data
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+static int simple_fpga_bus_bridge_enable(struct simple_fpga_bus *priv)
+{
+	int i, ret;
+
+	for (i = 0; i < priv->num_bridges; i++) {
+		ret = fpga_bridge_enable(priv->bridges[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * simple_fpga_bus_bridge_disable - disable the bridges
+ * @priv: simple fpga bus private data
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+static int simple_fpga_bus_bridge_disable(struct simple_fpga_bus *priv)
+{
+	int i, ret;
+
+	for (i = 0; i < priv->num_bridges; i++) {
+		ret = fpga_bridge_disable(priv->bridges[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * simple_fpga_bus_get_bridges - get references for fpga bridges
+ * @priv: simple fpga bus private data
+ *
+ * Given a simple fpga bus, get references for its associated fpga bridges.
+ * These are pointed to by "fpga-bridges" device tree property.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+static int simple_fpga_bus_get_bridges(struct simple_fpga_bus *priv)
+{
+	struct device *dev = priv->dev;
+	struct device_node *np = dev->of_node;
+	struct of_phandle_args out_args;
+	struct fpga_bridge *bridge, **bridges;
+	int i, num_bridges, ret;
+
+	/* If no bridges are specified, assume we don't need any. */
+	num_bridges = of_count_phandle_with_args(np, "fpga-bridges", NULL);
+	if (num_bridges <= 0)
+		return 0;
+
+	bridges = kcalloc(num_bridges, sizeof(struct fpga_bridge *),
+			  GFP_KERNEL);
+	if (!bridges)
+		return -ENOMEM;
+
+	for (i = 0; i < num_bridges; i++) {
+		ret = of_parse_phandle_with_args(np, "fpga-bridges", NULL, i,
+						 &out_args);
+		if (ret)
+			goto err_free_bridges;
+
+		bridge = of_fpga_bridge_get(out_args.np);
+		if (!bridge) {
+			dev_err(dev, "No fpga bridge found for phandle\n");
+			goto err_free_bridges;
+		}
+
+		dev_dbg(dev, "Found bridge: %s\n", dev_name(&bridge->dev));
+
+		bridges[i] = bridge;
+	}
+
+	priv->bridges = bridges;
+	priv->num_bridges = num_bridges;
+
+	return 0;
+
+err_free_bridges:
+	while (i)
+		fpga_bridge_put(bridges[--i]);
+
+	kfree(bridges);
+	return -EINVAL;
+}
+
+/**
+ * simple_fpga_bus_put_bridges - release references for the fpga bridges
+ * @priv: simple fpga bus private data
+ */
+static void simple_fpga_bus_put_bridges(struct simple_fpga_bus *priv)
+{
+	int i;
+
+	for (i = 0; i < priv->num_bridges; i++)
+		fpga_bridge_put(priv->bridges[i]);
+
+	kfree(priv->bridges);
+	priv->num_bridges = 0;
+}
+
+/**
+ * simple_fpga_bus_probe - Probe function for simple fpga bus.
+ * @pdev: platform device
+ *
+ * Do the necessary steps to program the FPGA and enable associated bridges.
+ * Then populate the device tree below this bus to get drivers probed for the
+ * hardware that is on the FPGA.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+static int simple_fpga_bus_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct simple_fpga_bus *priv;
+	struct fpga_manager *mgr;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+
+	/*
+	 * If simple_fpga_bus_get_mgr returns a negative error, the fpga
+	 * manager may not have probed yet.
+	 */
+	mgr = simple_fpga_bus_get_mgr(priv);
+	if (IS_ERR(mgr))
+		return -EPROBE_DEFER;
+
+	if (mgr) {
+		ret = simple_fpga_bus_get_bridges(priv);
+		if (ret) {
+			ret = -EPROBE_DEFER;
+			goto err_release_mgr;
+		}
+
+		ret = simple_fpga_bus_bridge_disable(priv);
+		if (ret)
+			goto err_release_br;
+
+		ret = simple_fpga_bus_load_image(priv, mgr);
+		if (ret)
+			goto err_release_br;
+
+		ret = simple_fpga_bus_bridge_enable(priv);
+		if (ret)
+			goto err_release_br;
+
+		fpga_mgr_put(mgr);
+	}
+
+	of_platform_populate(np, of_default_bus_match_table, NULL, dev);
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+
+err_release_br:
+	simple_fpga_bus_put_bridges(priv);
+err_release_mgr:
+	fpga_mgr_put(mgr);
+
+	return ret;
+}
+
+static int simple_fpga_bus_remove(struct platform_device *pdev)
+{
+	struct simple_fpga_bus *priv = platform_get_drvdata(pdev);
+
+	simple_fpga_bus_bridge_disable(priv);
+	simple_fpga_bus_put_bridges(priv);
+
+	return 0;
+}
+
+static const struct of_device_id simple_fpga_bus_of_match[] = {
+	{ .compatible = "simple-fpga-bus", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, simple_fpga_bus_of_match);
+
+static struct platform_driver simple_fpga_bus_driver = {
+	.probe = simple_fpga_bus_probe,
+	.remove = simple_fpga_bus_remove,
+	.driver = {
+		.name	= "simple-fpga-bus",
+		.of_match_table = of_match_ptr(simple_fpga_bus_of_match),
+	},
+};
+
+static int __init simple_fpga_bus_init(void)
+{
+	return platform_driver_register(&simple_fpga_bus_driver);
+}
+
+static void __exit simple_fpga_bus_exit(void)
+{
+	platform_driver_unregister(&simple_fpga_bus_driver);
+}
+
+module_init(simple_fpga_bus_init);
+module_exit(simple_fpga_bus_exit);
+
+MODULE_DESCRIPTION("Simple FPGA Bus");
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v13 4/6] fpga: add fpga bridge framework
  2015-11-03 17:10 [PATCH v13 0/6] simple fpga bus and fpga bridge framework atull
                   ` (2 preceding siblings ...)
  2015-11-03 17:11 ` [PATCH v13 3/6] fpga: add simple-fpga-bus atull
@ 2015-11-03 17:11 ` atull
  2015-11-19  4:50   ` Moritz Fischer
  2015-11-03 17:11 ` [PATCH v13 5/6] ARM: socfpga: add bindings document for fpga bridge drivers atull
  2015-11-03 17:11 ` [PATCH v13 6/6] ARM: socfpga: fpga bridge driver support atull
  5 siblings, 1 reply; 9+ messages in thread
From: atull @ 2015-11-03 17:11 UTC (permalink / raw)
  To: Rob Herring
  Cc: Moritz Fischer, Josh Cartwright, gregkh, monstr, michal.simek,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Jonathan Corbet, linux-kernel, devicetree, linux-doc,
	pantelis.antoniou, delicious.quinoa, dinguyen, Alan Tull

From: Alan Tull <atull@opensource.altera.com>

This framework adds API functions for enabling/
disabling FPGA bridges under kernel control.

This allows the Linux kernel to disable FPGA bridges
during FPGA reprogramming and to enable FPGA bridges
when FPGA reprogramming is done.  This framework is
be manufacturer-agnostic, allowing it to be used in
interfaces that use the FPGA Manager Framework to
reprogram FPGAs.

The functions are:
* of_fpga_bridge_get
* fpga_bridge_put
   Get/put a reference to a FPGA bridge.

* fpga_bridge_enable
* fpga_bridge_disable
   Enable/Disable traffic through a bridge.

* fpga_bridge_register
* fpga_bridge_unregister
   Register/unregister a device-specific low level FPGA
   Bridge driver.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
---
v2:  Minor cleanup
v12: Bump version to line up with simple fpga bus
     Remove sysfs
     Improve get/put functions, get the low level driver too.
     Clean up class implementation
     Add kernel doc documentation
     Rename (un)register_fpga_bridge -> fpga_bridge_(un)register
v13: Add inlined empty functions for if not CONFIG_FPGA_BRIDGE
     Clean up debugging
     Remove unneeded #include in .h
     Remove unnecessary prints
     Remove 'label' DT binding.
     Document the mutex
---
 drivers/fpga/Kconfig             |   7 ++
 drivers/fpga/Makefile            |   3 +
 drivers/fpga/fpga-bridge.c       | 229 +++++++++++++++++++++++++++++++++++++++
 include/linux/fpga/fpga-bridge.h |  74 +++++++++++++
 4 files changed, 313 insertions(+)
 create mode 100644 drivers/fpga/fpga-bridge.c
 create mode 100644 include/linux/fpga/fpga-bridge.h

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 5fcf60a..6383b47 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -31,6 +31,13 @@ config FPGA_MGR_ZYNQ_FPGA
 	help
 	  FPGA manager driver support for Xilinx Zynq FPGAs.
 
+config FPGA_BRIDGE
+       bool "FPGA Bridge Drivers"
+       depends on OF
+       help
+         Say Y here if you want to support bridges connected between host
+	 processors and FPGAs or between FPGAs.
+
 endif # FPGA
 
 endmenu
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 9b55ae0..5e9e0e1 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -9,5 +9,8 @@ obj-$(CONFIG_FPGA)			+= fpga-mgr.o
 obj-$(CONFIG_FPGA_MGR_SOCFPGA)		+= socfpga.o
 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)	+= zynq-fpga.o
 
+# FPGA Bridge Drivers
+obj-$(CONFIG_FPGA_BRIDGE)		+= fpga-bridge.o
+
 # High Level Interfaces
 obj-$(CONFIG_SIMPLE_FPGA_BUS)		+= simple-fpga-bus.o
diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
new file mode 100644
index 0000000..14cdb7f
--- /dev/null
+++ b/drivers/fpga/fpga-bridge.c
@@ -0,0 +1,229 @@
+/*
+ * fpga bridge driver
+ *
+ *  Copyright (C) 2013-2015 Altera Corporation, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/fpga/fpga-bridge.h>
+#include <linux/idr.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+
+static DEFINE_IDA(fpga_bridge_ida);
+static struct class *fpga_bridge_class;
+
+/**
+ * fpga_bridge_enable
+ * @bridge: fpga bridge
+ *
+ * Enable transactions on the bridge
+ *
+ * Return: 0 for success, error code otherwise.
+ */
+int fpga_bridge_enable(struct fpga_bridge *bridge)
+{
+	return bridge->br_ops->enable_set(bridge, 1);
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_enable);
+
+/**
+ * fpga_bridge_disable
+ * @bridge: fpga bridge
+ *
+ * Disable transactions on the bridge
+ *
+ * Return: 0 for success, error code otherwise.
+ */
+int fpga_bridge_disable(struct fpga_bridge *bridge)
+{
+	return bridge->br_ops->enable_set(bridge, 0);
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_disable);
+
+static int fpga_bridge_of_node_match(struct device *dev, const void *data)
+{
+	return dev->of_node == data;
+}
+
+/**
+ * of_fpga_bridge_get - get an exclusive reference to a fpga bridge
+ * @node: device node
+ *
+ * Given a device node, get an exclusive reference to a fpga bridge.
+ *
+ * Returns a fpga manager struct or IS_ERR() condition containing errno.
+ */
+struct fpga_bridge *of_fpga_bridge_get(struct device_node *node)
+{
+	struct device *dev;
+	struct fpga_bridge *bridge;
+	int ret = -ENODEV;
+
+	dev = class_find_device(fpga_bridge_class, NULL, node,
+				fpga_bridge_of_node_match);
+	if (!dev)
+		return ERR_PTR(-ENODEV);
+
+	bridge = to_fpga_bridge(dev);
+	if (!bridge)
+		goto err_dev;
+
+	if (!mutex_trylock(&bridge->mutex)) {
+		ret = -EBUSY;
+		goto err_dev;
+	}
+
+	if (!try_module_get(dev->parent->driver->owner))
+		goto err_ll_mod;
+
+	return bridge;
+
+err_ll_mod:
+	mutex_unlock(&bridge->mutex);
+err_dev:
+	put_device(dev);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
+
+/**
+ * fpga_bridge_put - release a reference to a fpga bridge
+ * @bridge: fpga bridge
+ */
+void fpga_bridge_put(struct fpga_bridge *bridge)
+{
+	module_put(bridge->dev.parent->driver->owner);
+	mutex_unlock(&bridge->mutex);
+	put_device(&bridge->dev);
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_put);
+
+/**
+ * fpga_bridge_register - register a fpga bridge driver
+ * @dev:	fpga bridge device from pdev
+ * @name:	fpga bridge name
+ * @br_ops:	pointer to structure of fpga bridge ops
+ * @priv:	fpga bridge private data
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+int fpga_bridge_register(struct device *dev, const char *name,
+			 struct fpga_bridge_ops *br_ops, void *priv)
+{
+	struct fpga_bridge *bridge;
+	int id, ret = 0;
+
+	if (!br_ops || !br_ops->enable_set || !br_ops->enable_show) {
+		dev_err(dev, "Attempt to register without fpga_bridge_ops\n");
+		return -EINVAL;
+	}
+
+	if (!name || !strlen(name)) {
+		dev_err(dev, "Attempt to register with no name!\n");
+		return -EINVAL;
+	}
+
+	bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
+	if (!bridge)
+		return -ENOMEM;
+
+	id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL);
+	if (id < 0) {
+		ret = id;
+		goto error_kfree;
+	}
+
+	mutex_init(&bridge->mutex);
+
+	bridge->name = name;
+	bridge->br_ops = br_ops;
+	bridge->priv = priv;
+
+	device_initialize(&bridge->dev);
+	bridge->dev.class = fpga_bridge_class;
+	bridge->dev.parent = dev;
+	bridge->dev.of_node = dev->of_node;
+	bridge->dev.id = id;
+	dev_set_drvdata(dev, bridge);
+
+	ret = dev_set_name(&bridge->dev, "br%d", id);
+	if (ret)
+		goto error_device;
+
+	ret = device_add(&bridge->dev);
+	if (ret)
+		goto error_device;
+
+	dev_info(bridge->dev.parent, "fpga bridge [%s] registered\n",
+		 bridge->name);
+
+	return 0;
+
+error_device:
+	ida_simple_remove(&fpga_bridge_ida, id);
+error_kfree:
+	kfree(bridge);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_register);
+
+void fpga_bridge_unregister(struct device *dev)
+{
+	struct fpga_bridge *bridge = dev_get_drvdata(dev);
+
+	/*
+	 * If the low level driver provides a method for putting bridge into
+	 * a desired state upon unregister, do it.
+	 */
+	if (bridge->br_ops->fpga_bridge_remove)
+		bridge->br_ops->fpga_bridge_remove(bridge);
+
+	device_unregister(&bridge->dev);
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
+
+static void fpga_bridge_dev_release(struct device *dev)
+{
+	struct fpga_bridge *bridge = to_fpga_bridge(dev);
+
+	ida_simple_remove(&fpga_bridge_ida, bridge->dev.id);
+	kfree(bridge);
+}
+
+static int __init fpga_bridge_dev_init(void)
+{
+	fpga_bridge_class = class_create(THIS_MODULE, "fpga_bridge");
+	if (IS_ERR(fpga_bridge_class))
+		return PTR_ERR(fpga_bridge_class);
+
+	fpga_bridge_class->dev_release = fpga_bridge_dev_release;
+
+	return 0;
+}
+
+static void __exit fpga_bridge_dev_exit(void)
+{
+	class_destroy(fpga_bridge_class);
+	ida_destroy(&fpga_bridge_ida);
+}
+
+MODULE_DESCRIPTION("FPGA Bridge Driver");
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_LICENSE("GPL v2");
+
+subsys_initcall(fpga_bridge_dev_init);
+module_exit(fpga_bridge_dev_exit);
diff --git a/include/linux/fpga/fpga-bridge.h b/include/linux/fpga/fpga-bridge.h
new file mode 100644
index 0000000..d6da725
--- /dev/null
+++ b/include/linux/fpga/fpga-bridge.h
@@ -0,0 +1,74 @@
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#ifndef _LINUX_FPGA_BRIDGE_H
+#define _LINUX_FPGA_BRIDGE_H
+
+struct fpga_bridge;
+
+/**
+ * struct fpga_bridge_ops - ops for low level fpga bridge drivers
+ * @enable_show: returns the FPGA bridge's status
+ * @enable_set: set a FPGA bridge as enabled or disabled
+ * @fpga_bridge_remove: set FPGA into a specific state during driver remove
+ */
+struct fpga_bridge_ops {
+	int (*enable_show)(struct fpga_bridge *bridge);
+	int (*enable_set)(struct fpga_bridge *bridge, bool enable);
+	void (*fpga_bridge_remove)(struct fpga_bridge *bridge);
+};
+
+/**
+ * struct fpga_bridge - fpga bridge structure
+ * @name: name of low level fpga bridge
+ * @dev: fpga bridge device
+ * @mutex: enforces exclusive reference to bridge
+ * @br_ops: pointer to struct of fpga bridge ops
+ * @priv: low level driver private date
+ */
+struct fpga_bridge {
+	const char *name;
+	struct device dev;
+	struct mutex mutex; /* for exclusive reference to bridge */
+	struct fpga_bridge_ops *br_ops;
+	void *priv;
+};
+
+#define to_fpga_bridge(d) container_of(d, struct fpga_bridge, dev)
+
+#if defined(CONFIG_FPGA_BRIDGE)
+
+struct fpga_bridge *of_fpga_bridge_get(struct device_node *node);
+void fpga_bridge_put(struct fpga_bridge *bridge);
+
+int fpga_bridge_enable(struct fpga_bridge *bridge);
+int fpga_bridge_disable(struct fpga_bridge *bridge);
+
+#else
+
+inline struct fpga_bridge *of_fpga_bridge_get(struct device_node *node)
+{
+	return 0;
+}
+
+inline void fpga_bridge_put(struct fpga_bridge *bridge)
+{
+}
+
+inline int fpga_bridge_enable(struct fpga_bridge *bridge)
+{
+	return 0;
+}
+
+inline int fpga_bridge_disable(struct fpga_bridge *bridge)
+{
+	return 0;
+}
+
+#endif /* CONFIG_FPGA_BRIDGE */
+
+int fpga_bridge_register(struct device *dev, const char *name,
+			 struct fpga_bridge_ops *br_ops, void *priv);
+void fpga_bridge_unregister(struct device *dev);
+
+#endif /* _LINUX_FPGA_BRIDGE_H */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v13 5/6] ARM: socfpga: add bindings document for fpga bridge drivers
  2015-11-03 17:10 [PATCH v13 0/6] simple fpga bus and fpga bridge framework atull
                   ` (3 preceding siblings ...)
  2015-11-03 17:11 ` [PATCH v13 4/6] fpga: add fpga bridge framework atull
@ 2015-11-03 17:11 ` atull
  2015-11-03 17:11 ` [PATCH v13 6/6] ARM: socfpga: fpga bridge driver support atull
  5 siblings, 0 replies; 9+ messages in thread
From: atull @ 2015-11-03 17:11 UTC (permalink / raw)
  To: Rob Herring
  Cc: Moritz Fischer, Josh Cartwright, gregkh, monstr, michal.simek,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Jonathan Corbet, linux-kernel, devicetree, linux-doc,
	pantelis.antoniou, delicious.quinoa, dinguyen, Alan Tull,
	Matthew Gerlach

From: Alan Tull <atull@opensource.altera.com>

Add bindings documentation for Altera SOCFPGA bridges:
 * fpga2sdram
 * fpga2hps
 * hps2fpga
 * lwhps2fpga

Signed-off-by: Alan Tull <atull@opensource.altera.com>
Signed-off-by: Matthew Gerlach <mgerlach@altera.com>
Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
---
v2:  separate into 2 documents for the 2 drivers
v12: bump version to line up with simple-fpga-bus version
     remove Linux specific notes such as references to sysfs
     move non-DT specific documentation elsewhere
     remove bindings that would have been used to pass configuration
     clean up formatting
v13: Remove 'label' property
     Change property from init-val to bridge-enable
     Fix email address
---
 .../bindings/fpga/altera-fpga2sdram-bridge.txt     | 15 +++++++++++
 .../bindings/fpga/altera-hps2fpga-bridge.txt       | 31 ++++++++++++++++++++++
 2 files changed, 46 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt
 create mode 100644 Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt

diff --git a/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt b/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt
new file mode 100644
index 0000000..81e2f06
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt
@@ -0,0 +1,15 @@
+Altera FPGA To SDRAM Bridge Driver
+
+Required properties:
+- compatible		: Should contain "altr,socfpga-fpga2sdram-bridge"
+
+Optional properties:
+- bridge-enable		: 0 if driver should disable bridge at startup
+			  1 if driver should enable bridge at startup
+			  Default is to leave bridge in current state.
+
+Example:
+	fpga2sdram_br: fpgabridge@3 {
+		compatible = "altr,socfpga-fpga2sdram-bridge";
+		bridge-enable = <0>;
+	};
diff --git a/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt b/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt
new file mode 100644
index 0000000..67c28b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt
@@ -0,0 +1,31 @@
+Altera FPGA/HPS Bridge Driver
+
+Required properties:
+- compatible	: Should contain one of:
+		  "altr,socfpga-hps2fpga-bridge",
+		  "altr,socfpga-lwhps2fpga-bridge", or
+		  "altr,socfpga-fpga2hps-bridge"
+- clocks	: Clocks used by this module.
+
+Optional properties:
+- bridge-enable	: 0 if driver should disable bridge at startup.
+		  1 if driver should enable bridge at startup.
+		  Default is to leave bridge in its current state.
+
+Example:
+	hps_fpgabridge0: fpgabridge@0 {
+		compatible = "altr,socfpga-hps2fpga-bridge";
+		clocks = <&l4_main_clk>;
+		bridge-enable = <1>;
+	};
+
+	hps_fpgabridge1: fpgabridge@1 {
+		compatible = "altr,socfpga-lwhps2fpga-bridge";
+		clocks = <&l4_main_clk>;
+		bridge-enable = <0>;
+	};
+
+	hps_fpgabridge2: fpgabridge@2 {
+		compatible = "altr,socfpga-fpga2hps-bridge";
+		clocks = <&l4_main_clk>;
+	};
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v13 6/6] ARM: socfpga: fpga bridge driver support
  2015-11-03 17:10 [PATCH v13 0/6] simple fpga bus and fpga bridge framework atull
                   ` (4 preceding siblings ...)
  2015-11-03 17:11 ` [PATCH v13 5/6] ARM: socfpga: add bindings document for fpga bridge drivers atull
@ 2015-11-03 17:11 ` atull
  5 siblings, 0 replies; 9+ messages in thread
From: atull @ 2015-11-03 17:11 UTC (permalink / raw)
  To: Rob Herring
  Cc: Moritz Fischer, Josh Cartwright, gregkh, monstr, michal.simek,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Jonathan Corbet, linux-kernel, devicetree, linux-doc,
	pantelis.antoniou, delicious.quinoa, dinguyen, Alan Tull,
	Matthew Gerlach

From: Alan Tull <atull@opensource.altera.com>

Supports Altera SOCFPGA bridges:
 * fpga2sdram
 * fpga2hps
 * hps2fpga
 * lwhps2fpga

Allows enabling/disabling the bridges through the FPGA
Bridge Framework API functions.

The fpga2sdram driver only supports enabling and disabling
of the ports that been configured early on.  This is due to
a hardware limitation where the read, write, and command
ports on the fpga2sdram bridge can only be reconfigured
while there are no transactions to the sdram, i.e. when
running out of OCRAM before the kernel boots.

Device tree property 'init-val' configures the driver to
enable or disable the bridge during probe.  If the property
does not exist, the driver will leave the bridge in its
current state.

Signed-off-by: Alan Tull <atull@opensource.altera.com>
Signed-off-by: Matthew Gerlach <mgerlach@altera.com>
Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
---
v2:  Use resets instead of directly writing reset registers
v12: Bump version to align with simple-fpga-bus version
     Get rid of the sysfs interface
     fpga2sdram: get configuration stored in handoff register
v13: Remove unneeded WARN_ON
     Change property from init-val to bridge-enable
     Checkpatch cleanup
     Fix email address
---
 drivers/fpga/Kconfig             |   7 ++
 drivers/fpga/Makefile            |   1 +
 drivers/fpga/altera-fpga2sdram.c | 185 +++++++++++++++++++++++++++++++
 drivers/fpga/altera-hps2fpga.c   | 233 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 426 insertions(+)
 create mode 100644 drivers/fpga/altera-fpga2sdram.c
 create mode 100644 drivers/fpga/altera-hps2fpga.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 6383b47..ccbacd0 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -38,6 +38,13 @@ config FPGA_BRIDGE
          Say Y here if you want to support bridges connected between host
 	 processors and FPGAs or between FPGAs.
 
+config SOCFPGA_FPGA_BRIDGE
+	bool "Altera SoCFPGA FPGA Bridges"
+	depends on ARCH_SOCFPGA && FPGA_BRIDGE
+	help
+	  Say Y to enable drivers for FPGA bridges for Altera SOCFPGA
+	  devices.
+
 endif # FPGA
 
 endmenu
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 5e9e0e1..93c7aff 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)	+= zynq-fpga.o
 
 # FPGA Bridge Drivers
 obj-$(CONFIG_FPGA_BRIDGE)		+= fpga-bridge.o
+obj-$(CONFIG_SOCFPGA_FPGA_BRIDGE)	+= altera-hps2fpga.o altera-fpga2sdram.o
 
 # High Level Interfaces
 obj-$(CONFIG_SIMPLE_FPGA_BUS)		+= simple-fpga-bus.o
diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c
new file mode 100644
index 0000000..acd52f1
--- /dev/null
+++ b/drivers/fpga/altera-fpga2sdram.c
@@ -0,0 +1,185 @@
+/*
+ * FPGA to SDRAM Bridge Driver for Altera SoCFPGA Devices
+ *
+ *  Copyright (C) 2013-2015 Altera Corporation, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This driver manages a bridge between an FPGA and the SDRAM used by the ARM
+ * host processor system (HPS).
+ *
+ * The bridge contains 4 read ports, 4 write ports, and 6 command ports.
+ * Reconfiguring these ports requires that no SDRAM transactions occur during
+ * reconfiguration.  The code reconfiguring the ports cannot run out of SDRAM
+ * nor can the FPGA access the SDRAM during reconfiguration.  This driver does
+ * not support reconfiguring the ports.  The ports are configured by code
+ * running out of on chip ram before Linux is started and the configuration
+ * is passed in a handoff register in the system manager.
+ *
+ * This driver supports enabling and disabling of the configured ports, which
+ * allows for safe reprogramming of the FPGA, assuming that the new FPGA image
+ * uses the same port configuration.  Bridges must be disabled before
+ * reprogramming the FPGA and re-enabled after the FPGA has been programmed.
+ */
+
+#include <linux/fpga/fpga-bridge.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+
+#define ALT_SDR_CTL_FPGAPORTRST_OFST		0x80
+#define ALT_SDR_CTL_FPGAPORTRST_PORTRSTN_MSK	0x00003fff
+#define ALT_SDR_CTL_FPGAPORTRST_RD_SHIFT	0
+#define ALT_SDR_CTL_FPGAPORTRST_WR_SHIFT	4
+#define ALT_SDR_CTL_FPGAPORTRST_CTRL_SHIFT	8
+
+#define SYSMGR_ISWGRP_HANDOFF3          (0x8C)
+#define ISWGRP_HANDOFF_FPGA2SDR         SYSMGR_ISWGRP_HANDOFF3
+
+#define F2S_BRIDGE_NAME "fpga2sdram"
+
+struct alt_fpga2sdram_data {
+	struct device *dev;
+	struct regmap *sdrctl;
+	int mask;
+};
+
+static int alt_fpga2sdram_enable_show(struct fpga_bridge *bridge)
+{
+	struct alt_fpga2sdram_data *priv = bridge->priv;
+	int value;
+
+	regmap_read(priv->sdrctl, ALT_SDR_CTL_FPGAPORTRST_OFST, &value);
+
+	return (value & priv->mask) == priv->mask;
+}
+
+static inline int _alt_fpga2sdram_enable_set(struct alt_fpga2sdram_data *priv,
+					     bool enable)
+{
+	return regmap_update_bits(priv->sdrctl, ALT_SDR_CTL_FPGAPORTRST_OFST,
+				  priv->mask, enable ? priv->mask : 0);
+}
+
+static int alt_fpga2sdram_enable_set(struct fpga_bridge *bridge, bool enable)
+{
+	return _alt_fpga2sdram_enable_set(bridge->priv, enable);
+}
+
+struct prop_map {
+	char *prop_name;
+	u32 *prop_value;
+	u32 prop_max;
+};
+
+struct fpga_bridge_ops altera_fpga2sdram_br_ops = {
+	.enable_set = alt_fpga2sdram_enable_set,
+	.enable_show = alt_fpga2sdram_enable_show,
+};
+
+static const struct of_device_id altera_fpga_of_match[] = {
+	{ .compatible = "altr,socfpga-fpga2sdram-bridge" },
+	{},
+};
+
+static int alt_fpga_bridge_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct alt_fpga2sdram_data *priv;
+	u32 enable;
+	struct regmap *sysmgr;
+	int ret = 0;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+
+	priv->sdrctl = syscon_regmap_lookup_by_compatible("altr,sdr-ctl");
+	if (IS_ERR(priv->sdrctl)) {
+		dev_err(dev, "regmap for altr,sdr-ctl lookup failed.\n");
+		return PTR_ERR(priv->sdrctl);
+	}
+
+	sysmgr = syscon_regmap_lookup_by_compatible("altr,sys-mgr");
+	if (IS_ERR(priv->sdrctl)) {
+		dev_err(dev, "regmap for altr,sys-mgr lookup failed.\n");
+		return PTR_ERR(sysmgr);
+	}
+
+	/* Get f2s bridge configuration saved in handoff register */
+	regmap_read(sysmgr, SYSMGR_ISWGRP_HANDOFF3, &priv->mask);
+
+	ret = fpga_bridge_register(dev, F2S_BRIDGE_NAME,
+				   &altera_fpga2sdram_br_ops, priv);
+	if (ret)
+		return ret;
+
+	dev_info(dev, "driver initialized with handoff %08x\n", priv->mask);
+
+	if (!of_property_read_u32(dev->of_node, "bridge-enable", &enable)) {
+		if (enable > 1) {
+			dev_warn(dev, "invalid bridge-enable %u > 1\n", enable);
+		} else {
+			dev_info(dev, "%s bridge\n",
+				 (enable ? "enabling" : "disabling"));
+			ret = _alt_fpga2sdram_enable_set(priv, enable);
+			if (ret) {
+				fpga_bridge_unregister(&pdev->dev);
+				return ret;
+			}
+		}
+	}
+
+	return ret;
+}
+
+static int alt_fpga_bridge_remove(struct platform_device *pdev)
+{
+	fpga_bridge_unregister(&pdev->dev);
+
+	return 0;
+}
+
+MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
+
+static struct platform_driver altera_fpga_driver = {
+	.remove = alt_fpga_bridge_remove,
+	.driver = {
+		.name	= "altera_fpga2sdram_bridge",
+		.of_match_table = of_match_ptr(altera_fpga_of_match),
+	},
+};
+
+static int __init alt_fpga_bridge_init(void)
+{
+	return platform_driver_probe(&altera_fpga_driver,
+				     alt_fpga_bridge_probe);
+}
+
+static void __exit alt_fpga_bridge_exit(void)
+{
+	platform_driver_unregister(&altera_fpga_driver);
+}
+
+module_init(alt_fpga_bridge_init);
+module_exit(alt_fpga_bridge_exit);
+
+MODULE_DESCRIPTION("Altera SoCFPGA FPGA to SDRAM Bridge");
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/fpga/altera-hps2fpga.c b/drivers/fpga/altera-hps2fpga.c
new file mode 100644
index 0000000..8e9c2d5
--- /dev/null
+++ b/drivers/fpga/altera-hps2fpga.c
@@ -0,0 +1,233 @@
+/*
+ * FPGA to/from HPS Bridge Driver for Altera SoCFPGA Devices
+ *
+ *  Copyright (C) 2013-2015 Altera Corporation, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This driver manages bridges on a Altera SOCFPGA between the ARM host
+ * processor system (HPS) and the embedded FPGA.
+ *
+ * This driver supports enabling and disabling of the configured ports, which
+ * allows for safe reprogramming of the FPGA, assuming that the new FPGA image
+ * uses the same port configuration.  Bridges must be disabled before
+ * reprogramming the FPGA and re-enabled after the FPGA has been programmed.
+ */
+
+#include <linux/clk.h>
+#include <linux/fpga/fpga-bridge.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#define SOCFPGA_RSTMGR_BRGMODRST		0x1c
+#define ALT_RSTMGR_BRGMODRST_H2F_MSK		0x00000001
+#define ALT_RSTMGR_BRGMODRST_LWH2F_MSK		0x00000002
+#define ALT_RSTMGR_BRGMODRST_F2H_MSK		0x00000004
+
+#define ALT_L3_REMAP_OFST			0x0
+#define ALT_L3_REMAP_MPUZERO_MSK		0x00000001
+#define ALT_L3_REMAP_H2F_MSK			0x00000008
+#define ALT_L3_REMAP_LWH2F_MSK			0x00000010
+
+#define HPS2FPGA_BRIDGE_NAME			"hps2fpga"
+#define LWHPS2FPGA_BRIDGE_NAME			"lwhps2fpga"
+#define FPGA2HPS_BRIDGE_NAME			"fpga2hps"
+
+struct altera_hps2fpga_data {
+	const char *name;
+	struct reset_control *bridge_reset;
+	struct regmap *l3reg;
+	/* The L3 REMAP register is write only, so keep a cached value. */
+	unsigned int l3_remap_value;
+	unsigned int reset_mask;
+	unsigned int remap_mask;
+	struct clk *clk;
+};
+
+static int alt_hps2fpga_enable_show(struct fpga_bridge *bridge)
+{
+	struct altera_hps2fpga_data *priv = bridge->priv;
+
+	return reset_control_status(priv->bridge_reset);
+}
+
+static int _alt_hps2fpga_enable_set(struct altera_hps2fpga_data *priv,
+				    bool enable)
+{
+	int ret;
+
+	/* bring bridge out of reset */
+	if (enable)
+		ret = reset_control_deassert(priv->bridge_reset);
+	else
+		ret = reset_control_assert(priv->bridge_reset);
+	if (ret)
+		return ret;
+
+	/* Allow bridge to be visible to L3 masters or not */
+	if (priv->remap_mask) {
+		priv->l3_remap_value |= ALT_L3_REMAP_MPUZERO_MSK;
+
+		if (enable)
+			priv->l3_remap_value |= priv->remap_mask;
+		else
+			priv->l3_remap_value &= ~priv->remap_mask;
+
+		ret = regmap_write(priv->l3reg, ALT_L3_REMAP_OFST,
+				   priv->l3_remap_value);
+	}
+
+	return ret;
+}
+
+static int alt_hps2fpga_enable_set(struct fpga_bridge *bridge, bool enable)
+{
+	return _alt_hps2fpga_enable_set(bridge->priv, enable);
+}
+
+struct fpga_bridge_ops altera_hps2fpga_br_ops = {
+	.enable_set = alt_hps2fpga_enable_set,
+	.enable_show = alt_hps2fpga_enable_show,
+};
+
+static struct altera_hps2fpga_data hps2fpga_data  = {
+	.name = HPS2FPGA_BRIDGE_NAME,
+	.reset_mask = ALT_RSTMGR_BRGMODRST_H2F_MSK,
+	.remap_mask = ALT_L3_REMAP_H2F_MSK,
+};
+
+static struct altera_hps2fpga_data lwhps2fpga_data  = {
+	.name = LWHPS2FPGA_BRIDGE_NAME,
+	.reset_mask = ALT_RSTMGR_BRGMODRST_LWH2F_MSK,
+	.remap_mask = ALT_L3_REMAP_LWH2F_MSK,
+};
+
+static struct altera_hps2fpga_data fpga2hps_data  = {
+	.name = FPGA2HPS_BRIDGE_NAME,
+	.reset_mask = ALT_RSTMGR_BRGMODRST_F2H_MSK,
+};
+
+static const struct of_device_id altera_fpga_of_match[] = {
+	{ .compatible = "altr,socfpga-hps2fpga-bridge",
+	  .data = &hps2fpga_data },
+	{ .compatible = "altr,socfpga-lwhps2fpga-bridge",
+	  .data = &lwhps2fpga_data },
+	{ .compatible = "altr,socfpga-fpga2hps-bridge",
+	  .data = &fpga2hps_data },
+	{},
+};
+
+static int alt_fpga_bridge_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct altera_hps2fpga_data *priv;
+	const struct of_device_id *of_id;
+	u32 enable;
+	int ret;
+
+	of_id = of_match_device(altera_fpga_of_match, dev);
+	priv = (struct altera_hps2fpga_data *)of_id->data;
+
+	priv->bridge_reset = devm_reset_control_get(dev, priv->name);
+	if (IS_ERR(priv->bridge_reset)) {
+		dev_err(dev, "Could not get %s reset control!\n", priv->name);
+		return PTR_ERR(priv->bridge_reset);
+	}
+
+	priv->l3reg = syscon_regmap_lookup_by_compatible("altr,l3regs");
+	if (IS_ERR(priv->l3reg)) {
+		dev_err(dev, "regmap for altr,l3regs lookup failed.\n");
+		return PTR_ERR(priv->l3reg);
+	}
+
+	priv->clk = of_clk_get(dev->of_node, 0);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "no clock specified\n");
+		return PTR_ERR(priv->clk);
+	}
+
+	ret = clk_prepare_enable(priv->clk);
+	if (ret) {
+		dev_err(dev, "could not enable clock\n");
+		return -EBUSY;
+	}
+
+	ret = fpga_bridge_register(dev, priv->name, &altera_hps2fpga_br_ops,
+				   priv);
+	if (ret)
+		return ret;
+
+	if (!of_property_read_u32(dev->of_node, "bridge-enable", &enable)) {
+		if (enable > 1) {
+			dev_warn(dev, "invalid bridge-enable %u > 1\n", enable);
+		} else {
+			dev_info(dev, "%s bridge\n",
+				 (enable ? "enabling" : "disabling"));
+
+			ret = _alt_hps2fpga_enable_set(priv, enable);
+			if (ret) {
+				fpga_bridge_unregister(&pdev->dev);
+				return ret;
+			}
+		}
+	}
+
+	return ret;
+}
+
+static int alt_fpga_bridge_remove(struct platform_device *pdev)
+{
+	struct fpga_bridge *bridge = platform_get_drvdata(pdev);
+	struct altera_hps2fpga_data *priv = bridge->priv;
+
+	fpga_bridge_unregister(&pdev->dev);
+
+	clk_disable_unprepare(priv->clk);
+	clk_put(priv->clk);
+
+	return 0;
+}
+
+MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
+
+static struct platform_driver altera_fpga_driver = {
+	.remove = alt_fpga_bridge_remove,
+	.driver = {
+		.name	= "altera_hps2fpga_bridge",
+		.of_match_table = of_match_ptr(altera_fpga_of_match),
+	},
+};
+
+static int __init alt_fpga_bridge_init(void)
+{
+	return platform_driver_probe(&altera_fpga_driver,
+				     alt_fpga_bridge_probe);
+}
+
+static void __exit alt_fpga_bridge_exit(void)
+{
+	platform_driver_unregister(&altera_fpga_driver);
+}
+
+module_init(alt_fpga_bridge_init);
+module_exit(alt_fpga_bridge_exit);
+
+MODULE_DESCRIPTION("Altera SoCFPGA HPS to FPGA Bridge");
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v13 4/6] fpga: add fpga bridge framework
  2015-11-03 17:11 ` [PATCH v13 4/6] fpga: add fpga bridge framework atull
@ 2015-11-19  4:50   ` Moritz Fischer
  2015-11-20 15:08     ` atull
  0 siblings, 1 reply; 9+ messages in thread
From: Moritz Fischer @ 2015-11-19  4:50 UTC (permalink / raw)
  To: Alan Tull
  Cc: Rob Herring, Josh Cartwright, Greg KH, Michal Simek,
	Michal Simek, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Jonathan Corbet, linux-kernel, devicetree, linux-doc,
	Pantelis Antoniou, Alan Tull, dinguyen

Hi Alan,

while trying to implement something that works for Zynq along these lines
I stumbled upon some minor stuff.

On Tue, Nov 3, 2015 at 9:11 AM,  <atull@opensource.altera.com> wrote:

> + * Return: 0 on success, negative error code otherwise.
> + */
> +int fpga_bridge_register(struct device *dev, const char *name,
> +                        struct fpga_bridge_ops *br_ops, void *priv)

const struct fpga_bridge_ops

> +int fpga_bridge_register(struct device *dev, const char *name,
> +                        struct fpga_bridge_ops *br_ops, void *priv);
const struct fpga_bridge_ops

Cheers,

Moritz

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v13 4/6] fpga: add fpga bridge framework
  2015-11-19  4:50   ` Moritz Fischer
@ 2015-11-20 15:08     ` atull
  0 siblings, 0 replies; 9+ messages in thread
From: atull @ 2015-11-20 15:08 UTC (permalink / raw)
  To: Moritz Fischer
  Cc: Rob Herring, Josh Cartwright, Greg KH, Michal Simek,
	Michal Simek, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Jonathan Corbet, linux-kernel, devicetree, linux-doc,
	Pantelis Antoniou, Alan Tull, dinguyen

On Thu, 19 Nov 2015, Moritz Fischer wrote:

> Hi Alan,
> 
> while trying to implement something that works for Zynq along these lines
> I stumbled upon some minor stuff.
> 
> On Tue, Nov 3, 2015 at 9:11 AM,  <atull@opensource.altera.com> wrote:
> 
> > + * Return: 0 on success, negative error code otherwise.
> > + */
> > +int fpga_bridge_register(struct device *dev, const char *name,
> > +                        struct fpga_bridge_ops *br_ops, void *priv)
> 
> const struct fpga_bridge_ops
> 
> > +int fpga_bridge_register(struct device *dev, const char *name,
> > +                        struct fpga_bridge_ops *br_ops, void *priv);
> const struct fpga_bridge_ops
> 
> Cheers,
> 
> Moritz
> 

Hi Moritz,

Thanks!

Alan

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2015-11-20 15:15 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-03 17:10 [PATCH v13 0/6] simple fpga bus and fpga bridge framework atull
2015-11-03 17:10 ` [PATCH v13 1/6] fpga: add usage documentation for simple fpga bus atull
2015-11-03 17:11 ` [PATCH v13 2/6] fpga: add bindings document " atull
2015-11-03 17:11 ` [PATCH v13 3/6] fpga: add simple-fpga-bus atull
2015-11-03 17:11 ` [PATCH v13 4/6] fpga: add fpga bridge framework atull
2015-11-19  4:50   ` Moritz Fischer
2015-11-20 15:08     ` atull
2015-11-03 17:11 ` [PATCH v13 5/6] ARM: socfpga: add bindings document for fpga bridge drivers atull
2015-11-03 17:11 ` [PATCH v13 6/6] ARM: socfpga: fpga bridge driver support atull

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).