mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [RFC PATCH 1/4] reset: add of_reset_control_get to header
@ 2017-08-01  9:19 Steffen Trumtrar
  2017-08-01  9:19 ` [RFC PATCH 2/4] drivers: add fpga bridge framework Steffen Trumtrar
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Steffen Trumtrar @ 2017-08-01  9:19 UTC (permalink / raw)
  To: barebox; +Cc: Steffen Trumtrar

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 include/linux/reset.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/reset.h b/include/linux/reset.h
index be0d1bb5a621..c5660f798193 100644
--- a/include/linux/reset.h
+++ b/include/linux/reset.h
@@ -11,6 +11,8 @@ int reset_control_assert(struct reset_control *rstc);
 int reset_control_deassert(struct reset_control *rstc);
 
 struct reset_control *reset_control_get(struct device_d *dev, const char *id);
+struct reset_control *of_reset_control_get(struct device_node *node,
+					   const char *id);
 void reset_control_put(struct reset_control *rstc);
 
 int __must_check device_reset(struct device_d *dev);
-- 
2.11.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [RFC PATCH 2/4] drivers: add fpga bridge framework
  2017-08-01  9:19 [RFC PATCH 1/4] reset: add of_reset_control_get to header Steffen Trumtrar
@ 2017-08-01  9:19 ` Steffen Trumtrar
  2017-08-01  9:19 ` [RFC PATCH 3/4] drivers: fpga: add socfpga bridges Steffen Trumtrar
  2017-08-01  9:19 ` [RFC PATCH 4/4] fpga: add fpga-region support Steffen Trumtrar
  2 siblings, 0 replies; 5+ messages in thread
From: Steffen Trumtrar @ 2017-08-01  9:19 UTC (permalink / raw)
  To: barebox; +Cc: Steffen Trumtrar

Import the fpga bridge framework from linux v4.10-rc2.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/Kconfig            |   1 +
 drivers/Makefile           |   1 +
 drivers/fpga/Kconfig       |  24 ++++
 drivers/fpga/Makefile      |   6 +
 drivers/fpga/fpga-bridge.c | 275 +++++++++++++++++++++++++++++++++++++++++++++
 include/fpga-bridge.h      |  57 ++++++++++
 6 files changed, 364 insertions(+)
 create mode 100644 drivers/fpga/Kconfig
 create mode 100644 drivers/fpga/Makefile
 create mode 100644 drivers/fpga/fpga-bridge.c
 create mode 100644 include/fpga-bridge.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 1e0246da6db1..3635e5a66e09 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -34,6 +34,7 @@ source "drivers/reset/Kconfig"
 source "drivers/pci/Kconfig"
 source "drivers/rtc/Kconfig"
 source "drivers/firmware/Kconfig"
+source "drivers/fpga/Kconfig"
 source "drivers/phy/Kconfig"
 source "drivers/crypto/Kconfig"
 source "drivers/memory/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 767789d5418f..d76efad5e65e 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_RESET_CONTROLLER) += reset/
 obj-$(CONFIG_PCI) += pci/
 obj-y += rtc/
 obj-$(CONFIG_FIRMWARE) += firmware/
+obj-$(CONFIG_FPGA) += fpga/
 obj-$(CONFIG_GENERIC_PHY) += phy/
 obj-$(CONFIG_HAB) += hab/
 obj-$(CONFIG_CRYPTO_HW) += crypto/
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
new file mode 100644
index 000000000000..cd3a5ba42552
--- /dev/null
+++ b/drivers/fpga/Kconfig
@@ -0,0 +1,24 @@
+#
+# FPGA framework configuration
+#
+
+menu "FPGA Configuration Support"
+
+config FPGA
+	tristate "FPGA Configuration Framework"
+	help
+	  Say Y here if you want support for configuring FPGAs from the
+	  kernel.  The FPGA framework adds a FPGA manager class and FPGA
+	  manager drivers.
+
+if FPGA
+
+config FPGA_BRIDGE
+	tristate "FPGA Bridge Framework"
+	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
new file mode 100644
index 000000000000..fc71a29d3b33
--- /dev/null
+++ b/drivers/fpga/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the fpga framework and fpga manager drivers.
+#
+
+# FPGA Bridge Drivers
+obj-$(CONFIG_FPGA_BRIDGE)		+= fpga-bridge.o
diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
new file mode 100644
index 000000000000..818f4e62cf7c
--- /dev/null
+++ b/drivers/fpga/fpga-bridge.c
@@ -0,0 +1,275 @@
+/*
+ * FPGA Bridge Framework Driver
+ *
+ *  Copyright (C) 2013-2016 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 <common.h>
+#include <fpga-bridge.h>
+
+/**
+ * fpga_bridge_enable - Enable transactions on the bridge
+ *
+ * @bridge: FPGA bridge
+ *
+ * Return: 0 for success, error code otherwise.
+ */
+int fpga_bridge_enable(struct fpga_bridge *bridge)
+{
+	dev_dbg(&bridge->dev, "enable\n");
+
+	if (bridge->br_ops && bridge->br_ops->enable_set)
+		return bridge->br_ops->enable_set(bridge, 1);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_enable);
+
+/**
+ * fpga_bridge_disable - Disable transactions on the bridge
+ *
+ * @bridge: FPGA bridge
+ *
+ * Return: 0 for success, error code otherwise.
+ */
+int fpga_bridge_disable(struct fpga_bridge *bridge)
+{
+	dev_dbg(&bridge->dev, "disable\n");
+
+	if (bridge->br_ops && bridge->br_ops->enable_set)
+		return bridge->br_ops->enable_set(bridge, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_disable);
+
+/**
+ * of_fpga_bridge_get - get an exclusive reference to a fpga bridge
+ *
+ * @np: node pointer of a FPGA bridge
+ * @info: fpga image specific information
+ *
+ * Return fpga_bridge struct if successful.
+ * Return -EBUSY if someone already has a reference to the bridge.
+ * Return -ENODEV if @np is not a FPGA Bridge.
+ */
+struct fpga_bridge *of_fpga_bridge_get(struct device_node *np,
+				       struct fpga_image_info *info)
+
+{
+	struct device_d *dev;
+	struct fpga_bridge *bridge;
+	int ret = -ENODEV;
+
+	dev = of_find_device_by_node(np);
+	if (!dev)
+		return ERR_PTR(ret);
+
+	bridge = dev->priv;
+
+	bridge->info = info;
+
+	dev_dbg(&bridge->dev, "get\n");
+
+	return bridge;
+}
+EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
+
+/**
+ * fpga_bridge_put - release a reference to a bridge
+ *
+ * @bridge: FPGA bridge
+ */
+void fpga_bridge_put(struct fpga_bridge *bridge)
+{
+	dev_dbg(&bridge->dev, "put\n");
+
+	bridge->info = NULL;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_put);
+
+/**
+ * fpga_bridges_enable - enable bridges in a list
+ * @bridge_list: list of FPGA bridges
+ *
+ * Enable each bridge in the list.  If list is empty, do nothing.
+ *
+ * Return 0 for success or empty bridge list; return error code otherwise.
+ */
+int fpga_bridges_enable(struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+	struct list_head *node;
+	int ret;
+
+	list_for_each(node, bridge_list) {
+		bridge = list_entry(node, struct fpga_bridge, node);
+		ret = fpga_bridge_enable(bridge);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridges_enable);
+
+/**
+ * fpga_bridges_disable - disable bridges in a list
+ *
+ * @bridge_list: list of FPGA bridges
+ *
+ * Disable each bridge in the list.  If list is empty, do nothing.
+ *
+ * Return 0 for success or empty bridge list; return error code otherwise.
+ */
+int fpga_bridges_disable(struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+	struct list_head *node;
+	int ret;
+
+	list_for_each(node, bridge_list) {
+		bridge = list_entry(node, struct fpga_bridge, node);
+		ret = fpga_bridge_disable(bridge);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridges_disable);
+
+/**
+ * fpga_bridges_put - put bridges
+ *
+ * @bridge_list: list of FPGA bridges
+ *
+ * For each bridge in the list, put the bridge and remove it from the list.
+ * If list is empty, do nothing.
+ */
+void fpga_bridges_put(struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+	struct list_head *node, *next;
+
+	list_for_each_safe(node, next, bridge_list) {
+		bridge = list_entry(node, struct fpga_bridge, node);
+
+		fpga_bridge_put(bridge);
+
+		list_del(&bridge->node);
+	}
+}
+EXPORT_SYMBOL_GPL(fpga_bridges_put);
+
+/**
+ * fpga_bridges_get_to_list - get a bridge, add it to a list
+ *
+ * @np: node pointer of a FPGA bridge
+ * @info: fpga image specific information
+ * @bridge_list: list of FPGA bridges
+ *
+ * Get an exclusive reference to the bridge and and it to the list.
+ *
+ * Return 0 for success, error code from of_fpga_bridge_get() othewise.
+ */
+int fpga_bridge_get_to_list(struct device_node *np,
+			    struct fpga_image_info *info,
+			    struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+
+	bridge = of_fpga_bridge_get(np, info);
+	if (IS_ERR(bridge))
+		return PTR_ERR(bridge);
+
+	list_add(&bridge->node, bridge_list);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_get_to_list);
+
+static int set_enable(struct param_d *p, void *priv)
+{
+	struct fpga_bridge *bridge = priv;
+
+	if (bridge->enable)
+		fpga_bridge_enable(bridge);
+	else
+		fpga_bridge_disable(bridge);
+
+	return 0;
+}
+
+/**
+ * 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 for success, error code otherwise.
+ */
+int fpga_bridge_register(struct device_d *dev, const char *name,
+			 const struct fpga_bridge_ops *br_ops, void *priv)
+{
+	struct fpga_bridge *bridge;
+	struct param_d *p;
+	int ret = 0;
+
+	if (!name || !strlen(name)) {
+		dev_err(dev, "Attempt to register with no name!\n");
+		return -EINVAL;
+	}
+
+	bridge = xzalloc(sizeof(*bridge));
+	if (!bridge)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&bridge->node);
+
+	bridge->br_ops = br_ops;
+	bridge->priv = priv;
+
+	bridge->dev.parent = dev;
+	bridge->dev.device_node = dev->device_node;
+	bridge->dev.id = DEVICE_ID_DYNAMIC;
+
+	strcpy(bridge->dev.name, name);
+
+	ret = register_device(&bridge->dev);
+	if (ret)
+		goto out;
+
+	dev->priv = bridge;
+
+	bridge->enable = 0;
+	p = dev_add_param_bool(&bridge->dev, "enable", set_enable,
+			       NULL, &bridge->enable, bridge);
+	if (IS_ERR(p))
+		return PTR_ERR(p);
+
+	of_platform_populate(dev->device_node, NULL, dev);
+
+	dev_info(bridge->dev.parent, "fpga bridge [%s] registered\n",
+		 bridge->dev.name);
+
+	return 0;
+
+out:
+	kfree(bridge);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_register);
diff --git a/include/fpga-bridge.h b/include/fpga-bridge.h
new file mode 100644
index 000000000000..91df9fa4b486
--- /dev/null
+++ b/include/fpga-bridge.h
@@ -0,0 +1,57 @@
+#include <common.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
+ * @info: fpga image specific information
+ * @node: FPGA bridge list node
+ * @priv: low level driver private date
+ */
+struct fpga_bridge {
+	struct device_d dev;
+	const struct fpga_bridge_ops *br_ops;
+	struct fpga_image_info *info;
+	struct list_head node;
+	unsigned int enable;
+	void *priv;
+};
+
+#define to_fpga_bridge(d) container_of(d, struct fpga_bridge, dev)
+
+struct fpga_bridge *of_fpga_bridge_get(struct device_node *node,
+				       struct fpga_image_info *info);
+void fpga_bridge_put(struct fpga_bridge *bridge);
+int fpga_bridge_enable(struct fpga_bridge *bridge);
+int fpga_bridge_disable(struct fpga_bridge *bridge);
+
+int fpga_bridges_enable(struct list_head *bridge_list);
+int fpga_bridges_disable(struct list_head *bridge_list);
+void fpga_bridges_put(struct list_head *bridge_list);
+int fpga_bridge_get_to_list(struct device_node *np,
+			    struct fpga_image_info *info,
+			    struct list_head *bridge_list);
+
+int fpga_bridge_register(struct device_d *dev, const char *name,
+			 const struct fpga_bridge_ops *br_ops, void *priv);
+
+#endif /* _LINUX_FPGA_BRIDGE_H */
-- 
2.11.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [RFC PATCH 3/4] drivers: fpga: add socfpga bridges
  2017-08-01  9:19 [RFC PATCH 1/4] reset: add of_reset_control_get to header Steffen Trumtrar
  2017-08-01  9:19 ` [RFC PATCH 2/4] drivers: add fpga bridge framework Steffen Trumtrar
@ 2017-08-01  9:19 ` Steffen Trumtrar
  2017-08-01  9:19 ` [RFC PATCH 4/4] fpga: add fpga-region support Steffen Trumtrar
  2 siblings, 0 replies; 5+ messages in thread
From: Steffen Trumtrar @ 2017-08-01  9:19 UTC (permalink / raw)
  To: barebox; +Cc: Steffen Trumtrar

Import the SoCFPGA bridges drivers from linux v4.10-rc2.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/fpga/Kconfig                     |   8 ++
 drivers/fpga/Makefile                    |   1 +
 drivers/fpga/socfpga-fpga2sdram-bridge.c | 143 ++++++++++++++++++++++++
 drivers/fpga/socfpga-hps2fpga-bridge.c   | 183 +++++++++++++++++++++++++++++++
 4 files changed, 335 insertions(+)
 create mode 100644 drivers/fpga/socfpga-fpga2sdram-bridge.c
 create mode 100644 drivers/fpga/socfpga-hps2fpga-bridge.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index cd3a5ba42552..77ae52519a50 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -19,6 +19,14 @@ 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
+	tristate "Altera SoCFPGA FPGA Bridges"
+	depends on ARCH_SOCFPGA && FPGA_BRIDGE
+	select RESET_CONTROLLER
+	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 fc71a29d3b33..86178fe7c078 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -4,3 +4,4 @@
 
 # FPGA Bridge Drivers
 obj-$(CONFIG_FPGA_BRIDGE)		+= fpga-bridge.o
+obj-$(CONFIG_SOCFPGA_FPGA_BRIDGE)	+= socfpga-hps2fpga-bridge.o socfpga-fpga2sdram-bridge.o
diff --git a/drivers/fpga/socfpga-fpga2sdram-bridge.c b/drivers/fpga/socfpga-fpga2sdram-bridge.c
new file mode 100644
index 000000000000..ff48248fb63f
--- /dev/null
+++ b/drivers/fpga/socfpga-fpga2sdram-bridge.c
@@ -0,0 +1,143 @@
+/*
+ * FPGA to SDRAM Bridge Driver for Altera SoCFPGA Devices
+ *
+ *  Copyright (C) 2013-2016 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 <common.h>
+#include <init.h>
+#include <io.h>
+#include <fpga-bridge.h>
+#include <mfd/syscon.h>
+#include <of_device.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+
+#define SOCFPGA_SDRCTL_ADDR			0xffc25000
+#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 SOCFPGA_SYSMGR_ADDR			0xffd08000
+/*
+ * From the Cyclone V HPS Memory Map document:
+ *   These registers are used to store handoff information between the
+ *   preloader and the OS. These 8 registers can be used to store any
+ *   information. The contents of these registers have no impact on
+ *   the state of the HPS hardware.
+ */
+#define SYSMGR_ISWGRP_HANDOFF3          (0x8C)
+
+#define F2S_BRIDGE_NAME "fpga2sdram"
+
+struct alt_fpga2sdram_data {
+	struct device_d *dev;
+	int mask;
+};
+
+static inline int _alt_fpga2sdram_enable_set(struct alt_fpga2sdram_data *priv,
+					     bool enable)
+{
+	int val;
+
+	val = readl(SOCFPGA_SDRCTL_ADDR + ALT_SDR_CTL_FPGAPORTRST_OFST);
+
+	if (enable)
+		val |= priv->mask;
+	else
+		val = 0;
+
+	/* The kernel driver expects this value in this register :-( */
+	writel(priv->mask, SOCFPGA_SYSMGR_ADDR + SYSMGR_ISWGRP_HANDOFF3);
+
+	dev_dbg(priv->dev, "setting fpgaportrst to 0x%08x\n", val);
+
+	return writel(val, SOCFPGA_SDRCTL_ADDR + ALT_SDR_CTL_FPGAPORTRST_OFST);
+}
+
+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;
+};
+
+static const struct fpga_bridge_ops altera_fpga2sdram_br_ops = {
+	.enable_set = alt_fpga2sdram_enable_set,
+};
+
+static const struct of_device_id altera_fpga_of_match[] = {
+	{ .compatible = "altr,socfpga-fpga2sdram-bridge" },
+	{},
+};
+
+static int alt_fpga_bridge_probe(struct device_d *dev)
+{
+	struct alt_fpga2sdram_data *priv;
+	int ret = 0;
+
+	priv = xzalloc(sizeof(*priv));
+	if (!priv)
+		return -ENOMEM;
+
+	/* enable all ports for now */
+	priv->mask = 0x3fff;
+
+	priv->dev = dev;
+
+	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);
+
+	return ret;
+}
+
+static struct driver_d altera_fpga_driver = {
+	.probe = alt_fpga_bridge_probe,
+	.of_compatible = DRV_OF_COMPAT(altera_fpga_of_match),
+};
+
+static int alt_fpga_bridge_init(void)
+{
+	return platform_driver_register(&altera_fpga_driver);
+}
+postcore_initcall(alt_fpga_bridge_init);
diff --git a/drivers/fpga/socfpga-hps2fpga-bridge.c b/drivers/fpga/socfpga-hps2fpga-bridge.c
new file mode 100644
index 000000000000..5850ab0bda10
--- /dev/null
+++ b/drivers/fpga/socfpga-hps2fpga-bridge.c
@@ -0,0 +1,183 @@
+/*
+ * FPGA to/from HPS Bridge Driver for Altera SoCFPGA Devices
+ *
+ *  Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
+ *
+ * Includes this patch from the mailing list:
+ *   fpga: altera-hps2fpga: fix HPS2FPGA bridge visibility to L3 masters
+ *   Signed-off-by: Anatolij Gustschin <agust@denx.de>
+ *
+ * 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 <common.h>
+#include <init.h>
+#include <io.h>
+#include <fpga-bridge.h>
+#include <mfd/syscon.h>
+#include <of_device.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+
+#define SOCFPGA_L3_ADDR				0xff800000
+#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 {
+	struct device_d *dev;
+	const char *name;
+	struct reset_control *bridge_reset;
+	unsigned int remap_mask;
+	struct clk *clk;
+};
+
+/* The L3 REMAP register is write only, so keep a cached value. */
+static unsigned int l3_remap_shadow;
+
+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) {
+		l3_remap_shadow |= ALT_L3_REMAP_MPUZERO_MSK;
+
+		if (enable)
+			l3_remap_shadow |= priv->remap_mask;
+		else
+			l3_remap_shadow &= ~priv->remap_mask;
+
+		dev_dbg(priv->dev, "setting L3 visibility to 0x%08x\n",
+			l3_remap_shadow);
+
+		writel(l3_remap_shadow, SOCFPGA_L3_ADDR + ALT_L3_REMAP_OFST);
+	}
+
+	return ret;
+}
+
+static int alt_hps2fpga_enable_set(struct fpga_bridge *bridge, bool enable)
+{
+	return _alt_hps2fpga_enable_set(bridge->priv, enable);
+}
+
+static const struct fpga_bridge_ops altera_hps2fpga_br_ops = {
+	.enable_set = alt_hps2fpga_enable_set,
+};
+
+static struct altera_hps2fpga_data hps2fpga_data  = {
+	.name = HPS2FPGA_BRIDGE_NAME,
+	.remap_mask = ALT_L3_REMAP_H2F_MSK,
+};
+
+static struct altera_hps2fpga_data lwhps2fpga_data  = {
+	.name = LWHPS2FPGA_BRIDGE_NAME,
+	.remap_mask = ALT_L3_REMAP_LWH2F_MSK,
+};
+
+static struct altera_hps2fpga_data fpga2hps_data  = {
+	.name = FPGA2HPS_BRIDGE_NAME,
+};
+
+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 },
+	{ /* sentinel */ },
+};
+
+static int alt_fpga_bridge_probe(struct device_d *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 = of_reset_control_get(dev->device_node, NULL);
+	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->clk = clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "no clock specified\n");
+		return PTR_ERR(priv->clk);
+	}
+
+	ret = clk_enable(priv->clk);
+	if (ret) {
+		dev_err(dev, "could not enable clock\n");
+		return -EBUSY;
+	}
+
+	priv->dev = dev;
+
+	if (!of_property_read_u32(dev->device_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)
+				return ret;
+		}
+	}
+
+	return fpga_bridge_register(dev, priv->name, &altera_hps2fpga_br_ops,
+				    priv);
+}
+
+static struct driver_d alt_fpga_bridge_driver = {
+	.probe = alt_fpga_bridge_probe,
+	.of_compatible = DRV_OF_COMPAT(altera_fpga_of_match),
+};
+
+static int alt_fpga_bridge_init(void)
+{
+	return platform_driver_register(&alt_fpga_bridge_driver);
+}
+postcore_initcall(alt_fpga_bridge_init);
-- 
2.11.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [RFC PATCH 4/4] fpga: add fpga-region support
  2017-08-01  9:19 [RFC PATCH 1/4] reset: add of_reset_control_get to header Steffen Trumtrar
  2017-08-01  9:19 ` [RFC PATCH 2/4] drivers: add fpga bridge framework Steffen Trumtrar
  2017-08-01  9:19 ` [RFC PATCH 3/4] drivers: fpga: add socfpga bridges Steffen Trumtrar
@ 2017-08-01  9:19 ` Steffen Trumtrar
  2017-08-01 20:22   ` Robert Schwebel
  2 siblings, 1 reply; 5+ messages in thread
From: Steffen Trumtrar @ 2017-08-01  9:19 UTC (permalink / raw)
  To: barebox; +Cc: Steffen Trumtrar

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 common/firmware.c          |  45 +++++++++-
 drivers/firmware/socfpga.c |   1 +
 drivers/fpga/Makefile      |   2 +-
 drivers/fpga/fpga-region.c | 209 +++++++++++++++++++++++++++++++++++++++++++++
 include/firmware.h         |   2 +
 5 files changed, 257 insertions(+), 2 deletions(-)
 create mode 100644 drivers/fpga/fpga-region.c

diff --git a/common/firmware.c b/common/firmware.c
index 664f9107d0f8..b66c13700913 100644
--- a/common/firmware.c
+++ b/common/firmware.c
@@ -13,6 +13,9 @@
 
 #include <firmware.h>
 #include <common.h>
+#include <environment.h>
+#include <globalvar.h>
+#include <magicvar.h>
 #include <malloc.h>
 #include <xfuncs.h>
 #include <fcntl.h>
@@ -35,6 +38,8 @@ struct firmware_mgr {
 
 static LIST_HEAD(firmwaremgr_list);
 
+static char *firmware_path;
+
 /*
  * firmwaremgr_find - find a firmware device handler
  *
@@ -188,6 +193,9 @@ int firmwaremgr_register(struct firmware_handler *fh)
 
 	list_add_tail(&mgr->list, &firmwaremgr_list);
 
+	firmware_path = xstrdup("");
+	globalvar_add_simple_string("firmware.root", &firmware_path);
+
 	return 0;
 out:
 	free(cdev->name);
@@ -202,11 +210,46 @@ out:
 int firmwaremgr_load_file(struct firmware_mgr *mgr, const char *firmware)
 {
 	int ret;
+	const char *full_name = NULL;
 	char *name = basprintf("/dev/%s", mgr->handler->id);
 
-	ret = copy_file(firmware, name, 0);
+	if (strlen(firmware_path) > 1)
+		full_name = basprintf("%s/%s", firmware_path, firmware);
+	else
+		full_name = firmware;
+
+	ret = copy_file(full_name, name, 0);
 
 	free(name);
 
 	return ret;
 }
+
+int of_firmwaremgr_load_file(struct device_node *np, const char *firmware)
+{
+	struct device_node *mgr_node;
+	struct firmware_handler *fh;
+	struct firmware_mgr *mgr;
+	struct device_d *dev;
+
+	mgr_node = of_parse_phandle(np, "fpga-mgr", 0);
+
+	if (mgr_node) {
+		dev = of_find_device_by_node(mgr_node);
+		if (!dev)
+			return -ENODEV;
+
+		fh = dev->priv;
+		if (!fh)
+			return -ENODEV;
+
+		mgr = firmwaremgr_find(fh->id);
+
+		return firmwaremgr_load_file(mgr, firmware);
+	}
+
+	return -ENODEV;
+}
+
+BAREBOX_MAGICVAR_NAMED(global_firmware_root, global.firmware.root,
+		       "directory where firmware files are found");
diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index 2d4b608c9a1c..170e835f2e1f 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -449,6 +449,7 @@ static int fpgamgr_probe(struct device_d *dev)
 	if (model)
 		fh->model = xstrdup(model);
 	fh->dev = dev;
+	dev->priv = fh;
 
 	dev_dbg(dev, "Registering FPGA firmware programmer\n");
 
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 86178fe7c078..532037035780 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -3,5 +3,5 @@
 #
 
 # FPGA Bridge Drivers
-obj-$(CONFIG_FPGA_BRIDGE)		+= fpga-bridge.o
+obj-$(CONFIG_FPGA_BRIDGE)		+= fpga-bridge.o fpga-region.o
 obj-$(CONFIG_SOCFPGA_FPGA_BRIDGE)	+= socfpga-hps2fpga-bridge.o socfpga-fpga2sdram-bridge.o
diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c
new file mode 100644
index 000000000000..9164ba2c3ac9
--- /dev/null
+++ b/drivers/fpga/fpga-region.c
@@ -0,0 +1,209 @@
+/*
+ * FPGA Region - Device Tree support for FPGA programming under Linux
+ *
+ *  Copyright (C) 2013-2016 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 <common.h>
+#include <init.h>
+#include <fpga-bridge.h>
+#include <firmware.h>
+#include <linux/list.h>
+
+/**
+ * struct fpga_region - FPGA Region structure
+ * @dev: FPGA Region device
+ * @mutex: enforces exclusive reference to region
+ * @bridge_list: list of FPGA bridges specified in region
+ * @info: fpga image specific information
+ */
+struct fpga_region {
+	struct device_d dev;
+	struct list_head bridge_list;
+	struct fpga_image_info *info;
+	const char *firmware_name;
+};
+
+#define to_fpga_region(d) container_of(d, struct fpga_region, dev)
+
+static const struct of_device_id fpga_region_of_match[] = {
+	{ .compatible = "fpga-region", },
+	{ /* sentinel */ },
+};
+
+/**
+ * fpga_region_get_bridges - create a list of bridges
+ * @region: FPGA region
+ * @overlay: device node of the overlay
+ *
+ * Create a list of bridges including the parent bridge and the bridges
+ * specified by "fpga-bridges" property.  Note that the
+ * fpga_bridges_enable/disable/put functions are all fine with an empty list
+ * if that happens.
+ *
+ * Caller should call fpga_bridges_put(&region->bridge_list) when
+ * done with the bridges.
+ *
+ * Return 0 for success (even if there are no bridges specified)
+ * or -EBUSY if any of the bridges are in use.
+ */
+static int fpga_region_get_bridges(struct fpga_region *region,
+				   struct device_node *overlay)
+{
+	struct device_d *dev = &region->dev;
+	struct device_node *region_np = dev->device_node;
+	struct device_node *br, *np, *parent_br = NULL;
+	int i, ret;
+
+	/* If parent is a bridge, add to list */
+	ret = fpga_bridge_get_to_list(region_np->parent, region->info,
+				      &region->bridge_list);
+	if (ret == -EBUSY)
+		return ret;
+
+	if (!ret)
+		parent_br = region_np->parent;
+
+	/* If overlay has a list of bridges, use it. */
+	if (of_parse_phandle(overlay, "fpga-bridges", 0))
+		np = overlay;
+	else
+		np = region_np;
+
+	for (i = 0; ; i++) {
+		br = of_parse_phandle(np, "fpga-bridges", i);
+		if (!br)
+			break;
+
+		/* If parent bridge is in list, skip it. */
+		if (br == parent_br)
+			continue;
+
+		/* If node is a bridge, get it and add to list */
+		ret = fpga_bridge_get_to_list(br, region->info,
+					      &region->bridge_list);
+
+		/* If any of the bridges are in use, give up */
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * fpga_region_program_fpga - program FPGA
+ * @region: FPGA region
+ * @firmware_name: name of FPGA image firmware file
+ * @overlay: device node of the overlay
+ * Program an FPGA using information in the device tree.
+ * Function assumes that there is a firmware-name property.
+ * Return 0 for success or negative error code.
+ */
+static int fpga_region_program_fpga(struct fpga_region *region)
+{
+	struct device_node *np = region->dev.device_node;
+	int ret;
+
+	ret = fpga_region_get_bridges(region, np);
+	if (ret) {
+		pr_err("failed to get fpga region bridges (%d)\n", ret);
+		goto err;
+	}
+
+	ret = fpga_bridges_disable(&region->bridge_list);
+	if (ret) {
+		pr_err("failed to disable region bridges (%d)\n", ret);
+		goto err;
+	}
+
+	ret = of_firmwaremgr_load_file(np, region->firmware_name);
+	if (ret) {
+		pr_err("failed to load fpga image %s (%d)\n",
+                       region->firmware_name, ret);
+		goto err;
+	}
+
+	ret = fpga_bridges_enable(&region->bridge_list);
+	if (ret) {
+		pr_err("failed to enable region bridges (%d)\n", ret);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	return ret;
+}
+
+static int fpga_region_detect(struct device_d *dev)
+{
+	struct fpga_region *region = dev->priv;
+	struct device_node *np = dev->device_node;
+	int ret;
+
+	ret = fpga_region_program_fpga(region);
+
+	of_platform_populate(np, fpga_region_of_match, dev);
+
+	return ret;
+}
+
+static int fpga_region_probe(struct device_d *dev)
+{
+	struct device_node *np = dev->device_node;
+	struct fpga_region *region;
+	int ret = 0;
+
+	region = xzalloc(sizeof(*region));
+	if (!region)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&region->bridge_list);
+
+	region->dev.parent = dev;
+	region->dev.device_node = np;
+	region->dev.id = DEVICE_ID_DYNAMIC;
+	region->dev.detect = fpga_region_detect;
+	region->dev.priv = region;
+
+	strcpy(region->dev.name, "region");
+
+	ret = register_device(&region->dev);
+	if (ret)
+		goto out;
+
+	of_property_read_string(np, "firmware-name", &region->firmware_name);
+
+	dev_info(dev, "FPGA Region probed\n");
+
+	return 0;
+
+out:
+	kfree(region);
+
+	return ret;
+}
+
+static struct driver_d fpga_region_driver = {
+	.probe = fpga_region_probe,
+	.of_compatible = DRV_OF_COMPAT(fpga_region_of_match),
+};
+
+static int fpga_region_init(void)
+{
+	return platform_driver_register(&fpga_region_driver);
+}
+postcore_initcall(fpga_region_init);
diff --git a/include/firmware.h b/include/firmware.h
index f6f78c840cac..6e7257c2f826 100644
--- a/include/firmware.h
+++ b/include/firmware.h
@@ -39,4 +39,6 @@ void firmwaremgr_list_handlers(void);
 
 int firmwaremgr_load_file(struct firmware_mgr *, const char *path);
 
+int of_firmwaremgr_load_file(struct device_node *np, const char *firmware);
+
 #endif /* FIRMWARE_H */
-- 
2.11.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [RFC PATCH 4/4] fpga: add fpga-region support
  2017-08-01  9:19 ` [RFC PATCH 4/4] fpga: add fpga-region support Steffen Trumtrar
@ 2017-08-01 20:22   ` Robert Schwebel
  0 siblings, 0 replies; 5+ messages in thread
From: Robert Schwebel @ 2017-08-01 20:22 UTC (permalink / raw)
  To: Steffen Trumtrar; +Cc: barebox

On Tue, Aug 01, 2017 at 11:19:34AM +0200, Steffen Trumtrar wrote:
> Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>

Could you add a more verbose patch description?

rsc
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

end of thread, other threads:[~2017-08-01 20:22 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-01  9:19 [RFC PATCH 1/4] reset: add of_reset_control_get to header Steffen Trumtrar
2017-08-01  9:19 ` [RFC PATCH 2/4] drivers: add fpga bridge framework Steffen Trumtrar
2017-08-01  9:19 ` [RFC PATCH 3/4] drivers: fpga: add socfpga bridges Steffen Trumtrar
2017-08-01  9:19 ` [RFC PATCH 4/4] fpga: add fpga-region support Steffen Trumtrar
2017-08-01 20:22   ` Robert Schwebel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox