mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v3 01/10] reset: add of_reset_control_get to header
@ 2021-06-15 11:24 Steffen Trumtrar
  2021-06-15 11:25 ` [PATCH v3 02/10] drivers: add fpga bridge framework Steffen Trumtrar
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Steffen Trumtrar @ 2021-06-15 11:24 UTC (permalink / raw)
  To: Barebox List

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

diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index 26a54f21dff0..1c9eeaec5491 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -147,7 +147,7 @@ EXPORT_SYMBOL_GPL(reset_control_deassert);
  *
  * Use of id names is optional.
  */
-static struct reset_control *of_reset_control_get(struct device_node *node,
+struct reset_control *of_reset_control_get(struct device_node *node,
 						  const char *id)
 {
 	struct reset_control *rstc;
diff --git a/include/linux/reset.h b/include/linux/reset.h
index a166fe1cfe04..726cb5c2057d 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.29.2


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


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

* [PATCH v3 02/10] drivers: add fpga bridge framework
  2021-06-15 11:24 [PATCH v3 01/10] reset: add of_reset_control_get to header Steffen Trumtrar
@ 2021-06-15 11:25 ` Steffen Trumtrar
  2021-06-15 11:25 ` [PATCH v3 03/10] drivers: fpga: add socfpga bridges Steffen Trumtrar
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Trumtrar @ 2021-06-15 11:25 UTC (permalink / raw)
  To: Barebox List

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

Description from the initial commit adding this to linux:
21aeda950c5f84a8351b862816d832120b217a9b

    fpga: add fpga bridge framework

    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 FPGA's.

    The functions are:
    * of_fpga_bridge_get
    * fpga_bridge_put
       Get/put an exclusive 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.

    Get an exclusive reference to a bridge and add it to a list:
    * fpga_bridge_get_to_list

    To enable/disable/put a set of bridges that are on a list:
    * fpga_bridges_enable
    * fpga_bridges_disable
    * fpga_bridges_put

    Signed-off-by: Alan Tull <atull@opensource.altera.com>

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>

---

v2->v3: add fpga_bridges_put function to deallocate bridge list
---
 drivers/Kconfig            |   1 +
 drivers/Makefile           |   1 +
 drivers/fpga/Kconfig       |  22 ++++
 drivers/fpga/Makefile      |   6 +
 drivers/fpga/fpga-bridge.c | 243 +++++++++++++++++++++++++++++++++++++
 include/fpga-bridge.h      |  74 +++++++++++
 6 files changed, 347 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 787d36693309..670e0a9f4c95 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -37,6 +37,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 be5b0b3b04c9..e21ac7095c6c 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -34,6 +34,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..fccdbff6eb3f
--- /dev/null
+++ b/drivers/fpga/Kconfig
@@ -0,0 +1,22 @@
+#
+# 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 barebox.
+
+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..6e8dcbfc0d16
--- /dev/null
+++ b/drivers/fpga/fpga-bridge.c
@@ -0,0 +1,243 @@
+/*
+ * 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
+ *
+ * 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 device_d *dev;
+	struct fpga_bridge *bridge;
+	int ret = -ENODEV;
+
+	dev = of_find_device_by_node(np);
+	if (!dev || !dev->priv)
+		return ERR_PTR(ret);
+
+	bridge = dev->priv;
+
+	return bridge;
+}
+EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
+
+/**
+ * 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;
+	int ret;
+
+	list_for_each_entry(bridge, bridge_list, 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;
+	int ret;
+
+	list_for_each_entry(bridge, bridge_list, 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, *next;
+
+	list_for_each_entry_safe(bridge, next, bridge_list, node)
+		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
+ * @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 list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+
+	bridge = of_fpga_bridge_get(np);
+	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;
+
+	bridge->dev.name = xstrdup(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..fef2a9ccbbd3
--- /dev/null
+++ b/include/fpga-bridge.h
@@ -0,0 +1,74 @@
+#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 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);
+void fpga_bridge_put(struct fpga_bridge *bridge);
+int fpga_bridge_enable(struct fpga_bridge *bridge);
+int fpga_bridge_disable(struct fpga_bridge *bridge);
+
+#ifdef CONFIG_FPGA_BRIDGE
+int fpga_bridges_enable(struct list_head *bridge_list);
+int fpga_bridges_disable(struct list_head *bridge_list);
+int fpga_bridge_get_to_list(struct device_node *np,
+			    struct list_head *bridge_list);
+void fpga_bridges_put(struct list_head *bridge_list);
+#else
+static inline int fpga_bridges_enable(struct list_head *bridge_list)
+{
+	return -ENOSYS;
+};
+static inline int fpga_bridges_disable(struct list_head *bridge_list)
+{
+	return -ENOSYS;
+};
+static inline int fpga_bridge_get_to_list(struct device_node *np,
+			    struct list_head *bridge_list)
+{
+	return -ENOSYS;
+};
+static inline void fpga_bridges_put(struct list_head *bridge_list)
+{
+	return;
+};
+#endif
+
+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.29.2


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


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

* [PATCH v3 03/10] drivers: fpga: add socfpga bridges
  2021-06-15 11:24 [PATCH v3 01/10] reset: add of_reset_control_get to header Steffen Trumtrar
  2021-06-15 11:25 ` [PATCH v3 02/10] drivers: add fpga bridge framework Steffen Trumtrar
@ 2021-06-15 11:25 ` Steffen Trumtrar
  2021-06-15 11:25 ` [PATCH v3 04/10] firmware: socfpga: change function prefixes Steffen Trumtrar
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Trumtrar @ 2021-06-15 11:25 UTC (permalink / raw)
  To: Barebox List

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

Description from the original commit:
e5f8efa5c8bf86c1fa698551d54db8f6aee221fd

    ARM: socfpga: fpga bridge driver support

    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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/fpga/Kconfig                     |   8 +
 drivers/fpga/Makefile                    |   1 +
 drivers/fpga/fpga-bridge.c               |   2 +-
 drivers/fpga/socfpga-fpga2sdram-bridge.c | 139 ++++++++++++++++++
 drivers/fpga/socfpga-hps2fpga-bridge.c   | 179 +++++++++++++++++++++++
 5 files changed, 328 insertions(+), 1 deletion(-)
 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 fccdbff6eb3f..64ce9f91b6a8 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -17,6 +17,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/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
index 6e8dcbfc0d16..6f9e943de904 100644
--- a/drivers/fpga/fpga-bridge.c
+++ b/drivers/fpga/fpga-bridge.c
@@ -68,7 +68,7 @@ struct fpga_bridge *of_fpga_bridge_get(struct device_node *np)
 {
 	struct device_d *dev;
 	struct fpga_bridge *bridge;
-	int ret = -ENODEV;
+	int ret = -EPROBE_DEFER;
 
 	dev = of_find_device_by_node(np);
 	if (!dev || !dev->priv)
diff --git a/drivers/fpga/socfpga-fpga2sdram-bridge.c b/drivers/fpga/socfpga-fpga2sdram-bridge.c
new file mode 100644
index 000000000000..a9760597ddb5
--- /dev/null
+++ b/drivers/fpga/socfpga-fpga2sdram-bridge.c
@@ -0,0 +1,139 @@
+/*
+ * 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 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 = ALT_SDR_CTL_FPGAPORTRST_PORTRSTN_MSK;
+
+	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,
+	.name = "altera-fpga2sdram-bridge",
+	.of_compatible = DRV_OF_COMPAT(altera_fpga_of_match),
+};
+device_platform_driver(altera_fpga_driver);
diff --git a/drivers/fpga/socfpga-hps2fpga-bridge.c b/drivers/fpga/socfpga-hps2fpga-bridge.c
new file mode 100644
index 000000000000..ecb33ea0b3a5
--- /dev/null
+++ b/drivers/fpga/socfpga-hps2fpga-bridge.c
@@ -0,0 +1,179 @@
+/*
+ * 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 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,
+	.name = "altera-hps2fpga-bridge",
+	.of_compatible = DRV_OF_COMPAT(altera_fpga_of_match),
+};
+device_platform_driver(alt_fpga_bridge_driver);
-- 
2.29.2


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


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

* [PATCH v3 04/10] firmware: socfpga: change function prefixes
  2021-06-15 11:24 [PATCH v3 01/10] reset: add of_reset_control_get to header Steffen Trumtrar
  2021-06-15 11:25 ` [PATCH v3 02/10] drivers: add fpga bridge framework Steffen Trumtrar
  2021-06-15 11:25 ` [PATCH v3 03/10] drivers: fpga: add socfpga bridges Steffen Trumtrar
@ 2021-06-15 11:25 ` Steffen Trumtrar
  2021-06-15 11:25 ` [PATCH v3 05/10] firmware: import fpga-mgr.h from linux Steffen Trumtrar
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Trumtrar @ 2021-06-15 11:25 UTC (permalink / raw)
  To: Barebox List

Since there is now a fpgamgr framework in barebox, the function names are
misleading. Change that to be SoCFPGA specific.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/firmware/socfpga.c | 58 +++++++++++++++++++-------------------
 1 file changed, 29 insertions(+), 29 deletions(-)

diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index c468c743720f..14875214b1aa 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -92,12 +92,12 @@ struct fpgamgr {
 };
 
 /* Get the FPGA mode */
-static uint32_t fpgamgr_get_mode(struct fpgamgr *mgr)
+static uint32_t socfpga_fpgamgr_get_mode(struct fpgamgr *mgr)
 {
 	return readl(mgr->regs + FPGAMGRREGS_STAT) & FPGAMGRREGS_STAT_MODE_MASK;
 }
 
-static int fpgamgr_dclkcnt_set(struct fpgamgr *mgr, unsigned long cnt)
+static int socfpga_fpgamgr_dclkcnt_set(struct fpgamgr *mgr, unsigned long cnt)
 {
 	uint64_t start;
 
@@ -121,7 +121,7 @@ static int fpgamgr_dclkcnt_set(struct fpgamgr *mgr, unsigned long cnt)
 }
 
 /* Start the FPGA programming by initialize the FPGA Manager */
-static int fpgamgr_program_init(struct fpgamgr *mgr)
+static int socfpga_fpgamgr_program_init(struct fpgamgr *mgr)
 {
 	unsigned long reg;
 	uint32_t ctrl = 0, ratio;
@@ -170,7 +170,7 @@ static int fpgamgr_program_init(struct fpgamgr *mgr)
 	/* (1) wait until FPGA enter reset phase */
 	start = get_time_ns();
 	while (1) {
-		if (fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_RESETPHASE)
+		if (socfpga_fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_RESETPHASE)
 			break;
 		if (is_timeout(start, 100 * MSECOND))
 			return -ETIMEDOUT;
@@ -184,7 +184,7 @@ static int fpgamgr_program_init(struct fpgamgr *mgr)
 	/* (2) wait until FPGA enter configuration phase */
 	start = get_time_ns();
 	while (1) {
-		if (fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_CFGPHASE)
+		if (socfpga_fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_CFGPHASE)
 			break;
 		if (is_timeout(start, 100 * MSECOND))
 			return -ETIMEDOUT;
@@ -202,7 +202,7 @@ static int fpgamgr_program_init(struct fpgamgr *mgr)
 }
 
 /* Ensure the FPGA entering config done */
-static int fpgamgr_program_poll_cd(struct fpgamgr *mgr)
+static int socfpga_fpgamgr_program_poll_cd(struct fpgamgr *mgr)
 {
 	unsigned long reg;
 	uint32_t val;
@@ -236,18 +236,18 @@ static int fpgamgr_program_poll_cd(struct fpgamgr *mgr)
 }
 
 /* Ensure the FPGA entering init phase */
-static int fpgamgr_program_poll_initphase(struct fpgamgr *mgr)
+static int socfpga_fpgamgr_program_poll_initphase(struct fpgamgr *mgr)
 {
 	uint64_t start;
 
 	/* additional clocks for the CB to enter initialization phase */
-	if (fpgamgr_dclkcnt_set(mgr, 0x4) != 0)
+	if (socfpga_fpgamgr_dclkcnt_set(mgr, 0x4) != 0)
 		return -5;
 
 	/* (4) wait until FPGA enter init phase or user mode */
 	start = get_time_ns();
 	while (1) {
-		int mode = fpgamgr_get_mode(mgr);
+		int mode = socfpga_fpgamgr_get_mode(mgr);
 
 		if (mode == FPGAMGRREGS_MODE_INITPHASE ||
 				mode == FPGAMGRREGS_MODE_USERMODE)
@@ -261,19 +261,19 @@ static int fpgamgr_program_poll_initphase(struct fpgamgr *mgr)
 }
 
 /* Ensure the FPGA entering user mode */
-static int fpgamgr_program_poll_usermode(struct fpgamgr *mgr)
+static int socfpga_fpgamgr_program_poll_usermode(struct fpgamgr *mgr)
 {
 	uint32_t val;
 	uint64_t start;
 
 	/* additional clocks for the CB to exit initialization phase */
-	if (fpgamgr_dclkcnt_set(mgr, 0x5000) != 0)
+	if (socfpga_fpgamgr_dclkcnt_set(mgr, 0x5000) != 0)
 		return -7;
 
 	/* (5) wait until FPGA enter user mode */
 	start = get_time_ns();
 	while (1) {
-		if (fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE)
+		if (socfpga_fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE)
 			break;
 		if (is_timeout(start, 100 * MSECOND))
 			return -ETIMEDOUT;
@@ -291,7 +291,7 @@ static int fpgamgr_program_poll_usermode(struct fpgamgr *mgr)
  * Using FPGA Manager to program the FPGA
  * Return 0 for sucess
  */
-static int fpgamgr_program_start(struct firmware_handler *fh)
+static int socfpga_fpgamgr_program_start(struct firmware_handler *fh)
 {
 	struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
 	int status;
@@ -313,7 +313,7 @@ static int fpgamgr_program_start(struct firmware_handler *fh)
 	dev_dbg(&mgr->dev, "start programming...\n");
 
 	/* initialize the FPGA Manager */
-	status = fpgamgr_program_init(mgr);
+	status = socfpga_fpgamgr_program_init(mgr);
 	if (status) {
 		dev_err(&mgr->dev, "program init failed with: %s\n",
 				strerror(-status));
@@ -324,7 +324,7 @@ static int fpgamgr_program_start(struct firmware_handler *fh)
 }
 
 /* Write the RBF data to FPGA Manager */
-static int fpgamgr_program_write_buf(struct firmware_handler *fh, const void *buf,
+static int socfpga_fpgamgr_program_write_buf(struct firmware_handler *fh, const void *buf,
 		size_t size)
 {
 	struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
@@ -355,7 +355,7 @@ static int fpgamgr_program_write_buf(struct firmware_handler *fh, const void *bu
 	return 0;
 }
 
-static int fpgamgr_program_finish(struct firmware_handler *fh)
+static int socfpga_fpgamgr_program_finish(struct firmware_handler *fh)
 {
 	struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
 	int status;
@@ -364,7 +364,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	void (*ocram_func)(void __iomem *ocram_base);
 
 	/* Ensure the FPGA entering config done */
-	status = fpgamgr_program_poll_cd(mgr);
+	status = socfpga_fpgamgr_program_poll_cd(mgr);
 	if (status) {
 		dev_err(&mgr->dev, "poll for config done failed with: %s\n",
 				strerror(-status));
@@ -374,7 +374,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	dev_dbg(&mgr->dev, "waiting for init phase...\n");
 
 	/* Ensure the FPGA entering init phase */
-	status = fpgamgr_program_poll_initphase(mgr);
+	status = socfpga_fpgamgr_program_poll_initphase(mgr);
 	if (status) {
 		dev_err(&mgr->dev, "poll for init phase failed with: %s\n",
 				strerror(-status));
@@ -384,7 +384,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	dev_dbg(&mgr->dev, "waiting for user mode...\n");
 
 	/* Ensure the FPGA entering user mode */
-	status = fpgamgr_program_poll_usermode(mgr);
+	status = socfpga_fpgamgr_program_poll_usermode(mgr);
 	if (status) {
 		dev_err(&mgr->dev, "poll for user mode with: %s\n",
 				strerror(-status));
@@ -410,11 +410,11 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 static int programmed_get(struct param_d *p, void *priv)
 {
 	struct fpgamgr *mgr = priv;
-	mgr->programmed = fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE;
+	mgr->programmed = socfpga_fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE;
 	return 0;
 }
 
-static int fpgamgr_probe(struct device_d *dev)
+static int socfpga_fpgamgr_probe(struct device_d *dev)
 {
 	struct resource *iores;
 	struct fpgamgr *mgr;
@@ -448,9 +448,9 @@ static int fpgamgr_probe(struct device_d *dev)
 	else
 		fh->id = xstrdup("socfpga-fpga");
 
-	fh->open = fpgamgr_program_start;
-	fh->write = fpgamgr_program_write_buf;
-	fh->close = fpgamgr_program_finish;
+	fh->open = socfpga_fpgamgr_program_start;
+	fh->write = socfpga_fpgamgr_program_write_buf;
+	fh->close = socfpga_fpgamgr_program_finish;
 	of_property_read_string(dev->device_node, "compatible", &model);
 	if (model)
 		fh->model = xstrdup(model);
@@ -488,7 +488,7 @@ static int fpgamgr_probe(struct device_d *dev)
 	return ret;
 }
 
-static struct of_device_id fpgamgr_id_table[] = {
+static struct of_device_id socfpga_fpgamgr_id_table[] = {
 	{
 		.compatible = "altr,socfpga-fpga-mgr",
 	},
@@ -498,9 +498,9 @@ static struct of_device_id fpgamgr_id_table[] = {
 	{ /* sentinel */ }
 };
 
-static struct driver_d fpgamgr_driver = {
+static struct driver_d socfpga_fpgamgr_driver = {
 	.name = "socfpa-fpgamgr",
-	.of_compatible = DRV_OF_COMPAT(fpgamgr_id_table),
-	.probe = fpgamgr_probe,
+	.of_compatible = DRV_OF_COMPAT(socfpga_fpgamgr_id_table),
+	.probe = socfpga_fpgamgr_probe,
 };
-device_platform_driver(fpgamgr_driver);
+device_platform_driver(socfpga_fpgamgr_driver);
-- 
2.29.2


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


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

* [PATCH v3 05/10] firmware: import fpga-mgr.h from linux
  2021-06-15 11:24 [PATCH v3 01/10] reset: add of_reset_control_get to header Steffen Trumtrar
                   ` (2 preceding siblings ...)
  2021-06-15 11:25 ` [PATCH v3 04/10] firmware: socfpga: change function prefixes Steffen Trumtrar
@ 2021-06-15 11:25 ` Steffen Trumtrar
  2021-06-15 11:25 ` [PATCH v3 06/10] of: kconfig: of_overlay uses firmwaremgr_load_file Steffen Trumtrar
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Trumtrar @ 2021-06-15 11:25 UTC (permalink / raw)
  To: Barebox List

Instead of defining the fpga-mgr structure in the socfpga driver, import
the fpga-mgr.h file from linux v4.13.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/firmware/socfpga.c |   9 +---
 include/firmware.h         |   1 +
 include/fpga-mgr.h         | 102 +++++++++++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+), 8 deletions(-)
 create mode 100644 include/fpga-mgr.h

diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index 14875214b1aa..605c931604c9 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -27,6 +27,7 @@
  */
 
 #include <firmware.h>
+#include <fpga-mgr.h>
 #include <command.h>
 #include <common.h>
 #include <malloc.h>
@@ -83,14 +84,6 @@
 extern void socfpga_sdram_apply_static_cfg(void __iomem *sdrctrlgrp);
 extern void socfpga_sdram_apply_static_cfg_end(void *);
 
-struct fpgamgr {
-	struct firmware_handler fh;
-	struct device_d dev;
-	void __iomem *regs;
-	void __iomem *regs_data;
-	int programmed;
-};
-
 /* Get the FPGA mode */
 static uint32_t socfpga_fpgamgr_get_mode(struct fpgamgr *mgr)
 {
diff --git a/include/firmware.h b/include/firmware.h
index 19777d9bf711..2fef97a48f56 100644
--- a/include/firmware.h
+++ b/include/firmware.h
@@ -13,6 +13,7 @@ struct firmware_handler {
 	char *id; /* unique identifier for this firmware device */
 	char *model; /* description for this device */
 	struct device_d *dev;
+	void *priv;
 	/* called once to prepare the firmware's programming cycle */
 	int (*open)(struct firmware_handler*);
 	/* called multiple times to program the firmware with the given data */
diff --git a/include/fpga-mgr.h b/include/fpga-mgr.h
new file mode 100644
index 000000000000..a120b3918990
--- /dev/null
+++ b/include/fpga-mgr.h
@@ -0,0 +1,102 @@
+/*
+ * FPGA Framework
+ *
+ *  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/>.
+ */
+#ifndef _LINUX_FPGA_MGR_H
+#define _LINUX_FPGA_MGR_H
+
+#include <firmware.h>
+
+struct fpga_manager;
+
+/**
+ * enum fpga_mgr_states - fpga framework states
+ * @FPGA_MGR_STATE_UNKNOWN: can't determine state
+ * @FPGA_MGR_STATE_POWER_OFF: FPGA power is off
+ * @FPGA_MGR_STATE_POWER_UP: FPGA reports power is up
+ * @FPGA_MGR_STATE_RESET: FPGA in reset state
+ * @FPGA_MGR_STATE_FIRMWARE_REQ: firmware request in progress
+ * @FPGA_MGR_STATE_FIRMWARE_REQ_ERR: firmware request failed
+ * @FPGA_MGR_STATE_WRITE_INIT: preparing FPGA for programming
+ * @FPGA_MGR_STATE_WRITE_INIT_ERR: Error during WRITE_INIT stage
+ * @FPGA_MGR_STATE_WRITE: writing image to FPGA
+ * @FPGA_MGR_STATE_WRITE_ERR: Error while writing FPGA
+ * @FPGA_MGR_STATE_WRITE_COMPLETE: Doing post programming steps
+ * @FPGA_MGR_STATE_WRITE_COMPLETE_ERR: Error during WRITE_COMPLETE
+ * @FPGA_MGR_STATE_OPERATING: FPGA is programmed and operating
+ */
+enum fpga_mgr_states {
+	/* default FPGA states */
+	FPGA_MGR_STATE_UNKNOWN,
+	FPGA_MGR_STATE_POWER_OFF,
+	FPGA_MGR_STATE_POWER_UP,
+	FPGA_MGR_STATE_RESET,
+
+	/* getting an image for loading */
+	FPGA_MGR_STATE_FIRMWARE_REQ,
+	FPGA_MGR_STATE_FIRMWARE_REQ_ERR,
+
+	/* write sequence: init, write, complete */
+	FPGA_MGR_STATE_WRITE_INIT,
+	FPGA_MGR_STATE_WRITE_INIT_ERR,
+	FPGA_MGR_STATE_WRITE,
+	FPGA_MGR_STATE_WRITE_ERR,
+	FPGA_MGR_STATE_WRITE_COMPLETE,
+	FPGA_MGR_STATE_WRITE_COMPLETE_ERR,
+
+	/* fpga is programmed and operating */
+	FPGA_MGR_STATE_OPERATING,
+};
+
+/*
+ * FPGA Manager flags
+ * FPGA_MGR_PARTIAL_RECONFIG: do partial reconfiguration if supported
+ * FPGA_MGR_EXTERNAL_CONFIG: FPGA has been configured prior to Linux booting
+ * FPGA_MGR_BITSTREAM_LSB_FIRST: SPI bitstream bit order is LSB first
+ * FPGA_MGR_COMPRESSED_BITSTREAM: FPGA bitstream is compressed
+ */
+#define FPGA_MGR_PARTIAL_RECONFIG	BIT(0)
+#define FPGA_MGR_EXTERNAL_CONFIG	BIT(1)
+#define FPGA_MGR_ENCRYPTED_BITSTREAM	BIT(2)
+#define FPGA_MGR_BITSTREAM_LSB_FIRST	BIT(3)
+#define FPGA_MGR_COMPRESSED_BITSTREAM	BIT(4)
+
+/**
+ * struct fpga_image_info - information specific to a FPGA image
+ * @flags: boolean flags as defined above
+ * @enable_timeout_us: maximum time to enable traffic through bridge (uSec)
+ * @disable_timeout_us: maximum time to disable traffic through bridge (uSec)
+ * @config_complete_timeout_us: maximum time for FPGA to switch to operating
+ *	   status in the write_complete op.
+ */
+struct fpga_image_info {
+	u32 flags;
+	u32 enable_timeout_us;
+	u32 disable_timeout_us;
+	u32 config_complete_timeout_us;
+};
+
+struct fpgamgr {
+	struct firmware_handler fh;
+	struct device_d dev;
+	void *priv;
+	void __iomem *regs;
+	void __iomem *regs_data;
+	int programmed;
+};
+
+
+#endif /*_LINUX_FPGA_MGR_H */
-- 
2.29.2


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


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

* [PATCH v3 06/10] of: kconfig: of_overlay uses firmwaremgr_load_file
  2021-06-15 11:24 [PATCH v3 01/10] reset: add of_reset_control_get to header Steffen Trumtrar
                   ` (3 preceding siblings ...)
  2021-06-15 11:25 ` [PATCH v3 05/10] firmware: import fpga-mgr.h from linux Steffen Trumtrar
@ 2021-06-15 11:25 ` Steffen Trumtrar
  2021-06-15 11:25 ` [PATCH v3 07/10] of: of_firmware: add support for fpga bridges Steffen Trumtrar
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Trumtrar @ 2021-06-15 11:25 UTC (permalink / raw)
  To: Barebox List

From: Steffen Trumtrar <str@pengutronix.de>

As of_firmware.c uses the firmwaremgr_load_file function, it depends on
FIRMWARE.

Signed-off-by: Steffen Trumtrar <str@pengutronix.de>
---
 drivers/of/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 23be25d85d09..e58fe50f7090 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -49,6 +49,7 @@ config OF_BAREBOX_ENV_IN_FS
 
 config OF_OVERLAY
 	select OFTREE
+	select FIRMWARE
 	bool "Devicetree overlays"
 	help
 	  Overlays allow to patch the devicetree. Unlike Linux, Barebox does
-- 
2.29.2


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


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

* [PATCH v3 07/10] of: of_firmware: add support for fpga bridges
  2021-06-15 11:24 [PATCH v3 01/10] reset: add of_reset_control_get to header Steffen Trumtrar
                   ` (4 preceding siblings ...)
  2021-06-15 11:25 ` [PATCH v3 06/10] of: kconfig: of_overlay uses firmwaremgr_load_file Steffen Trumtrar
@ 2021-06-15 11:25 ` Steffen Trumtrar
  2021-06-15 11:25 ` [PATCH v3 08/10] commands: firmwareload: allow loading firmware from dt Steffen Trumtrar
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Trumtrar @ 2021-06-15 11:25 UTC (permalink / raw)
  To: Barebox List

Add support for potentially defined FPGA-bridges in the overlay.

While at it also add support for loading the firmware directly via a
path instead of 'needing' an overlay for that.
The direct loading will be done with the existent firmwareload command.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>

---

v2->v3 - basprintf -> plain 'compatible = "fpga-region"'
       - assign root in if-clause
---
 drivers/of/Makefile      |   3 +-
 drivers/of/of_firmware.c | 129 +++++++++++++++++++++++++++++++++++++--
 include/of.h             |  23 +++++--
 3 files changed, 142 insertions(+), 13 deletions(-)

diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index b6847752d247..6199c9791f52 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -6,4 +6,5 @@ obj-y += partition.o
 obj-y += of_net.o
 obj-$(CONFIG_MTD) += of_mtd.o
 obj-$(CONFIG_OF_BAREBOX_DRIVERS) += barebox.o
-obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o of_firmware.o
+obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o
+obj-$(CONFIG_FIRMWARE) += of_firmware.o
diff --git a/drivers/of/of_firmware.c b/drivers/of/of_firmware.c
index 096f84572e63..26864a6a13ef 100644
--- a/drivers/of/of_firmware.c
+++ b/drivers/of/of_firmware.c
@@ -4,12 +4,52 @@
  */
 #include <common.h>
 #include <firmware.h>
+#include <fpga-bridge.h>
 #include <of.h>
 
 struct overlay_info {
 	const char *firmware_path;
 };
 
+#ifdef CONFIG_FPGA_BRIDGE
+static int of_get_bridges(struct device_node *region, struct list_head *bridges)
+{
+	struct device_node *br, *parent_br = NULL;
+	int i, ret;
+
+	/* If parent is a bridge, add to list */
+	ret = fpga_bridge_get_to_list(region->parent, bridges);
+	if (!ret) {
+		parent_br = region->parent;
+		pr_debug("Add %s to list of bridges\n", parent_br->name);
+	}
+
+	for (i = 0; ; i++) {
+		br = of_parse_phandle(region, "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, bridges);
+		if (ret)
+			return ret;
+
+		pr_debug("Add %s to list of bridges\n", br->name);
+	}
+
+	return 0;
+}
+#else
+static int of_get_bridges(struct device_node *np, struct list_head *br)
+{
+	return 0;
+}
+#endif
+
 static struct firmware_mgr *of_node_get_mgr(struct device_node *np)
 {
 	struct device_node *mgr_node;
@@ -25,6 +65,35 @@ static struct firmware_mgr *of_node_get_mgr(struct device_node *np)
 	return NULL;
 }
 
+static int of_load_firmware(struct device_node *target, const char *path)
+{
+	struct list_head bridge_list;
+	struct firmware_mgr *mgr;
+	int err;
+
+	mgr = of_node_get_mgr(target);
+	if (!mgr)
+		return -EINVAL;
+
+	pr_debug("Found firmware manager @%s\n", target->name);
+
+	INIT_LIST_HEAD(&bridge_list);
+
+	of_get_bridges(target, &bridge_list);
+
+	fpga_bridges_disable(&bridge_list);
+
+	pr_debug("Loading %s to %s\n", path, target->name);
+
+	err = firmwaremgr_load_file(mgr, path);
+
+	fpga_bridges_enable(&bridge_list);
+
+	fpga_bridges_put(&bridge_list);
+
+	return err;
+}
+
 static int load_firmware(struct device_node *target,
 			 struct device_node *fragment, void *data)
 {
@@ -33,7 +102,6 @@ static int load_firmware(struct device_node *target,
 	const char *firmware_path = info->firmware_path;
 	char *firmware;
 	int err;
-	struct firmware_mgr *mgr;
 
 	err = of_property_read_string(fragment,
 				      "firmware-name", &firmware_name);
@@ -46,21 +114,70 @@ static int load_firmware(struct device_node *target,
 	if (!target)
 		return -EINVAL;
 
-	mgr = of_node_get_mgr(target);
-	if (!mgr)
-		return -EINVAL;
-
 	firmware = basprintf("%s/%s", firmware_path, firmware_name);
 	if (!firmware)
 		return -ENOMEM;
 
-	err = firmwaremgr_load_file(mgr, firmware);
+	err = of_load_firmware(target, firmware);
 
 	free(firmware);
 
 	return err;
 }
 
+int of_firmware_load_file(const char *path, const char *compatible,
+			  const char *search_path, const char *firmware)
+{
+	struct overlay_info info = {
+		.firmware_path = search_path,
+	};
+	struct device_node *target;
+	struct device_node *node;
+	struct device_node *root;
+
+	if (!compatible)
+		compatible = "fpga-region";
+
+	/*
+	 * firmware-name not specified. Use load_firmware function to get it from
+	 * the devicetree. This allows loading firmware to multiple devices.
+	 */
+	if (!firmware && !path) {
+		int err;
+
+		pr_debug("No firmware specified. Searching devicetree for %s\n", compatible);
+		for_each_compatible_node(node, NULL, compatible) {
+			pr_debug("Load firmware from %s\n", node->name);
+			err = load_firmware(node, node, &info);
+			if (err == -ENOMEM)
+				return err;
+		}
+
+		return 0;
+	}
+
+	if (path) {
+		root = of_get_root_node();
+
+		target = of_find_node_by_path_or_alias(root, path);
+		if (!target) {
+			pr_debug("Cannot find nodepath %s\n", path);
+			return -ENOENT;
+		}
+	} else {
+		target = of_find_compatible_node(NULL, NULL, compatible);
+		if (!target) {
+			pr_debug("No node matching %s found\n", compatible);
+			return -ENOSYS;
+		}
+	}
+	
+	if (!firmware)
+		return load_firmware(target, target, &info);
+
+	return of_load_firmware(target, firmware);
+}
+
 int of_firmware_load_overlay(struct device_node *overlay, const char *path)
 {
 	struct overlay_info info = {
diff --git a/include/of.h b/include/of.h
index 645f429bdeed..3c922bdb1414 100644
--- a/include/of.h
+++ b/include/of.h
@@ -1020,6 +1020,23 @@ static inline struct device_node *of_find_root_node(struct device_node *node)
 	return node;
 }
 
+#ifdef CONFIG_FIRMWARE
+int of_firmware_load_file(const char *path, const char *compatible,
+			  const char *search_path, const char *firmware);
+int of_firmware_load_overlay(struct device_node *overlay, const char *path);
+#else
+static inline int of_firmware_load_file(const char *path, const char *compatible,
+					const char *search_path, const char *firmware)
+{
+	return -ENOSYS;
+}
+
+static inline int of_firmware_load_overlay(const char *path)
+{
+	return -ENOSYS;
+}
+#endif
+
 #ifdef CONFIG_OF_OVERLAY
 struct device_node *of_resolve_phandles(struct device_node *root,
 					const struct device_node *overlay);
@@ -1032,7 +1049,6 @@ int of_process_overlay(struct device_node *root,
 				   struct device_node *overlay, void *data),
 		    void *data);
 
-int of_firmware_load_overlay(struct device_node *overlay, const char *path);
 #else
 static inline struct device_node *of_resolve_phandles(struct device_node *root,
 					const struct device_node *overlay)
@@ -1059,11 +1075,6 @@ static inline int of_process_overlay(struct device_node *root,
 {
 	return -ENOSYS;
 }
-
-static inline int of_firmware_load_overlay(struct device_node *overlay, const char *path)
-{
-	return -ENOSYS;
-}
 #endif
 
 #endif /* __OF_H */
-- 
2.29.2


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


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

* [PATCH v3 08/10] commands: firmwareload: allow loading firmware from dt
  2021-06-15 11:24 [PATCH v3 01/10] reset: add of_reset_control_get to header Steffen Trumtrar
                   ` (5 preceding siblings ...)
  2021-06-15 11:25 ` [PATCH v3 07/10] of: of_firmware: add support for fpga bridges Steffen Trumtrar
@ 2021-06-15 11:25 ` Steffen Trumtrar
  2021-06-15 11:25 ` [PATCH v3 09/10] drivers: firmware: socfpga: remove bridges shutdown Steffen Trumtrar
  2021-06-15 11:25 ` [PATCH v3 10/10] firmware: add support for compressed images Steffen Trumtrar
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Trumtrar @ 2021-06-15 11:25 UTC (permalink / raw)
  To: Barebox List

firmwareload can only load a bitstream into an FPGA without any
knowledge of possible additional needs (e.g. FPGA bridges).

These are defined in the fpga-region nodes in the devicetree. The
fpga-region describes the layout of the FPGA and the bridges it needs
en/disabled.

Add an option to let firmwareload go via the oftree route and load the
firmware that way.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>

---

v2->v3 - remove unused arg 'o'
       - use xstrdup()
---
 commands/firmwareload.c | 39 +++++++++++++++++++++++++++++++++------
 1 file changed, 33 insertions(+), 6 deletions(-)

diff --git a/commands/firmwareload.c b/commands/firmwareload.c
index b735088f6117..c2a017c45479 100644
--- a/commands/firmwareload.c
+++ b/commands/firmwareload.c
@@ -5,18 +5,35 @@
 #include <command.h>
 #include <getopt.h>
 #include <firmware.h>
+#include <of.h>
 
 static int do_firmwareload(int argc, char *argv[])
 {
-	int ret, opt;
+	int opt;
 	const char *name = NULL, *firmware;
 	struct firmware_mgr *mgr;
+	char *path = NULL;
+	char *search_path = NULL;
+	char *compatible = NULL;
+	int oftree = 0;
 
-	while ((opt = getopt(argc, argv, "t:l")) > 0) {
+	while ((opt = getopt(argc, argv, "t:c:S:D:l")) > 0) {
 		switch (opt) {
 		case 't':
 			name = optarg;
 			break;
+		case 'c':
+			compatible = xstrdup(optarg);
+			oftree = 1;
+			break;
+		case 'S':
+			search_path = xstrdup(optarg);
+			oftree = 1;
+			break;
+		case 'D':
+			path = xstrdup(optarg);
+			oftree = 1;
+			break;
 		case 'l':
 			firmwaremgr_list_handlers();
 			return 0;
@@ -25,11 +42,20 @@ static int do_firmwareload(int argc, char *argv[])
 		}
 	}
 
-	if (!(argc - optind))
+	if (!oftree && !(argc - optind))
 		return COMMAND_ERROR_USAGE;
 
 	firmware = argv[optind];
 
+	if (oftree) {
+		if (!search_path && !firmware) {
+			printf("Provide at least a file to load or a search path (-S)\n");
+			return 1;
+		}
+
+		return of_firmware_load_file(path, compatible, search_path, firmware);
+	}
+
 	mgr = firmwaremgr_find(name);
 
 	if (!mgr) {
@@ -38,14 +64,15 @@ static int do_firmwareload(int argc, char *argv[])
 		return 1;
 	}
 
-	ret = firmwaremgr_load_file(mgr, firmware);
-
-	return ret;
+	return firmwaremgr_load_file(mgr, firmware);
 }
 
 BAREBOX_CMD_HELP_START(firmwareload)
 BAREBOX_CMD_HELP_TEXT("Options:")
 BAREBOX_CMD_HELP_OPT("-t <target>", "define the firmware handler by name")
+BAREBOX_CMD_HELP_OPT("-c <compatible>", "type of firmware device (e.g. 'fpga-region')")
+BAREBOX_CMD_HELP_OPT("-D <path>", "load firmware to oftree path")
+BAREBOX_CMD_HELP_OPT("-S <path>", "load firmware using this search path")
 BAREBOX_CMD_HELP_OPT("-l\t", "list devices capable of firmware loading")
 BAREBOX_CMD_HELP_END
 
-- 
2.29.2


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


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

* [PATCH v3 09/10] drivers: firmware: socfpga: remove bridges shutdown
  2021-06-15 11:24 [PATCH v3 01/10] reset: add of_reset_control_get to header Steffen Trumtrar
                   ` (6 preceding siblings ...)
  2021-06-15 11:25 ` [PATCH v3 08/10] commands: firmwareload: allow loading firmware from dt Steffen Trumtrar
@ 2021-06-15 11:25 ` Steffen Trumtrar
  2021-06-15 11:25 ` [PATCH v3 10/10] firmware: add support for compressed images Steffen Trumtrar
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Trumtrar @ 2021-06-15 11:25 UTC (permalink / raw)
  To: Barebox List

The bridges are now handled via the bridges driver. There is no
need to hardcode the memory writes anymore.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/firmware/socfpga.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index 605c931604c9..eb3fc557c7fe 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -294,15 +294,6 @@ static int socfpga_fpgamgr_program_start(struct firmware_handler *fh)
 	/* disable all signals from hps peripheral controller to fpga */
 	writel(0, SYSMGR_FPGAINTF_MODULE);
 
-	/* disable all signals from fpga to hps sdram */
-	writel(0, (CYCLONE5_SDR_ADDRESS + SDR_CTRLGRP_FPGAPORTRST_ADDRESS));
-
-	/* disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
-	writel(~0, CYCLONE5_RSTMGR_ADDRESS + RESET_MGR_BRG_MOD_RESET_OFS);
-
-	/* unmap the bridges from NIC-301 */
-	writel(0x1, CYCLONE5_L3REGS_ADDRESS);
-
 	dev_dbg(&mgr->dev, "start programming...\n");
 
 	/* initialize the FPGA Manager */
-- 
2.29.2


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


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

* [PATCH v3 10/10] firmware: add support for compressed images
  2021-06-15 11:24 [PATCH v3 01/10] reset: add of_reset_control_get to header Steffen Trumtrar
                   ` (7 preceding siblings ...)
  2021-06-15 11:25 ` [PATCH v3 09/10] drivers: firmware: socfpga: remove bridges shutdown Steffen Trumtrar
@ 2021-06-15 11:25 ` Steffen Trumtrar
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Trumtrar @ 2021-06-15 11:25 UTC (permalink / raw)
  To: Barebox List

At least bitstreams for FPGAs can consist of a lot of zeros depending on
device utilization. These bitstreams can be compressed very effectively.

Let the firmware code accept these images and decompress them before
handing it to the firmware-manager in question.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>

---

v2->v3 - better error handling
       - fix free'ing and close'ing
       - remove O_CREAT for devicefd. Destination is always a device
         that shall be written with a firmware (FPGA etc). If it doesn't
         exist, creating it is useless.
---
 common/firmware.c | 52 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 48 insertions(+), 4 deletions(-)

diff --git a/common/firmware.c b/common/firmware.c
index 58509d5da615..47defbd739ca 100644
--- a/common/firmware.c
+++ b/common/firmware.c
@@ -14,6 +14,8 @@
 #include <linux/list.h>
 #include <linux/stat.h>
 #include <linux/err.h>
+#include <uncompress.h>
+#include <filetype.h>
 
 #define BUFSIZ 4096
 
@@ -211,12 +213,54 @@ int firmwaremgr_register(struct firmware_handler *fh)
  */
 int firmwaremgr_load_file(struct firmware_mgr *mgr, const char *firmware)
 {
-	int ret;
-	char *name = basprintf("/dev/%s", mgr->handler->id);
+	char *dst;
+	enum filetype type;
+	int ret = 0;
+	int firmwarefd = 0;
+	int devicefd = 0;
+
+	if (!firmware)
+		return -EINVAL;
+
+	if (!mgr->handler->id) {
+		pr_err("id not defined for handler\n");
+		return -ENODEV;
+	}
+
+	dst = basprintf("/dev/%s", mgr->handler->id);
+
+	type = file_name_detect_type(firmware);
+
+	if (type == filetype_unknown) {
+		ret = copy_file(firmware, dst, 0);
+	} else {
+		firmwarefd = open(firmware, O_RDONLY);
+		if (firmwarefd < 0) {
+			printf("could not open %s: %s\n", firmwarefd,
+			       errno_str());
+			ret = firmwarefd;
+			goto out;
+		}
 
-	ret = copy_file(firmware, name, 0);
+		devicefd = open(dst, O_WRONLY);
+
+		if (devicefd < 0) {
+			printf("could not open %s: %s\n", dst, errno_str());
+			ret = devicefd;
+			goto out;
+		}
+
+		ret = uncompress_fd_to_fd(firmwarefd, devicefd,
+					  uncompress_err_stdout);
+	}
+
+out:
+	free(dst);
 
-	free(name);
+	if (firmwarefd > 0)
+		close(firmwarefd);
+	if (devicefd > 0)
+		close(devicefd);
 
 	return ret;
 }
-- 
2.29.2


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


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

end of thread, other threads:[~2021-06-15 18:31 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-15 11:24 [PATCH v3 01/10] reset: add of_reset_control_get to header Steffen Trumtrar
2021-06-15 11:25 ` [PATCH v3 02/10] drivers: add fpga bridge framework Steffen Trumtrar
2021-06-15 11:25 ` [PATCH v3 03/10] drivers: fpga: add socfpga bridges Steffen Trumtrar
2021-06-15 11:25 ` [PATCH v3 04/10] firmware: socfpga: change function prefixes Steffen Trumtrar
2021-06-15 11:25 ` [PATCH v3 05/10] firmware: import fpga-mgr.h from linux Steffen Trumtrar
2021-06-15 11:25 ` [PATCH v3 06/10] of: kconfig: of_overlay uses firmwaremgr_load_file Steffen Trumtrar
2021-06-15 11:25 ` [PATCH v3 07/10] of: of_firmware: add support for fpga bridges Steffen Trumtrar
2021-06-15 11:25 ` [PATCH v3 08/10] commands: firmwareload: allow loading firmware from dt Steffen Trumtrar
2021-06-15 11:25 ` [PATCH v3 09/10] drivers: firmware: socfpga: remove bridges shutdown Steffen Trumtrar
2021-06-15 11:25 ` [PATCH v3 10/10] firmware: add support for compressed images Steffen Trumtrar

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