diff --git a/arch/arm/dts/armada-7040-db.dts b/arch/arm/dts/armada-7040-db.dts
index b8fe5a9cb93dcf9e4e49505800f182d7fb8b58df..466c6dcc3f3b25c7038b0ae0a63074a012a2aedf 100644
--- a/arch/arm/dts/armada-7040-db.dts
+++ b/arch/arm/dts/armada-7040-db.dts
@@ -66,36 +66,14 @@
 	};
 };
 
-&i2c0 {
-	status = "okay";
-	clock-frequency = <100000>;
-};
-
-&spi0 {
-	status = "okay";
-
-	spi-flash@0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "jedec,spi-nor";
-		reg = <0>;
-		spi-max-frequency = <10000000>;
-
-		partitions {
-			compatible = "fixed-partitions";
-			#address-cells = <1>;
-			#size-cells = <1>;
-
-			partition@0 {
-				label = "U-Boot";
-				reg = <0 0x200000>;
-			};
-			partition@400000 {
-				label = "Filesystem";
-				reg = <0x200000 0xce0000>;
-			};
-		};
-	};
+&ap_pinctl {
+	   /* MPP Bus:
+	    * SDIO  [0-5]
+	    * UART0 [11,19]
+	    */
+		  /* 0 1 2 3 4 5 6 7 8 9 */
+	pin-func = < 1 1 1 1 1 1 0 0 0 0
+		     0 3 0 0 0 0 0 0 0 3 >;
 };
 
 &uart0 {
@@ -108,11 +86,37 @@
 };
 
 &cpm_i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_i2c0_pins>;
 	status = "okay";
 	clock-frequency = <100000>;
 };
 
+&cpm_pinctl {
+		/* MPP Bus:
+		 * TDM	 [0-11]
+		 * SPI   [13-16]
+		 * SATA1 [28]
+		 * UART0 [29-30]
+		 * SMI	 [32,34]
+		 * XSMI  [35-36]
+		 * I2C	 [37-38]
+		 * RGMII1[44-55]
+		 * SD	 [56-62]
+		 */
+		/*   0   1   2   3   4   5   6   7   8   9 */
+	pin-func = < 4   4   4   4   4   4   4   4   4   4
+		     4   4   0   3   3   3   3   0   0   0
+		     0   0   0   0   0   0   0   0   9   0xA
+		     0xA 0   7   0   7   7   7   2   2   0
+		     0   0   0   0   1   1   1   1   1   1
+		     1   1   1   1   1   1   0xE 0xE 0xE 0xE
+		     0xE 0xE 0xE >;
+};
+
 &cpm_spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_spi0_pins>;
 	status = "okay";
 
 	spi-flash@0 {
diff --git a/arch/arm/dts/armada-8040-db.dts b/arch/arm/dts/armada-8040-db.dts
index 7fb674b8b77fe94b2e0a223bd274e4d45ccd2309..40def9d6cddff4551c1ded6b13c08fbfe241b382 100644
--- a/arch/arm/dts/armada-8040-db.dts
+++ b/arch/arm/dts/armada-8040-db.dts
@@ -57,7 +57,7 @@
 
 	aliases {
 		i2c0 = &cpm_i2c0;
-		spi0 = &spi0;
+		spi0 = &cps_spi1;
 	};
 
 	memory@00000000 {
@@ -66,50 +66,55 @@
 	};
 };
 
-&i2c0 {
+/* Accessible over the mini-USB CON9 connector on the main board */
+&uart0 {
 	status = "okay";
-	clock-frequency = <100000>;
 };
 
-&spi0 {
-	status = "okay";
-
-	spi-flash@0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "jedec,spi-nor";
-		reg = <0>;
-		spi-max-frequency = <10000000>;
-
-		partitions {
-			compatible = "fixed-partitions";
-			#address-cells = <1>;
-			#size-cells = <1>;
-
-			partition@0 {
-				label = "U-Boot";
-				reg = <0 0x200000>;
-			};
-			partition@400000 {
-				label = "Filesystem";
-				reg = <0x200000 0xce0000>;
-			};
-		};
-	};
+&ap_pinctl {
+	/* MPP Bus:
+	 * SDIO  [0-10]
+	 * UART0 [11,19]
+	 */
+		  /* 0 1 2 3 4 5 6 7 8 9 */
+	pin-func = < 1 1 1 1 1 1 1 1 1 1
+		     1 3 0 0 0 0 0 0 0 3 >;
 };
 
-/* Accessible over the mini-USB CON9 connector on the main board */
-&uart0 {
-	status = "okay";
+&cpm_pinctl {
+	/* MPP Bus:
+	 * [0-31] = 0xff: Keep default CP0_shared_pins:
+	 * [11] CLKOUT_MPP_11 (out)
+	 * [23] LINK_RD_IN_CP2CP (in)
+	 * [25] CLKOUT_MPP_25 (out)
+	 * [29] AVS_FB_IN_CP2CP (in)
+	 * [32,34] SMI
+	 * [31]    GPIO: push button/Wake
+	 * [35-36] GPIO
+	 * [37-38] I2C
+	 * [40-41] SATA[0/1]_PRESENT_ACTIVEn
+	 * [42-43] XSMI
+	 * [44-55] RGMII1
+	 * [56-62] SD
+	 */
+		/*   0    1    2    3    4    5    6    7    8    9 */
+	pin-func = < 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0    7    0    7    0    0    2    2    0
+		     0    0    8    8    1    1    1    1    1    1
+		     1    1    1    1    1    1    0xe  0xe  0xe  0xe
+		     0xe  0xe  0xe >;
 };
 
-
 /* CON5 on CP0 expansion */
 &cpm_pcie2 {
 	status = "okay";
 };
 
 &cpm_i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpm_i2c0_pins>;
 	status = "okay";
 	clock-frequency = <100000>;
 };
@@ -129,14 +134,55 @@
 	status = "okay";
 };
 
+&cps_pinctl {
+	/* MPP Bus:
+	 * [0-11]  RGMII0
+	 * [13-16] SPI1
+	 * [27,31] GE_MDIO/MDC
+	 * [32-62] = 0xff: Keep default CP1_shared_pins:
+	 */
+		/*   0    1    2    3    4    5    6    7    8    9 */
+	pin-func = < 0x3  0x3  0x3  0x3  0x3  0x3  0x3  0x3  0x3  0x3
+		     0x3  0x3  0xff 0x3  0x3  0x3  0x3  0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x8  0xff 0xff
+		     0xff 0x8  0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+		     0xff 0xff 0xff >;
+};
+
 /* CON5 on CP1 expansion */
 &cps_pcie2 {
 	status = "okay";
 };
 
-&cps_i2c0 {
+&cps_spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cps_spi1_pins>;
 	status = "okay";
-	clock-frequency = <100000>;
+
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-Boot";
+				reg = <0 0x200000>;
+			};
+			partition@400000 {
+				label = "Filesystem";
+				reg = <0x200000 0xce0000>;
+			};
+		};
+	};
 };
 
 /* CON4 on CP1 expansion */
diff --git a/arch/arm/dts/armada-ap806.dtsi b/arch/arm/dts/armada-ap806.dtsi
index d315b29cd0583213488a5018913414474904b024..efb383b9f394cd29bdc3e5e67bff778bd3e14852 100644
--- a/arch/arm/dts/armada-ap806.dtsi
+++ b/arch/arm/dts/armada-ap806.dtsi
@@ -140,6 +140,24 @@
 				marvell,spi-base = <128>, <136>, <144>, <152>;
 			};
 
+			ap_pinctl: ap-pinctl@6F4000 {
+				compatible = "marvell,armada-ap806-pinctrl";
+				bank-name ="apn-806";
+				reg = <0x6F4000 0x10>;
+				pin-count = <20>;
+				max-func = <3>;
+
+				ap_i2c0_pins: i2c-pins-0 {
+					marvell,pins = < 4 5 >;
+					marvell,function = <3>;
+				};
+				ap_emmc_pins: emmc-pins-0 {
+					marvell,pins = < 0 1 2 3 4 5 6 7
+							 8 9 10 >;
+					marvell,function = <1>;
+				};
+			};
+
 			xor@400000 {
 				compatible = "marvell,mv-xor-v2";
 				reg = <0x400000 0x1000>,
diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi
index 422d7544012df6733f68f9499c1d44a9b1af5c5e..d637867615fd190b44a55efcfbea8efaf9451b4a 100644
--- a/arch/arm/dts/armada-cp110-master.dtsi
+++ b/arch/arm/dts/armada-cp110-master.dtsi
@@ -81,6 +81,38 @@
 					"cpm-usb3dev", "cpm-eip150", "cpm-eip197";
 			};
 
+			cpm_pinctl: cpm-pinctl@440000 {
+				compatible = "marvell,mvebu-pinctrl",
+					     "marvell,a70x0-pinctrl",
+					     "marvell,a80x0-cp0-pinctrl";
+				bank-name ="cp0-110";
+				reg = <0x440000 0x20>;
+				pin-count = <63>;
+				max-func = <0xf>;
+
+				cpm_i2c0_pins: cpm-i2c-pins-0 {
+					marvell,pins = < 37 38 >;
+					marvell,function = <2>;
+				};
+				cpm_ge2_rgmii_pins: cpm-ge-rgmii-pins-0 {
+					marvell,pins = < 44 45 46 47 48 49 50 51
+							 52 53 54 55 >;
+					marvell,function = <1>;
+				};
+				pca0_pins: cpm-pca0_pins {
+					marvell,pins = <62>;
+					marvell,function = <0>;
+				};
+				cpm_sdhci_pins: cpm-sdhi-pins-0 {
+					marvell,pins = < 56 57 58 59 60 61 >;
+					marvell,function = <14>;
+				};
+				cpm_spi0_pins: cpm-spi-pins-0 {
+					marvell,pins = < 13 14 15 16 >;
+					marvell,function = <3>;
+				};
+			};
+
 			cpm_sata0: sata@540000 {
 				compatible = "marvell,armada-8k-ahci";
 				reg = <0x540000 0x30000>;
diff --git a/arch/arm/dts/armada-cp110-slave.dtsi b/arch/arm/dts/armada-cp110-slave.dtsi
index a7f77b95153c91e34b7d8eb06e6f1d69c2517be2..92ef55cf267218834f9e63dcee0f4c5826d31d23 100644
--- a/arch/arm/dts/armada-cp110-slave.dtsi
+++ b/arch/arm/dts/armada-cp110-slave.dtsi
@@ -81,6 +81,25 @@
 					"cps-usb3dev", "cps-eip150", "cps-eip197";
 			};
 
+			cps_pinctl: cps-pinctl@440000 {
+				compatible = "marvell,mvebu-pinctrl",
+					     "marvell,a80x0-cp1-pinctrl";
+				bank-name ="cp1-110";
+				reg = <0x440000 0x20>;
+				pin-count = <63>;
+				max-func = <0xf>;
+
+				cps_ge1_rgmii_pins: cps-ge-rgmii-pins-0 {
+					marvell,pins = < 0  1  2  3  4  5  6  7
+							 8  9  10 11 >;
+					marvell,function = <3>;
+				};
+				cps_spi1_pins: cps-spi-pins-1 {
+					marvell,pins = < 13 14 15 16 >;
+					marvell,function = <3>;
+				};
+			};
+
 			cps_sata0: sata@540000 {
 				compatible = "marvell,armada-8k-ahci";
 				reg = <0x540000 0x30000>;
diff --git a/arch/arm/include/asm/arch-armada8k/cache_llc.h b/arch/arm/include/asm/arch-armada8k/cache_llc.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f97e6d7766828ea19d6d33822b391ac0b5ae213
--- /dev/null
+++ b/arch/arm/include/asm/arch-armada8k/cache_llc.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ * https://spdx.org/licenses
+ */
+
+#ifndef _CACHE_LLC_H_
+#define _CACHE_LLC_H_
+
+/* Armada-7K/8K last level cache */
+
+#define MVEBU_A8K_REGS_BASE_MSB		0xf000
+#define LLC_BASE_ADDR			0x8000
+#define LLC_CACHE_SYNC			0x700
+#define LLC_CACHE_SYNC_COMPLETE		0x730
+#define LLC_FLUSH_BY_WAY		0x7fc
+#define LLC_WAY_MASK			0xffffffff
+#define LLC_CACHE_SYNC_MASK		0x1
+
+#endif	/* _CACHE_LLC_H_ */
diff --git a/arch/arm/include/asm/arch-armada8k/soc-info.h b/arch/arm/include/asm/arch-armada8k/soc-info.h
new file mode 100644
index 0000000000000000000000000000000000000000..bae39951eed00bb97bfc112bb5f915395f828cf4
--- /dev/null
+++ b/arch/arm/include/asm/arch-armada8k/soc-info.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ * https://spdx.org/licenses
+ */
+
+#ifndef _SOC_INFO_H_
+#define _SOC_INFO_H_
+
+/* Pin Ctrl driver definitions */
+#define BITS_PER_PIN		4
+#define PIN_FUNC_MASK		((1 << BITS_PER_PIN) - 1)
+#define PIN_REG_SHIFT		3
+#define PIN_FIELD_MASK		((1 << PIN_REG_SHIFT) - 1)
+
+#endif	/* _SOC_INFO_H_ */
diff --git a/arch/arm/mach-mvebu/armada8k/Makefile b/arch/arm/mach-mvebu/armada8k/Makefile
index 84c69d90e73f1b5840ed738da824b04c72c9c3de..0facf14942df62d39ecc52e773b36341b37ae5e2 100644
--- a/arch/arm/mach-mvebu/armada8k/Makefile
+++ b/arch/arm/mach-mvebu/armada8k/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-y = cpu.o
+obj-y += cache_llc.o
diff --git a/arch/arm/mach-mvebu/armada8k/cache_llc.S b/arch/arm/mach-mvebu/armada8k/cache_llc.S
new file mode 100644
index 0000000000000000000000000000000000000000..71aecb2dde807c6a32a9c779c0bdcf8971d25749
--- /dev/null
+++ b/arch/arm/mach-mvebu/armada8k/cache_llc.S
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ * https://spdx.org/licenses
+ */
+
+#include <asm/arch-armada8k/cache_llc.h>
+#include <linux/linkage.h>
+
+/*
+ * int __asm_flush_l3_dcache
+ *
+ * flush Armada-8K last level cache.
+ *
+ */
+ENTRY(__asm_flush_l3_dcache)
+	/* flush cache */
+	mov     x0, #LLC_BASE_ADDR
+	add	x0, x0, #LLC_FLUSH_BY_WAY
+	movk    x0, #MVEBU_A8K_REGS_BASE_MSB, lsl #16
+	mov     w1, #LLC_WAY_MASK
+	str     w1, [x0]
+	/* sync cache */
+	mov     x0, #LLC_BASE_ADDR
+	add	x0, x0, #LLC_CACHE_SYNC
+	movk    x0, #MVEBU_A8K_REGS_BASE_MSB, lsl #16
+	str     wzr, [x0]
+	/* check that cache sync completed */
+	mov     x0, #LLC_BASE_ADDR
+	add	x0, x0, #LLC_CACHE_SYNC_COMPLETE
+	movk    x0, #MVEBU_A8K_REGS_BASE_MSB, lsl #16
+1:	ldr	w1, [x0]
+	and	w1, w1, #LLC_CACHE_SYNC_MASK
+	cbnz	w1, 1b
+	/* return success */
+	mov	x0, #0
+	ret
+ENDPROC(__asm_flush_l3_dcache)
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 586a6456e4f3597e74fef347e3ffbb1841d62abe..bffa7134f7513bf46e8f98623e5637bda0b8c24a 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -653,6 +653,9 @@ config CMD_QFW
 	  This provides access to the QEMU firmware interface.  The main
 	  feature is to allow easy loading of files passed to qemu-system
 	  via -kernel / -initrd
+
+source "cmd/mvebu/Kconfig"
+
 endmenu
 
 config CMD_BOOTSTAGE
diff --git a/cmd/Makefile b/cmd/Makefile
index 9c9a9d112b0db745fd798e880a8e6559fbcd5148..34bc5448b9382fcb35fe9781bb30743db79ca463 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -163,3 +163,5 @@ obj-$(CONFIG_CMD_BLOB) += blob.o
 
 # core command
 obj-y += nvedit.o
+
+obj-$(CONFIG_ARCH_MVEBU) += mvebu/
diff --git a/cmd/mvebu/Kconfig b/cmd/mvebu/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..ad10a572a365eaad248f2a89329f37d4faa989a4
--- /dev/null
+++ b/cmd/mvebu/Kconfig
@@ -0,0 +1,52 @@
+menu "MVEBU commands"
+depends on ARCH_MVEBU
+
+config CMD_MVEBU_BUBT
+	bool "bubt"
+	default n
+	help
+	  bubt - Burn a u-boot image to flash
+	  For details about bubt command please see the documentation
+	  in doc/mvebu/cmd/bubt.txt
+
+choice
+	prompt "Flash for image"
+	default MVEBU_SPI_BOOT
+
+config MVEBU_NAND_BOOT
+	bool "NAND flash boot"
+	depends on NAND_PXA3XX
+	help
+	  Enable boot from NAND flash.
+	  Allow usage of NAND flash as a target for "bubt" command
+	  For details about bubt command please see the documentation
+	  in doc/mvebu/cmd/bubt.txt
+
+config MVEBU_SPI_BOOT
+	bool "SPI flash boot"
+	depends on SPI_FLASH
+	help
+	  Enable boot from SPI flash.
+	  Allow usage of SPI flash as a target for "bubt" command
+	  For details about bubt command please see the documentation
+	  in doc/mvebu/cmd/bubt.txt
+
+config MVEBU_MMC_BOOT
+	bool "eMMC flash boot"
+	depends on MVEBU_MMC
+	help
+	  Enable boot from eMMC boot partition
+	  Allow usage of eMMC/SD device as a target for "bubt" command
+	  For details about bubt command please see the documentation
+	  in doc/mvebu/cmd/bubt.txt
+
+endchoice
+
+config MVEBU_UBOOT_DFLT_NAME
+	string "Default image name for bubt command"
+	default "flash-image.bin"
+	help
+	  This option should contain a default file name to be used with
+	  MVEBU "bubt" command if the source file name is omitted
+
+endmenu
diff --git a/cmd/mvebu/Makefile b/cmd/mvebu/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..03de53ecddbf34519aab87f9f19336bf7ae4cb73
--- /dev/null
+++ b/cmd/mvebu/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (C) 2016 Marvell International Ltd.
+#
+# SPDX-License-Identifier:	GPL-2.0
+# https://spdx.org/licenses
+
+
+obj-$(CONFIG_CMD_MVEBU_BUBT) += bubt.o
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c
new file mode 100644
index 0000000000000000000000000000000000000000..1cbfcf0863548eafdd823ead29455a03e8624a79
--- /dev/null
+++ b/cmd/mvebu/bubt.c
@@ -0,0 +1,767 @@
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ * https://spdx.org/licenses
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+#include <vsprintf.h>
+#include <errno.h>
+#include <dm.h>
+
+#include <spi_flash.h>
+#include <spi.h>
+#include <nand.h>
+#include <usb.h>
+#include <fs.h>
+#include <mmc.h>
+#include <u-boot/sha1.h>
+#include <u-boot/sha256.h>
+
+#ifndef CONFIG_SYS_MMC_ENV_DEV
+#define CONFIG_SYS_MMC_ENV_DEV	0
+#endif
+
+#if defined(CONFIG_ARMADA_8K)
+#define MAIN_HDR_MAGIC		0xB105B002
+
+struct mvebu_image_header {
+	u32	magic;			/*  0-3  */
+	u32	prolog_size;		/*  4-7  */
+	u32	prolog_checksum;	/*  8-11 */
+	u32	boot_image_size;	/* 12-15 */
+	u32	boot_image_checksum;	/* 16-19 */
+	u32	rsrvd0;			/* 20-23 */
+	u32	load_addr;		/* 24-27 */
+	u32	exec_addr;		/* 28-31 */
+	u8	uart_cfg;		/*  32   */
+	u8	baudrate;		/*  33   */
+	u8	ext_count;		/*  34   */
+	u8	aux_flags;		/*  35   */
+	u32	io_arg_0;		/* 36-39 */
+	u32	io_arg_1;		/* 40-43 */
+	u32	io_arg_2;		/* 43-47 */
+	u32	io_arg_3;		/* 48-51 */
+	u32	rsrvd1;			/* 52-55 */
+	u32	rsrvd2;			/* 56-59 */
+	u32	rsrvd3;			/* 60-63 */
+};
+#elif defined(CONFIG_ARMADA_3700)	/* A3700 */
+#define HASH_SUM_LEN		16
+#define IMAGE_VERSION_3_6_0	0x030600
+#define IMAGE_VERSION_3_5_0	0x030500
+
+struct common_tim_data {
+	u32	version;
+	u32	identifier;
+	u32	trusted;
+	u32	issue_date;
+	u32	oem_unique_id;
+	u32	reserved[5];		/* Reserve 20 bytes */
+	u32	boot_flash_sign;
+	u32	num_images;
+	u32	num_keys;
+	u32	size_of_reserved;
+};
+
+struct mvebu_image_info {
+	u32	image_id;
+	u32	next_image_id;
+	u32	flash_entry_addr;
+	u32	load_addr;
+	u32	image_size;
+	u32	image_size_to_hash;
+	u32	hash_algorithm_id;
+	u32	hash[HASH_SUM_LEN];	/* Reserve 512 bits for the hash */
+	u32	partition_number;
+	u32	enc_algorithm_id;
+	u32	encrypt_start_offset;
+	u32	encrypt_size;
+};
+#endif /* CONFIG_ARMADA_XXX */
+
+struct bubt_dev {
+	char name[8];
+	size_t (*read)(const char *file_name);
+	int (*write)(size_t image_size);
+	int (*active)(void);
+};
+
+static ulong get_load_addr(void)
+{
+	const char *addr_str;
+	unsigned long addr;
+
+	addr_str = getenv("loadaddr");
+	if (addr_str)
+		addr = simple_strtoul(addr_str, NULL, 16);
+	else
+		addr = CONFIG_SYS_LOAD_ADDR;
+
+	return addr;
+}
+
+/********************************************************************
+ *     eMMC services
+ ********************************************************************/
+#ifdef CONFIG_DM_MMC
+static int mmc_burn_image(size_t image_size)
+{
+	struct mmc	*mmc;
+	lbaint_t	start_lba;
+	lbaint_t	blk_count;
+	ulong		blk_written;
+	int		err;
+	const u8	mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
+
+	mmc = find_mmc_device(mmc_dev_num);
+	if (!mmc) {
+		printf("No SD/MMC/eMMC card found\n");
+		return -ENOMEDIUM;
+	}
+
+	err = mmc_init(mmc);
+	if (err) {
+		printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
+		       mmc_dev_num);
+		return err;
+	}
+
+#ifdef CONFIG_SYS_MMC_ENV_PART
+	if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART) {
+		err = mmc_switch_part(mmc_dev_num, CONFIG_SYS_MMC_ENV_PART);
+		if (err) {
+			printf("MMC partition switch failed\n");
+			return err;
+		}
+	}
+#endif
+
+	/* SD reserves LBA-0 for MBR and boots from LBA-1,
+	 * MMC/eMMC boots from LBA-0
+	 */
+	start_lba = IS_SD(mmc) ? 1 : 0;
+	blk_count = image_size / mmc->block_dev.blksz;
+	if (image_size % mmc->block_dev.blksz)
+		blk_count += 1;
+
+	blk_written = mmc->block_dev.block_write(mmc_dev_num,
+						start_lba, blk_count,
+						(void *)get_load_addr());
+	if (blk_written != blk_count) {
+		printf("Error - written %#lx blocks\n", blk_written);
+		return -ENOSPC;
+	}
+	printf("Done!\n");
+
+#ifdef CONFIG_SYS_MMC_ENV_PART
+	if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART)
+		mmc_switch_part(mmc_dev_num, mmc->part_num);
+#endif
+
+	return 0;
+}
+
+static size_t mmc_read_file(const char *file_name)
+{
+	loff_t		act_read = 0;
+	int		rc;
+	struct mmc	*mmc;
+	const u8	mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
+
+	mmc = find_mmc_device(mmc_dev_num);
+	if (!mmc) {
+		printf("No SD/MMC/eMMC card found\n");
+		return 0;
+	}
+
+	if (mmc_init(mmc)) {
+		printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
+		       mmc_dev_num);
+		return 0;
+	}
+
+	/* Load from data partition (0) */
+	if (fs_set_blk_dev("mmc", "0", FS_TYPE_ANY)) {
+		printf("Error: MMC 0 not found\n");
+		return 0;
+	}
+
+	/* Perfrom file read */
+	rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read);
+	if (rc)
+		return 0;
+
+	return act_read;
+}
+
+static int is_mmc_active(void)
+{
+	return 1;
+}
+#else /* CONFIG_DM_MMC */
+static int mmc_burn_image(size_t image_size)
+{
+	return -ENODEV;
+}
+
+static size_t mmc_read_file(const char *file_name)
+{
+	return 0;
+}
+
+static int is_mmc_active(void)
+{
+	return 0;
+}
+#endif /* CONFIG_DM_MMC */
+
+/********************************************************************
+ *     SPI services
+ ********************************************************************/
+#ifdef CONFIG_SPI_FLASH
+static int spi_burn_image(size_t image_size)
+{
+	int ret;
+	struct spi_flash *flash;
+	u32 erase_bytes;
+
+	/* Probe the SPI bus to get the flash device */
+	flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
+				CONFIG_ENV_SPI_CS,
+				CONFIG_SF_DEFAULT_SPEED,
+				CONFIG_SF_DEFAULT_MODE);
+	if (!flash) {
+		printf("Failed to probe SPI Flash\n");
+		return -ENOMEDIUM;
+	}
+
+#ifdef CONFIG_SPI_FLASH_PROTECTION
+	spi_flash_protect(flash, 0);
+#endif
+	erase_bytes = image_size +
+		(flash->erase_size - image_size % flash->erase_size);
+	printf("Erasing %d bytes (%d blocks) at offset 0 ...",
+	       erase_bytes, erase_bytes / flash->erase_size);
+	ret = spi_flash_erase(flash, 0, erase_bytes);
+	if (ret)
+		printf("Error!\n");
+	else
+		printf("Done!\n");
+
+	printf("Writing %d bytes from 0x%lx to offset 0 ...",
+	       (int)image_size, get_load_addr());
+	ret = spi_flash_write(flash, 0, image_size, (void *)get_load_addr());
+	if (ret)
+		printf("Error!\n");
+	else
+		printf("Done!\n");
+
+#ifdef CONFIG_SPI_FLASH_PROTECTION
+	spi_flash_protect(flash, 1);
+#endif
+
+	return ret;
+}
+
+static int is_spi_active(void)
+{
+	return 1;
+}
+
+#else /* CONFIG_SPI_FLASH */
+static int spi_burn_image(size_t image_size)
+{
+	return -ENODEV;
+}
+
+static int is_spi_active(void)
+{
+	return 0;
+}
+#endif /* CONFIG_SPI_FLASH */
+
+/********************************************************************
+ *     NAND services
+ ********************************************************************/
+#ifdef CONFIG_CMD_NAND
+static int nand_burn_image(size_t image_size)
+{
+	int ret, block_size;
+	nand_info_t *nand;
+	int dev = nand_curr_device;
+
+	if ((dev < 0) || (dev >= CONFIG_SYS_MAX_NAND_DEVICE) ||
+	    (!nand_info[dev].name)) {
+		puts("\nno devices available\n");
+		return -ENOMEDIUM;
+	}
+	nand = &nand_info[dev];
+	block_size = nand->erasesize;
+
+	/* Align U-Boot size to currently used blocksize */
+	image_size = ((image_size + (block_size - 1)) & (~(block_size - 1)));
+
+	/* Erase the U-BOOT image space */
+	printf("Erasing 0x%x - 0x%x:...", 0, (int)image_size);
+	ret = nand_erase(nand, 0, image_size);
+	if (ret) {
+		printf("Error!\n");
+		goto error;
+	}
+	printf("Done!\n");
+
+	/* Write the image to flash */
+	printf("Writing image:...");
+	printf("&image_size = 0x%p\n", (void *)&image_size);
+	ret = nand_write(nand, 0, &image_size, (void *)get_load_addr());
+	if (ret)
+		printf("Error!\n");
+	else
+		printf("Done!\n");
+
+error:
+	return ret;
+}
+
+static int is_nand_active(void)
+{
+	return 1;
+}
+
+#else /* CONFIG_CMD_NAND */
+static int nand_burn_image(size_t image_size)
+{
+	return -ENODEV;
+}
+
+static int is_nand_active(void)
+{
+	return 0;
+}
+#endif /* CONFIG_CMD_NAND */
+
+/********************************************************************
+ *     USB services
+ ********************************************************************/
+#if defined(CONFIG_USB_STORAGE) && defined(CONFIG_BLK)
+static size_t usb_read_file(const char *file_name)
+{
+	loff_t act_read = 0;
+	struct udevice *dev;
+	int rc;
+
+	usb_stop();
+
+	if (usb_init() < 0) {
+		printf("Error: usb_init failed\n");
+		return 0;
+	}
+
+	/* Try to recognize storage devices immediately */
+	blk_first_device(IF_TYPE_USB, &dev);
+	if (!dev) {
+		printf("Error: USB storage device not found\n");
+		return 0;
+	}
+
+	/* Always load from usb 0 */
+	if (fs_set_blk_dev("usb", "0", FS_TYPE_ANY)) {
+		printf("Error: USB 0 not found\n");
+		return 0;
+	}
+
+	/* Perfrom file read */
+	rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read);
+	if (rc)
+		return 0;
+
+	return act_read;
+}
+
+static int is_usb_active(void)
+{
+	return 1;
+}
+
+#else /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */
+static size_t usb_read_file(const char *file_name)
+{
+	return 0;
+}
+
+static int is_usb_active(void)
+{
+	return 0;
+}
+#endif /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */
+
+/********************************************************************
+ *     Network services
+ ********************************************************************/
+#ifdef CONFIG_CMD_NET
+static size_t tftp_read_file(const char *file_name)
+{
+	/* update global variable load_addr before tftp file from network */
+	load_addr = get_load_addr();
+	return net_loop(TFTPGET);
+}
+
+static int is_tftp_active(void)
+{
+	return 1;
+}
+
+#else
+static size_t tftp_read_file(const char *file_name)
+{
+	return 0;
+}
+
+static int is_tftp_active(void)
+{
+	return 0;
+}
+#endif /* CONFIG_CMD_NET */
+
+enum bubt_devices {
+	BUBT_DEV_NET = 0,
+	BUBT_DEV_USB,
+	BUBT_DEV_MMC,
+	BUBT_DEV_SPI,
+	BUBT_DEV_NAND,
+
+	BUBT_MAX_DEV
+};
+
+struct bubt_dev bubt_devs[BUBT_MAX_DEV] = {
+	{"tftp", tftp_read_file, NULL, is_tftp_active},
+	{"usb",  usb_read_file,  NULL, is_usb_active},
+	{"mmc",  mmc_read_file,  mmc_burn_image, is_mmc_active},
+	{"spi",  NULL, spi_burn_image,  is_spi_active},
+	{"nand", NULL, nand_burn_image, is_nand_active},
+};
+
+static int bubt_write_file(struct bubt_dev *dst, size_t image_size)
+{
+	if (!dst->write) {
+		printf("Error: Write not supported on device %s\n", dst->name);
+		return -ENOTSUPP;
+	}
+
+	return dst->write(image_size);
+}
+
+#if defined(CONFIG_ARMADA_8K)
+u32 do_checksum32(u32 *start, int32_t len)
+{
+	u32 sum = 0;
+	u32 *startp = start;
+
+	do {
+		sum += *startp;
+		startp++;
+		len -= 4;
+	} while (len > 0);
+
+	return sum;
+}
+
+static int check_image_header(void)
+{
+	struct mvebu_image_header *hdr =
+			(struct mvebu_image_header *)get_load_addr();
+	u32 header_len = hdr->prolog_size;
+	u32 checksum;
+	u32 checksum_ref = hdr->prolog_checksum;
+
+	/*
+	 * For now compare checksum, and magic. Later we can
+	 * verify more stuff on the header like interface type, etc
+	 */
+	if (hdr->magic != MAIN_HDR_MAGIC) {
+		printf("ERROR: Bad MAGIC 0x%08x != 0x%08x\n",
+		       hdr->magic, MAIN_HDR_MAGIC);
+		return -ENOEXEC;
+	}
+
+	/* The checksum value is discarded from checksum calculation */
+	hdr->prolog_checksum = 0;
+
+	checksum = do_checksum32((u32 *)hdr, header_len);
+	if (checksum != checksum_ref) {
+		printf("Error: Bad Image checksum. 0x%x != 0x%x\n",
+		       checksum, checksum_ref);
+		return -ENOEXEC;
+	}
+
+	/* Restore the checksum before writing */
+	hdr->prolog_checksum = checksum_ref;
+	printf("Image checksum...OK!\n");
+
+	return 0;
+}
+#elif defined(CONFIG_ARMADA_3700) /* Armada 3700 */
+static int check_image_header(void)
+{
+	struct common_tim_data *hdr = (struct common_tim_data *)get_load_addr();
+	int image_num;
+	u8 hash_160_output[SHA1_SUM_LEN];
+	u8 hash_256_output[SHA256_SUM_LEN];
+	sha1_context hash1_text;
+	sha256_context hash256_text;
+	u8 *hash_output;
+	u32 hash_algorithm_id;
+	u32 image_size_to_hash;
+	u32 flash_entry_addr;
+	u32 *hash_value;
+	u32 internal_hash[HASH_SUM_LEN];
+	const u8 *buff;
+	u32 num_of_image = hdr->num_images;
+	u32 version = hdr->version;
+	u32 trusted = hdr->trusted;
+
+	/* bubt checksum validation only supports nontrusted images */
+	if (trusted == 1) {
+		printf("bypass image validation, ");
+		printf("only untrusted image is supported now\n");
+		return 0;
+	}
+	/* only supports image version 3.5 and 3.6 */
+	if (version != IMAGE_VERSION_3_5_0 && version != IMAGE_VERSION_3_6_0) {
+		printf("Error: Unsupported Image version = 0x%08x\n", version);
+		return -ENOEXEC;
+	}
+	/* validate images hash value */
+	for (image_num = 0; image_num < num_of_image; image_num++) {
+		struct mvebu_image_info *info =
+				(struct mvebu_image_info *)(get_load_addr() +
+				sizeof(struct common_tim_data) +
+				image_num * sizeof(struct mvebu_image_info));
+		hash_algorithm_id = info->hash_algorithm_id;
+		image_size_to_hash = info->image_size_to_hash;
+		flash_entry_addr = info->flash_entry_addr;
+		hash_value = info->hash;
+		buff = (const u8 *)(get_load_addr() + flash_entry_addr);
+
+		if (image_num == 0) {
+			/*
+			 * The first image includes hash values in its content.
+			 * For hash calculation, we need to save the original
+			 * hash values to a local variable that will be
+			 * copied back for comparsion and set all zeros to
+			 * the orignal hash values for calculating new value.
+			 * First image original format :
+			 * x...x (datum1) x...x(orig. hash values) x...x(datum2)
+			 * Replaced first image format :
+			 * x...x (datum1) 0...0(hash values) x...x(datum2)
+			 */
+			memcpy(internal_hash, hash_value,
+			       sizeof(internal_hash));
+			memset(hash_value, 0, sizeof(internal_hash));
+		}
+		if (image_size_to_hash == 0) {
+			printf("Warning: Image_%d hash checksum is disabled, ",
+			       image_num);
+			printf("skip the image validation.\n");
+			continue;
+		}
+		switch (hash_algorithm_id) {
+		case SHA1_SUM_LEN:
+			sha1_starts(&hash1_text);
+			sha1_update(&hash1_text, buff, image_size_to_hash);
+			sha1_finish(&hash1_text, hash_160_output);
+			hash_output = hash_160_output;
+			break;
+		case SHA256_SUM_LEN:
+			sha256_starts(&hash256_text);
+			sha256_update(&hash256_text, buff, image_size_to_hash);
+			sha256_finish(&hash256_text, hash_256_output);
+			hash_output = hash_256_output;
+			break;
+		default:
+			printf("Error: Unsupported hash_algorithm_id = %d\n",
+			       hash_algorithm_id);
+			return -ENOEXEC;
+		}
+		if (image_num == 0)
+			memcpy(hash_value, internal_hash,
+			       sizeof(internal_hash));
+		if (memcmp(hash_value, hash_output, hash_algorithm_id) != 0) {
+			printf("Error: Image_%d checksum is not correct\n",
+			       image_num);
+			return -ENOEXEC;
+		}
+	}
+	printf("Image checksum...OK!\n");
+
+	return 0;
+}
+
+#else /* Not ARMADA? */
+static int check_image_header(void)
+{
+	printf("bubt cmd does not support this SoC device or family!\n");
+	return -ENOEXEC;
+}
+#endif
+
+static int bubt_verify(size_t image_size)
+{
+	int err;
+
+	/* Check a correct image header exists */
+	err = check_image_header();
+	if (err) {
+		printf("Error: Image header verification failed\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int bubt_read_file(struct bubt_dev *src)
+{
+	size_t image_size;
+
+	if (!src->read) {
+		printf("Error: Read not supported on device \"%s\"\n",
+		       src->name);
+		return 0;
+	}
+
+	image_size = src->read(net_boot_file_name);
+	if (image_size <= 0) {
+		printf("Error: Failed to read file %s from %s\n",
+		       net_boot_file_name, src->name);
+		return 0;
+	}
+
+	return image_size;
+}
+
+static int bubt_is_dev_active(struct bubt_dev *dev)
+{
+	if (!dev->active) {
+		printf("Device \"%s\" not supported by U-BOOT image\n",
+		       dev->name);
+		return 0;
+	}
+
+	if (!dev->active()) {
+		printf("Device \"%s\" is inactive\n", dev->name);
+		return 0;
+	}
+
+	return 1;
+}
+
+struct bubt_dev *find_bubt_dev(char *dev_name)
+{
+	int dev;
+
+	for (dev = 0; dev < BUBT_MAX_DEV; dev++) {
+		if (strcmp(bubt_devs[dev].name, dev_name) == 0)
+			return &bubt_devs[dev];
+	}
+
+	return 0;
+}
+
+#define DEFAULT_BUBT_SRC "tftp"
+
+#ifndef DEFAULT_BUBT_DST
+#ifdef CONFIG_MVEBU_SPI_BOOT
+#define DEFAULT_BUBT_DST "spi"
+#elif defined(CONFIG_MVEBU_NAND_BOOT)
+#define DEFAULT_BUBT_DST "nand"
+#elif defined(CONFIG_MVEBU_MMC_BOOT)
+#define DEFAULT_BUBT_DST "mmc"
+else
+#define DEFAULT_BUBT_DST "error"
+#endif
+#endif /* DEFAULT_BUBT_DST */
+
+int do_bubt_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct bubt_dev *src, *dst;
+	size_t image_size;
+	char src_dev_name[8];
+	char dst_dev_name[8];
+	char *name;
+	int  err;
+
+	if (argc < 2)
+		copy_filename(net_boot_file_name,
+			      CONFIG_MVEBU_UBOOT_DFLT_NAME,
+			      sizeof(net_boot_file_name));
+	else
+		copy_filename(net_boot_file_name, argv[1],
+			      sizeof(net_boot_file_name));
+
+	if (argc >= 3) {
+		strncpy(dst_dev_name, argv[2], 8);
+	} else {
+		name = DEFAULT_BUBT_DST;
+		strncpy(dst_dev_name, name, 8);
+	}
+
+	if (argc >= 4)
+		strncpy(src_dev_name, argv[3], 8);
+	else
+		strncpy(src_dev_name, DEFAULT_BUBT_SRC, 8);
+
+	/* Figure out the destination device */
+	dst = find_bubt_dev(dst_dev_name);
+	if (!dst) {
+		printf("Error: Unknown destination \"%s\"\n", dst_dev_name);
+		return -EINVAL;
+	}
+
+	if (!bubt_is_dev_active(dst))
+		return -ENODEV;
+
+	/* Figure out the source device */
+	src = find_bubt_dev(src_dev_name);
+	if (!src) {
+		printf("Error: Unknown source \"%s\"\n", src_dev_name);
+		return 1;
+	}
+
+	if (!bubt_is_dev_active(src))
+		return -ENODEV;
+
+	printf("Burning U-BOOT image \"%s\" from \"%s\" to \"%s\"\n",
+	       net_boot_file_name, src->name, dst->name);
+
+	image_size = bubt_read_file(src);
+	if (!image_size)
+		return -EIO;
+
+	err = bubt_verify(image_size);
+	if (err)
+		return err;
+
+	err = bubt_write_file(dst, image_size);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	bubt, 4, 0, do_bubt_cmd,
+	"Burn a u-boot image to flash",
+	"[file-name] [destination [source]]\n"
+	"\t-file-name     The image file name to burn. Default = flash-image.bin\n"
+	"\t-destination   Flash to burn to [spi, nand, mmc]. Default = active boot device\n"
+	"\t-source        The source to load image from [tftp, usb, mmc]. Default = tftp\n"
+	"Examples:\n"
+	"\tbubt - Burn flash-image.bin from tftp to active boot device\n"
+	"\tbubt flash-image-new.bin nand - Burn flash-image-new.bin from tftp to NAND flash\n"
+	"\tbubt backup-flash-image.bin mmc usb - Burn backup-flash-image.bin from usb to MMC\n"
+
+);
diff --git a/configs/mvebu_db-88f7040_defconfig b/configs/mvebu_db-88f7040_defconfig
index f153b9cd779dc7ba1f33e83fb69814795540c72c..a2bb97a9bab912f69809bca37a5135bf031e41c2 100644
--- a/configs/mvebu_db-88f7040_defconfig
+++ b/configs/mvebu_db-88f7040_defconfig
@@ -27,6 +27,7 @@ CONFIG_CMD_EXT4=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_CMD_MVEBU_BUBT=y
 CONFIG_BLOCK_CACHE=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_MVTWSI=y
@@ -36,6 +37,9 @@ CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_SPANSION=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_PHYLIB=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_PCIE_DW_MVEBU=y
 CONFIG_MVEBU_COMPHY_SUPPORT=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DEBUG_UART=y
@@ -50,3 +54,5 @@ CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_SMBIOS_MANUFACTURER=""
+CONFIG_PINCTRL=y
+CONFIG_HUSH_PARSER=y
diff --git a/configs/mvebu_db-88f8040_defconfig b/configs/mvebu_db-88f8040_defconfig
index 61d58b50c2eba5afc84d26ae4786fa5b5592b5b0..1e92e9fa5b6f0cd3597b8bb253df580f64ef340d 100644
--- a/configs/mvebu_db-88f8040_defconfig
+++ b/configs/mvebu_db-88f8040_defconfig
@@ -27,6 +27,7 @@ CONFIG_CMD_EXT4=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_CMD_MVEBU_BUBT=y
 CONFIG_BLOCK_CACHE=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_MVTWSI=y
@@ -53,3 +54,5 @@ CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_SMBIOS_MANUFACTURER=""
+CONFIG_PINCTRL=y
+CONFIG_HUSH_PARSER=y
diff --git a/doc/device-tree-bindings/pinctrl/marvell,armada-apn806-pinctrl.txt b/doc/device-tree-bindings/pinctrl/marvell,armada-apn806-pinctrl.txt
new file mode 100644
index 0000000000000000000000000000000000000000..51f2f2c79c50b482c5e3c12ef54b3a3f92ff783b
--- /dev/null
+++ b/doc/device-tree-bindings/pinctrl/marvell,armada-apn806-pinctrl.txt
@@ -0,0 +1,25 @@
+	Functions of Armada APN806 pin controller
+	Function 0x0 for any MPP ID activates GPIO pin mode
+----------------------------------------------------------------------
+MPP#	0x1			0x2		0x3		0x4
+----------------------------------------------------------------------
+0	SDIO_CLK		-		SPI0_CLK 	-
+1	SDIO_CMD		-		SPI0_MISO	-
+2	SDIO_D[0]		-		SPI0_MOSI 	-
+3	SDIO_D[1]		-		SPI0_CS0n 	-
+4	SDIO_D[2]		-		I2C0_SDA	SPI0_CS1n
+5	SDIO_D[3]		-		I2C0_SCK	-
+6	SDIO_DS			-		-		-
+7	SDIO_D[4]		-		UART1_RXD	-
+8	SDIO_D[5]		-		UART1_TXD 	-
+9	SDIO_D[6]		-		SPI0_CS1n 	-
+10	SDIO_D[7]		-		-		-
+11	-			-		UART0_TXD 	-
+12	SDIO_CARD_PW_OFF 	SDIO_HW_RST 	-		-
+13	-			-		-		-
+14	-			-		-		-
+15	-			-		-		-
+16	-			-		-		-
+17	-			-		-		-
+18	-			-		-		-
+19	-			-		UART0_RXD	-
diff --git a/doc/device-tree-bindings/pinctrl/marvell,armada-cp110-pinctrl.txt b/doc/device-tree-bindings/pinctrl/marvell,armada-cp110-pinctrl.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3adcf3aae498f916fa289709bce7464298e4f72e
--- /dev/null
+++ b/doc/device-tree-bindings/pinctrl/marvell,armada-cp110-pinctrl.txt
@@ -0,0 +1,270 @@
+	Functions of Armada CP110 pin controller
+	Function 0x0 for any MPP ID activates GPIO pin mode
+	Function 0xc for any MPP ID activates DEBUG_BUS pin mode
+-------------------------------------------------------------------------------
+MPP#	0x1			0x2		0x3		0x4
+-------------------------------------------------------------------------------
+0	DEV_ALE[1]		AU_I2SMCLK	GE0_RXD[3]	TDM_PCLK
+1	DEV_ALE[0]		AU_I2SDO_SPDIFO	GE0_RXD[2]	TDM_DRX
+2	DEV_AD[15]		AU_I2SEXTCLK	GE0_RXD[1]	TDM_DTX
+3	DEV_AD[14]		AU_I2SLRCLK	GE0_RXD[0]	TDM_FSYNC
+4	DEV_AD[13]		AU_I2SBCLK	GE0_RXCTL	TDM_RSTn
+5	DEV_AD[12]		AU_I2SDI	GE0_RXCLK	TDM_INTn
+6	DEV_AD[11]		-		GE0_TXD[3]	SPI0_CSn[2]
+7	DEV_AD[10]		-		GE0_TXD[2]	SPI0_CSn[1]
+8	DEV_AD[9]		-		GE0_TXD[1]	SPI0_CSn[0]
+9	DEV_AD[8]		-		GE0_TXD[0]	SPI0_MOSI
+10	DEV_READYn		-		GE0_TXCTL	SPI0_MISO
+11	DEV_WEn[1]		-		GE0_TXCLKOUT	SPI0_CLK
+12	DEV_CLK_OUT		NF_RBn[1]	SPI1_CSn[1]	GE0_RXCLK
+13	DEV_BURSTn		NF_RBn[0]	SPI1_MISO	GE0_RXCTL
+14	DEV_BOOTCSn		DEV_CSn[0]	SPI1_CSn[0]	SPI0_CSn[3]
+15	DEV_AD[7]		-		SPI1_MOSI	-
+16	DEV_AD[6]		-		SPI1_CLK	-
+17	DEV_AD[5]		-		-		GE0_TXD[3]
+18	DEV_AD[4]		-		-		GE0_TXD[2]
+19	DEV_AD[3]		-		-		GE0_TXD[1]
+20	DEV_AD[2]		-		-		GE0_TXD[0]
+21	DEV_AD[1]		-		-		GE0_TXCTL
+22	DEV_AD[0]		-		-		GE0_TXCLKOUT
+23	DEV_A[1]		-		-		-
+24	DEV_A[0]		-		-		-
+25	DEV_OEn	-		-		-		-
+26	DEV_WEn[0]		-		-		-
+27	DEV_CSn[0]		SPI1_MISO	MSS_GPIO[4]	GE0_RXD[3]
+28	DEV_CSn[1]		SPI1_CSn[0]	MSS_GPIO[5]	GE0_RXD[2]
+29	DEV_CSn[2]		SPI1_MOSI	MSS_GPIO[6]	GE0_RXD[1]
+30	DEV_CSn[3]		SPI1_CLK	MSS_GPIO[7]	GE0_RXD[0]
+31	DEV_A[2]		-		MSS_GPIO[4]	-
+32	MII_COL			MII_TXERR	MSS_SPI_MISO	TDM_DRX
+33	MII_TXCLK		SDIO_PWR1[0]	MSS_SPI_CSn	TDM_FSYNC
+34	MII_RXERR		SDIO_PWR1[1]	MSS_SPI_MOSI	TDM_DTX
+35	SATA1_PRESENT_ACTIVEn	TWSI1_SDA	MSS_SPI_CLK	TDM_PCLK
+36	SYNCE2_CLK		TWSI1_SCK	PTP_CLK		SYNCE1_CLK
+37	UART2_RXD		TWSI0_SCK	PTP_PCLK_OUT	TDM_INTn
+38	UART2_TXD		TWSI0_SDA	PTP_PULSE	TDM_RSTn
+39	SDIO_WR_PROTECT		-	-	AU_I2SBCLK	PTP_CLK
+40	SDIO_PWR1[1]		SYNCE1_CLK	MSS_TWSI_SDA	AU_I2SDO_SPDIFO
+41	SDIO_PWR1[0]		SDIO_BUS_PWR	MSS_TWSI_SCK	AU_I2SLRCLK
+42	SDIO_V18_EN		SDIO_WR_PROTECT	SYNCE2_CLK	AU_I2SMCLK
+43	SDIO_CARD_DETECT	-		SYNCE1_CLK	AU_I2SEXTCLK
+44	GE1_TXD[2]		-		-		-
+45	GE1_TXD[3]		-		-		-
+46	GE1_TXD[1]		-		-		-
+47	GE1_TXD[0]		-		-		-
+48	GE1_TXCTL_MII_TXEN	-		-		-
+49	GE1_TXCLKOUT		MII_CRS		-		-
+50	GE1_RXCLK		MSS_TWSI_SDA	-		-
+51	GE1_RXD[0]		MSS_TWSI_SCK	-		-
+52	GE1_RXD[1]		SYNCE1_CLK	-		SYNCE2_CLK
+53	GE1_RXD[2]		-		PTP_CLK		-
+54	GE1_RXD[3]		SYNCE2_CLK	PTP_PCLK_OUT	SYNCE1_CLK
+55	GE1_RXCTL_MII_RXDV	-		PTP_PULSE	-
+56	-			-		-		TDM_DRX
+57	-			MSS_TWSI_SDA	PTP_PCLK_OUT	TDM_INTn
+58	-			MSS_TWSI_SCK	PTP_CLK		TDM_RSTn
+59	MSS_GPIO[7]		SYNCE2_CLK	-		TDM_FSYNC
+60	MSS_GPIO[6]		-		PTP_PULSE	TDM_DTX
+61	MSS_GPIO[5]		-		PTP_CLK		TDM_PCLK
+62	MSS_GPIO[4]		SYNCE1_CLK	PTP_PCLK_OUT	-
+
+-------------------------------------------------------------------------------
+MPP#	0x5			0x6			0x7
+-------------------------------------------------------------------------------
+0	-			PTP_PULSE		MSS_TWSI_SDA
+1	-			PTP_CLK			MSS_TWSI_SCK
+2	MSS_UART_RXD		PTP_PCLK_OUT		TWSI1_SCK
+3	MSS_UART_TXD		PCIe_RSTOUTn		TWSI1_SDA
+4	MSS_UART_RXD		UART1_CTS		PCIe0_CLKREQ
+5	MSS_UART_TXD		UART1_RTS		PCIe1_CLKREQ
+6	AU_I2SEXTCLK		SATA1_PRESENT_ACTIVEn	PCIe2_CLKREQ
+7	SPI1_CSn[1]		SATA0_PRESENT_ACTIVEn	LED_DATA
+8	SPI1_CSn[0]		UART0_CTS		LED_STB
+9	SPI1_MOSI		-			PCIe_RSTOUTn
+10	SPI1_MISO		UART0_CTS		SATA1_PRESENT_ACTIVEn
+11	SPI1_CLK		UART0_RTS		LED_CLK
+12	-			-			-
+13	-			-			-
+14	AU_I2SEXTCLK		SPI0_MISO		SATA0_PRESENT_ACTIVEn
+15	-			SPI0_MOSI		-
+16	-			-			-
+17	-			-			-
+18	-			-			-
+19	-			-			-
+20	-			-			-
+21	-			-			-
+22	-			-			-
+23	AU_I2SMCLK		-			-
+24	AU_I2SLRCLK		-			-
+25	AU_I2SDO_SPDIFO		-			-
+26	AU_I2SBCLK		-			-
+27	SPI0_CSn[4]		-			-
+28	SPI0_CSn[5]		PCIe2_CLKREQ		PTP_PULSE
+29	SPI0_CSn[6]		PCIe1_CLKREQ		PTP_CLK
+30	SPI0_CSn[7]		PCIe0_CLKREQ		PTP_PCLK_OUT
+31	-			PCIe_RSTOUTn		-
+32	AU_I2SEXTCLK		AU_I2SDI		GE_MDIO
+33	AU_I2SMCLK		SDIO_BUS_PWR		-
+34	AU_I2SLRCLK		SDIO_WR_PROTECT		GE_MDC
+35	AU_I2SDO_SPDIFO		SDIO_CARD_DETECT	XG_MDIO
+36	AU_I2SBCLK		SATA0_PRESENT_ACTIVEn	XG_MDC
+37	MSS_TWSI_SCK		SATA1_PRESENT_ACTIVEn	GE_MDC
+38	MSS_TWSI_SDA		SATA0_PRESENT_ACTIVEn	GE_MDIO
+39	SPI0_CSn[1]		-			-
+40	PTP_PCLK_OUT		SPI0_CLK		UART1_TXD
+41	PTP_PULSE		SPI0_MOSI		UART1_RXD
+42	MSS_UART_TXD		SPI0_MISO		UART1_CTS
+43	MSS_UART_RXD		SPI0_CSn[0]		UART1_RTS
+44	-			-			UART0_RTS
+45	-			-			UART0_TXD
+46	-			-			UART1_RTS
+47	SPI1_CLK		-			UART1_TXD
+48	SPI1_MOSI		-			-
+49	SPI1_MISO		-			UART1_RXD
+50	SPI1_CSn[0]		UART2_TXD		UART0_RXD
+51	SPI1_CSn[1]		UART2_RXD		UART0_CTS
+52	SPI1_CSn[2]		-			UART1_CTS
+53	SPI1_CSn[3]		-			UART1_RXD
+54	-			-			-
+55	-			-			-
+56	AU_I2SDO_SPDIFO		SPI0_CLK		UART1_RXD
+57	AU_I2SBCLK		SPI0_MOSI		UART1_TXD
+58	AU_I2SDI		SPI0_MISO		UART1_CTS
+59	AU_I2SLRCLK		SPI0_CSn[0]		UART0_CTS
+60	AU_I2SMCLK		SPI0_CSn[1]		UART0_RTS
+61	AU_I2SEXTCLK		SPI0_CSn[2]		UART0_TXD
+62	SATA1_PRESENT_ACTIVEn	SPI0_CSn[3]		UART0_RXD
+
+-------------------------------------------------------------------------------
+MPP#	0x8			0x9			0xA
+-------------------------------------------------------------------------------
+0	UART0_RXD		SATA0_PRESENT_ACTIVEn	GE_MDIO
+1	UART0_TXD		SATA1_PRESENT_ACTIVEn	GE_MDC
+2	UART1_RXD		SATA0_PRESENT_ACTIVEn	XG_MDC
+3	UART1_TXD		SATA1_PRESENT_ACTIVEn	XG_MDIO
+4	UART3_RXD		-			GE_MDC
+5	UART3_TXD		-			GE_MDIO
+6	UART0_RXD		PTP_PULSE		-
+7	UART0_TXD		PTP_CLK			-
+8	UART2_RXD		PTP_PCLK_OUT		SYNCE1_CLK
+9	-			-			SYNCE2_CLK
+10	-			-			-
+11	UART2_TXD		SATA0_PRESENT_ACTIVEn	-
+12	-			-			-
+13	MSS_SPI_MISO		-			-
+14	MSS_SPI_CSn		-			-
+15	MSS_SPI_MOSI		-			-
+16	MSS_SPI_CLK		-			-
+17	-			-			-
+18	-			-			-
+19	-			-			-
+20	-			-			-
+21	-			-			-
+22	-			-			-
+23	-			-			-
+24	-			-			-
+25	-			-			-
+26	-			-			-
+27	GE_MDIO			SATA0_PRESENT_ACTIVEn	UART0_RTS
+28	GE_MDC			SATA1_PRESENT_ACTIVEn	UART0_CTS
+29	MSS_TWSI_SDA		SATA0_PRESENT_ACTIVEn	UART0_RXD
+30	MSS_TWSI_SCK		SATA1_PRESENT_ACTIVEn	UART0_TXD
+31	GE_MDC			-			-
+32	SDIO_V18_EN		PCIe1_CLKREQ		MSS_GPIO[0]
+33	XG_MDIO			PCIe2_CLKREQ		MSS_GPIO[1]
+34	-			PCIe0_CLKREQ		MSS_GPIO[2]
+35	GE_MDIO			PCIe_RSTOUTn		MSS_GPIO[3]
+36	GE_MDC			PCIe2_CLKREQ		MSS_GPIO[5]
+37	XG_MDC			PCIe1_CLKREQ		MSS_GPIO[6]
+38	XG_MDIO			AU_I2SEXTCLK		MSS_GPIO[7]
+39	SATA1_PRESENT_ACTIVEn				MSS_GPIO[0]
+40	GE_MDIO			SATA0_PRESENT_ACTIVEn	MSS_GPIO[1]
+41	GE_MDC			SATA1_PRESENT_ACTIVEn	MSS_GPIO[2]
+42	XG_MDC			SATA0_PRESENT_ACTIVEn	MSS_GPIO[4]
+43	XG_MDIO			SATA1_PRESENT_ACTIVEn	MSS_GPIO[5]
+44	-			-			-
+45	-			PCIe_RSTOUTn		-
+46	-			-			-
+47	GE_MDC			CLKOUT			-
+48	XG_MDC			-			-
+49	GE_MDIO			PCIe0_CLKREQ		SDIO_V18_EN
+50	XG_MDIO			-			SDIO_PWR1[1]
+51	-			-			SDIO_PWR1[0]
+52	LED_CLK			PCIe_RSTOUTn		PCIe0_CLKREQ
+53	LED_STB			-			-
+54	LED_DATA		-			SDIO_HW_RST
+55	-			-			SDIO_LED
+56	-			SATA1_PRESENT_ACTIVEn	-
+57	-			SATA0_PRESENT_ACTIVEn	-
+58	LED_CLK			-			-
+59	LED_STB			UART1_TXD		-
+60	LED_DATA		UART1_RXD		-
+61	UART2_TXD		SATA1_PRESENT_ACTIVEn	GE_MDIO
+62	UART2_RXD		SATA0_PRESENT_ACTIVEn	GE_MDC
+
+-------------------------------------------------------------------------------
+MPP#	0xB			0xD			0xE
+-------------------------------------------------------------------------------
+0	-			-			-
+1	-			-			-
+2	-			-			-
+3	-			-			-
+4	-			-			-
+5	-			-			-
+6	-			-			-
+7	-			-			-
+8	-			-			-
+9	-			-			-
+10	-			-			-
+11	-			CLKOUT_MPP_11		-
+12	-			-			-
+13	-			-			-
+14	-			-			-
+15	PTP_PULSE_CP2CP		SAR_IN[5]		-
+16	-			SAR_IN[3]		-
+17	-			SAR_IN[6]		-
+18	PTP_CLK_CP2CP		SAR_IN[11]		-
+19	WAKEUP_OUT_CP2CP	SAR_IN[7]		-
+20	-			SAR_IN[9]		-
+21	SEI_IN_CP2CP		SAR_IN[8]		-
+22	WAKEUP_IN_CP2CP		SAR_IN[10]		-
+23	LINK_RD_IN_CP2CP	SAR_IN[4]		-
+24	-			-			-
+25	-			CLKOUT_MPP_25		-
+26	-			SAR_IN[0]		-
+27	REI_IN_CP2CP		SAR_IN[1]		-
+28	LED_DATA		SAR_IN[2]		-
+29	LED_STB			AVS_FB_IN_CP2CP		-
+30	LED_CLK			SAR_IN[13]		-
+31	-			-			-
+32	-			SAR_CP2CP_OUT[0]	-
+33	-			SAR_CP2CP_OUT[1]	-
+34	-			SAR_CP2CP_OUT[2]	-
+35	-			SAR_CP2CP_OUT[3]	-
+36	-			CLKIN			-
+37	LINK_RD_OUT_CP2CP	SAR_CP2CP_OUT[4]	-
+38	PTP_PULSE_CP2CP		SAR_CP2CP_OUT[5]	-
+39	-			AVS_FB_OUT_CP2CP	-
+40	-			-			-
+41	REI_OUT_CP2CP		-			-
+42	-			SAR_CP2CP_OUT[9]	-
+43	WAKEUP_OUT_CP2CP	SAR_CP2CP_OUT[10]	-
+44	PTP_CLK_CP2CP		SAR_CP2CP_OUT[11]	-
+45	-			SAR_CP2CP_OUT[6]	-
+46	-			SAR_CP2CP_OUT[13]	-
+47	-			-			-
+48	WAKEUP_IN_CP2CP		SAR_CP2CP_OUT[7]	-
+49	SEI_OUT_CP2CP		SAR_CP2CP_OUT[8]	-
+50	-			-			-
+51	-			-			-
+52	-			-			-
+53	SDIO_LED		-			-
+54	SDIO_WR_PROTECT		-			-
+55	SDIO_CARD_DETECT	-			-
+56	-			-			SDIO0_CLK
+57	-			-			SDIO0_CMD
+58	-			-			SDIO0_D[0]
+59	-			-			SDIO0_D[1]
+60	-			-			SDIO0_D[2]
+61	-			-			SDIO0_D[3]
+62	-			-			-
diff --git a/doc/device-tree-bindings/pinctrl/marvell,mvebu-pinctrl.txt b/doc/device-tree-bindings/pinctrl/marvell,mvebu-pinctrl.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5f86c0a00bfa75c5c04cd7cfc76509f6b746a2b4
--- /dev/null
+++ b/doc/device-tree-bindings/pinctrl/marvell,mvebu-pinctrl.txt
@@ -0,0 +1,113 @@
+The pinctrl driver enables Marvell Armada 8K SoCs to configure the multi-purpose
+pins (mpp) to a specific function.
+A Marvell SoC pin configuration node is a node of a group of pins which can
+be used for a specific device or function. Each node requires one or more
+mpp pins or group of pins and a mpp function common to all pins.
+
+Required properties for the pinctrl driver:
+- compatible:	"marvell,mvebu-pinctrl",
+		"marvell,armada-ap806-pinctrl",
+		"marvell,a70x0-pinctrl",
+		"marvell,a80x0-cp0-pinctrl",
+		"marvell,a80x0-cp1-pinctrl"
+- bank-name:	A string defining the pinc controller bank name
+- reg: 		A pair of values defining the pin controller base address
+		and the address space
+- pin-count:	Numeric value defining the amount of multi purpose pins
+		included in this bank
+- max-func:	Numeric value defining the maximum function value for
+		pins in this bank
+- pin-func:	Array of pin function values for every pin in the bank.
+		When the function value for a specific pin equal 0xFF,
+		the pin configuration is skipped and a default function
+		value is used for this pin.
+
+The A8K is a hybrid SoC that contains several silicon dies interconnected in
+a single package. Each such die may have a separate pin controller.
+
+Example:
+/ {
+	ap806 {
+		config-space {
+			pinctl: pinctl@6F4000 {
+				compatible = "marvell,mvebu-pinctrl",
+					     "marvell,armada-ap806-pinctrl";
+				bank-name ="apn-806";
+				reg = <0x6F4000 0x10>;
+				pin-count = <20>;
+				max-func = <3>;
+				/* MPP Bus:
+				 * SPI0 [0-3]
+				 * I2C0 [4-5]
+				 * UART0 [11,19]
+				 */
+					  /* 0 1 2 3 4 5 6 7 8 9 */
+				pin-func = < 3 3 3 3 3 3 0 0 0 0
+					     0 3 0 0 0 0 0 0 0 3>;
+			};
+		};
+	};
+
+	cp110-master {
+		config-space {
+			cpm_pinctl: pinctl@44000 {
+				compatible = "marvell,mvebu-pinctrl",
+					     "marvell,a70x0-pinctrl",
+					     "marvell,a80x0-cp0-pinctrl";
+				bank-name ="cp0-110";
+				reg = <0x440000 0x20>;
+				pin-count = <63>;
+				max-func = <0xf>;
+				/* MPP Bus:
+				 * [0-31] = 0xff: Keep default CP0_shared_pins:
+				 * [11] CLKOUT_MPP_11 (out)
+				 * [23] LINK_RD_IN_CP2CP (in)
+				 * [25] CLKOUT_MPP_25 (out)
+				 * [29] AVS_FB_IN_CP2CP (in)
+				 * [32,34] SMI
+				 * [31]    GPIO: push button/Wake
+				 * [35-36] GPIO
+				 * [37-38] I2C
+				 * [40-41] SATA[0/1]_PRESENT_ACTIVEn
+				 * [42-43] XSMI
+				 * [44-55] RGMII1
+				 * [56-62] SD
+				 */
+					/*   0    1    2    3    4    5    6    7    8    9 */
+				pin-func = < 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+					     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+					     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+					     0xff 0    7    0    7    0    0    2    2    0
+					     0    0    8    8    1    1    1    1    1    1
+					     1    1    1    1    1    1    0xE  0xE  0xE  0xE
+					     0xE  0xE  0xE>;
+			};
+		};
+	};
+
+	cp110-slave {
+		config-space {
+			cps_pinctl: pinctl@44000 {
+				compatible = "marvell,mvebu-pinctrl",
+					     "marvell,a80x0-cp1-pinctrl";
+				bank-name ="cp1-110";
+				reg = <0x440000 0x20>;
+				pin-count = <63>;
+				max-func = <0xf>;
+				/* MPP Bus:
+				 * [0-11]  RGMII0
+				 * [27,31] GE_MDIO/MDC
+				 * [32-62] = 0xff: Keep default CP1_shared_pins:
+				 */
+					/*   0    1    2    3    4    5    6    7    8    9 */
+				pin-func = < 0x3  0x3  0x3  0x3  0x3  0x3  0x3  0x3  0x3  0x3
+					     0x3  0x3  0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+					     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x8  0xff 0xff
+					     0xff 0x8  0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+					     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+					     0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+					     0xff 0xff 0xff>;
+			};
+		};
+	};
+}
diff --git a/doc/mvebu/cmd/bubt.txt b/doc/mvebu/cmd/bubt.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6f9f525936ba2add9128913c5151f004bd51c1c2
--- /dev/null
+++ b/doc/mvebu/cmd/bubt.txt
@@ -0,0 +1,64 @@
+BUBT (Burn ATF) command
+--------------------------
+Bubt command is used to burn a new ATF image to flash device.
+
+The bubt command gets the following parameters: ATF file name, destination device and source device.
+bubt [file-name] [destination [source]]
+	- file-name		Image file name to burn. default = flash-image.bin
+	- destination		Flash to burn to [spi, nand, mmc]. default = active flash
+	- source		Source to load image from [tftp, usb]. default = tftp
+
+Examples:
+	bubt				- Burn flash-image.bin from tftp to active flash
+	bubt latest-spi.bin nand	- Burn latest-spi.bin from tftp to NAND flash
+
+Notes:
+- For the TFTP interface set serverip and ipaddr.
+- To burn image to SD/eMMC device, the target is defined
+  by parameters CONFIG_SYS_MMC_ENV_DEV and CONFIG_SYS_MMC_ENV_PART.
+
+Bubt command details (burn image step by-step)
+----------------------------------------------
+This section describes bubt command flow:
+
+1. Fetch the requested ATF image from an available interface (USB/SD/SATA/XDB, etc.)
+   into the DRAM, and place it at <load_address>
+   Example: when using the FAT file system on USB flash device:
+   # usb reset
+   # fatls usb 0 (see files in device)
+   # fatload usb 0 <load_address> <file_name>
+
+2. Erase the target device:
+	- NAND:		# nand erase 0 100000
+	- SPI:		# sf probe 0
+			# sf erase 0 100000
+	- SD/eMMC:	# mmc dev <dev_id> <boot_partition>
+
+Notes:
+- The eMMC has 2 boot partitions (BOOT0 and BOOT1) and a user data partition (DATA).
+  The boot partitions are numbered as partition 1 and 2 in MMC driver.
+  Number 0 is used for user data partition and should not be utilized for storing
+  boot images and U-Boot environment in RAW mode since it will break file system
+  structures usually located here.
+  The default boot partition is BOOT0. It is selected by the following parameter:
+  CONFIG_SYS_MMC_ENV_PART=1
+  Valid values for this parameter are 1 for BOOT0 and 2 for BOOT1.
+  Please never use partition number 0 here!
+  The eMMC has 2 boot partitions (BOOT0 and BOOT1) and a user data partition (DATA).
+  The boot partitions are numbered as partition 1 and 2 in MMC driver.
+  Number 0 is used for user data partition and should not be utilized for storing
+  boot images and U-Boot environment in RAW mode since it will break file system
+  structures usually located here.
+  The default boot partition is BOOT0. It is selected by the following parameter:
+  CONFIG_SYS_MMC_ENV_PART=1
+  Valid values for this parameter are 1 for BOOT0 and 2 for BOOT1.
+  Please never use partition number 0 here!
+- The partition number is ignored if the target device is SD card.
+- The boot image offset starts at block 0 for eMMC and block 1 for SD devices.
+  The block 0 on SD devices is left for MBR storage.
+
+3. Write the ATF image:
+	- NAND:		# nand write <load_address> 0 <ATF Size>
+	- SPI:		# sf write <load_address> 0 <ATF Size>
+	- SD/eMMC:	# mmc write <load_address> [0|1] <ATF Size>/<block_size>
+
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 12be3cfe0b8aaf5d86b330b810fb7bb2043d4fd2..efcb4c0003a68935e777d3fcca4bb90cbc7ef4d0 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -181,5 +181,6 @@ source "drivers/pinctrl/meson/Kconfig"
 source "drivers/pinctrl/nxp/Kconfig"
 source "drivers/pinctrl/uniphier/Kconfig"
 source "drivers/pinctrl/exynos/Kconfig"
+source "drivers/pinctrl/mvebu/Kconfig"
 
 endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f28b5c18f6874e778ed1e71ba998899a562a1676..512112af649e1027ce1982d6038b388991e2a225 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_PINCTRL_UNIPHIER)	+= uniphier/
 obj-$(CONFIG_PIC32_PINCTRL)	+= pinctrl_pic32.o
 obj-$(CONFIG_PINCTRL_EXYNOS)	+= exynos/
 obj-$(CONFIG_PINCTRL_MESON)	+= meson/
+obj-$(CONFIG_PINCTRL_MVEBU)	+= mvebu/
diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..cf9c299f13a98ffe3abc9f41547f484a33aba3e1
--- /dev/null
+++ b/drivers/pinctrl/mvebu/Kconfig
@@ -0,0 +1,7 @@
+config PINCTRL_MVEBU
+	depends on ARCH_MVEBU
+	bool
+	default y
+	help
+	   Support pin multiplexing and pin configuration control on
+	   Marvell's Armada-8K SoC.
diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..f4f78640b95c98f62604e38049d348a3dfca03f8
--- /dev/null
+++ b/drivers/pinctrl/mvebu/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2016 Marvell International Ltd.
+#
+# SPDX-License-Identifier:	GPL-2.0
+# https://spdx.org/licenses
+
+obj-$(CONFIG_PINCTRL_MVEBU)	+= pinctrl-mvebu.o
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
new file mode 100644
index 0000000000000000000000000000000000000000..b07763931fe8a2c102b9fdf0f3ba1daddbc46e26
--- /dev/null
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ * https://spdx.org/licenses
+ */
+
+#include <common.h>
+#include <config.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/arch-armada8k/soc-info.h>
+#include "pinctrl-mvebu.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * mvebu_pinctrl_set_state: configure pin functions.
+ * @dev: the pinctrl device to be configured.
+ * @config: the state to be configured.
+ * @return: 0 in success
+ */
+int mvebu_pinctrl_set_state(struct udevice *dev, struct udevice *config)
+{
+	const void *blob = gd->fdt_blob;
+	int node = config->of_offset;
+	struct mvebu_pinctrl_priv *priv;
+	u32 pin_arr[MVEBU_MAX_PINS_PER_BANK];
+	u32 function;
+	int i, pin_count;
+
+	priv = dev_get_priv(dev);
+
+	pin_count = fdtdec_get_int_array_count(blob, node,
+					       "marvell,pins",
+					       pin_arr,
+					       MVEBU_MAX_PINS_PER_BANK);
+	if (pin_count <= 0) {
+		debug("Failed reading pins array for pinconfig %s (%d)\n",
+		      config->name, pin_count);
+		return -EINVAL;
+	}
+
+	function = fdtdec_get_int(blob, node, "marvell,function", 0xff);
+
+	for (i = 0; i < pin_count; i++) {
+	int reg_offset;
+	int field_offset;
+		int pin = pin_arr[i];
+
+		if (function > priv->max_func) {
+			debug("Illegal function %d for pinconfig %s\n",
+			      function, config->name);
+			return -EINVAL;
+		}
+
+		/* Calculate register address and bit in register */
+		reg_offset   = priv->reg_direction * 4 *
+					(pin >> (PIN_REG_SHIFT));
+		field_offset = (BITS_PER_PIN) * (pin & PIN_FIELD_MASK);
+
+		clrsetbits_le32(priv->base_reg + reg_offset,
+				PIN_FUNC_MASK << field_offset,
+				(function & PIN_FUNC_MASK) << field_offset);
+	}
+
+	return 0;
+}
+
+/*
+ * mvebu_pinctrl_set_state_all: configure the entire bank pin functions.
+ * @dev: the pinctrl device to be configured.
+ * @config: the state to be configured.
+ * @return: 0 in success
+ */
+static int mvebu_pinctrl_set_state_all(struct udevice *dev,
+				       struct udevice *config)
+{
+	const void *blob = gd->fdt_blob;
+	int node = config->of_offset;
+	struct mvebu_pinctrl_priv *priv;
+	u32 func_arr[MVEBU_MAX_PINS_PER_BANK];
+	int pin, err;
+
+	priv = dev_get_priv(dev);
+
+	err = fdtdec_get_int_array(blob, node, "pin-func",
+				   func_arr, priv->pin_cnt);
+	if (err) {
+		debug("Failed reading pin functions for bank %s\n",
+		      priv->bank_name);
+		return -EINVAL;
+	}
+
+	for (pin = 0; pin < priv->pin_cnt; pin++) {
+		int reg_offset;
+		int field_offset;
+		u32 func = func_arr[pin];
+
+		/* Bypass pins with function 0xFF */
+		if (func == 0xff) {
+			debug("Warning: pin %d value is not modified ", pin);
+			debug("(kept as default)\n");
+			continue;
+		} else if (func > priv->max_func) {
+			debug("Illegal function %d for pin %d\n", func, pin);
+			return -EINVAL;
+		}
+
+		/* Calculate register address and bit in register */
+		reg_offset   = priv->reg_direction * 4 *
+					(pin >> (PIN_REG_SHIFT));
+		field_offset = (BITS_PER_PIN) * (pin & PIN_FIELD_MASK);
+
+		clrsetbits_le32(priv->base_reg + reg_offset,
+				PIN_FUNC_MASK << field_offset,
+				(func & PIN_FUNC_MASK) << field_offset);
+	}
+
+	return 0;
+}
+
+int mvebu_pinctl_probe(struct udevice *dev)
+{
+	const void *blob = gd->fdt_blob;
+	int node = dev->of_offset;
+	struct mvebu_pinctrl_priv *priv;
+
+	priv = dev_get_priv(dev);
+	if (!priv) {
+		debug("%s: Failed to get private\n", __func__);
+		return -EINVAL;
+	}
+
+	priv->base_reg = dev_get_addr_ptr(dev);
+	if (priv->base_reg == (void *)FDT_ADDR_T_NONE) {
+		debug("%s: Failed to get base address\n", __func__);
+		return -EINVAL;
+	}
+
+	priv->pin_cnt   = fdtdec_get_int(blob, node, "pin-count",
+					MVEBU_MAX_PINS_PER_BANK);
+	priv->max_func  = fdtdec_get_int(blob, node, "max-func",
+					 MVEBU_MAX_FUNC);
+	priv->bank_name = fdt_getprop(blob, node, "bank-name", NULL);
+
+	priv->reg_direction = 1;
+	if (fdtdec_get_bool(blob, node, "reverse-reg"))
+		priv->reg_direction = -1;
+
+	return mvebu_pinctrl_set_state_all(dev, dev);
+}
+
+static struct pinctrl_ops mvebu_pinctrl_ops = {
+	.set_state	= mvebu_pinctrl_set_state
+};
+
+static const struct udevice_id mvebu_pinctrl_ids[] = {
+	{ .compatible = "marvell,mvebu-pinctrl" },
+	{ .compatible = "marvell,armada-ap806-pinctrl" },
+	{ .compatible = "marvell,a70x0-pinctrl" },
+	{ .compatible = "marvell,a80x0-cp0-pinctrl" },
+	{ .compatible = "marvell,a80x0-cp1-pinctrl" },
+	{ }
+};
+
+U_BOOT_DRIVER(pinctrl_mvebu) = {
+	.name		= "mvebu_pinctrl",
+	.id		= UCLASS_PINCTRL,
+	.of_match	= mvebu_pinctrl_ids,
+	.priv_auto_alloc_size = sizeof(struct mvebu_pinctrl_priv),
+	.ops		= &mvebu_pinctrl_ops,
+	.probe		= mvebu_pinctl_probe
+};
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a1d3ef5e0ad046cb57403011882adca6613face
--- /dev/null
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ * https://spdx.org/licenses
+ */
+
+ #ifndef __PINCTRL_MVEBU_H_
+ #define __PINCTRL_MVEBU_H_
+
+ #define MVEBU_MAX_PINCTL_BANKS		4
+ #define MVEBU_MAX_PINS_PER_BANK	100
+ #define MVEBU_MAX_FUNC			0xF
+
+/*
+ * struct mvebu_pin_bank_data: mvebu-pinctrl bank data
+ * @base_reg: controller base address for this bank
+ * @pin_cnt:  number of pins included in this bank
+ * @max_func: maximum configurable function value for pins in this bank
+ * @reg_direction:
+ * @bank_name: the pin's bank name
+ */
+struct mvebu_pinctrl_priv {
+	void		*base_reg;
+	uint		pin_cnt;
+	uint		max_func;
+	int		reg_direction;
+	const char	*bank_name;
+};
+
+#endif /* __PINCTRL_MVEBU_H_ */