diff --git a/arch/arm/dts/armada-xp-theadorable.dts b/arch/arm/dts/armada-xp-theadorable.dts
index cf1be2a3d4eb94fa035c1343d876a561a0c85fc0..7087ccfc2f0f60565b7824233dbb055e2fb1942b 100644
--- a/arch/arm/dts/armada-xp-theadorable.dts
+++ b/arch/arm/dts/armada-xp-theadorable.dts
@@ -69,6 +69,7 @@
 
 	aliases {
 		spi0 = &spi0;
+		spi1 = &spi1;
 		ethernet0 = &eth0;
 	};
 
@@ -137,6 +138,26 @@
 					reg = <0>; /* Chip select 0 */
 					spi-max-frequency = <27777777>;
 				};
+
+				fpga@1 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "spi-generic-device";
+					reg = <1>; /* Chip select 1 */
+					spi-max-frequency = <27777777>;
+				};
+			};
+
+			spi1: spi@10680 {
+				status = "okay";
+
+				fpga@2 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "spi-generic-device";
+					reg = <2>; /* Chip select 2 */
+					spi-max-frequency = <27777777>;
+				};
 			};
 		};
 	};
diff --git a/arch/arm/include/asm/arch-mvebu/spi.h b/arch/arm/include/asm/arch-mvebu/spi.h
index e512dcec1621c8e5a3f336cc56521f2123f83097..526fea68e6a363f8272e0fb1bd37e40220d33961 100644
--- a/arch/arm/include/asm/arch-mvebu/spi.h
+++ b/arch/arm/include/asm/arch-mvebu/spi.h
@@ -19,6 +19,9 @@ struct kwspi_registers {
 	u32 din;	/* 0x1060c */
 	u32 irq_cause;	/* 0x10610 */
 	u32 irq_mask;	/* 0x10614 */
+	u32 timing1;	/* 0x10618 */
+	u32 timing2;	/* 0x1061c */
+	u32 dw_cfg;	/* 0x10620 - Direct Write Configuration */
 };
 
 /* They are used to define CONFIG_SYS_KW_SPI_MPP
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index 017d55f412ed01b9e871f7300c85a083cb5686dd..dd58b4adc45f4d13409d9ef0d14cb23833343732 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -47,6 +47,9 @@ enum cpu_attrib {
 	CPU_ATTR_DRAM_CS3 = 0x07,
 	CPU_ATTR_NANDFLASH = 0x2f,
 	CPU_ATTR_SPIFLASH = 0x1e,
+	CPU_ATTR_SPI0_CS0 = 0x1e,
+	CPU_ATTR_SPI0_CS1 = 0x5e,
+	CPU_ATTR_SPI1_CS2 = 0x9a,
 	CPU_ATTR_BOOTROM = 0x1d,
 	CPU_ATTR_PCIE_IO = 0xe0,
 	CPU_ATTR_PCIE_MEM = 0xe8,
diff --git a/board/Marvell/db-88f6820-gp/binary.0 b/board/Marvell/db-88f6820-gp/binary.0
deleted file mode 100644
index 57a4cbf3304693ab0c39f54ed2a5cee03caf1939..0000000000000000000000000000000000000000
--- a/board/Marvell/db-88f6820-gp/binary.0
+++ /dev/null
@@ -1,16 +0,0 @@
---------
-WARNING:
---------
-This file should contain the bin_hdr generated by the original Marvell
-U-Boot implementation. As this is currently not included in this
-U-Boot version, we have added this placeholder, so that the U-Boot
-image can be generated without errors.
-
-If you have a known to be working bin_hdr for your board, then you
-just need to replace this text file here with the binary header
-and recompile U-Boot.
-
-In a few weeks, mainline U-Boot will get support to generate the
-bin_hdr with the DDR training code itself. By implementing this code
-as SPL U-Boot. Then this file will not be needed any more and will
-get removed.
diff --git a/board/theadorable/Makefile b/board/theadorable/Makefile
index 9d5b39e696439bef79bf4801ce6df2f6548bb55c..ef5a519ada9c190c5abad7ff814ce3881cfc7657 100644
--- a/board/theadorable/Makefile
+++ b/board/theadorable/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-y	:= theadorable.o
+obj-y	+= fpga.o
diff --git a/board/theadorable/fpga.c b/board/theadorable/fpga.c
new file mode 100644
index 0000000000000000000000000000000000000000..6f068c38ada3e8f37bc2d0010802a617a8b4801b
--- /dev/null
+++ b/board/theadorable/fpga.c
@@ -0,0 +1,179 @@
+/*
+ * 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(&reg->ctrl);
+	config_reg = readl(&reg->cfg);
+	writel(0x00000214, &reg->cfg);		/* 27MHz clock */
+	writel(0x00000000, &reg->dw_cfg);	/* don't de-asset CS */
+	writel(KWSPI_CSN_ACT, &reg->ctrl);	/* activate CS */
+
+	/* Copy data to the SPI direct mapped window */
+	memcpy(dst, buf, len);
+
+	/* Restore original register values */
+	writel(control_reg, &reg->ctrl);
+	writel(config_reg, &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]);
+}
diff --git a/board/theadorable/theadorable.c b/board/theadorable/theadorable.c
index 0e232656fc906f05d95b84fd61797f39aa5dbda7..ee88a98a24169c0de3a0fef2592d1e89385aaf08 100644
--- a/board/theadorable/theadorable.c
+++ b/board/theadorable/theadorable.c
@@ -8,9 +8,11 @@
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
+#include <linux/mbus.h>
 #ifdef CONFIG_NET
 #include <netdev.h>
 #endif
+#include "theadorable.h"
 
 #include "../drivers/ddr/marvell/axp/ddr3_hw_training.h"
 #include "../arch/arm/mach-mvebu/serdes/axp/high_speed_env_spec.h"
@@ -136,6 +138,15 @@ int board_init(void)
 	/* adress of boot parameters */
 	gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
+	/*
+	 * Map SPI devices via MBUS so that they can be accessed via
+	 * the SPI direct access mode
+	 */
+	mbus_dt_setup_win(&mbus_state, SPI_BUS0_DEV1_BASE, SPI_BUS0_DEV1_SIZE,
+			  CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPI0_CS1);
+	mbus_dt_setup_win(&mbus_state, SPI_BUS1_DEV2_BASE, SPI_BUS0_DEV1_SIZE,
+			  CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPI1_CS2);
+
 	return 0;
 }
 
@@ -143,6 +154,8 @@ int checkboard(void)
 {
 	puts("Board: theadorable\n");
 
+	board_fpga_add();
+
 	return 0;
 }
 
diff --git a/board/theadorable/theadorable.h b/board/theadorable/theadorable.h
new file mode 100644
index 0000000000000000000000000000000000000000..89fe1179a4820177ade51780feb839c5c2d12592
--- /dev/null
+++ b/board/theadorable/theadorable.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/* Base addresses for the SPI direct access mode */
+#define SPI_BUS0_DEV1_BASE	0xe0000000
+#define SPI_BUS0_DEV1_SIZE	(1 << 20)
+#define SPI_BUS1_DEV2_BASE	(SPI_BUS0_DEV1_BASE + SPI_BUS0_DEV1_SIZE)
+
+void board_fpga_add(void);
diff --git a/configs/theadorable_debug_defconfig b/configs/theadorable_debug_defconfig
index 62a6ee6663bd4f9e76e64731c4fb41b4682aa028..054038a03bed673571ebcbd6152203595e9dbddf 100644
--- a/configs/theadorable_debug_defconfig
+++ b/configs/theadorable_debug_defconfig
@@ -2,6 +2,7 @@ CONFIG_ARM=y
 CONFIG_ARCH_MVEBU=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_TARGET_THEADORABLE=y
+CONFIG_DM_GPIO=y
 CONFIG_DEFAULT_DEVICE_TREE="armada-xp-theadorable"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL=y
@@ -10,7 +11,7 @@ CONFIG_FIT=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_SF=y
 CONFIG_CMD_USB=y
-# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPIO=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_OF_TRANSLATE=y
diff --git a/configs/theadorable_defconfig b/configs/theadorable_defconfig
index 4d5f3b0a0aaa608a5b4653674773d791ff2202bd..9a6abf2f7e33c1cf4cbe63211cc4373af91adcd4 100644
--- a/configs/theadorable_defconfig
+++ b/configs/theadorable_defconfig
@@ -2,6 +2,7 @@ CONFIG_ARM=y
 CONFIG_ARCH_MVEBU=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_TARGET_THEADORABLE=y
+CONFIG_DM_GPIO=y
 CONFIG_DEFAULT_DEVICE_TREE="armada-xp-theadorable"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL=y
@@ -9,7 +10,6 @@ CONFIG_FIT=y
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_SF=y
-# CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
diff --git a/drivers/ddr/marvell/a38x/ddr3_init.c b/drivers/ddr/marvell/a38x/ddr3_init.c
index 556f877039aa0bb488d0a279d41d54d90c378b71..ee05f57f43670409297cca0df0f14c9ac1de5a00 100644
--- a/drivers/ddr/marvell/a38x/ddr3_init.c
+++ b/drivers/ddr/marvell/a38x/ddr3_init.c
@@ -305,8 +305,6 @@ int ddr3_init(void)
 		SAR1_CPU_CORE_OFFSET;
 	switch (soc_num) {
 	case 0x3:
-		reg_bit_set(CPU_CONFIGURATION_REG(3), CPU_MRVL_ID_OFFSET);
-		reg_bit_set(CPU_CONFIGURATION_REG(2), CPU_MRVL_ID_OFFSET);
 	case 0x1:
 		reg_bit_set(CPU_CONFIGURATION_REG(1), CPU_MRVL_ID_OFFSET);
 	case 0x0:
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 6aa24d43590b68e24851cdc9919dab887e2a16de..fec3fecbdfbf0e8b06a37bf332f1237458f84240 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -17,5 +17,6 @@ obj-y += altera.o
 obj-$(CONFIG_FPGA_ACEX1K) += ACEX1K.o
 obj-$(CONFIG_FPGA_CYCLON2) += cyclon2.o
 obj-$(CONFIG_FPGA_STRATIX_II) += stratixII.o
+obj-$(CONFIG_FPGA_STRATIX_V) += stratixv.o
 obj-$(CONFIG_FPGA_SOCFPGA) += socfpga.o
 endif
diff --git a/drivers/fpga/altera.c b/drivers/fpga/altera.c
index a5bfe5dce19a3dce36d35053031bfe4bf24c775e..135a3572a83c9e9f8b9bbbc7b9faeac965aec770 100644
--- a/drivers/fpga/altera.c
+++ b/drivers/fpga/altera.c
@@ -37,6 +37,9 @@ static const struct altera_fpga {
 	{ Altera_StratixII, "StratixII", StratixII_load,
 	  StratixII_dump, StratixII_info },
 #endif
+#if defined(CONFIG_FPGA_STRATIX_V)
+	{ Altera_StratixV, "StratixV", stratixv_load, NULL, NULL },
+#endif
 #if defined(CONFIG_FPGA_SOCFPGA)
 	{ Altera_SoCFPGA, "SoC FPGA", socfpga_load, NULL, NULL },
 #endif
diff --git a/drivers/fpga/stratixv.c b/drivers/fpga/stratixv.c
new file mode 100644
index 0000000000000000000000000000000000000000..cc035eb2a14f50453d95ae814b3571b0f4ac32e0
--- /dev/null
+++ b/drivers/fpga/stratixv.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <altera.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+/* Write the RBF data to FPGA via SPI */
+static int program_write(int spi_bus, int spi_dev, const void *rbf_data,
+			 unsigned long rbf_size)
+{
+	struct spi_slave *slave;
+	int ret;
+
+	debug("%s (%d): data=%p size=%ld\n",
+	      __func__, __LINE__, rbf_data, rbf_size);
+
+	/* FIXME: How to get the max. SPI clock and SPI mode? */
+	slave = spi_setup_slave(spi_bus, spi_dev, 27777777, SPI_MODE_3);
+	if (!slave)
+		return -1;
+
+	if (spi_claim_bus(slave))
+		return -1;
+
+	ret = spi_xfer(slave, rbf_size * 8, rbf_data, (void *)rbf_data,
+		       SPI_XFER_BEGIN | SPI_XFER_END);
+
+	spi_release_bus(slave);
+
+	return ret;
+}
+
+/*
+ * This is the interface used by FPGA driver.
+ * Return 0 for sucess, non-zero for error.
+ */
+int stratixv_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
+{
+	altera_board_specific_func *pfns = desc->iface_fns;
+	int cookie = desc->cookie;
+	int spi_bus;
+	int spi_dev;
+	int ret = 0;
+
+	if ((u32)rbf_data & 0x3) {
+		puts("FPGA: Unaligned data, realign to 32bit boundary.\n");
+		return -EINVAL;
+	}
+
+	/* Run the pre configuration function if there is one */
+	if (pfns->pre)
+		(pfns->pre)(cookie);
+
+	/* Establish the initial state */
+	if (pfns->config) {
+		/* De-assert nCONFIG */
+		(pfns->config)(false, true, cookie);
+
+		/* nConfig minimum low pulse width is 2us */
+		udelay(200);
+
+		/* Assert nCONFIG */
+		(pfns->config)(true, true, cookie);
+
+		/* nCONFIG high to first rising clock on DCLK min 1506 us */
+		udelay(1600);
+	}
+
+	/* Write the RBF data to FPGA */
+	if (pfns->write) {
+		/*
+		 * Use board specific data function to write bitstream
+		 * into the FPGA
+		 */
+		ret = (pfns->write)(rbf_data, rbf_size, true, cookie);
+	} else {
+		/*
+		 * Use common SPI functions to write bitstream into the
+		 * FPGA
+		 */
+		spi_bus = COOKIE2SPI_BUS(cookie);
+		spi_dev = COOKIE2SPI_DEV(cookie);
+		ret = program_write(spi_bus, spi_dev, rbf_data, rbf_size);
+	}
+	if (ret)
+		return ret;
+
+	/* Check done pin */
+	if (pfns->done) {
+		ret = (pfns->done)(cookie);
+
+		if (ret)
+			printf("Error: DONE not set (ret=%d)!\n", ret);
+	}
+
+	return ret;
+}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a5da5e7e8825f4bf3ed8f1e00f934ac997ad4608..23113090b3982208fd09f8410b6b43c94d31edbd 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -105,4 +105,11 @@ config PIC32_GPIO
 	help
 	  Say yes here to support Microchip PIC32 GPIOs.
 
+config MVEBU_GPIO
+	bool "Marvell MVEBU GPIO driver"
+	depends on DM_GPIO && ARCH_MVEBU
+	default y
+	help
+	  Say yes here to support Marvell MVEBU (Armada XP/38x) GPIOs.
+
 endmenu
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index e7b7ec45b7a02b107e0de54cce9466fda26f97e0..ea6e2ede0d8f7179b2a74d97f98a1057b603df0e 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -49,3 +49,4 @@ obj-$(CONFIG_ZYNQ_GPIO)		+= zynq_gpio.o
 obj-$(CONFIG_VYBRID_GPIO)	+= vybrid_gpio.o
 obj-$(CONFIG_HIKEY_GPIO)	+= hi6220_gpio.o
 obj-$(CONFIG_PIC32_GPIO)	+= pic32_gpio.o
+obj-$(CONFIG_MVEBU_GPIO)	+= mvebu_gpio.o
diff --git a/drivers/gpio/mvebu_gpio.c b/drivers/gpio/mvebu_gpio.c
new file mode 100644
index 0000000000000000000000000000000000000000..9564ce2b13ea9f313f006d5e6a5448fad36bbd76
--- /dev/null
+++ b/drivers/gpio/mvebu_gpio.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define MVEBU_GPIOS_PER_BANK	32
+
+struct mvebu_gpio_regs {
+	u32 data_out;
+	u32 io_conf;
+	u32 blink_en;
+	u32 in_pol;
+	u32 data_in;
+};
+
+struct mvebu_gpio_priv {
+	struct mvebu_gpio_regs *regs;
+	char name[2];
+};
+
+static int mvebu_gpio_direction_input(struct udevice *dev, unsigned int gpio)
+{
+	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+	struct mvebu_gpio_regs *regs = priv->regs;
+
+	setbits_le32(&regs->io_conf, BIT(gpio));
+
+	return 0;
+}
+
+static int mvebu_gpio_direction_output(struct udevice *dev, unsigned gpio,
+				       int value)
+{
+	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+	struct mvebu_gpio_regs *regs = priv->regs;
+
+	clrbits_le32(&regs->io_conf, BIT(gpio));
+
+	return 0;
+}
+
+static int mvebu_gpio_get_function(struct udevice *dev, unsigned gpio)
+{
+	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+	struct mvebu_gpio_regs *regs = priv->regs;
+	u32 val;
+
+	val = readl(&regs->io_conf) & BIT(gpio);
+	if (val)
+		return GPIOF_INPUT;
+	else
+		return GPIOF_OUTPUT;
+}
+
+static int mvebu_gpio_set_value(struct udevice *dev, unsigned gpio,
+				int value)
+{
+	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+	struct mvebu_gpio_regs *regs = priv->regs;
+
+	if (value)
+		setbits_le32(&regs->data_out, BIT(gpio));
+	else
+		clrbits_le32(&regs->data_out, BIT(gpio));
+
+	return 0;
+}
+
+static int mvebu_gpio_get_value(struct udevice *dev, unsigned gpio)
+{
+	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+	struct mvebu_gpio_regs *regs = priv->regs;
+
+	return !!(readl(&regs->data_in) & BIT(gpio));
+}
+
+static int mvebu_gpio_probe(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+
+	priv->regs = (struct mvebu_gpio_regs *)dev_get_addr(dev);
+	uc_priv->gpio_count = MVEBU_GPIOS_PER_BANK;
+	priv->name[0] = 'A' + dev->req_seq;
+	uc_priv->bank_name = priv->name;
+
+	return 0;
+}
+
+static const struct dm_gpio_ops mvebu_gpio_ops = {
+	.direction_input	= mvebu_gpio_direction_input,
+	.direction_output	= mvebu_gpio_direction_output,
+	.get_function		= mvebu_gpio_get_function,
+	.get_value		= mvebu_gpio_get_value,
+	.set_value		= mvebu_gpio_set_value,
+};
+
+static const struct udevice_id mvebu_gpio_ids[] = {
+	{ .compatible = "marvell,orion-gpio" },
+	{ }
+};
+
+U_BOOT_DRIVER(gpio_mvebu) = {
+	.name			= "gpio_mvebu",
+	.id			= UCLASS_GPIO,
+	.of_match		= mvebu_gpio_ids,
+	.ops			= &mvebu_gpio_ops,
+	.probe			= mvebu_gpio_probe,
+	.priv_auto_alloc_size	= sizeof(struct mvebu_gpio_priv),
+};
diff --git a/include/altera.h b/include/altera.h
index c2991ad800073b0de56c844456eade3d8e823023..48d3eb73c9899f67a44464c4b26dbf92f85cb816 100644
--- a/include/altera.h
+++ b/include/altera.h
@@ -10,6 +10,19 @@
 #ifndef _ALTERA_H_
 #define _ALTERA_H_
 
+/*
+ * For the StratixV FPGA programming via SPI, the following
+ * information is coded in the 32bit cookie:
+ * Bit 31 ... Bit 0
+ * SPI-Bus | SPI-Dev | Config-Pin | Done-Pin
+ */
+#define FPGA_COOKIE(bus, dev, config, done)			\
+	(((bus) << 24) | ((dev) << 16) | ((config) << 8) | (done))
+#define COOKIE2SPI_BUS(c)	(((c) >> 24) & 0xff)
+#define COOKIE2SPI_DEV(c)	(((c) >> 16) & 0xff)
+#define COOKIE2CONFIG(c)	(((c) >> 8) & 0xff)
+#define COOKIE2DONE(c)		((c) & 0xff)
+
 enum altera_iface {
 	/* insert all new types after this */
 	min_altera_iface_type,
@@ -40,6 +53,8 @@ enum altera_family {
 	Altera_CYC2,
 	/* StratixII Family */
 	Altera_StratixII,
+	/* StratixV Family */
+	Altera_StratixV,
 	/* SoCFPGA Family */
 	Altera_SoCFPGA,
 
@@ -89,6 +104,7 @@ typedef struct {
 	Altera_done_fn done;
 	Altera_clk_fn clk;
 	Altera_data_fn data;
+	Altera_write_fn write;
 	Altera_abort_fn abort;
 	Altera_post_fn post;
 } altera_board_specific_func;
@@ -97,4 +113,8 @@ typedef struct {
 int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size);
 #endif
 
+#ifdef CONFIG_FPGA_STRATIX_V
+int stratixv_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size);
+#endif
+
 #endif /* _ALTERA_H_ */
diff --git a/include/configs/sheevaplug.h b/include/configs/sheevaplug.h
index c529636a66def1c894330942a8fc657bc8d8f033..f9fb9bc9afb55797c86ff5dac01923bc14e997ba 100644
--- a/include/configs/sheevaplug.h
+++ b/include/configs/sheevaplug.h
@@ -64,12 +64,12 @@
 
 #define CONFIG_MTDPARTS		\
 	"orion_nand:512K(uboot),"				\
-	"512K(env),1M(script),6M(kernel),"				\
-	"12M(ramdisk),4M(spare),-(rootfs)\0"
+	"512K(env),4M(kernel),"					\
+	"-(rootfs)\0"
 
 #define CONFIG_EXTRA_ENV_SETTINGS	"x_bootargs=console"	\
 	"=ttyS0,115200 mtdparts="CONFIG_MTDPARTS	\
-	"x_bootcmd_kernel=nand read 0x6400000 0x100000 0x300000\0" \
+	"x_bootcmd_kernel=nand read 0x6400000 0x100000 0x400000\0" \
 	"x_bootcmd_usb=usb start\0" \
 	"x_bootargs_root=root=/dev/mtdblock3 rw rootfstype=jffs2\0"
 
diff --git a/include/configs/theadorable.h b/include/configs/theadorable.h
index 9f186add71f427af7430b1a7235c9222d3ebe56b..a4bcf212108ed7b4d0d111bc07ffe850717b5576 100644
--- a/include/configs/theadorable.h
+++ b/include/configs/theadorable.h
@@ -114,6 +114,11 @@
 #define CONFIG_VGA_AS_SINGLE_DEVICE
 #define CONFIG_CMD_BMP
 
+/* FPGA programming support */
+#define CONFIG_FPGA
+#define CONFIG_FPGA_ALTERA
+#define CONFIG_FPGA_STRATIX_V
+
 /*
  * mv-common.h should be defined after CMD configs since it used them
  * to enable certain macros
diff --git a/tools/kwboot.c b/tools/kwboot.c
index 905ade3b01236d11e4727e32a354c9d866ca618a..e00958a4ce593cb9060e84b03dc365311b7acc20 100644
--- a/tools/kwboot.c
+++ b/tools/kwboot.c
@@ -76,6 +76,7 @@ static int kwboot_verbose;
 
 static int msg_req_delay = KWBOOT_MSG_REQ_DELAY;
 static int msg_rsp_timeo = KWBOOT_MSG_RSP_TIMEO;
+static int blk_rsp_timeo = KWBOOT_BLK_RSP_TIMEO;
 
 static void
 kwboot_printv(const char *fmt, ...)
@@ -380,7 +381,7 @@ kwboot_xm_sendblock(int fd, struct kwboot_block *block)
 			break;
 
 		do {
-			rc = kwboot_tty_recv(fd, &c, 1, KWBOOT_BLK_RSP_TIMEO);
+			rc = kwboot_tty_recv(fd, &c, 1, blk_rsp_timeo);
 			if (rc)
 				break;
 
@@ -684,7 +685,7 @@ static void
 kwboot_usage(FILE *stream, char *progname)
 {
 	fprintf(stream,
-		"Usage: %s [-d | -a | -q <req-delay> | -s <resp-timeo> | -b <image> | -D <image> ] [ -t ] [-B <baud> ] <TTY>\n",
+		"Usage: %s [OPTIONS] [-b <image> | -D <image> ] [-B <baud> ] <TTY>\n",
 		progname);
 	fprintf(stream, "\n");
 	fprintf(stream,
@@ -696,6 +697,8 @@ kwboot_usage(FILE *stream, char *progname)
 	fprintf(stream, "  -a: use timings for Armada XP\n");
 	fprintf(stream, "  -q <req-delay>:  use specific request-delay\n");
 	fprintf(stream, "  -s <resp-timeo>: use specific response-timeout\n");
+	fprintf(stream,
+		"  -o <block-timeo>: use specific xmodem block timeout\n");
 	fprintf(stream, "\n");
 	fprintf(stream, "  -t: mini terminal\n");
 	fprintf(stream, "\n");
@@ -728,7 +731,7 @@ main(int argc, char **argv)
 	kwboot_verbose = isatty(STDOUT_FILENO);
 
 	do {
-		int c = getopt(argc, argv, "hb:ptaB:dD:q:s:");
+		int c = getopt(argc, argv, "hb:ptaB:dD:q:s:o:");
 		if (c < 0)
 			break;
 
@@ -768,6 +771,10 @@ main(int argc, char **argv)
 			msg_rsp_timeo = atoi(optarg);
 			break;
 
+		case 'o':
+			blk_rsp_timeo = atoi(optarg);
+			break;
+
 		case 'B':
 			speed = kwboot_tty_speed(atoi(optarg));
 			if (speed == -1)