* [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd
@ 2021-01-27 13:44 Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 02/12] firmware: socfpga: set APPLYCFG after loading bitstream Steffen Trumtrar
` (10 more replies)
0 siblings, 11 replies; 15+ messages in thread
From: Steffen Trumtrar @ 2021-01-27 13:44 UTC (permalink / raw)
To: barebox
From: Sascha Hauer <s.hauer@pengutronix.de>
When creating a 2nd level page table from a section inherit the flags
from the section rather than assuming the section was mapped cached
previously. This fixes creating a 2nd level pagetable when the section
was mapped differently than we expected.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/cpu/mmu.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index 6af228505dd1..6388e1bf14f6 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -138,6 +138,29 @@ static u32 *arm_create_pte(unsigned long virt, uint32_t flags)
return table;
}
+static u32 pmd_flags_to_pte(u32 pmd)
+{
+ u32 pte = 0;
+
+ if (pmd & PMD_SECT_BUFFERABLE)
+ pte |= PTE_BUFFERABLE;
+ if (pmd & PMD_SECT_CACHEABLE)
+ pte |= PTE_CACHEABLE;
+ if (pmd & PMD_SECT_nG)
+ pte |= PTE_EXT_NG;
+ if (pmd & PMD_SECT_XN)
+ pte |= PTE_EXT_XN;
+
+ /* TEX[2:0] */
+ pte |= PTE_EXT_TEX((pmd >> 12) & 7);
+ /* AP[1:0] */
+ pte |= ((pmd >> 10) & 0x3) << 4;
+ /* AP[2] */
+ pte |= ((pmd >> 15) & 0x1) << 9;
+
+ return pte;
+}
+
int arch_remap_range(void *start, size_t size, unsigned flags)
{
u32 addr = (u32)start;
@@ -206,11 +229,8 @@ int arch_remap_range(void *start, size_t size, unsigned flags)
* If PTE is not found it means that
* we needs to split this section and
* create a new page table for it
- *
- * NOTE: Here we assume that section
- * we just split was mapped as cached
*/
- table = arm_create_pte(addr, pte_flags_cached);
+ table = arm_create_pte(addr, pmd_flags_to_pte(*pgd));
pte = find_pte(addr);
BUG_ON(!pte);
}
--
2.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 02/12] firmware: socfpga: set APPLYCFG after loading bitstream
2021-01-27 13:44 [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd Steffen Trumtrar
@ 2021-01-27 13:44 ` Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 03/12] reset: add of_reset_control_get to header Steffen Trumtrar
` (9 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Steffen Trumtrar @ 2021-01-27 13:44 UTC (permalink / raw)
To: barebox
To make changes to the SDRAM controller effective, the APPLYCFG bit must
be set after programming the bitstream to the FPGA. This has to be done
without any SDRAM usage. Therefore copy the function to execute to the
OCRAM and execute it from there.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
.../mach-socfpga/include/mach/cyclone5-regs.h | 1 +
drivers/firmware/Makefile | 2 +-
drivers/firmware/socfpga.c | 21 +++++++++++++++++++
drivers/firmware/socfpga_sdr.S | 17 +++++++++++++++
4 files changed, 40 insertions(+), 1 deletion(-)
create mode 100644 drivers/firmware/socfpga_sdr.S
diff --git a/arch/arm/mach-socfpga/include/mach/cyclone5-regs.h b/arch/arm/mach-socfpga/include/mach/cyclone5-regs.h
index e88daf718917..1a7d787a27bf 100644
--- a/arch/arm/mach-socfpga/include/mach/cyclone5-regs.h
+++ b/arch/arm/mach-socfpga/include/mach/cyclone5-regs.h
@@ -18,5 +18,6 @@
#define CYCLONE5_SYSMGR_ADDRESS 0xffd08000
#define CYCLONE5_SCANMGR_ADDRESS 0xfff02000
#define CYCLONE5_SMP_TWD_ADDRESS 0xfffec600
+#define CYCLONE5_OCRAM_ADDRESS 0xffff0000
#endif /* __MACH_SOCFPGA_REGS_H */
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index b162b08b0a80..bbd2bcda9780 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_FIRMWARE_ALTERA_SERIAL) += altera_serial.o
-obj-$(CONFIG_FIRMWARE_ALTERA_SOCFPGA) += socfpga.o
+obj-$(CONFIG_FIRMWARE_ALTERA_SOCFPGA) += socfpga.o socfpga_sdr.o
obj-$(CONFIG_FIRMWARE_ZYNQMP_FPGA) += zynqmp-fpga.o
diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index 393c78c45d79..c468c743720f 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -38,6 +38,9 @@
#include <mach/cyclone5-reset-manager.h>
#include <mach/cyclone5-regs.h>
#include <mach/cyclone5-sdram.h>
+#include <asm/fncpy.h>
+#include <mmu.h>
+#include <asm/cache.h>
#define FPGAMGRREGS_STAT 0x0
#define FPGAMGRREGS_CTRL 0x4
@@ -77,6 +80,9 @@
#define CDRATIO_x4 0x2
#define CDRATIO_x8 0x3
+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;
@@ -353,6 +359,9 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
{
struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
int status;
+ unsigned int func_size = &socfpga_sdram_apply_static_cfg_end -
+ &socfpga_sdram_apply_static_cfg;
+ void (*ocram_func)(void __iomem *ocram_base);
/* Ensure the FPGA entering config done */
status = fpgamgr_program_poll_cd(mgr);
@@ -382,6 +391,18 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
return status;
}
+ remap_range((void *)CYCLONE5_OCRAM_ADDRESS, PAGE_SIZE, MAP_CACHED);
+
+ dev_dbg(&mgr->dev, "Setting APPLYCFG bit...\n");
+
+ ocram_func = fncpy((void __iomem *)CYCLONE5_OCRAM_ADDRESS,
+ &socfpga_sdram_apply_static_cfg, func_size);
+
+ sync_caches_for_execution();
+
+ ocram_func((void __iomem *) (CYCLONE5_SDR_ADDRESS +
+ SDR_CTRLGRP_STATICCFG_ADDRESS));
+
return 0;
}
diff --git a/drivers/firmware/socfpga_sdr.S b/drivers/firmware/socfpga_sdr.S
new file mode 100644
index 000000000000..d634d6362722
--- /dev/null
+++ b/drivers/firmware/socfpga_sdr.S
@@ -0,0 +1,17 @@
+#include <linux/linkage.h>
+
+ .arch armv7-a
+ .arm
+
+/*
+ * r0 : sdram controller staticcfg
+ */
+
+ENTRY(socfpga_sdram_apply_static_cfg)
+ push {ip,lr}
+ ldr r1, [r0]
+ orr r1, r1, #8
+ str r1, [r0]
+ pop {ip,pc}
+ .align
+ENTRY(socfpga_sdram_apply_static_cfg_end)
--
2.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 03/12] reset: add of_reset_control_get to header
2021-01-27 13:44 [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 02/12] firmware: socfpga: set APPLYCFG after loading bitstream Steffen Trumtrar
@ 2021-01-27 13:44 ` Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 04/12] drivers: add fpga bridge framework Steffen Trumtrar
` (8 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Steffen Trumtrar @ 2021-01-27 13:44 UTC (permalink / raw)
To: barebox
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 4a92a177bc75..76f40145d949 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.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 04/12] drivers: add fpga bridge framework
2021-01-27 13:44 [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 02/12] firmware: socfpga: set APPLYCFG after loading bitstream Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 03/12] reset: add of_reset_control_get to header Steffen Trumtrar
@ 2021-01-27 13:44 ` Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 05/12] drivers: fpga: add socfpga bridges Steffen Trumtrar
` (7 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Steffen Trumtrar @ 2021-01-27 13:44 UTC (permalink / raw)
To: barebox
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>
---
drivers/Kconfig | 1 +
drivers/Makefile | 1 +
drivers/fpga/Kconfig | 22 ++++
drivers/fpga/Makefile | 6 +
drivers/fpga/fpga-bridge.c | 226 +++++++++++++++++++++++++++++++++++++
include/fpga-bridge.h | 69 +++++++++++
6 files changed, 325 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 dda240578067..3bb9c09536e8 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -36,6 +36,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 5a03bdceab81..5221c2ca5586 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..edf29b0ecf13
--- /dev/null
+++ b/drivers/fpga/fpga-bridge.c
@@ -0,0 +1,226 @@
+/*
+ * 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_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..8d55043a7738
--- /dev/null
+++ b/include/fpga-bridge.h
@@ -0,0 +1,69 @@
+#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);
+#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;
+};
+#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.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 05/12] drivers: fpga: add socfpga bridges
2021-01-27 13:44 [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd Steffen Trumtrar
` (2 preceding siblings ...)
2021-01-27 13:44 ` [PATCH v2 04/12] drivers: add fpga bridge framework Steffen Trumtrar
@ 2021-01-27 13:44 ` Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 06/12] firmware: socfpga: change function prefixes Steffen Trumtrar
` (6 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Steffen Trumtrar @ 2021-01-27 13:44 UTC (permalink / raw)
To: barebox
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 edf29b0ecf13..b5c74a6e63d4 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.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 06/12] firmware: socfpga: change function prefixes
2021-01-27 13:44 [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd Steffen Trumtrar
` (3 preceding siblings ...)
2021-01-27 13:44 ` [PATCH v2 05/12] drivers: fpga: add socfpga bridges Steffen Trumtrar
@ 2021-01-27 13:44 ` Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 07/12] firmware: import fpga-mgr.h from linux Steffen Trumtrar
` (5 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Steffen Trumtrar @ 2021-01-27 13:44 UTC (permalink / raw)
To: barebox
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.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 07/12] firmware: import fpga-mgr.h from linux
2021-01-27 13:44 [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd Steffen Trumtrar
` (4 preceding siblings ...)
2021-01-27 13:44 ` [PATCH v2 06/12] firmware: socfpga: change function prefixes Steffen Trumtrar
@ 2021-01-27 13:44 ` Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 08/12] of: kconfig: of_overlay uses firmwaremgr_load_file Steffen Trumtrar
` (4 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Steffen Trumtrar @ 2021-01-27 13:44 UTC (permalink / raw)
To: barebox
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.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 08/12] of: kconfig: of_overlay uses firmwaremgr_load_file
2021-01-27 13:44 [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd Steffen Trumtrar
` (5 preceding siblings ...)
2021-01-27 13:44 ` [PATCH v2 07/12] firmware: import fpga-mgr.h from linux Steffen Trumtrar
@ 2021-01-27 13:44 ` Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 09/12] of: of_firmware: add support for fpga bridges Steffen Trumtrar
` (3 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Steffen Trumtrar @ 2021-01-27 13:44 UTC (permalink / raw)
To: barebox
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.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 09/12] of: of_firmware: add support for fpga bridges
2021-01-27 13:44 [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd Steffen Trumtrar
` (6 preceding siblings ...)
2021-01-27 13:44 ` [PATCH v2 08/12] of: kconfig: of_overlay uses firmwaremgr_load_file Steffen Trumtrar
@ 2021-01-27 13:44 ` Steffen Trumtrar
2021-01-28 15:10 ` Sascha Hauer
2021-01-27 13:44 ` [PATCH v2 10/12] commands: firmwareload: allow loading firmware from dt Steffen Trumtrar
` (2 subsequent siblings)
10 siblings, 1 reply; 15+ messages in thread
From: Steffen Trumtrar @ 2021-01-27 13:44 UTC (permalink / raw)
To: barebox
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>
---
drivers/of/Makefile | 3 +-
drivers/of/of_firmware.c | 130 +++++++++++++++++++++++++++++++++++++--
include/of.h | 23 +++++--
3 files changed, 143 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..ff5ac60e9fd5 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,33 @@ 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);
+
+ return err;
+}
+
static int load_firmware(struct device_node *target,
struct device_node *fragment, void *data)
{
@@ -33,7 +100,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 +112,73 @@ 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 = basprintf("fpga-region");
+ if (!compatible)
+ return -ENOMEM;
+ }
+
+ /*
+ * 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;
+ }
+
+ root = of_get_root_node();
+
+ if (path) {
+ 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..b18875478dc0 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
+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.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 10/12] commands: firmwareload: allow loading firmware from dt
2021-01-27 13:44 [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd Steffen Trumtrar
` (7 preceding siblings ...)
2021-01-27 13:44 ` [PATCH v2 09/12] of: of_firmware: add support for fpga bridges Steffen Trumtrar
@ 2021-01-27 13:44 ` Steffen Trumtrar
2021-01-28 15:16 ` Sascha Hauer
2021-01-27 13:44 ` [PATCH v2 11/12] drivers: firmware: socfpga: remove bridges shutdown Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 12/12] firmware: add support for compressed images Steffen Trumtrar
10 siblings, 1 reply; 15+ messages in thread
From: Steffen Trumtrar @ 2021-01-27 13:44 UTC (permalink / raw)
To: barebox
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>
---
commands/firmwareload.c | 42 +++++++++++++++++++++++++++++++++++------
1 file changed, 36 insertions(+), 6 deletions(-)
diff --git a/commands/firmwareload.c b/commands/firmwareload.c
index b735088f6117..2b1e770662d1 100644
--- a/commands/firmwareload.c
+++ b/commands/firmwareload.c
@@ -5,18 +5,38 @@
#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:lo")) > 0) {
switch (opt) {
case 't':
name = optarg;
break;
+ case 'c':
+ compatible = xzalloc(strlen(optarg) + 1);
+ strcpy(compatible, optarg);
+ oftree = 1;
+ break;
+ case 'S':
+ search_path = xzalloc(strlen(optarg) + 1);
+ strcpy(search_path, optarg);
+ oftree = 1;
+ break;
+ case 'D':
+ path = xzalloc(strlen(optarg) + 1);
+ strcpy(path, optarg);
+ oftree = 1;
+ break;
case 'l':
firmwaremgr_list_handlers();
return 0;
@@ -25,11 +45,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 +67,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.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 11/12] drivers: firmware: socfpga: remove bridges shutdown
2021-01-27 13:44 [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd Steffen Trumtrar
` (8 preceding siblings ...)
2021-01-27 13:44 ` [PATCH v2 10/12] commands: firmwareload: allow loading firmware from dt Steffen Trumtrar
@ 2021-01-27 13:44 ` Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 12/12] firmware: add support for compressed images Steffen Trumtrar
10 siblings, 0 replies; 15+ messages in thread
From: Steffen Trumtrar @ 2021-01-27 13:44 UTC (permalink / raw)
To: barebox
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.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 12/12] firmware: add support for compressed images
2021-01-27 13:44 [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd Steffen Trumtrar
` (9 preceding siblings ...)
2021-01-27 13:44 ` [PATCH v2 11/12] drivers: firmware: socfpga: remove bridges shutdown Steffen Trumtrar
@ 2021-01-27 13:44 ` Steffen Trumtrar
2021-01-28 15:27 ` Sascha Hauer
10 siblings, 1 reply; 15+ messages in thread
From: Steffen Trumtrar @ 2021-01-27 13:44 UTC (permalink / raw)
To: barebox
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>
---
common/firmware.c | 43 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 38 insertions(+), 5 deletions(-)
diff --git a/common/firmware.c b/common/firmware.c
index 58509d5da615..c617ecc0f129 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,43 @@ 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);
-
- ret = copy_file(firmware, name, 0);
+ char *dst;
+ enum filetype type;
+ int ret = -ENOENT;
+ int srcfd = 0;
+ int dstfd = 0;
+
+ if (mgr->handler->id) {
+ dst = basprintf("/dev/%s", mgr->handler->id);
+ } else {
+ pr_err("id not defined for handler\n");
+ return -ENODEV;
+ }
- free(name);
+ if (firmware) {
+ type = file_name_detect_type(firmware);
+ if (type == filetype_unknown) {
+ ret = copy_file(firmware, dst, 0);
+ } else {
+ srcfd = open(firmware, O_RDONLY);
+ if (srcfd < 0)
+ return srcfd;
+ dstfd = open(dst, O_WRONLY | O_CREAT);
+
+ if (dstfd < 0) {
+ printf("could not open %s: %s\n", dst, errno_str());
+ ret = dstfd;
+ goto out;
+ }
+
+ ret = uncompress_fd_to_fd(srcfd, dstfd, uncompress_err_stdout);
+
+ close(dstfd);
+ }
+ }
+out:
+ close(srcfd);
+ free(dst);
return ret;
}
--
2.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 09/12] of: of_firmware: add support for fpga bridges
2021-01-27 13:44 ` [PATCH v2 09/12] of: of_firmware: add support for fpga bridges Steffen Trumtrar
@ 2021-01-28 15:10 ` Sascha Hauer
0 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2021-01-28 15:10 UTC (permalink / raw)
To: Steffen Trumtrar; +Cc: barebox
On Wed, Jan 27, 2021 at 02:44:20PM +0100, Steffen Trumtrar wrote:
> +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);
The resources added to this list are never freed.
> +
> + return err;
> +}
> +
> static int load_firmware(struct device_node *target,
> struct device_node *fragment, void *data)
> {
> @@ -33,7 +100,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 +112,73 @@ 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 = basprintf("fpga-region");
> + if (!compatible)
> + return -ENOMEM;
> + }
compatible is not freed. The original pointer comes in as a const char *,
allocated and freed outside of this function, so you can do a plain
if (!compatible)
comaptible = "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;
> + }
> +
> + root = of_get_root_node();
root is only used in the if () path below, so you can assign it there.
> +
> + if (path) {
> + 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..b18875478dc0 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
> +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.20.1
>
>
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
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] 15+ messages in thread
* Re: [PATCH v2 10/12] commands: firmwareload: allow loading firmware from dt
2021-01-27 13:44 ` [PATCH v2 10/12] commands: firmwareload: allow loading firmware from dt Steffen Trumtrar
@ 2021-01-28 15:16 ` Sascha Hauer
0 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2021-01-28 15:16 UTC (permalink / raw)
To: Steffen Trumtrar; +Cc: barebox
On Wed, Jan 27, 2021 at 02:44:21PM +0100, Steffen Trumtrar wrote:
> 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>
> ---
> commands/firmwareload.c | 42 +++++++++++++++++++++++++++++++++++------
> 1 file changed, 36 insertions(+), 6 deletions(-)
>
> diff --git a/commands/firmwareload.c b/commands/firmwareload.c
> index b735088f6117..2b1e770662d1 100644
> --- a/commands/firmwareload.c
> +++ b/commands/firmwareload.c
> @@ -5,18 +5,38 @@
> #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:lo")) > 0) {
'o' is added but not handled.
> switch (opt) {
> case 't':
> name = optarg;
> break;
> + case 'c':
> + compatible = xzalloc(strlen(optarg) + 1);
> + strcpy(compatible, optarg);
Use xstrdup(). The string is not freed.
> + oftree = 1;
> + break;
> + case 'S':
> + search_path = xzalloc(strlen(optarg) + 1);
> + strcpy(search_path, optarg);
ditto
> + oftree = 1;
> + break;
> + case 'D':
> + path = xzalloc(strlen(optarg) + 1);
> + strcpy(path, optarg);
ditto
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
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] 15+ messages in thread
* Re: [PATCH v2 12/12] firmware: add support for compressed images
2021-01-27 13:44 ` [PATCH v2 12/12] firmware: add support for compressed images Steffen Trumtrar
@ 2021-01-28 15:27 ` Sascha Hauer
0 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2021-01-28 15:27 UTC (permalink / raw)
To: Steffen Trumtrar; +Cc: barebox
On Wed, Jan 27, 2021 at 02:44:23PM +0100, Steffen Trumtrar wrote:
> 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>
> ---
> common/firmware.c | 43 ++++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 38 insertions(+), 5 deletions(-)
>
> diff --git a/common/firmware.c b/common/firmware.c
> index 58509d5da615..c617ecc0f129 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,43 @@ 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);
> -
> - ret = copy_file(firmware, name, 0);
> + char *dst;
> + enum filetype type;
> + int ret = -ENOENT;
> + int srcfd = 0;
> + int dstfd = 0;
> +
> + if (mgr->handler->id) {
> + dst = basprintf("/dev/%s", mgr->handler->id);
> + } else {
> + pr_err("id not defined for handler\n");
> + return -ENODEV;
> + }
I'd do the error handling for !mgr->handler->id first, then the dst =
basprintf(...) doesn't have to be done conditionally.
>
> - free(name);
> + if (firmware) {
This function seems to do nothing when firmware is not given. Is this
the correct behaviour? If yes, then you could bail out early instead of
putting the rest of the function inside an if() {}
> + type = file_name_detect_type(firmware);
> + if (type == filetype_unknown) {
> + ret = copy_file(firmware, dst, 0);
When going this way srcfd is closed below, but never opened.
> + } else {
> + srcfd = open(firmware, O_RDONLY);
> + if (srcfd < 0)
> + return srcfd;
'dst' is not freed here.
> + dstfd = open(dst, O_WRONLY | O_CREAT);
You'll probably want to add a O_TRUNC here because otherwise if the file
existed before and was bigger than the data you gonna write to it you'll
have garbage at the end of the file.
OTOH I don't know what 'dst' is. When this could be a device file then
truncating it will fail.
> +
> + if (dstfd < 0) {
> + printf("could not open %s: %s\n", dst, errno_str());
> + ret = dstfd;
> + goto out;
> + }
> +
> + ret = uncompress_fd_to_fd(srcfd, dstfd, uncompress_err_stdout);
> +
> + close(dstfd);
> + }
> + }
> +out:
> + close(srcfd);
> + free(dst);
>
> return ret;
> }
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
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] 15+ messages in thread
end of thread, other threads:[~2021-01-28 15:27 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-27 13:44 [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 02/12] firmware: socfpga: set APPLYCFG after loading bitstream Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 03/12] reset: add of_reset_control_get to header Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 04/12] drivers: add fpga bridge framework Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 05/12] drivers: fpga: add socfpga bridges Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 06/12] firmware: socfpga: change function prefixes Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 07/12] firmware: import fpga-mgr.h from linux Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 08/12] of: kconfig: of_overlay uses firmwaremgr_load_file Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 09/12] of: of_firmware: add support for fpga bridges Steffen Trumtrar
2021-01-28 15:10 ` Sascha Hauer
2021-01-27 13:44 ` [PATCH v2 10/12] commands: firmwareload: allow loading firmware from dt Steffen Trumtrar
2021-01-28 15:16 ` Sascha Hauer
2021-01-27 13:44 ` [PATCH v2 11/12] drivers: firmware: socfpga: remove bridges shutdown Steffen Trumtrar
2021-01-27 13:44 ` [PATCH v2 12/12] firmware: add support for compressed images Steffen Trumtrar
2021-01-28 15:27 ` Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox