Re: [PATCH v9 2/3] fpga manager: Add cyclone-ps-spi driver for Altera FPGAs

2017-02-15 Thread Joshua Clayton

On 02/15/2017 09:14 AM, Alan Tull wrote:
> On Wed, Feb 15, 2017 at 9:26 AM, Anatolij Gustschin  wrote:
>> Hi Joshua,
>>
>> On Tue, 24 Jan 2017 14:19:33 -0800
>> Joshua Clayton stillcompil...@gmail.com wrote:
>> ...
>>> +static int cyclonespi_write(struct fpga_manager *mgr, const char *buf,
>>> +  size_t count)
>>> +{
>>> +  struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
>>> +  const char *fw_data = buf;
>>> +  const char *fw_data_end = fw_data + count;
>>> +
>>> +  while (fw_data < fw_data_end) {
>>> +  int ret;
>>> +  size_t stride = min(fw_data_end - fw_data, SZ_4K);
>>> +
>>> +  rev_buf(fw_data, stride);
>> Can we make rev_buf() optional here? I've tested this driver with
>> Stratix-V FPGA using orion_spi driver. It works without swapping
>> the data.
Thanks for testing!
I'd be happy to make it an optional feature, rather than integral.
> I replied earlier, but something in my email settings bounced.
>
> The way to make it optional is to add a bit to the flags of the
> fpga_image_info struct.
>
> Alan
OK.
>
>> Thanks,
>> Anatolij



Re: [PATCH v9 2/3] fpga manager: Add cyclone-ps-spi driver for Altera FPGAs

2017-02-15 Thread Joshua Clayton

On 02/15/2017 09:14 AM, Alan Tull wrote:
> On Wed, Feb 15, 2017 at 9:26 AM, Anatolij Gustschin  wrote:
>> Hi Joshua,
>>
>> On Tue, 24 Jan 2017 14:19:33 -0800
>> Joshua Clayton stillcompil...@gmail.com wrote:
>> ...
>>> +static int cyclonespi_write(struct fpga_manager *mgr, const char *buf,
>>> +  size_t count)
>>> +{
>>> +  struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
>>> +  const char *fw_data = buf;
>>> +  const char *fw_data_end = fw_data + count;
>>> +
>>> +  while (fw_data < fw_data_end) {
>>> +  int ret;
>>> +  size_t stride = min(fw_data_end - fw_data, SZ_4K);
>>> +
>>> +  rev_buf(fw_data, stride);
>> Can we make rev_buf() optional here? I've tested this driver with
>> Stratix-V FPGA using orion_spi driver. It works without swapping
>> the data.
Thanks for testing!
I'd be happy to make it an optional feature, rather than integral.
> I replied earlier, but something in my email settings bounced.
>
> The way to make it optional is to add a bit to the flags of the
> fpga_image_info struct.
>
> Alan
OK.
>
>> Thanks,
>> Anatolij



Re: [PATCH v9 2/3] fpga manager: Add cyclone-ps-spi driver for Altera FPGAs

2017-02-15 Thread Alan Tull
On Wed, Feb 15, 2017 at 9:26 AM, Anatolij Gustschin  wrote:
> Hi Joshua,
>
> On Tue, 24 Jan 2017 14:19:33 -0800
> Joshua Clayton stillcompil...@gmail.com wrote:
> ...
>>+static int cyclonespi_write(struct fpga_manager *mgr, const char *buf,
>>+  size_t count)
>>+{
>>+  struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
>>+  const char *fw_data = buf;
>>+  const char *fw_data_end = fw_data + count;
>>+
>>+  while (fw_data < fw_data_end) {
>>+  int ret;
>>+  size_t stride = min(fw_data_end - fw_data, SZ_4K);
>>+
>>+  rev_buf(fw_data, stride);
>
> Can we make rev_buf() optional here? I've tested this driver with
> Stratix-V FPGA using orion_spi driver. It works without swapping
> the data.

I replied earlier, but something in my email settings bounced.

The way to make it optional is to add a bit to the flags of the
fpga_image_info struct.

Alan

>
> Thanks,
> Anatolij


Re: [PATCH v9 2/3] fpga manager: Add cyclone-ps-spi driver for Altera FPGAs

2017-02-15 Thread Alan Tull
On Wed, Feb 15, 2017 at 9:26 AM, Anatolij Gustschin  wrote:
> Hi Joshua,
>
> On Tue, 24 Jan 2017 14:19:33 -0800
> Joshua Clayton stillcompil...@gmail.com wrote:
> ...
>>+static int cyclonespi_write(struct fpga_manager *mgr, const char *buf,
>>+  size_t count)
>>+{
>>+  struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
>>+  const char *fw_data = buf;
>>+  const char *fw_data_end = fw_data + count;
>>+
>>+  while (fw_data < fw_data_end) {
>>+  int ret;
>>+  size_t stride = min(fw_data_end - fw_data, SZ_4K);
>>+
>>+  rev_buf(fw_data, stride);
>
> Can we make rev_buf() optional here? I've tested this driver with
> Stratix-V FPGA using orion_spi driver. It works without swapping
> the data.

I replied earlier, but something in my email settings bounced.

The way to make it optional is to add a bit to the flags of the
fpga_image_info struct.

Alan

>
> Thanks,
> Anatolij


Re: [PATCH v9 2/3] fpga manager: Add cyclone-ps-spi driver for Altera FPGAs

2017-02-15 Thread Anatolij Gustschin
Hi Joshua,

On Tue, 24 Jan 2017 14:19:33 -0800
Joshua Clayton stillcompil...@gmail.com wrote:
...
>+static int cyclonespi_write(struct fpga_manager *mgr, const char *buf,
>+  size_t count)
>+{
>+  struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
>+  const char *fw_data = buf;
>+  const char *fw_data_end = fw_data + count;
>+
>+  while (fw_data < fw_data_end) {
>+  int ret;
>+  size_t stride = min(fw_data_end - fw_data, SZ_4K);
>+
>+  rev_buf(fw_data, stride);

Can we make rev_buf() optional here? I've tested this driver with
Stratix-V FPGA using orion_spi driver. It works without swapping
the data.

Thanks,
Anatolij


Re: [PATCH v9 2/3] fpga manager: Add cyclone-ps-spi driver for Altera FPGAs

2017-02-15 Thread Anatolij Gustschin
Hi Joshua,

On Tue, 24 Jan 2017 14:19:33 -0800
Joshua Clayton stillcompil...@gmail.com wrote:
...
>+static int cyclonespi_write(struct fpga_manager *mgr, const char *buf,
>+  size_t count)
>+{
>+  struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
>+  const char *fw_data = buf;
>+  const char *fw_data_end = fw_data + count;
>+
>+  while (fw_data < fw_data_end) {
>+  int ret;
>+  size_t stride = min(fw_data_end - fw_data, SZ_4K);
>+
>+  rev_buf(fw_data, stride);

Can we make rev_buf() optional here? I've tested this driver with
Stratix-V FPGA using orion_spi driver. It works without swapping
the data.

Thanks,
Anatolij


[PATCH v9 2/3] fpga manager: Add cyclone-ps-spi driver for Altera FPGAs

2017-01-24 Thread Joshua Clayton
cyclone-ps-spi loads FPGA firmware over spi, using the "passive serial"
interface on Altera Cyclone FPGAS.

This is one of the simpler ways to set up an FPGA at runtime.
The signal interface is close to unidirectional spi with lsb first.

Signed-off-by: Joshua Clayton 
---
 drivers/fpga/Kconfig  |   7 ++
 drivers/fpga/Makefile |   1 +
 drivers/fpga/cyclone-ps-spi.c | 185 ++
 3 files changed, 193 insertions(+)
 create mode 100644 drivers/fpga/cyclone-ps-spi.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index ce861a2..e6c032d 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -20,6 +20,13 @@ config FPGA_REGION
  FPGA Regions allow loading FPGA images under control of
  the Device Tree.
 
+config FPGA_MGR_CYCLONE_PS_SPI
+   tristate "Altera Cyclone FPGA Passive Serial over SPI"
+   depends on SPI
+   help
+ FPGA manager driver support for Altera Cyclone using the
+ passive serial interface 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 8df07bc..a112bef 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_CYCLONE_PS_SPI)  += cyclone-ps-spi.o
 obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
 obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o
 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)   += zynq-fpga.o
diff --git a/drivers/fpga/cyclone-ps-spi.c b/drivers/fpga/cyclone-ps-spi.c
new file mode 100644
index 000..56c3853
--- /dev/null
+++ b/drivers/fpga/cyclone-ps-spi.c
@@ -0,0 +1,185 @@
+/**
+ * Altera Cyclone Passive Serial SPI Driver
+ *
+ *  Copyright (c) 2017 United Western Technologies, Corporation
+ *
+ *  Joshua Clayton 
+ *
+ * Manage Altera FPGA firmware that is loaded over spi using the passive
+ * serial configuration method.
+ * Firmware must be in binary "rbf" format.
+ * Works on Cyclone V. Should work on cyclone series.
+ * May work on other Altera FPGAs.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define FPGA_RESET_TIME50   /* time in usecs to trigger FPGA 
config */
+#define FPGA_MIN_DELAY 50   /* min usecs to wait for config status */
+#define FPGA_MAX_DELAY 1000 /* max usecs to wait for config status */
+
+struct cyclonespi_conf {
+   struct gpio_desc *config;
+   struct gpio_desc *status;
+   struct spi_device *spi;
+};
+
+static const struct of_device_id of_ef_match[] = {
+   { .compatible = "altr,fpga-passive-serial", },
+   {}
+};
+MODULE_DEVICE_TABLE(of, of_ef_match);
+
+static enum fpga_mgr_states cyclonespi_state(struct fpga_manager *mgr)
+{
+   struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
+
+   if (gpiod_get_value(conf->status))
+   return FPGA_MGR_STATE_RESET;
+
+   return FPGA_MGR_STATE_UNKNOWN;
+}
+
+static int cyclonespi_write_init(struct fpga_manager *mgr,
+struct fpga_image_info *info,
+const char *buf, size_t count)
+{
+   struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
+   int i;
+
+   if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
+   dev_err(>dev, "Partial reconfiguration not supported.\n");
+   return -EINVAL;
+   }
+
+   gpiod_set_value(conf->config, 1);
+   usleep_range(FPGA_RESET_TIME, FPGA_RESET_TIME + 20);
+   if (!gpiod_get_value(conf->status)) {
+   dev_err(>dev, "Status pin failed to show a reset\n");
+   return -EIO;
+   }
+
+   gpiod_set_value(conf->config, 0);
+   for (i = 0; i < (FPGA_MAX_DELAY / FPGA_MIN_DELAY); i++) {
+   usleep_range(FPGA_MIN_DELAY, FPGA_MIN_DELAY + 20);
+   if (!gpiod_get_value(conf->status))
+   return 0;
+   }
+
+   dev_err(>dev, "Status pin not ready.\n");
+   return -EIO;
+}
+
+static void rev_buf(char *buf, size_t len)
+{
+   const char *fw_end = (buf + len);
+
+   /* set buffer to lsb first */
+   while (buf < fw_end) {
+   *buf = bitrev8(*buf);
+   buf++;
+   }
+}
+
+static int cyclonespi_write(struct fpga_manager *mgr, const char *buf,
+   size_t count)
+{
+   struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
+   const char *fw_data = buf;
+   const char *fw_data_end = fw_data + count;
+
+   while (fw_data < fw_data_end) {
+   int ret;
+   size_t stride = min(fw_data_end - fw_data, SZ_4K);
+
+   rev_buf(fw_data, stride);
+   ret = spi_write(conf->spi, fw_data, 

[PATCH v9 2/3] fpga manager: Add cyclone-ps-spi driver for Altera FPGAs

2017-01-24 Thread Joshua Clayton
cyclone-ps-spi loads FPGA firmware over spi, using the "passive serial"
interface on Altera Cyclone FPGAS.

This is one of the simpler ways to set up an FPGA at runtime.
The signal interface is close to unidirectional spi with lsb first.

Signed-off-by: Joshua Clayton 
---
 drivers/fpga/Kconfig  |   7 ++
 drivers/fpga/Makefile |   1 +
 drivers/fpga/cyclone-ps-spi.c | 185 ++
 3 files changed, 193 insertions(+)
 create mode 100644 drivers/fpga/cyclone-ps-spi.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index ce861a2..e6c032d 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -20,6 +20,13 @@ config FPGA_REGION
  FPGA Regions allow loading FPGA images under control of
  the Device Tree.
 
+config FPGA_MGR_CYCLONE_PS_SPI
+   tristate "Altera Cyclone FPGA Passive Serial over SPI"
+   depends on SPI
+   help
+ FPGA manager driver support for Altera Cyclone using the
+ passive serial interface 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 8df07bc..a112bef 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_CYCLONE_PS_SPI)  += cyclone-ps-spi.o
 obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
 obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o
 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)   += zynq-fpga.o
diff --git a/drivers/fpga/cyclone-ps-spi.c b/drivers/fpga/cyclone-ps-spi.c
new file mode 100644
index 000..56c3853
--- /dev/null
+++ b/drivers/fpga/cyclone-ps-spi.c
@@ -0,0 +1,185 @@
+/**
+ * Altera Cyclone Passive Serial SPI Driver
+ *
+ *  Copyright (c) 2017 United Western Technologies, Corporation
+ *
+ *  Joshua Clayton 
+ *
+ * Manage Altera FPGA firmware that is loaded over spi using the passive
+ * serial configuration method.
+ * Firmware must be in binary "rbf" format.
+ * Works on Cyclone V. Should work on cyclone series.
+ * May work on other Altera FPGAs.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define FPGA_RESET_TIME50   /* time in usecs to trigger FPGA 
config */
+#define FPGA_MIN_DELAY 50   /* min usecs to wait for config status */
+#define FPGA_MAX_DELAY 1000 /* max usecs to wait for config status */
+
+struct cyclonespi_conf {
+   struct gpio_desc *config;
+   struct gpio_desc *status;
+   struct spi_device *spi;
+};
+
+static const struct of_device_id of_ef_match[] = {
+   { .compatible = "altr,fpga-passive-serial", },
+   {}
+};
+MODULE_DEVICE_TABLE(of, of_ef_match);
+
+static enum fpga_mgr_states cyclonespi_state(struct fpga_manager *mgr)
+{
+   struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
+
+   if (gpiod_get_value(conf->status))
+   return FPGA_MGR_STATE_RESET;
+
+   return FPGA_MGR_STATE_UNKNOWN;
+}
+
+static int cyclonespi_write_init(struct fpga_manager *mgr,
+struct fpga_image_info *info,
+const char *buf, size_t count)
+{
+   struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
+   int i;
+
+   if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
+   dev_err(>dev, "Partial reconfiguration not supported.\n");
+   return -EINVAL;
+   }
+
+   gpiod_set_value(conf->config, 1);
+   usleep_range(FPGA_RESET_TIME, FPGA_RESET_TIME + 20);
+   if (!gpiod_get_value(conf->status)) {
+   dev_err(>dev, "Status pin failed to show a reset\n");
+   return -EIO;
+   }
+
+   gpiod_set_value(conf->config, 0);
+   for (i = 0; i < (FPGA_MAX_DELAY / FPGA_MIN_DELAY); i++) {
+   usleep_range(FPGA_MIN_DELAY, FPGA_MIN_DELAY + 20);
+   if (!gpiod_get_value(conf->status))
+   return 0;
+   }
+
+   dev_err(>dev, "Status pin not ready.\n");
+   return -EIO;
+}
+
+static void rev_buf(char *buf, size_t len)
+{
+   const char *fw_end = (buf + len);
+
+   /* set buffer to lsb first */
+   while (buf < fw_end) {
+   *buf = bitrev8(*buf);
+   buf++;
+   }
+}
+
+static int cyclonespi_write(struct fpga_manager *mgr, const char *buf,
+   size_t count)
+{
+   struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
+   const char *fw_data = buf;
+   const char *fw_data_end = fw_data + count;
+
+   while (fw_data < fw_data_end) {
+   int ret;
+   size_t stride = min(fw_data_end - fw_data, SZ_4K);
+
+   rev_buf(fw_data, stride);
+   ret = spi_write(conf->spi, fw_data, stride);
+   if (ret) {
+