summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-06-08 21:26:50 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-06-08 21:26:50 +0200
commitb23338788b937ccc278b62b6286438ca10a896a6 (patch)
treeed086e07e792b912be61ca47106b28670425c2e9
parent099b02d3ddabc4b1764976670816621ee82ea656 (diff)
parent43a1974da6bc7ce8f4d1dc1d03d56997428c29c3 (diff)
downloadlinux-next-b23338788b937ccc278b62b6286438ca10a896a6.tar.gz
linux-next-b23338788b937ccc278b62b6286438ca10a896a6.zip
Merge tag 'fpga-for-7.2-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/fpga/linux-fpga into char-misc-next
Xu writes: FPGA Manager changes for 7.2-rc1 - Wentao fixes use-after-free issue in of-fpga-region - Phil adds the of matching for Altera ts73xx fpga driver - Ian adds Efinix FPGA SPI programming driver - Andy fixes several minor issues for Lattice FPGA driver - Manish converts dt-bindings to YAML schema for several Altera devices - Sebastian fixes several minor issues for Intel DFL & Microchip FPGAs All patches have been reviewed on the mailing list, and have been in the last linux-next releases (as part of our for-next branch). Signed-off-by: Xu Yilun <yilun.xu@intel.com> * tag 'fpga-for-7.2-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/fpga/linux-fpga: fpga: microchip-spi: fix zero header_size OOB read in mpf_ops_parse_header() fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() fpga: dfl: add bounds check in dfh_get_param_size() dt-bindings: fpga: altr,socfpga-fpga-mgr: convert to DT schema dt-bindings: fpga: altr,a10-pr-ip: convert to DT schema fpga: lattice-sysconfig-spi: simplify with spi_get_device_match_data() fpga: lattice-sysconfig-spi: Don't use "proxy" headers fpga: lattice-sysconfig-spi: Drop of_match_ptr() protection fpga: lattice-sysconfig-spi: Fix the terminator entries in ID tables fpga-mgr: Add Efinix SPI programming driver dt-bindings: fpga: Add Efinix SPI programming bindings dt-bindings: vendor-prefix: Add prefix for Efinix, Inc. fpga: ts73xx-fpga: add OF match table for device tree probing dt-bindings: fpga: Add Technologic Systems TS-7300 FPGA Manager fpga: region: fix use-after-free in child_regions_with_firmware()
-rw-r--r--Documentation/devicetree/bindings/fpga/altera-pr-ip.txt12
-rw-r--r--Documentation/devicetree/bindings/fpga/altera-socfpga-fpga-mgr.txt17
-rw-r--r--Documentation/devicetree/bindings/fpga/altr,a10-pr-ip.yaml34
-rw-r--r--Documentation/devicetree/bindings/fpga/altr,socfpga-fpga-mgr.yaml38
-rw-r--r--Documentation/devicetree/bindings/fpga/efinix,trion-config.yaml98
-rw-r--r--Documentation/devicetree/bindings/fpga/technologic,ts7300-fpga.yaml36
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.yaml2
-rw-r--r--drivers/fpga/Kconfig7
-rw-r--r--drivers/fpga/Makefile1
-rw-r--r--drivers/fpga/dfl-afu-main.c3
-rw-r--r--drivers/fpga/dfl.c2
-rw-r--r--drivers/fpga/efinix-spi.c260
-rw-r--r--drivers/fpga/lattice-sysconfig-spi.c29
-rw-r--r--drivers/fpga/microchip-spi.c3
-rw-r--r--drivers/fpga/of-fpga-region.c3
-rw-r--r--drivers/fpga/ts73xx-fpga.c9
16 files changed, 507 insertions, 47 deletions
diff --git a/Documentation/devicetree/bindings/fpga/altera-pr-ip.txt b/Documentation/devicetree/bindings/fpga/altera-pr-ip.txt
deleted file mode 100644
index 52a294cf2730..000000000000
--- a/Documentation/devicetree/bindings/fpga/altera-pr-ip.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-Altera Arria10 Partial Reconfiguration IP
-
-Required properties:
-- compatible : should contain "altr,a10-pr-ip"
-- reg : base address and size for memory mapped io.
-
-Example:
-
- fpga_mgr: fpga-mgr@ff20c000 {
- compatible = "altr,a10-pr-ip";
- reg = <0xff20c000 0x10>;
- };
diff --git a/Documentation/devicetree/bindings/fpga/altera-socfpga-fpga-mgr.txt b/Documentation/devicetree/bindings/fpga/altera-socfpga-fpga-mgr.txt
deleted file mode 100644
index d52f3340414d..000000000000
--- a/Documentation/devicetree/bindings/fpga/altera-socfpga-fpga-mgr.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Altera SOCFPGA FPGA Manager
-
-Required properties:
-- compatible : should contain "altr,socfpga-fpga-mgr"
-- reg : base address and size for memory mapped io.
- - The first index is for FPGA manager register access.
- - The second index is for writing FPGA configuration data.
-- interrupts : interrupt for the FPGA Manager device.
-
-Example:
-
- hps_0_fpgamgr: fpgamgr@ff706000 {
- compatible = "altr,socfpga-fpga-mgr";
- reg = <0xFF706000 0x1000
- 0xFFB90000 0x1000>;
- interrupts = <0 175 4>;
- };
diff --git a/Documentation/devicetree/bindings/fpga/altr,a10-pr-ip.yaml b/Documentation/devicetree/bindings/fpga/altr,a10-pr-ip.yaml
new file mode 100644
index 000000000000..1f4df40308bd
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/altr,a10-pr-ip.yaml
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/fpga/altr,a10-pr-ip.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Altera Arria10 Partial Reconfiguration IP
+
+maintainers:
+ - Matthew Gerlach <matthew.gerlach@linux.intel.com>
+
+description:
+ The Altera Arria 10 Partial Reconfiguration IP core allows the host
+ processor to perform partial reconfiguration of the FPGA fabric.
+
+properties:
+ compatible:
+ const: altr,a10-pr-ip
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ fpga-mgr@ff20c000 {
+ compatible = "altr,a10-pr-ip";
+ reg = <0xff20c000 0x10>;
+ };
diff --git a/Documentation/devicetree/bindings/fpga/altr,socfpga-fpga-mgr.yaml b/Documentation/devicetree/bindings/fpga/altr,socfpga-fpga-mgr.yaml
new file mode 100644
index 000000000000..9bcc1200d61d
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/altr,socfpga-fpga-mgr.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/fpga/altr,socfpga-fpga-mgr.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Altera SOCFPGA FPGA Manager
+
+maintainers:
+ - Steffen Trumtrar <s.trumtrar@pengutronix.de>
+
+properties:
+ compatible:
+ const: altr,socfpga-fpga-mgr
+
+ reg:
+ items:
+ - description: FPGA manager register access
+ - description: Writing FPGA configuration data
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ fpgamgr@ff706000 {
+ compatible = "altr,socfpga-fpga-mgr";
+ reg = <0xff706000 0x1000>,
+ <0xffb90000 0x1000>;
+ interrupts = <0 175 4>;
+ };
diff --git a/Documentation/devicetree/bindings/fpga/efinix,trion-config.yaml b/Documentation/devicetree/bindings/fpga/efinix,trion-config.yaml
new file mode 100644
index 000000000000..7c7444ff9c3a
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/efinix,trion-config.yaml
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/fpga/efinix,trion-config.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Efinix SPI FPGA Manager
+
+maintainers:
+ - Ian Dannapel <iansdannapel@gmail.com>
+
+description: |
+ Efinix FPGAs (Trion, Topaz, and Titanium families) support loading bitstreams
+ through "SPI Passive Mode".
+ Additional pin hogs for bus width configuration should be set
+ elsewhere, if necessary.
+
+ References:
+ - https://www.efinixinc.com/docs/an006-configuring-trion-fpgas-v6.3.pdf
+ - https://www.efinixinc.com/docs/an033-configuring-titanium-fpgas-v2.8.pdf
+ - https://www.efinixinc.com/docs/an061-configuring-topaz-fpgas-v1.1.pdf
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - efinix,titanium-config
+ - efinix,topaz-config
+ - const: efinix,trion-config
+ - const: efinix,trion-config
+
+ spi-cpha: true
+
+ spi-cpol: true
+
+ spi-max-frequency:
+ maximum: 25000000
+
+ reg:
+ maxItems: 1
+
+ reset-gpios:
+ description:
+ reset and re-configuration trigger pin (low active)
+ maxItems: 1
+
+ cdone-gpios:
+ description:
+ optional configuration done status pin (high active)
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - reset-gpios
+ - spi-cpha
+ - spi-cpol
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+ fpga-mgr@0 {
+ compatible = "efinix,trion-config";
+ reg = <0>;
+ spi-max-frequency = <25000000>;
+ spi-cpha;
+ spi-cpol;
+ reset-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>;
+ cdone-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
+ };
+ };
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+ fpga-mgr@0 {
+ compatible = "efinix,titanium-config", "efinix,trion-config";
+ reg = <0>;
+ spi-max-frequency = <25000000>;
+ spi-cpha;
+ spi-cpol;
+ reset-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>;
+ cdone-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/fpga/technologic,ts7300-fpga.yaml b/Documentation/devicetree/bindings/fpga/technologic,ts7300-fpga.yaml
new file mode 100644
index 000000000000..c93e3a1a135b
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/technologic,ts7300-fpga.yaml
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/fpga/technologic,ts7300-fpga.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Technologic Systems TS-7300 FPGA Manager
+
+maintainers:
+ - Florian Fainelli <f.fainelli@gmail.com>
+
+description:
+ FPGA manager for the Altera Cyclone II FPGA on Technologic Systems
+ TS-7300 board. The FPGA is programmed via the memory-mapped interface
+ implemented in the CPLD.
+
+properties:
+ compatible:
+ const: technologic,ts7300-fpga
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ fpga-mgr@13c00000 {
+ compatible = "technologic,ts7300-fpga";
+ reg = <0x13c00000 0x2>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 28784d66ae7b..f42f2d9dad4d 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -489,6 +489,8 @@ patternProperties:
description: Emtop Embedded Solutions
"^eeti,.*":
description: eGalax_eMPIA Technology Inc
+ "^efinix,.*":
+ description: Efinix, Inc.
"^egnite,.*":
description: egnite GmbH
"^einfochips,.*":
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 37b35f58f0df..748fc210c135 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -288,6 +288,13 @@ config FPGA_MGR_LATTICE_SYSCONFIG_SPI
FPGA manager driver support for Lattice FPGAs programming over slave
SPI sysCONFIG interface.
+config FPGA_MGR_EFINIX_SPI
+ tristate "Efinix FPGA configuration over SPI"
+ depends on SPI
+ help
+ FPGA manager driver support for Efinix FPGAs configuration over SPI
+ (passive mode only).
+
source "drivers/fpga/tests/Kconfig"
endif # FPGA
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index aeb89bb13517..6f5798b27e0d 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_FPGA_MGR_LATTICE_SYSCONFIG) += lattice-sysconfig.o
obj-$(CONFIG_FPGA_MGR_LATTICE_SYSCONFIG_SPI) += lattice-sysconfig-spi.o
obj-$(CONFIG_ALTERA_PR_IP_CORE) += altera-pr-ip-core.o
obj-$(CONFIG_ALTERA_PR_IP_CORE_PLAT) += altera-pr-ip-core-plat.o
+obj-$(CONFIG_FPGA_MGR_EFINIX_SPI) += efinix-spi.o
# FPGA Secure Update Drivers
obj-$(CONFIG_FPGA_M10_BMC_SEC_UPDATE) += intel-m10-bmc-sec-update.o
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 3bf8e7338dbe..097a97eeea66 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -723,6 +723,9 @@ afu_ioctl_dma_map(struct dfl_feature_dev_data *fdata, void __user *arg)
if (map.argsz < minsz || map.flags)
return -EINVAL;
+ if (map.length >> PAGE_SHIFT > (u64)INT_MAX)
+ return -EINVAL;
+
ret = afu_dma_map_region(fdata, map.user_addr, map.length, &map.iova);
if (ret)
return ret;
diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
index 4087a36a0571..4c63c7c8579b 100644
--- a/drivers/fpga/dfl.c
+++ b/drivers/fpga/dfl.c
@@ -1132,6 +1132,8 @@ static int dfh_get_param_size(void __iomem *dfh_base, resource_size_t max)
return -EINVAL;
size += next * sizeof(u64);
+ if (size > max)
+ return -EINVAL;
if (FIELD_GET(DFHv1_PARAM_HDR_NEXT_EOP, v))
return size;
diff --git a/drivers/fpga/efinix-spi.c b/drivers/fpga/efinix-spi.c
new file mode 100644
index 000000000000..ed9a41232a32
--- /dev/null
+++ b/drivers/fpga/efinix-spi.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * FPGA Manager Driver for Efinix
+ *
+ * Copyright (C) 2025 iris-GmbH infrared & intelligent sensors
+ *
+ * Ian Dannapel <iansdannapel@gmail.com>
+ *
+ * Load Efinix FPGA firmware over SPI using the serial configuration interface.
+ *
+ * Note: Only passive mode (host initiates transfer) is currently supported.
+ */
+
+#include <linux/delay.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/spi/spi.h>
+
+/*
+ * 13 dummy bytes generate 104 SPI clock cycles (8 bits each).
+ * Used to meet the requirement for >100 clock cycles idle sequence.
+ */
+#define EFINIX_SPI_IDLE_CYCLES_BYTES 13
+
+/*
+ * tDMIN: Minimum time between deassertion of CRESET_N to first
+ * valid configuration data. (32 µs)
+ */
+#define EFINIX_TDMIN_US_MIN 35
+#define EFINIX_TDMIN_US_MAX 40
+
+/*
+ * tCRESET_N: Minimum CRESET_N low pulse width required to
+ * trigger re-configuration. (320 ns)
+ */
+#define EFINIX_TCRESETN_DELAY_MIN_US 1
+#define EFINIX_TCRESETN_DELAY_MAX_US 2
+
+/*
+ * tUSER: Minimum configuration duration after CDONE goes high
+ * before entering user mode. (25 µs)
+ */
+#define EFINIX_TUSER_US_MIN 30
+#define EFINIX_TUSER_US_MAX 35
+
+struct efinix_spi_conf {
+ struct spi_device *spi;
+ struct gpio_desc *cdone;
+ struct gpio_desc *reset;
+};
+
+static void efinix_spi_reset(struct efinix_spi_conf *conf)
+{
+ gpiod_set_value(conf->reset, 1);
+ usleep_range(EFINIX_TCRESETN_DELAY_MIN_US, EFINIX_TCRESETN_DELAY_MAX_US);
+ gpiod_set_value(conf->reset, 0);
+ usleep_range(EFINIX_TDMIN_US_MIN, EFINIX_TDMIN_US_MAX);
+}
+
+static enum fpga_mgr_states efinix_spi_state(struct fpga_manager *mgr)
+{
+ struct efinix_spi_conf *conf = mgr->priv;
+
+ if (conf->cdone && gpiod_get_value(conf->cdone) == 1)
+ return FPGA_MGR_STATE_OPERATING;
+
+ return FPGA_MGR_STATE_UNKNOWN;
+}
+
+static int efinix_spi_write_init(struct fpga_manager *mgr,
+ struct fpga_image_info *info,
+ const char *buf, size_t count)
+{
+ struct efinix_spi_conf *conf = mgr->priv;
+ struct spi_transfer assert_cs = {
+ /* Keep CS asserted across configuration. */
+ .cs_change = 1,
+ };
+ struct spi_message message;
+ int ret;
+
+ if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
+ dev_err(&mgr->dev, "Partial reconfiguration not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ /*
+ * Efinix passive SPI configuration requires chip select to stay
+ * asserted from reset until the bitstream is fully clocked in.
+ * Lock the SPI bus so no other device can toggle CS between the
+ * reset pulse and the write/complete transfers.
+ */
+ spi_bus_lock(conf->spi->controller);
+ spi_message_init_with_transfers(&message, &assert_cs, 1);
+ ret = spi_sync_locked(conf->spi, &message);
+ if (ret) {
+ spi_bus_unlock(conf->spi->controller);
+ return ret;
+ }
+
+ /* Reset with CS asserted */
+ efinix_spi_reset(conf);
+
+ return 0;
+}
+
+static int efinix_spi_write(struct fpga_manager *mgr, const char *buf,
+ size_t count)
+{
+ struct spi_transfer write_xfer = {
+ .tx_buf = buf,
+ .len = count,
+ .cs_change = 1,
+ };
+ struct efinix_spi_conf *conf = mgr->priv;
+ struct spi_message message;
+ int ret;
+
+ spi_message_init_with_transfers(&message, &write_xfer, 1);
+ ret = spi_sync_locked(conf->spi, &message);
+ if (ret) {
+ dev_err(&mgr->dev, "SPI error in firmware write: %d\n", ret);
+ spi_bus_unlock(conf->spi->controller);
+ }
+
+ return ret;
+}
+
+static int efinix_spi_write_complete(struct fpga_manager *mgr,
+ struct fpga_image_info *info)
+{
+ unsigned long timeout =
+ jiffies + usecs_to_jiffies(info->config_complete_timeout_us);
+ struct spi_transfer clk_cycles = {
+ .len = EFINIX_SPI_IDLE_CYCLES_BYTES,
+ /* Release CS after the trailing idle clocks are sent. */
+ .cs_change = 0,
+ };
+ struct efinix_spi_conf *conf = mgr->priv;
+ struct spi_message message;
+ int done, ret;
+ bool expired = false;
+ u8 *dummy_buf;
+
+ dummy_buf = kzalloc(EFINIX_SPI_IDLE_CYCLES_BYTES, GFP_KERNEL);
+ if (!dummy_buf) {
+ ret = -ENOMEM;
+ goto unlock_spi;
+ }
+
+ /*
+ * Keep the bus locked while sending the trailing idle clocks, then
+ * let this final transfer deassert CS to terminate configuration.
+ */
+ clk_cycles.tx_buf = dummy_buf;
+ spi_message_init_with_transfers(&message, &clk_cycles, 1);
+ ret = spi_sync_locked(conf->spi, &message);
+ if (ret) {
+ dev_err(&mgr->dev, "SPI error in write complete: %d\n", ret);
+ goto free_buf;
+ }
+
+ if (conf->cdone) {
+ while (!expired) {
+ done = gpiod_get_value(conf->cdone);
+ if (done < 0) {
+ ret = done;
+ goto free_buf;
+ }
+ if (done)
+ break;
+
+ usleep_range(10, 20);
+ expired = time_after(jiffies, timeout);
+ }
+
+ if (expired) {
+ dev_err(&mgr->dev, "Timeout waiting for CDONE\n");
+ ret = -ETIMEDOUT;
+ goto free_buf;
+ }
+ }
+
+ usleep_range(EFINIX_TUSER_US_MIN, EFINIX_TUSER_US_MAX);
+
+free_buf:
+ kfree(dummy_buf);
+unlock_spi:
+ spi_bus_unlock(conf->spi->controller);
+
+ return ret;
+}
+
+static const struct fpga_manager_ops efinix_spi_ops = {
+ .state = efinix_spi_state,
+ .write_init = efinix_spi_write_init,
+ .write = efinix_spi_write,
+ .write_complete = efinix_spi_write_complete,
+};
+
+static int efinix_spi_probe(struct spi_device *spi)
+{
+ struct efinix_spi_conf *conf;
+ struct fpga_manager *mgr;
+
+ if (!(spi->mode & SPI_CPHA) || !(spi->mode & SPI_CPOL))
+ return dev_err_probe(&spi->dev, -EINVAL,
+ "Unsupported SPI mode, set CPHA and CPOL\n");
+
+ conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL);
+ if (!conf)
+ return -ENOMEM;
+
+ conf->reset = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(conf->reset))
+ return dev_err_probe(&spi->dev, PTR_ERR(conf->reset),
+ "Failed to get RESET gpio\n");
+
+ conf->cdone = devm_gpiod_get_optional(&spi->dev, "cdone", GPIOD_IN);
+ if (IS_ERR(conf->cdone))
+ return dev_err_probe(&spi->dev, PTR_ERR(conf->cdone),
+ "Failed to get CDONE gpio\n");
+
+ conf->spi = spi;
+
+ mgr = devm_fpga_mgr_register(&spi->dev,
+ "Efinix FPGA Manager",
+ &efinix_spi_ops, conf);
+
+ return PTR_ERR_OR_ZERO(mgr);
+}
+
+static const struct of_device_id efinix_spi_of_match[] = {
+ { .compatible = "efinix,trion-config", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, efinix_spi_of_match);
+
+static const struct spi_device_id efinix_ids[] = {
+ { "trion-config", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(spi, efinix_ids);
+
+static struct spi_driver efinix_spi_driver = {
+ .driver = {
+ .name = "efinix-spi",
+ .of_match_table = efinix_spi_of_match,
+ },
+ .probe = efinix_spi_probe,
+ .id_table = efinix_ids,
+};
+
+module_spi_driver(efinix_spi_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ian Dannapel <iansdannapel@gmail.com>");
+MODULE_DESCRIPTION("Efinix FPGA SPI Programming Driver");
diff --git a/drivers/fpga/lattice-sysconfig-spi.c b/drivers/fpga/lattice-sysconfig-spi.c
index 44691cfcf50a..5d195602b261 100644
--- a/drivers/fpga/lattice-sysconfig-spi.c
+++ b/drivers/fpga/lattice-sysconfig-spi.c
@@ -3,8 +3,14 @@
* Lattice FPGA programming over slave SPI sysCONFIG interface.
*/
-#include <linux/of.h>
+#include <linux/dev_printk.h>
+#include <linux/device/devres.h>
+#include <linux/errno.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/slab.h>
#include <linux/spi/spi.h>
+#include <linux/types.h>
#include "lattice-sysconfig.h"
@@ -85,7 +91,6 @@ static int sysconfig_spi_bitstream_burst_complete(struct sysconfig_priv *priv)
static int sysconfig_spi_probe(struct spi_device *spi)
{
- const struct spi_device_id *dev_id;
struct device *dev = &spi->dev;
struct sysconfig_priv *priv;
const u32 *spi_max_speed;
@@ -94,15 +99,7 @@ static int sysconfig_spi_probe(struct spi_device *spi)
if (!priv)
return -ENOMEM;
- spi_max_speed = device_get_match_data(dev);
- if (!spi_max_speed) {
- dev_id = spi_get_device_id(spi);
- if (!dev_id)
- return -ENODEV;
-
- spi_max_speed = (const u32 *)dev_id->driver_data;
- }
-
+ spi_max_speed = spi_get_device_match_data(spi);
if (!spi_max_speed)
return -EINVAL;
@@ -125,26 +122,26 @@ static const struct spi_device_id sysconfig_spi_ids[] = {
{
.name = "sysconfig-ecp5",
.driver_data = (kernel_ulong_t)&ecp5_spi_max_speed_hz,
- }, {},
+ },
+ {}
};
MODULE_DEVICE_TABLE(spi, sysconfig_spi_ids);
-#if IS_ENABLED(CONFIG_OF)
static const struct of_device_id sysconfig_of_ids[] = {
{
.compatible = "lattice,sysconfig-ecp5",
.data = &ecp5_spi_max_speed_hz,
- }, {},
+ },
+ {}
};
MODULE_DEVICE_TABLE(of, sysconfig_of_ids);
-#endif /* IS_ENABLED(CONFIG_OF) */
static struct spi_driver lattice_sysconfig_driver = {
.probe = sysconfig_spi_probe,
.id_table = sysconfig_spi_ids,
.driver = {
.name = "lattice_sysconfig_spi_fpga_mgr",
- .of_match_table = of_match_ptr(sysconfig_of_ids),
+ .of_match_table = sysconfig_of_ids,
},
};
module_spi_driver(lattice_sysconfig_driver);
diff --git a/drivers/fpga/microchip-spi.c b/drivers/fpga/microchip-spi.c
index 6134cea86ac8..cc8f6d7bb978 100644
--- a/drivers/fpga/microchip-spi.c
+++ b/drivers/fpga/microchip-spi.c
@@ -116,6 +116,9 @@ static int mpf_ops_parse_header(struct fpga_manager *mgr,
}
header_size = *(buf + MPF_HEADER_SIZE_OFFSET);
+ if (!header_size)
+ return -EINVAL;
+
if (header_size > count) {
info->header_size = header_size;
return -EAGAIN;
diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c
index caa091224dc5..9107a5b461d3 100644
--- a/drivers/fpga/of-fpga-region.c
+++ b/drivers/fpga/of-fpga-region.c
@@ -168,11 +168,10 @@ static int child_regions_with_firmware(struct device_node *overlay)
fpga_region_of_match);
}
- of_node_put(child_region);
-
if (ret)
pr_err("firmware-name not allowed in child FPGA region: %pOF",
child_region);
+ of_node_put(child_region);
return ret;
}
diff --git a/drivers/fpga/ts73xx-fpga.c b/drivers/fpga/ts73xx-fpga.c
index 4e1d2a4d3df4..3460e4809f86 100644
--- a/drivers/fpga/ts73xx-fpga.c
+++ b/drivers/fpga/ts73xx-fpga.c
@@ -11,6 +11,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/iopoll.h>
@@ -119,9 +120,17 @@ static int ts73xx_fpga_probe(struct platform_device *pdev)
return PTR_ERR_OR_ZERO(mgr);
}
+static const struct of_device_id ts73xx_fpga_of_match[] = {
+ { .compatible = "technologic,ts7300-fpga" },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, ts73xx_fpga_of_match);
+
static struct platform_driver ts73xx_fpga_driver = {
.driver = {
.name = "ts73xx-fpga-mgr",
+ .of_match_table = ts73xx_fpga_of_match,
},
.probe = ts73xx_fpga_probe,
};