diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-06-08 21:26:50 +0200 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-06-08 21:26:50 +0200 |
| commit | b23338788b937ccc278b62b6286438ca10a896a6 (patch) | |
| tree | ed086e07e792b912be61ca47106b28670425c2e9 | |
| parent | 099b02d3ddabc4b1764976670816621ee82ea656 (diff) | |
| parent | 43a1974da6bc7ce8f4d1dc1d03d56997428c29c3 (diff) | |
| download | linux-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.txt | 12 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/fpga/altera-socfpga-fpga-mgr.txt | 17 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/fpga/altr,a10-pr-ip.yaml | 34 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/fpga/altr,socfpga-fpga-mgr.yaml | 38 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/fpga/efinix,trion-config.yaml | 98 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/fpga/technologic,ts7300-fpga.yaml | 36 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 | ||||
| -rw-r--r-- | drivers/fpga/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/fpga/Makefile | 1 | ||||
| -rw-r--r-- | drivers/fpga/dfl-afu-main.c | 3 | ||||
| -rw-r--r-- | drivers/fpga/dfl.c | 2 | ||||
| -rw-r--r-- | drivers/fpga/efinix-spi.c | 260 | ||||
| -rw-r--r-- | drivers/fpga/lattice-sysconfig-spi.c | 29 | ||||
| -rw-r--r-- | drivers/fpga/microchip-spi.c | 3 | ||||
| -rw-r--r-- | drivers/fpga/of-fpga-region.c | 3 | ||||
| -rw-r--r-- | drivers/fpga/ts73xx-fpga.c | 9 |
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, }; |
