All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] fpga: ts73xx and iCE40 support
@ 2017-02-27 22:14 Alan Tull
  2017-02-27 22:14 ` [PATCH 1/5] FPGA: Add TS-7300 FPGA manager Alan Tull
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Alan Tull @ 2017-02-27 22:14 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Moritz Fischer, Alan Tull, linux-kernel, linux-fpga

Hi Greg,

Please take these patches that add FPGA suppport
for ts73xx and iCE0 FPGAs.  I've done small fixups.

drivers/fpga/ice40-spi.c:
 fix printf format s/%ld/%d/ in 2 places

drivers/fpga/ts73xx-fpga.c:
 remove error message in probe. 

More details on the fixups:

diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c
index 6a4194be9f00..7fca82023062 100644
--- a/drivers/fpga/ice40-spi.c
+++ b/drivers/fpga/ice40-spi.c
@@ -163,14 +163,14 @@ static int ice40_fpga_probe(struct spi_device *spi)
        priv->cdone = devm_gpiod_get(dev, "cdone", GPIOD_IN);
        if (IS_ERR(priv->cdone)) {
                ret = PTR_ERR(priv->cdone);
-               dev_err(dev, "Failed to get CDONE GPIO: %ld\n", ret);
+               dev_err(dev, "Failed to get CDONE GPIO: %d\n", ret);
                return ret;
        }
 
        priv->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(priv->reset)) {
                ret = PTR_ERR(priv->reset);
-               dev_err(dev, "Failed to get CRESET_B GPIO: %ld\n", ret);
+               dev_err(dev, "Failed to get CRESET_B GPIO: %d\n", ret);
                return ret;
        }
 
diff --git a/drivers/fpga/ts73xx-fpga.c b/drivers/fpga/ts73xx-fpga.c
index 5acdbcfe447b..f6a96b42e2ca 100644
--- a/drivers/fpga/ts73xx-fpga.c
+++ b/drivers/fpga/ts73xx-fpga.c
@@ -117,7 +117,6 @@ static int ts73xx_fpga_probe(struct platform_device *pdev)
        struct device *kdev = &pdev->dev;
        struct ts73xx_fpga_priv *priv;
        struct resource *res;
-       int err;
 
        priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
@@ -132,14 +131,8 @@ static int ts73xx_fpga_probe(struct platform_device *pdev)
                return PTR_ERR(priv->io_base);
        }
 
-       err = fpga_mgr_register(kdev, "TS-73xx FPGA Manager",
-                               &ts73xx_fpga_ops, priv);
-       if (err) {
-               dev_err(kdev, "failed to register FPGA manager\n");
-               return err;
-       }
-
-       return err;
+       return fpga_mgr_register(kdev, "TS-73xx FPGA Manager",
+                                &ts73xx_fpga_ops, priv);
 }
 
 static int ts73xx_fpga_remove(struct platform_device *pdev)

Alan

Florian Fainelli (2):
  FPGA: Add TS-7300 FPGA manager
  ARM: ep93xx: Register ts73xx-fpga manager driver for TS-7300

Joel Holdsworth (3):
  of: Add vendor prefix for Lattice Semiconductor
  Documentation: Add binding document for Lattice iCE40 FPGA manager
  fpga: Add support for Lattice iCE40 FPGAs

 .../bindings/fpga/lattice-ice40-fpga-mgr.txt       |  21 +++
 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/mach-ep93xx/ts72xx.c                      |  26 +++
 drivers/fpga/Kconfig                               |  13 ++
 drivers/fpga/Makefile                              |   2 +
 drivers/fpga/ice40-spi.c                           | 207 +++++++++++++++++++++
 drivers/fpga/ts73xx-fpga.c                         | 156 ++++++++++++++++
 7 files changed, 426 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt
 create mode 100644 drivers/fpga/ice40-spi.c
 create mode 100644 drivers/fpga/ts73xx-fpga.c

-- 
2.7.4

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

* [PATCH 1/5] FPGA: Add TS-7300 FPGA manager
  2017-02-27 22:14 [PATCH 0/5] fpga: ts73xx and iCE40 support Alan Tull
@ 2017-02-27 22:14 ` Alan Tull
  2017-03-15  2:24   ` Florian Fainelli
  2017-02-27 22:14 ` [PATCH 2/5] ARM: ep93xx: Register ts73xx-fpga manager driver for TS-7300 Alan Tull
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Alan Tull @ 2017-02-27 22:14 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Moritz Fischer, Alan Tull, linux-kernel, linux-fpga, Florian Fainelli

From: Florian Fainelli <f.fainelli@gmail.com>

Add support for loading bitstreams on the Altera Cyclone II FPGA
populated on the TS-7300 board. This is done through the configuration
and data registers offered through a memory interface between the EP93xx
SoC and the FPGA via an intermediate CPLD device.

The EP93xx SoC on the TS-7300 does not have direct means of configuring
the on-board FPGA other than by using the special memory mapped
interface to the CPLD. No other entity on the system can control the
FPGA bitstream.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Acked-by: Alan Tull <atull@opensource.altera.com>
Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
---
v5: 'return fpga_mgr_register' at end of probe function
---
 drivers/fpga/Kconfig       |   7 ++
 drivers/fpga/Makefile      |   1 +
 drivers/fpga/ts73xx-fpga.c | 156 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 164 insertions(+)
 create mode 100644 drivers/fpga/ts73xx-fpga.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index ce861a2..d9cbef6 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -33,6 +33,13 @@ config FPGA_MGR_SOCFPGA_A10
 	help
 	  FPGA manager driver support for Altera Arria10 SoCFPGA.
 
+config FPGA_MGR_TS73XX
+	tristate "Technologic Systems TS-73xx SBC FPGA Manager"
+	depends on ARCH_EP93XX && MACH_TS72XX
+	help
+	  FPGA manager driver support for the Altera Cyclone II FPGA
+	  present on the TS-73xx SBC boards.
+
 config FPGA_MGR_ZYNQ_FPGA
 	tristate "Xilinx Zynq FPGA"
 	depends on ARCH_ZYNQ || COMPILE_TEST
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 8df07bc..a116016 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_FPGA)			+= fpga-mgr.o
 # FPGA Manager Drivers
 obj-$(CONFIG_FPGA_MGR_SOCFPGA)		+= socfpga.o
 obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10)	+= socfpga-a10.o
+obj-$(CONFIG_FPGA_MGR_TS73XX)		+= ts73xx-fpga.o
 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)	+= zynq-fpga.o
 
 # FPGA Bridge Drivers
diff --git a/drivers/fpga/ts73xx-fpga.c b/drivers/fpga/ts73xx-fpga.c
new file mode 100644
index 0000000..f6a96b4
--- /dev/null
+++ b/drivers/fpga/ts73xx-fpga.c
@@ -0,0 +1,156 @@
+/*
+ * Technologic Systems TS-73xx SBC FPGA loader
+ *
+ * Copyright (C) 2016 Florian Fainelli <f.fainelli@gmail.com>
+ *
+ * FPGA Manager Driver for the on-board Altera Cyclone II FPGA found on
+ * TS-7300, heavily based on load_fpga.c in their vendor tree.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/iopoll.h>
+#include <linux/fpga/fpga-mgr.h>
+
+#define TS73XX_FPGA_DATA_REG		0
+#define TS73XX_FPGA_CONFIG_REG		1
+
+#define TS73XX_FPGA_WRITE_DONE		0x1
+#define TS73XX_FPGA_WRITE_DONE_TIMEOUT	1000	/* us */
+#define TS73XX_FPGA_RESET		0x2
+#define TS73XX_FPGA_RESET_LOW_DELAY	30	/* us */
+#define TS73XX_FPGA_RESET_HIGH_DELAY	80	/* us */
+#define TS73XX_FPGA_LOAD_OK		0x4
+#define TS73XX_FPGA_CONFIG_LOAD		0x8
+
+struct ts73xx_fpga_priv {
+	void __iomem	*io_base;
+	struct device	*dev;
+};
+
+static enum fpga_mgr_states ts73xx_fpga_state(struct fpga_manager *mgr)
+{
+	return FPGA_MGR_STATE_UNKNOWN;
+}
+
+static int ts73xx_fpga_write_init(struct fpga_manager *mgr,
+				  struct fpga_image_info *info,
+				  const char *buf, size_t count)
+{
+	struct ts73xx_fpga_priv *priv = mgr->priv;
+
+	/* Reset the FPGA */
+	writeb(0, priv->io_base + TS73XX_FPGA_CONFIG_REG);
+	udelay(TS73XX_FPGA_RESET_LOW_DELAY);
+	writeb(TS73XX_FPGA_RESET, priv->io_base + TS73XX_FPGA_CONFIG_REG);
+	udelay(TS73XX_FPGA_RESET_HIGH_DELAY);
+
+	return 0;
+}
+
+static int ts73xx_fpga_write(struct fpga_manager *mgr, const char *buf,
+			     size_t count)
+{
+	struct ts73xx_fpga_priv *priv = mgr->priv;
+	size_t i = 0;
+	int ret;
+	u8 reg;
+
+	while (count--) {
+		ret = readb_poll_timeout(priv->io_base + TS73XX_FPGA_CONFIG_REG,
+					 reg, !(reg & TS73XX_FPGA_WRITE_DONE),
+					 1, TS73XX_FPGA_WRITE_DONE_TIMEOUT);
+		if (ret < 0)
+			return ret;
+
+		writeb(buf[i], priv->io_base + TS73XX_FPGA_DATA_REG);
+		i++;
+	}
+
+	return 0;
+}
+
+static int ts73xx_fpga_write_complete(struct fpga_manager *mgr,
+				      struct fpga_image_info *info)
+{
+	struct ts73xx_fpga_priv *priv = mgr->priv;
+	u8 reg;
+
+	usleep_range(1000, 2000);
+	reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG);
+	reg |= TS73XX_FPGA_CONFIG_LOAD;
+	writeb(reg, priv->io_base + TS73XX_FPGA_CONFIG_REG);
+
+	usleep_range(1000, 2000);
+	reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG);
+	reg &= ~TS73XX_FPGA_CONFIG_LOAD;
+	writeb(reg, priv->io_base + TS73XX_FPGA_CONFIG_REG);
+
+	reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG);
+	if ((reg & TS73XX_FPGA_LOAD_OK) != TS73XX_FPGA_LOAD_OK)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static const struct fpga_manager_ops ts73xx_fpga_ops = {
+	.state		= ts73xx_fpga_state,
+	.write_init	= ts73xx_fpga_write_init,
+	.write		= ts73xx_fpga_write,
+	.write_complete	= ts73xx_fpga_write_complete,
+};
+
+static int ts73xx_fpga_probe(struct platform_device *pdev)
+{
+	struct device *kdev = &pdev->dev;
+	struct ts73xx_fpga_priv *priv;
+	struct resource *res;
+
+	priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = kdev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->io_base = devm_ioremap_resource(kdev, res);
+	if (IS_ERR(priv->io_base)) {
+		dev_err(kdev, "unable to remap registers\n");
+		return PTR_ERR(priv->io_base);
+	}
+
+	return fpga_mgr_register(kdev, "TS-73xx FPGA Manager",
+				 &ts73xx_fpga_ops, priv);
+}
+
+static int ts73xx_fpga_remove(struct platform_device *pdev)
+{
+	fpga_mgr_unregister(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver ts73xx_fpga_driver = {
+	.driver	= {
+		.name	= "ts73xx-fpga-mgr",
+	},
+	.probe	= ts73xx_fpga_probe,
+	.remove	= ts73xx_fpga_remove,
+};
+module_platform_driver(ts73xx_fpga_driver);
+
+MODULE_AUTHOR("Florian Fainelli <f.fainelli@gmail.com>");
+MODULE_DESCRIPTION("TS-73xx FPGA Manager driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

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

* [PATCH 2/5] ARM: ep93xx: Register ts73xx-fpga manager driver for TS-7300
  2017-02-27 22:14 [PATCH 0/5] fpga: ts73xx and iCE40 support Alan Tull
  2017-02-27 22:14 ` [PATCH 1/5] FPGA: Add TS-7300 FPGA manager Alan Tull
@ 2017-02-27 22:14 ` Alan Tull
  2017-02-27 22:14 ` [PATCH 3/5] of: Add vendor prefix for Lattice Semiconductor Alan Tull
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Alan Tull @ 2017-02-27 22:14 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Moritz Fischer, Alan Tull, linux-kernel, linux-fpga, Florian Fainelli

From: Florian Fainelli <f.fainelli@gmail.com>

Register the TS-7300 FPGA manager device drivers which allows us to load
bitstreams into the on-board Altera Cyclone II FPGA.

Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Acked-by: Alan Tull <atull@opensource.altera.com>
Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
---
 arch/arm/mach-ep93xx/ts72xx.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 8a5b6f0..55b186e 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -210,6 +210,28 @@ static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
 	.phy_id		= 1,
 };
 
+#if IS_ENABLED(CONFIG_FPGA_MGR_TS73XX)
+
+/* Relative to EP93XX_CS1_PHYS_BASE */
+#define TS73XX_FPGA_LOADER_BASE		0x03c00000
+
+static struct resource ts73xx_fpga_resources[] = {
+	{
+		.start	= EP93XX_CS1_PHYS_BASE + TS73XX_FPGA_LOADER_BASE,
+		.end	= EP93XX_CS1_PHYS_BASE + TS73XX_FPGA_LOADER_BASE + 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device ts73xx_fpga_device = {
+	.name	= "ts73xx-fpga-mgr",
+	.id	= -1,
+	.resource = ts73xx_fpga_resources,
+	.num_resources = ARRAY_SIZE(ts73xx_fpga_resources),
+};
+
+#endif
+
 static void __init ts72xx_init_machine(void)
 {
 	ep93xx_init_devices();
@@ -218,6 +240,10 @@ static void __init ts72xx_init_machine(void)
 	platform_device_register(&ts72xx_wdt_device);
 
 	ep93xx_register_eth(&ts72xx_eth_data, 1);
+#if IS_ENABLED(CONFIG_FPGA_MGR_TS73XX)
+	if (board_is_ts7300())
+		platform_device_register(&ts73xx_fpga_device);
+#endif
 }
 
 MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
-- 
2.7.4

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

* [PATCH 3/5] of: Add vendor prefix for Lattice Semiconductor
  2017-02-27 22:14 [PATCH 0/5] fpga: ts73xx and iCE40 support Alan Tull
  2017-02-27 22:14 ` [PATCH 1/5] FPGA: Add TS-7300 FPGA manager Alan Tull
  2017-02-27 22:14 ` [PATCH 2/5] ARM: ep93xx: Register ts73xx-fpga manager driver for TS-7300 Alan Tull
@ 2017-02-27 22:14 ` Alan Tull
  2017-02-27 22:14 ` [PATCH 4/5] Documentation: Add binding document for Lattice iCE40 FPGA manager Alan Tull
  2017-02-27 22:14 ` [PATCH 5/5] fpga: Add support for Lattice iCE40 FPGAs Alan Tull
  4 siblings, 0 replies; 8+ messages in thread
From: Alan Tull @ 2017-02-27 22:14 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Moritz Fischer, Alan Tull, linux-kernel, linux-fpga, Joel Holdsworth

From: Joel Holdsworth <joel@airwebreathe.org.uk>

Lattice Semiconductor Corporation is a manufacturer of integrated
circuits and IP products, including low-power FPGAs, video connectivity
devices and millimeter wave wireless products.

Website: http://latticesemi.com

Signed-off-by: Joel Holdsworth <joel@airwebreathe.org.uk>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Alan Tull <atull@opensource.altera.com>
Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index a76b981..65b7ad5 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -164,6 +164,7 @@ kosagi	Sutajio Ko-Usagi PTE Ltd.
 kyo	Kyocera Corporation
 lacie	LaCie
 lantiq	Lantiq Semiconductor
+lattice	Lattice Semiconductor
 lego	LEGO Systems A/S
 lenovo	Lenovo Group Ltd.
 lg	LG Corporation
-- 
2.7.4

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

* [PATCH 4/5] Documentation: Add binding document for Lattice iCE40 FPGA manager
  2017-02-27 22:14 [PATCH 0/5] fpga: ts73xx and iCE40 support Alan Tull
                   ` (2 preceding siblings ...)
  2017-02-27 22:14 ` [PATCH 3/5] of: Add vendor prefix for Lattice Semiconductor Alan Tull
@ 2017-02-27 22:14 ` Alan Tull
  2017-02-27 22:14 ` [PATCH 5/5] fpga: Add support for Lattice iCE40 FPGAs Alan Tull
  4 siblings, 0 replies; 8+ messages in thread
From: Alan Tull @ 2017-02-27 22:14 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Moritz Fischer, Alan Tull, linux-kernel, linux-fpga, Joel Holdsworth

From: Joel Holdsworth <joel@airwebreathe.org.uk>

This adds documentation of the device tree bindings of the Lattice iCE40
FPGA driver for the FPGA manager framework.

Signed-off-by: Joel Holdsworth <joel@airwebreathe.org.uk>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Alan Tull <atull@opensource.altera.com>
Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
Acked-by: Marek Vasut <marex@denx.de>
---
 .../bindings/fpga/lattice-ice40-fpga-mgr.txt        | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt

diff --git a/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt b/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt
new file mode 100644
index 0000000..4dc4124
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt
@@ -0,0 +1,21 @@
+Lattice iCE40 FPGA Manager
+
+Required properties:
+- compatible:		Should contain "lattice,ice40-fpga-mgr"
+- reg:			SPI chip select
+- spi-max-frequency:	Maximum SPI frequency (>=1000000, <=25000000)
+- cdone-gpios:		GPIO input connected to CDONE pin
+- reset-gpios:		Active-low GPIO output connected to CRESET_B pin. Note
+			that unless the GPIO is held low during startup, the
+			FPGA will enter Master SPI mode and drive SCK with a
+			clock signal potentially jamming other devices on the
+			bus until the firmware is loaded.
+
+Example:
+	fpga: fpga@0 {
+		compatible = "lattice,ice40-fpga-mgr";
+		reg = <0>;
+		spi-max-frequency = <1000000>;
+		cdone-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
+		reset-gpios = <&gpio 22 GPIO_ACTIVE_LOW>;
+	};
-- 
2.7.4

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

* [PATCH 5/5] fpga: Add support for Lattice iCE40 FPGAs
  2017-02-27 22:14 [PATCH 0/5] fpga: ts73xx and iCE40 support Alan Tull
                   ` (3 preceding siblings ...)
  2017-02-27 22:14 ` [PATCH 4/5] Documentation: Add binding document for Lattice iCE40 FPGA manager Alan Tull
@ 2017-02-27 22:14 ` Alan Tull
  4 siblings, 0 replies; 8+ messages in thread
From: Alan Tull @ 2017-02-27 22:14 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Moritz Fischer, Alan Tull, linux-kernel, linux-fpga, Joel Holdsworth

From: Joel Holdsworth <joel@airwebreathe.org.uk>

This patch adds support to the FPGA manager for configuring the SRAM of
iCE40LM, iCE40LP, iCE40HX, iCE40 Ultra, iCE40 UltraLite and iCE40
UltraPlus devices, through slave SPI.

Signed-off-by: Joel Holdsworth <joel@airwebreathe.org.uk>
Reviewed-by: Marek Vasut <marex@denx.de>
Reviewed-by: Moritz Fischer <moritz.fischer@ettus.com>
Acked-by: Alan Tull <atull@opensource.altera.com>
---
 drivers/fpga/Kconfig     |   6 ++
 drivers/fpga/Makefile    |   1 +
 drivers/fpga/ice40-spi.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 214 insertions(+)
 create mode 100644 drivers/fpga/ice40-spi.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index d9cbef6..dee470f 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -20,6 +20,12 @@ config FPGA_REGION
 	  FPGA Regions allow loading FPGA images under control of
 	  the Device Tree.
 
+config FPGA_MGR_ICE40_SPI
+	tristate "Lattice iCE40 SPI"
+	depends on OF && SPI
+	help
+	  FPGA manager driver support for Lattice iCE40 FPGAs over SPI.
+
 config FPGA_MGR_SOCFPGA
 	tristate "Altera SOCFPGA FPGA Manager"
 	depends on ARCH_SOCFPGA || COMPILE_TEST
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index a116016..a5ee3ff 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_FPGA)			+= fpga-mgr.o
 
 # FPGA Manager Drivers
+obj-$(CONFIG_FPGA_MGR_ICE40_SPI)	+= ice40-spi.o
 obj-$(CONFIG_FPGA_MGR_SOCFPGA)		+= socfpga.o
 obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10)	+= socfpga-a10.o
 obj-$(CONFIG_FPGA_MGR_TS73XX)		+= ts73xx-fpga.o
diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c
new file mode 100644
index 0000000..7fca820
--- /dev/null
+++ b/drivers/fpga/ice40-spi.c
@@ -0,0 +1,207 @@
+/*
+ * FPGA Manager Driver for Lattice iCE40.
+ *
+ *  Copyright (c) 2016 Joel Holdsworth
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This driver adds support to the FPGA manager for configuring the SRAM of
+ * Lattice iCE40 FPGAs through slave SPI.
+ */
+
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/stringify.h>
+
+#define ICE40_SPI_MAX_SPEED 25000000 /* Hz */
+#define ICE40_SPI_MIN_SPEED 1000000 /* Hz */
+
+#define ICE40_SPI_RESET_DELAY 1 /* us (>200ns) */
+#define ICE40_SPI_HOUSEKEEPING_DELAY 1200 /* us */
+
+#define ICE40_SPI_NUM_ACTIVATION_BYTES DIV_ROUND_UP(49, 8)
+
+struct ice40_fpga_priv {
+	struct spi_device *dev;
+	struct gpio_desc *reset;
+	struct gpio_desc *cdone;
+};
+
+static enum fpga_mgr_states ice40_fpga_ops_state(struct fpga_manager *mgr)
+{
+	struct ice40_fpga_priv *priv = mgr->priv;
+
+	return gpiod_get_value(priv->cdone) ? FPGA_MGR_STATE_OPERATING :
+		FPGA_MGR_STATE_UNKNOWN;
+}
+
+static int ice40_fpga_ops_write_init(struct fpga_manager *mgr,
+				     struct fpga_image_info *info,
+				     const char *buf, size_t count)
+{
+	struct ice40_fpga_priv *priv = mgr->priv;
+	struct spi_device *dev = priv->dev;
+	struct spi_message message;
+	struct spi_transfer assert_cs_then_reset_delay = {
+		.cs_change   = 1,
+		.delay_usecs = ICE40_SPI_RESET_DELAY
+	};
+	struct spi_transfer housekeeping_delay_then_release_cs = {
+		.delay_usecs = ICE40_SPI_HOUSEKEEPING_DELAY
+	};
+	int ret;
+
+	if ((info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+		dev_err(&dev->dev,
+			"Partial reconfiguration is not supported\n");
+		return -ENOTSUPP;
+	}
+
+	/* Lock the bus, assert CRESET_B and SS_B and delay >200ns */
+	spi_bus_lock(dev->master);
+
+	gpiod_set_value(priv->reset, 1);
+
+	spi_message_init(&message);
+	spi_message_add_tail(&assert_cs_then_reset_delay, &message);
+	ret = spi_sync_locked(dev, &message);
+
+	/* Come out of reset */
+	gpiod_set_value(priv->reset, 0);
+
+	/* Abort if the chip-select failed */
+	if (ret)
+		goto fail;
+
+	/* Check CDONE is de-asserted i.e. the FPGA is reset */
+	if (gpiod_get_value(priv->cdone)) {
+		dev_err(&dev->dev, "Device reset failed, CDONE is asserted\n");
+		ret = -EIO;
+		goto fail;
+	}
+
+	/* Wait for the housekeeping to complete, and release SS_B */
+	spi_message_init(&message);
+	spi_message_add_tail(&housekeeping_delay_then_release_cs, &message);
+	ret = spi_sync_locked(dev, &message);
+
+fail:
+	spi_bus_unlock(dev->master);
+
+	return ret;
+}
+
+static int ice40_fpga_ops_write(struct fpga_manager *mgr,
+				const char *buf, size_t count)
+{
+	struct ice40_fpga_priv *priv = mgr->priv;
+
+	return spi_write(priv->dev, buf, count);
+}
+
+static int ice40_fpga_ops_write_complete(struct fpga_manager *mgr,
+					 struct fpga_image_info *info)
+{
+	struct ice40_fpga_priv *priv = mgr->priv;
+	struct spi_device *dev = priv->dev;
+	const u8 padding[ICE40_SPI_NUM_ACTIVATION_BYTES] = {0};
+
+	/* Check CDONE is asserted */
+	if (!gpiod_get_value(priv->cdone)) {
+		dev_err(&dev->dev,
+			"CDONE was not asserted after firmware transfer\n");
+		return -EIO;
+	}
+
+	/* Send of zero-padding to activate the firmware */
+	return spi_write(dev, padding, sizeof(padding));
+}
+
+static const struct fpga_manager_ops ice40_fpga_ops = {
+	.state = ice40_fpga_ops_state,
+	.write_init = ice40_fpga_ops_write_init,
+	.write = ice40_fpga_ops_write,
+	.write_complete = ice40_fpga_ops_write_complete,
+};
+
+static int ice40_fpga_probe(struct spi_device *spi)
+{
+	struct device *dev = &spi->dev;
+	struct ice40_fpga_priv *priv;
+	int ret;
+
+	priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = spi;
+
+	/* Check board setup data. */
+	if (spi->max_speed_hz > ICE40_SPI_MAX_SPEED) {
+		dev_err(dev, "SPI speed is too high, maximum speed is "
+			__stringify(ICE40_SPI_MAX_SPEED) "\n");
+		return -EINVAL;
+	}
+
+	if (spi->max_speed_hz < ICE40_SPI_MIN_SPEED) {
+		dev_err(dev, "SPI speed is too low, minimum speed is "
+			__stringify(ICE40_SPI_MIN_SPEED) "\n");
+		return -EINVAL;
+	}
+
+	if (spi->mode & SPI_CPHA) {
+		dev_err(dev, "Bad SPI mode, CPHA not supported\n");
+		return -EINVAL;
+	}
+
+	/* Set up the GPIOs */
+	priv->cdone = devm_gpiod_get(dev, "cdone", GPIOD_IN);
+	if (IS_ERR(priv->cdone)) {
+		ret = PTR_ERR(priv->cdone);
+		dev_err(dev, "Failed to get CDONE GPIO: %d\n", ret);
+		return ret;
+	}
+
+	priv->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(priv->reset)) {
+		ret = PTR_ERR(priv->reset);
+		dev_err(dev, "Failed to get CRESET_B GPIO: %d\n", ret);
+		return ret;
+	}
+
+	/* Register with the FPGA manager */
+	return fpga_mgr_register(dev, "Lattice iCE40 FPGA Manager",
+				 &ice40_fpga_ops, priv);
+}
+
+static int ice40_fpga_remove(struct spi_device *spi)
+{
+	fpga_mgr_unregister(&spi->dev);
+	return 0;
+}
+
+static const struct of_device_id ice40_fpga_of_match[] = {
+	{ .compatible = "lattice,ice40-fpga-mgr", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ice40_fpga_of_match);
+
+static struct spi_driver ice40_fpga_driver = {
+	.probe = ice40_fpga_probe,
+	.remove = ice40_fpga_remove,
+	.driver = {
+		.name = "ice40spi",
+		.of_match_table = of_match_ptr(ice40_fpga_of_match),
+	},
+};
+
+module_spi_driver(ice40_fpga_driver);
+
+MODULE_AUTHOR("Joel Holdsworth <joel@airwebreathe.org.uk>");
+MODULE_DESCRIPTION("Lattice iCE40 FPGA Manager");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

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

* Re: [PATCH 1/5] FPGA: Add TS-7300 FPGA manager
  2017-02-27 22:14 ` [PATCH 1/5] FPGA: Add TS-7300 FPGA manager Alan Tull
@ 2017-03-15  2:24   ` Florian Fainelli
  2017-03-15 16:45     ` Alan Tull
  0 siblings, 1 reply; 8+ messages in thread
From: Florian Fainelli @ 2017-03-15  2:24 UTC (permalink / raw)
  To: Alan Tull, Greg Kroah-Hartman; +Cc: Moritz Fischer, linux-kernel, linux-fpga



On 02/27/2017 02:14 PM, Alan Tull wrote:
> From: Florian Fainelli <f.fainelli@gmail.com>
> 
> Add support for loading bitstreams on the Altera Cyclone II FPGA
> populated on the TS-7300 board. This is done through the configuration
> and data registers offered through a memory interface between the EP93xx
> SoC and the FPGA via an intermediate CPLD device.
> 
> The EP93xx SoC on the TS-7300 does not have direct means of configuring
> the on-board FPGA other than by using the special memory mapped
> interface to the CPLD. No other entity on the system can control the
> FPGA bitstream.
> 
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> Acked-by: Alan Tull <atull@opensource.altera.com>
> Acked-by: Moritz Fischer <moritz.fischer@ettus.com>

Is this queued somewhere for 4.11? I see Jason's zynq patches merged in,
but not these two ep93xx ones?

https://git.kernel.org/pub/scm/linux/kernel/git/atull/linux-fpga.git/log/?h=test

Thanks

> ---
> v5: 'return fpga_mgr_register' at end of probe function
> ---
>  drivers/fpga/Kconfig       |   7 ++
>  drivers/fpga/Makefile      |   1 +
>  drivers/fpga/ts73xx-fpga.c | 156 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 164 insertions(+)
>  create mode 100644 drivers/fpga/ts73xx-fpga.c
> 
> diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
> index ce861a2..d9cbef6 100644
> --- a/drivers/fpga/Kconfig
> +++ b/drivers/fpga/Kconfig
> @@ -33,6 +33,13 @@ config FPGA_MGR_SOCFPGA_A10
>  	help
>  	  FPGA manager driver support for Altera Arria10 SoCFPGA.
>  
> +config FPGA_MGR_TS73XX
> +	tristate "Technologic Systems TS-73xx SBC FPGA Manager"
> +	depends on ARCH_EP93XX && MACH_TS72XX
> +	help
> +	  FPGA manager driver support for the Altera Cyclone II FPGA
> +	  present on the TS-73xx SBC boards.
> +
>  config FPGA_MGR_ZYNQ_FPGA
>  	tristate "Xilinx Zynq FPGA"
>  	depends on ARCH_ZYNQ || COMPILE_TEST
> diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
> index 8df07bc..a116016 100644
> --- a/drivers/fpga/Makefile
> +++ b/drivers/fpga/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_FPGA)			+= fpga-mgr.o
>  # FPGA Manager Drivers
>  obj-$(CONFIG_FPGA_MGR_SOCFPGA)		+= socfpga.o
>  obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10)	+= socfpga-a10.o
> +obj-$(CONFIG_FPGA_MGR_TS73XX)		+= ts73xx-fpga.o
>  obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)	+= zynq-fpga.o
>  
>  # FPGA Bridge Drivers
> diff --git a/drivers/fpga/ts73xx-fpga.c b/drivers/fpga/ts73xx-fpga.c
> new file mode 100644
> index 0000000..f6a96b4
> --- /dev/null
> +++ b/drivers/fpga/ts73xx-fpga.c
> @@ -0,0 +1,156 @@
> +/*
> + * Technologic Systems TS-73xx SBC FPGA loader
> + *
> + * Copyright (C) 2016 Florian Fainelli <f.fainelli@gmail.com>
> + *
> + * FPGA Manager Driver for the on-board Altera Cyclone II FPGA found on
> + * TS-7300, heavily based on load_fpga.c in their vendor tree.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that 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.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/string.h>
> +#include <linux/iopoll.h>
> +#include <linux/fpga/fpga-mgr.h>
> +
> +#define TS73XX_FPGA_DATA_REG		0
> +#define TS73XX_FPGA_CONFIG_REG		1
> +
> +#define TS73XX_FPGA_WRITE_DONE		0x1
> +#define TS73XX_FPGA_WRITE_DONE_TIMEOUT	1000	/* us */
> +#define TS73XX_FPGA_RESET		0x2
> +#define TS73XX_FPGA_RESET_LOW_DELAY	30	/* us */
> +#define TS73XX_FPGA_RESET_HIGH_DELAY	80	/* us */
> +#define TS73XX_FPGA_LOAD_OK		0x4
> +#define TS73XX_FPGA_CONFIG_LOAD		0x8
> +
> +struct ts73xx_fpga_priv {
> +	void __iomem	*io_base;
> +	struct device	*dev;
> +};
> +
> +static enum fpga_mgr_states ts73xx_fpga_state(struct fpga_manager *mgr)
> +{
> +	return FPGA_MGR_STATE_UNKNOWN;
> +}
> +
> +static int ts73xx_fpga_write_init(struct fpga_manager *mgr,
> +				  struct fpga_image_info *info,
> +				  const char *buf, size_t count)
> +{
> +	struct ts73xx_fpga_priv *priv = mgr->priv;
> +
> +	/* Reset the FPGA */
> +	writeb(0, priv->io_base + TS73XX_FPGA_CONFIG_REG);
> +	udelay(TS73XX_FPGA_RESET_LOW_DELAY);
> +	writeb(TS73XX_FPGA_RESET, priv->io_base + TS73XX_FPGA_CONFIG_REG);
> +	udelay(TS73XX_FPGA_RESET_HIGH_DELAY);
> +
> +	return 0;
> +}
> +
> +static int ts73xx_fpga_write(struct fpga_manager *mgr, const char *buf,
> +			     size_t count)
> +{
> +	struct ts73xx_fpga_priv *priv = mgr->priv;
> +	size_t i = 0;
> +	int ret;
> +	u8 reg;
> +
> +	while (count--) {
> +		ret = readb_poll_timeout(priv->io_base + TS73XX_FPGA_CONFIG_REG,
> +					 reg, !(reg & TS73XX_FPGA_WRITE_DONE),
> +					 1, TS73XX_FPGA_WRITE_DONE_TIMEOUT);
> +		if (ret < 0)
> +			return ret;
> +
> +		writeb(buf[i], priv->io_base + TS73XX_FPGA_DATA_REG);
> +		i++;
> +	}
> +
> +	return 0;
> +}
> +
> +static int ts73xx_fpga_write_complete(struct fpga_manager *mgr,
> +				      struct fpga_image_info *info)
> +{
> +	struct ts73xx_fpga_priv *priv = mgr->priv;
> +	u8 reg;
> +
> +	usleep_range(1000, 2000);
> +	reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG);
> +	reg |= TS73XX_FPGA_CONFIG_LOAD;
> +	writeb(reg, priv->io_base + TS73XX_FPGA_CONFIG_REG);
> +
> +	usleep_range(1000, 2000);
> +	reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG);
> +	reg &= ~TS73XX_FPGA_CONFIG_LOAD;
> +	writeb(reg, priv->io_base + TS73XX_FPGA_CONFIG_REG);
> +
> +	reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG);
> +	if ((reg & TS73XX_FPGA_LOAD_OK) != TS73XX_FPGA_LOAD_OK)
> +		return -ETIMEDOUT;
> +
> +	return 0;
> +}
> +
> +static const struct fpga_manager_ops ts73xx_fpga_ops = {
> +	.state		= ts73xx_fpga_state,
> +	.write_init	= ts73xx_fpga_write_init,
> +	.write		= ts73xx_fpga_write,
> +	.write_complete	= ts73xx_fpga_write_complete,
> +};
> +
> +static int ts73xx_fpga_probe(struct platform_device *pdev)
> +{
> +	struct device *kdev = &pdev->dev;
> +	struct ts73xx_fpga_priv *priv;
> +	struct resource *res;
> +
> +	priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->dev = kdev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	priv->io_base = devm_ioremap_resource(kdev, res);
> +	if (IS_ERR(priv->io_base)) {
> +		dev_err(kdev, "unable to remap registers\n");
> +		return PTR_ERR(priv->io_base);
> +	}
> +
> +	return fpga_mgr_register(kdev, "TS-73xx FPGA Manager",
> +				 &ts73xx_fpga_ops, priv);
> +}
> +
> +static int ts73xx_fpga_remove(struct platform_device *pdev)
> +{
> +	fpga_mgr_unregister(&pdev->dev);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver ts73xx_fpga_driver = {
> +	.driver	= {
> +		.name	= "ts73xx-fpga-mgr",
> +	},
> +	.probe	= ts73xx_fpga_probe,
> +	.remove	= ts73xx_fpga_remove,
> +};
> +module_platform_driver(ts73xx_fpga_driver);
> +
> +MODULE_AUTHOR("Florian Fainelli <f.fainelli@gmail.com>");
> +MODULE_DESCRIPTION("TS-73xx FPGA Manager driver");
> +MODULE_LICENSE("GPL v2");
> 

-- 
Florian

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

* Re: [PATCH 1/5] FPGA: Add TS-7300 FPGA manager
  2017-03-15  2:24   ` Florian Fainelli
@ 2017-03-15 16:45     ` Alan Tull
  0 siblings, 0 replies; 8+ messages in thread
From: Alan Tull @ 2017-03-15 16:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Florian Fainelli
  Cc: Moritz Fischer, linux-kernel, linux-fpga

On Tue, Mar 14, 2017 at 9:24 PM, Florian Fainelli <f.fainelli@gmail.com> wrote:

Hi Florain,

I reposted your patches with a minor fixup on 2/27.  I never heard
back that it made it into next but I think that's normal at this point
of the Linux cycle.

Alan

>
>
> On 02/27/2017 02:14 PM, Alan Tull wrote:
>> From: Florian Fainelli <f.fainelli@gmail.com>
>>
>> Add support for loading bitstreams on the Altera Cyclone II FPGA
>> populated on the TS-7300 board. This is done through the configuration
>> and data registers offered through a memory interface between the EP93xx
>> SoC and the FPGA via an intermediate CPLD device.
>>
>> The EP93xx SoC on the TS-7300 does not have direct means of configuring
>> the on-board FPGA other than by using the special memory mapped
>> interface to the CPLD. No other entity on the system can control the
>> FPGA bitstream.
>>
>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>> Acked-by: Alan Tull <atull@opensource.altera.com>
>> Acked-by: Moritz Fischer <moritz.fischer@ettus.com>
>
> Is this queued somewhere for 4.11? I see Jason's zynq patches merged in,
> but not these two ep93xx ones?
>
> https://git.kernel.org/pub/scm/linux/kernel/git/atull/linux-fpga.git/log/?h=test
>
> Thanks
>
>> ---
>> v5: 'return fpga_mgr_register' at end of probe function
>> ---
>>  drivers/fpga/Kconfig       |   7 ++
>>  drivers/fpga/Makefile      |   1 +
>>  drivers/fpga/ts73xx-fpga.c | 156 +++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 164 insertions(+)
>>  create mode 100644 drivers/fpga/ts73xx-fpga.c
>>
>> diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
>> index ce861a2..d9cbef6 100644
>> --- a/drivers/fpga/Kconfig
>> +++ b/drivers/fpga/Kconfig
>> @@ -33,6 +33,13 @@ config FPGA_MGR_SOCFPGA_A10
>>       help
>>         FPGA manager driver support for Altera Arria10 SoCFPGA.
>>
>> +config FPGA_MGR_TS73XX
>> +     tristate "Technologic Systems TS-73xx SBC FPGA Manager"
>> +     depends on ARCH_EP93XX && MACH_TS72XX
>> +     help
>> +       FPGA manager driver support for the Altera Cyclone II FPGA
>> +       present on the TS-73xx SBC boards.
>> +
>>  config FPGA_MGR_ZYNQ_FPGA
>>       tristate "Xilinx Zynq FPGA"
>>       depends on ARCH_ZYNQ || COMPILE_TEST
>> diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
>> index 8df07bc..a116016 100644
>> --- a/drivers/fpga/Makefile
>> +++ b/drivers/fpga/Makefile
>> @@ -8,6 +8,7 @@ obj-$(CONFIG_FPGA)                    += fpga-mgr.o
>>  # FPGA Manager Drivers
>>  obj-$(CONFIG_FPGA_MGR_SOCFPGA)               += socfpga.o
>>  obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10)   += socfpga-a10.o
>> +obj-$(CONFIG_FPGA_MGR_TS73XX)                += ts73xx-fpga.o
>>  obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)     += zynq-fpga.o
>>
>>  # FPGA Bridge Drivers
>> diff --git a/drivers/fpga/ts73xx-fpga.c b/drivers/fpga/ts73xx-fpga.c
>> new file mode 100644
>> index 0000000..f6a96b4
>> --- /dev/null
>> +++ b/drivers/fpga/ts73xx-fpga.c
>> @@ -0,0 +1,156 @@
>> +/*
>> + * Technologic Systems TS-73xx SBC FPGA loader
>> + *
>> + * Copyright (C) 2016 Florian Fainelli <f.fainelli@gmail.com>
>> + *
>> + * FPGA Manager Driver for the on-board Altera Cyclone II FPGA found on
>> + * TS-7300, heavily based on load_fpga.c in their vendor tree.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; version 2 of the License.
>> + *
>> + * This program is distributed in the hope that 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.
>> + */
>> +
>> +#include <linux/delay.h>
>> +#include <linux/io.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/string.h>
>> +#include <linux/iopoll.h>
>> +#include <linux/fpga/fpga-mgr.h>
>> +
>> +#define TS73XX_FPGA_DATA_REG         0
>> +#define TS73XX_FPGA_CONFIG_REG               1
>> +
>> +#define TS73XX_FPGA_WRITE_DONE               0x1
>> +#define TS73XX_FPGA_WRITE_DONE_TIMEOUT       1000    /* us */
>> +#define TS73XX_FPGA_RESET            0x2
>> +#define TS73XX_FPGA_RESET_LOW_DELAY  30      /* us */
>> +#define TS73XX_FPGA_RESET_HIGH_DELAY 80      /* us */
>> +#define TS73XX_FPGA_LOAD_OK          0x4
>> +#define TS73XX_FPGA_CONFIG_LOAD              0x8
>> +
>> +struct ts73xx_fpga_priv {
>> +     void __iomem    *io_base;
>> +     struct device   *dev;
>> +};
>> +
>> +static enum fpga_mgr_states ts73xx_fpga_state(struct fpga_manager *mgr)
>> +{
>> +     return FPGA_MGR_STATE_UNKNOWN;
>> +}
>> +
>> +static int ts73xx_fpga_write_init(struct fpga_manager *mgr,
>> +                               struct fpga_image_info *info,
>> +                               const char *buf, size_t count)
>> +{
>> +     struct ts73xx_fpga_priv *priv = mgr->priv;
>> +
>> +     /* Reset the FPGA */
>> +     writeb(0, priv->io_base + TS73XX_FPGA_CONFIG_REG);
>> +     udelay(TS73XX_FPGA_RESET_LOW_DELAY);
>> +     writeb(TS73XX_FPGA_RESET, priv->io_base + TS73XX_FPGA_CONFIG_REG);
>> +     udelay(TS73XX_FPGA_RESET_HIGH_DELAY);
>> +
>> +     return 0;
>> +}
>> +
>> +static int ts73xx_fpga_write(struct fpga_manager *mgr, const char *buf,
>> +                          size_t count)
>> +{
>> +     struct ts73xx_fpga_priv *priv = mgr->priv;
>> +     size_t i = 0;
>> +     int ret;
>> +     u8 reg;
>> +
>> +     while (count--) {
>> +             ret = readb_poll_timeout(priv->io_base + TS73XX_FPGA_CONFIG_REG,
>> +                                      reg, !(reg & TS73XX_FPGA_WRITE_DONE),
>> +                                      1, TS73XX_FPGA_WRITE_DONE_TIMEOUT);
>> +             if (ret < 0)
>> +                     return ret;
>> +
>> +             writeb(buf[i], priv->io_base + TS73XX_FPGA_DATA_REG);
>> +             i++;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static int ts73xx_fpga_write_complete(struct fpga_manager *mgr,
>> +                                   struct fpga_image_info *info)
>> +{
>> +     struct ts73xx_fpga_priv *priv = mgr->priv;
>> +     u8 reg;
>> +
>> +     usleep_range(1000, 2000);
>> +     reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG);
>> +     reg |= TS73XX_FPGA_CONFIG_LOAD;
>> +     writeb(reg, priv->io_base + TS73XX_FPGA_CONFIG_REG);
>> +
>> +     usleep_range(1000, 2000);
>> +     reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG);
>> +     reg &= ~TS73XX_FPGA_CONFIG_LOAD;
>> +     writeb(reg, priv->io_base + TS73XX_FPGA_CONFIG_REG);
>> +
>> +     reg = readb(priv->io_base + TS73XX_FPGA_CONFIG_REG);
>> +     if ((reg & TS73XX_FPGA_LOAD_OK) != TS73XX_FPGA_LOAD_OK)
>> +             return -ETIMEDOUT;
>> +
>> +     return 0;
>> +}
>> +
>> +static const struct fpga_manager_ops ts73xx_fpga_ops = {
>> +     .state          = ts73xx_fpga_state,
>> +     .write_init     = ts73xx_fpga_write_init,
>> +     .write          = ts73xx_fpga_write,
>> +     .write_complete = ts73xx_fpga_write_complete,
>> +};
>> +
>> +static int ts73xx_fpga_probe(struct platform_device *pdev)
>> +{
>> +     struct device *kdev = &pdev->dev;
>> +     struct ts73xx_fpga_priv *priv;
>> +     struct resource *res;
>> +
>> +     priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL);
>> +     if (!priv)
>> +             return -ENOMEM;
>> +
>> +     priv->dev = kdev;
>> +
>> +     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +     priv->io_base = devm_ioremap_resource(kdev, res);
>> +     if (IS_ERR(priv->io_base)) {
>> +             dev_err(kdev, "unable to remap registers\n");
>> +             return PTR_ERR(priv->io_base);
>> +     }
>> +
>> +     return fpga_mgr_register(kdev, "TS-73xx FPGA Manager",
>> +                              &ts73xx_fpga_ops, priv);
>> +}
>> +
>> +static int ts73xx_fpga_remove(struct platform_device *pdev)
>> +{
>> +     fpga_mgr_unregister(&pdev->dev);
>> +
>> +     return 0;
>> +}
>> +
>> +static struct platform_driver ts73xx_fpga_driver = {
>> +     .driver = {
>> +             .name   = "ts73xx-fpga-mgr",
>> +     },
>> +     .probe  = ts73xx_fpga_probe,
>> +     .remove = ts73xx_fpga_remove,
>> +};
>> +module_platform_driver(ts73xx_fpga_driver);
>> +
>> +MODULE_AUTHOR("Florian Fainelli <f.fainelli@gmail.com>");
>> +MODULE_DESCRIPTION("TS-73xx FPGA Manager driver");
>> +MODULE_LICENSE("GPL v2");
>>
>
> --
> Florian

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

end of thread, other threads:[~2017-03-15 16:45 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-27 22:14 [PATCH 0/5] fpga: ts73xx and iCE40 support Alan Tull
2017-02-27 22:14 ` [PATCH 1/5] FPGA: Add TS-7300 FPGA manager Alan Tull
2017-03-15  2:24   ` Florian Fainelli
2017-03-15 16:45     ` Alan Tull
2017-02-27 22:14 ` [PATCH 2/5] ARM: ep93xx: Register ts73xx-fpga manager driver for TS-7300 Alan Tull
2017-02-27 22:14 ` [PATCH 3/5] of: Add vendor prefix for Lattice Semiconductor Alan Tull
2017-02-27 22:14 ` [PATCH 4/5] Documentation: Add binding document for Lattice iCE40 FPGA manager Alan Tull
2017-02-27 22:14 ` [PATCH 5/5] fpga: Add support for Lattice iCE40 FPGAs Alan Tull

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.