--- /dev/null
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <altera.h>
+#include <errno.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <asm/arch-mvebu/spi.h>
+#include "theadorable.h"
+
+/*
+ * FPGA programming support
+ */
+static int fpga_pre_fn(int cookie)
+{
+       int gpio_config = COOKIE2CONFIG(cookie);
+       int gpio_done = COOKIE2DONE(cookie);
+       int ret;
+
+       debug("%s (%d): cookie=%08x gpio_config=%d gpio_done=%d\n",
+             __func__, __LINE__, cookie, gpio_config, gpio_done);
+
+       /* Configure config pin */
+       /* Set to output */
+       ret = gpio_request(gpio_config, "CONFIG");
+       if (ret < 0)
+               return ret;
+       gpio_direction_output(gpio_config, 1);
+
+       /* Configure done pin */
+       /* Set to input */
+       ret = gpio_request(gpio_done, "DONE");
+       if (ret < 0)
+               return ret;
+
+       gpio_direction_input(gpio_done);
+
+       return 0;
+}
+
+static int fpga_config_fn(int assert, int flush, int cookie)
+{
+       int gpio_config = COOKIE2CONFIG(cookie);
+
+       debug("%s (%d): cookie=%08x gpio_config=%d\n",
+             __func__, __LINE__, cookie, gpio_config);
+
+       if (assert)
+               gpio_set_value(gpio_config, 1);
+       else
+               gpio_set_value(gpio_config, 0);
+
+       return 0;
+}
+
+static int fpga_write_fn(const void *buf, size_t len, int flush, int cookie)
+{
+       int spi_bus = COOKIE2SPI_BUS(cookie);
+       int spi_dev = COOKIE2SPI_DEV(cookie);
+       struct kwspi_registers *reg;
+       u32 control_reg;
+       u32 config_reg;
+       void *dst;
+
+       /*
+        * Write data to FPGA attached to SPI bus via SPI direct write.
+        * This results in the fastest and easiest way to program the
+        * bitstream into the FPGA.
+        */
+       debug("%s (%d): cookie=%08x spi_bus=%d spi_dev=%d\n",
+             __func__, __LINE__, cookie, spi_bus, spi_dev);
+
+       if (spi_bus == 0) {
+               reg = (struct kwspi_registers *)MVEBU_REGISTER(0x10600);
+               dst = (void *)SPI_BUS0_DEV1_BASE;
+       } else {
+               reg = (struct kwspi_registers *)MVEBU_REGISTER(0x10680);
+               dst = (void *)SPI_BUS1_DEV2_BASE;
+       }
+
+       /* Configure SPI controller for direct access mode */
+       control_reg = readl(®->ctrl);
+       config_reg = readl(®->cfg);
+       writel(0x00000214, ®->cfg);          /* 27MHz clock */
+       writel(0x00000000, ®->dw_cfg);       /* don't de-asset CS */
+       writel(KWSPI_CSN_ACT, ®->ctrl);      /* activate CS */
+
+       /* Copy data to the SPI direct mapped window */
+       memcpy(dst, buf, len);
+
+       /* Restore original register values */
+       writel(control_reg, ®->ctrl);
+       writel(config_reg, ®->cfg);
+
+       return 0;
+}
+
+/* Returns the state of CONF_DONE Pin */
+static int fpga_done_fn(int cookie)
+{
+       int gpio_done = COOKIE2DONE(cookie);
+       unsigned long ts;
+
+       debug("%s (%d): cookie=%08x gpio_done=%d\n",
+             __func__, __LINE__, cookie, gpio_done);
+
+       ts = get_timer(0);
+       do {
+               if (gpio_get_value(gpio_done))
+                       return 0;
+       } while (get_timer(ts) < 1000);
+
+       /* timeout so return error */
+       return -ENODEV;
+}
+
+static altera_board_specific_func stratixv_fns = {
+       .pre = fpga_pre_fn,
+       .config = fpga_config_fn,
+       .write = fpga_write_fn,
+       .done = fpga_done_fn,
+};
+
+static Altera_desc altera_fpga[] = {
+       {
+               /* Family */
+               Altera_StratixV,
+               /* Interface type */
+               passive_serial,
+               /* No limitation as additional data will be ignored */
+               -1,
+               /* Device function table */
+               (void *)&stratixv_fns,
+               /* Base interface address specified in driver */
+               NULL,
+               /* Cookie implementation */
+               /*
+                * In this 32bit word the following information is coded:
+                * Bit 31 ... Bit 0
+                * SPI-Bus | SPI-Dev | Config-Pin | Done-Pin
+                */
+               FPGA_COOKIE(0, 1, 26, 7)
+       },
+       {
+               /* Family */
+               Altera_StratixV,
+               /* Interface type */
+               passive_serial,
+               /* No limitation as additional data will be ignored */
+               -1,
+               /* Device function table */
+               (void *)&stratixv_fns,
+               /* Base interface address specified in driver */
+               NULL,
+               /* Cookie implementation */
+               /*
+                * In this 32bit word the following information is coded:
+                * Bit 31 ... Bit 0
+                * SPI-Bus | SPI-Dev | Config-Pin | Done-Pin
+                */
+               FPGA_COOKIE(1, 2, 29, 9)
+       },
+};
+
+/* Add device descriptor to FPGA device table */
+void board_fpga_add(void)
+{
+       int i;
+
+       fpga_init();
+       for (i = 0; i < ARRAY_SIZE(altera_fpga); i++)
+               fpga_add(fpga_altera, &altera_fpga[i]);
+}