Merge branch 'u-boot-ti/master' into 'u-boot-arm/master'
diff --git a/Makefile b/Makefile
index 176ce10..1f56e85 100644
--- a/Makefile
+++ b/Makefile
@@ -752,6 +752,9 @@
 ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot.img
 ALL-$(CONFIG_TPL) += tpl/u-boot-tpl.bin
 ALL-$(CONFIG_OF_SEPARATE) += u-boot.dtb u-boot-dtb.bin
+ifeq ($(CONFIG_SPL_FRAMEWORK),y)
+ALL-$(CONFIG_OF_SEPARATE) += u-boot-dtb.img
+endif
 ALL-$(CONFIG_OF_HOSTFILE) += u-boot.dtb
 ifneq ($(CONFIG_SPL_TARGET),)
 ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%)
@@ -854,6 +857,11 @@
 u-boot.img u-boot.kwb u-boot.pbl: u-boot.bin FORCE
 	$(call if_changed,mkimage)
 
+MKIMAGEFLAGS_u-boot-dtb.img = $(MKIMAGEFLAGS_u-boot.img)
+
+u-boot-dtb.img: u-boot-dtb.bin FORCE
+	$(call if_changed,mkimage)
+
 u-boot.sha1:	u-boot.bin
 		tools/ubsha1 u-boot.bin
 
diff --git a/README b/README
index 5f89552..a280435 100644
--- a/README
+++ b/README
@@ -1534,6 +1534,16 @@
 			CONFIG_SH_MMCIF_CLK
 			Define the clock frequency for MMCIF
 
+		CONFIG_GENERIC_MMC
+		Enable the generic MMC driver
+
+		CONFIG_SUPPORT_EMMC_BOOT
+		Enable some additional features of the eMMC boot partitions.
+
+		CONFIG_SUPPORT_EMMC_RPMB
+		Enable the commands for reading, writing and programming the
+		key for the Replay Protection Memory Block partition in eMMC.
+
 - USB Device Firmware Update (DFU) class support:
 		CONFIG_DFU_FUNCTION
 		This enables the USB portion of the DFU USB class
@@ -1579,6 +1589,28 @@
 		entering dfuMANIFEST state. Host waits this timeout, before
 		sending again an USB request to the device.
 
+- USB Device Android Fastboot support:
+		CONFIG_CMD_FASTBOOT
+		This enables the command "fastboot" which enables the Android
+		fastboot mode for the platform's USB device. Fastboot is a USB
+		protocol for downloading images, flashing and device control
+		used on Android devices.
+		See doc/README.android-fastboot for more information.
+
+		CONFIG_ANDROID_BOOT_IMAGE
+		This enables support for booting images which use the Android
+		image format header.
+
+		CONFIG_USB_FASTBOOT_BUF_ADDR
+		The fastboot protocol requires a large memory buffer for
+		downloads. Define this to the starting RAM address to use for
+		downloaded images.
+
+		CONFIG_USB_FASTBOOT_BUF_SIZE
+		The fastboot protocol requires a large memory buffer for
+		downloads. This buffer should be as large as possible for a
+		platform. Define this to the size available RAM for fastboot.
+
 - Journaling Flash filesystem support:
 		CONFIG_JFFS2_NAND, CONFIG_JFFS2_NAND_OFF, CONFIG_JFFS2_NAND_SIZE,
 		CONFIG_JFFS2_NAND_DEV
@@ -2550,6 +2582,19 @@
 
 		Specify the number of FPGA devices to support.
 
+		CONFIG_CMD_FPGA_LOADMK
+
+		Enable support for fpga loadmk command
+
+		CONFIG_CMD_FPGA_LOADP
+
+		Enable support for fpga loadp command - load partial bitstream
+
+		CONFIG_CMD_FPGA_LOADBP
+
+		Enable support for fpga loadbp command - load partial bitstream
+		(Xilinx only)
+
 		CONFIG_SYS_FPGA_PROG_FEEDBACK
 
 		Enable printing of hash marks during FPGA configuration.
diff --git a/arch/arm/cpu/armv7/rmobile/pfc-r8a7791.c b/arch/arm/cpu/armv7/rmobile/pfc-r8a7791.c
index f49f990..46d6e60 100644
--- a/arch/arm/cpu/armv7/rmobile/pfc-r8a7791.c
+++ b/arch/arm/cpu/armv7/rmobile/pfc-r8a7791.c
@@ -913,7 +913,7 @@
 		/* SEL_SCIF3 [2] */
 		FN_SEL_SCIF3_0, FN_SEL_SCIF3_1, FN_SEL_SCIF3_2, FN_SEL_SCIF3_3,
 		/* SEL_IEB [2] */
-		FN_SEL_IEB_0, FN_SEL_IEB_1, FN_SEL_IEB_2,
+		FN_SEL_IEB_0, FN_SEL_IEB_1, FN_SEL_IEB_2, 0,
 		/* SEL_MMC [1] */
 		FN_SEL_MMC_0, FN_SEL_MMC_1,
 		/* SEL_SCIF5 [1] */
diff --git a/arch/arm/cpu/armv7/zynq/cpu.c b/arch/arm/cpu/armv7/zynq/cpu.c
index 7626b5c..816d0c5 100644
--- a/arch/arm/cpu/armv7/zynq/cpu.c
+++ b/arch/arm/cpu/armv7/zynq/cpu.c
@@ -14,6 +14,9 @@
 {
 }
 
+#define ZYNQ_SILICON_VER_MASK	0xF0000000
+#define ZYNQ_SILICON_VER_SHIFT	28
+
 int arch_cpu_init(void)
 {
 	zynq_slcr_unlock();
@@ -42,6 +45,16 @@
 	return 0;
 }
 
+unsigned int zynq_get_silicon_version(void)
+{
+	unsigned int ver;
+
+	ver = (readl(&devcfg_base->mctrl) &
+	       ZYNQ_SILICON_VER_MASK) >> ZYNQ_SILICON_VER_SHIFT;
+
+	return ver;
+}
+
 void reset_cpu(ulong addr)
 {
 	zynq_slcr_cpu_reset();
diff --git a/arch/arm/cpu/armv7/zynq/ddrc.c b/arch/arm/cpu/armv7/zynq/ddrc.c
index ba6a6ae..e0ed3bf 100644
--- a/arch/arm/cpu/armv7/zynq/ddrc.c
+++ b/arch/arm/cpu/armv7/zynq/ddrc.c
@@ -40,11 +40,8 @@
 		 * first stage bootloader. To get ECC to work all memory has
 		 * been initialized by writing any value.
 		 */
-		memset(0, 0, 1 * 1024 * 1024);
+		memset((void *)0, 0, 1 * 1024 * 1024);
 	} else {
 		puts("Memory: ECC disabled\n");
 	}
-
-	if (width == ZYNQ_DDRC_CTRLREG_BUSWIDTH_16BIT)
-		gd->ram_size /= 2;
 }
diff --git a/arch/arm/cpu/armv7/zynq/slcr.c b/arch/arm/cpu/armv7/zynq/slcr.c
index d7c1882..934ccc3 100644
--- a/arch/arm/cpu/armv7/zynq/slcr.c
+++ b/arch/arm/cpu/armv7/zynq/slcr.c
@@ -8,26 +8,75 @@
 #include <asm/io.h>
 #include <malloc.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
 #include <asm/arch/clk.h>
 
 #define SLCR_LOCK_MAGIC		0x767B
 #define SLCR_UNLOCK_MAGIC	0xDF0D
 
+#define SLCR_USB_L1_SEL			0x04
+
 #define SLCR_IDCODE_MASK	0x1F000
 #define SLCR_IDCODE_SHIFT	12
 
+/*
+ * zynq_slcr_mio_get_status - Get the status of MIO peripheral.
+ *
+ * @peri_name: Name of the peripheral for checking MIO status
+ * @get_pins: Pointer to array of get pin for this peripheral
+ * @num_pins: Number of pins for this peripheral
+ * @mask: Mask value
+ * @check_val: Required check value to get the status of  periph
+ */
+struct zynq_slcr_mio_get_status {
+	const char *peri_name;
+	const int *get_pins;
+	int num_pins;
+	u32 mask;
+	u32 check_val;
+};
+
+static const int usb0_pins[] = {
+	28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
+};
+
+static const int usb1_pins[] = {
+	40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+};
+
+static const struct zynq_slcr_mio_get_status mio_periphs[] = {
+	{
+		"usb0",
+		usb0_pins,
+		ARRAY_SIZE(usb0_pins),
+		SLCR_USB_L1_SEL,
+		SLCR_USB_L1_SEL,
+	},
+	{
+		"usb1",
+		usb1_pins,
+		ARRAY_SIZE(usb1_pins),
+		SLCR_USB_L1_SEL,
+		SLCR_USB_L1_SEL,
+	},
+};
+
 static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */
 
 void zynq_slcr_lock(void)
 {
-	if (!slcr_lock)
+	if (!slcr_lock) {
 		writel(SLCR_LOCK_MAGIC, &slcr_base->slcr_lock);
+		slcr_lock = 1;
+	}
 }
 
 void zynq_slcr_unlock(void)
 {
-	if (slcr_lock)
+	if (slcr_lock) {
 		writel(SLCR_UNLOCK_MAGIC, &slcr_base->slcr_unlock);
+		slcr_lock = 0;
+	}
 }
 
 /* Reset the entire system */
@@ -82,7 +131,7 @@
 {
 	zynq_slcr_unlock();
 
-	/* Disable AXI interface */
+	/* Disable AXI interface by asserting FPGA resets */
 	writel(0xFFFFFFFF, &slcr_base->fpga_rst_ctrl);
 
 	/* Set Level Shifters DT618760 */
@@ -98,7 +147,7 @@
 	/* Set Level Shifters DT618760 */
 	writel(0xF, &slcr_base->lvl_shftr_en);
 
-	/* Disable AXI interface */
+	/* Enable AXI interface by de-asserting FPGA resets */
 	writel(0x0, &slcr_base->fpga_rst_ctrl);
 
 	zynq_slcr_lock();
@@ -115,3 +164,33 @@
 	return (readl(&slcr_base->pss_idcode) & SLCR_IDCODE_MASK) >>
 							SLCR_IDCODE_SHIFT;
 }
+
+/*
+ * zynq_slcr_get_mio_pin_status - Get the MIO pin status of peripheral.
+ *
+ * @periph: Name of the peripheral
+ *
+ * Returns count to indicate the number of pins configured for the
+ * given @periph.
+ */
+int zynq_slcr_get_mio_pin_status(const char *periph)
+{
+	const struct zynq_slcr_mio_get_status *mio_ptr;
+	int val, i, j;
+	int mio = 0;
+
+	for (i = 0; i < ARRAY_SIZE(mio_periphs); i++) {
+		if (strcmp(periph, mio_periphs[i].peri_name) == 0) {
+			mio_ptr = &mio_periphs[i];
+			for (j = 0; j < mio_ptr->num_pins; j++) {
+				val = readl(&slcr_base->mio_pin
+						[mio_ptr->get_pins[j]]);
+				if ((val & mio_ptr->mask) == mio_ptr->check_val)
+					mio++;
+			}
+			break;
+		}
+	}
+
+	return mio;
+}
diff --git a/arch/arm/cpu/armv7/zynq/spl.c b/arch/arm/cpu/armv7/zynq/spl.c
index fcad762..d73e5cb 100644
--- a/arch/arm/cpu/armv7/zynq/spl.c
+++ b/arch/arm/cpu/armv7/zynq/spl.c
@@ -28,6 +28,13 @@
 	board_init_r(NULL, 0);
 }
 
+#ifdef CONFIG_SPL_BOARD_INIT
+void spl_board_init(void)
+{
+	board_init();
+}
+#endif
+
 u32 spl_boot_device(void)
 {
 	u32 mode;
@@ -67,3 +74,11 @@
 	return 0;
 }
 #endif
+
+__weak void ps7_init(void)
+{
+	/*
+	 * This function is overridden by the one in
+	 * board/xilinx/zynq/ps7_init.c, if it exists.
+	 */
+}
diff --git a/arch/arm/dts/zynq-7000.dtsi b/arch/arm/dts/zynq-7000.dtsi
index f20b8bd..2d076f1 100644
--- a/arch/arm/dts/zynq-7000.dtsi
+++ b/arch/arm/dts/zynq-7000.dtsi
@@ -10,4 +10,198 @@
 
 / {
 	compatible = "xlnx,zynq-7000";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <0>;
+			clocks = <&clkc 3>;
+			clock-latency = <1000>;
+			operating-points = <
+				/* kHz    uV */
+				666667  1000000
+				333334  1000000
+				222223  1000000
+			>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <1>;
+			clocks = <&clkc 3>;
+		};
+	};
+
+	pmu {
+		compatible = "arm,cortex-a9-pmu";
+		interrupts = <0 5 4>, <0 6 4>;
+		interrupt-parent = <&intc>;
+		reg = < 0xf8891000 0x1000 0xf8893000 0x1000 >;
+	};
+
+	amba {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupt-parent = <&intc>;
+		ranges;
+
+		i2c0: zynq-i2c@e0004000 {
+			compatible = "cdns,i2c-r1p10";
+			status = "disabled";
+			clocks = <&clkc 38>;
+			interrupt-parent = <&intc>;
+			interrupts = <0 25 4>;
+			reg = <0xe0004000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c1: zynq-i2c@e0005000 {
+			compatible = "cdns,i2c-r1p10";
+			status = "disabled";
+			clocks = <&clkc 39>;
+			interrupt-parent = <&intc>;
+			interrupts = <0 48 4>;
+			reg = <0xe0005000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		intc: interrupt-controller@f8f01000 {
+			compatible = "arm,cortex-a9-gic";
+			#interrupt-cells = <3>;
+			#address-cells = <1>;
+			interrupt-controller;
+			reg = <0xF8F01000 0x1000>,
+			      <0xF8F00100 0x100>;
+		};
+
+		L2: cache-controller {
+			compatible = "arm,pl310-cache";
+			reg = <0xF8F02000 0x1000>;
+			arm,data-latency = <3 2 2>;
+			arm,tag-latency = <2 2 2>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		uart0: uart@e0000000 {
+			compatible = "xlnx,xuartps";
+			status = "disabled";
+			clocks = <&clkc 23>, <&clkc 40>;
+			clock-names = "ref_clk", "aper_clk";
+			reg = <0xE0000000 0x1000>;
+			interrupts = <0 27 4>;
+		};
+
+		uart1: uart@e0001000 {
+			compatible = "xlnx,xuartps";
+			status = "disabled";
+			clocks = <&clkc 24>, <&clkc 41>;
+			clock-names = "ref_clk", "aper_clk";
+			reg = <0xE0001000 0x1000>;
+			interrupts = <0 50 4>;
+		};
+
+		gem0: ethernet@e000b000 {
+			compatible = "cdns,gem";
+			reg = <0xe000b000 0x4000>;
+			status = "disabled";
+			interrupts = <0 22 4>;
+			clocks = <&clkc 30>, <&clkc 30>, <&clkc 13>;
+			clock-names = "pclk", "hclk", "tx_clk";
+		};
+
+		gem1: ethernet@e000c000 {
+			compatible = "cdns,gem";
+			reg = <0xe000c000 0x4000>;
+			status = "disabled";
+			interrupts = <0 45 4>;
+			clocks = <&clkc 31>, <&clkc 31>, <&clkc 14>;
+			clock-names = "pclk", "hclk", "tx_clk";
+		};
+
+		sdhci0: ps7-sdhci@e0100000 {
+			compatible = "arasan,sdhci-8.9a";
+			status = "disabled";
+			clock-names = "clk_xin", "clk_ahb";
+			clocks = <&clkc 21>, <&clkc 32>;
+			interrupt-parent = <&intc>;
+			interrupts = <0 24 4>;
+			reg = <0xe0100000 0x1000>;
+		} ;
+
+		sdhci1: ps7-sdhci@e0101000 {
+			compatible = "arasan,sdhci-8.9a";
+			status = "disabled";
+			clock-names = "clk_xin", "clk_ahb";
+			clocks = <&clkc 22>, <&clkc 33>;
+			interrupt-parent = <&intc>;
+			interrupts = <0 47 4>;
+			reg = <0xe0101000 0x1000>;
+		} ;
+
+		slcr: slcr@f8000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "xlnx,zynq-slcr", "syscon";
+			reg = <0xF8000000 0x1000>;
+			ranges;
+			clkc: clkc@100 {
+				#clock-cells = <1>;
+				compatible = "xlnx,ps7-clkc";
+				ps-clk-frequency = <33333333>;
+				fclk-enable = <0>;
+				clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x",
+						"cpu_3or2x", "cpu_2x", "cpu_1x", "ddr2x", "ddr3x",
+						"dci", "lqspi", "smc", "pcap", "gem0", "gem1",
+						"fclk0", "fclk1", "fclk2", "fclk3", "can0", "can1",
+						"sdio0", "sdio1", "uart0", "uart1", "spi0", "spi1",
+						"dma", "usb0_aper", "usb1_aper", "gem0_aper",
+						"gem1_aper", "sdio0_aper", "sdio1_aper",
+						"spi0_aper", "spi1_aper", "can0_aper", "can1_aper",
+						"i2c0_aper", "i2c1_aper", "uart0_aper", "uart1_aper",
+						"gpio_aper", "lqspi_aper", "smc_aper", "swdt",
+						"dbg_trc", "dbg_apb";
+				reg = <0x100 0x100>;
+			};
+		};
+
+		global_timer: timer@f8f00200 {
+			compatible = "arm,cortex-a9-global-timer";
+			reg = <0xf8f00200 0x20>;
+			interrupts = <1 11 0x301>;
+			interrupt-parent = <&intc>;
+			clocks = <&clkc 4>;
+		};
+
+		ttc0: ttc0@f8001000 {
+			interrupt-parent = <&intc>;
+			interrupts = < 0 10 4 0 11 4 0 12 4 >;
+			compatible = "cdns,ttc";
+			clocks = <&clkc 6>;
+			reg = <0xF8001000 0x1000>;
+		};
+
+		ttc1: ttc1@f8002000 {
+			interrupt-parent = <&intc>;
+			interrupts = < 0 37 4 0 38 4 0 39 4 >;
+			compatible = "cdns,ttc";
+			clocks = <&clkc 6>;
+			reg = <0xF8002000 0x1000>;
+		};
+		scutimer: scutimer@f8f00600 {
+			interrupt-parent = <&intc>;
+			interrupts = < 1 13 0x301 >;
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = < 0xf8f00600 0x20 >;
+			clocks = <&clkc 4>;
+		} ;
+	};
 };
diff --git a/arch/arm/dts/zynq-microzed.dts b/arch/arm/dts/zynq-microzed.dts
index 6da71c1..c373a2c 100644
--- a/arch/arm/dts/zynq-microzed.dts
+++ b/arch/arm/dts/zynq-microzed.dts
@@ -11,4 +11,13 @@
 / {
 	model = "Zynq MicroZED Board";
 	compatible = "xlnx,zynq-microzed", "xlnx,zynq-7000";
+
+	aliases {
+		serial0 = &uart1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x40000000>;
+	};
 };
diff --git a/arch/arm/dts/zynq-zc702.dts b/arch/arm/dts/zynq-zc702.dts
index 667dc28..4fa0b00 100644
--- a/arch/arm/dts/zynq-zc702.dts
+++ b/arch/arm/dts/zynq-zc702.dts
@@ -11,4 +11,13 @@
 / {
 	model = "Zynq ZC702 Board";
 	compatible = "xlnx,zynq-zc702", "xlnx,zynq-7000";
+
+	aliases {
+		serial0 = &uart1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x40000000>;
+	};
 };
diff --git a/arch/arm/dts/zynq-zc706.dts b/arch/arm/dts/zynq-zc706.dts
index 526fc88..2a80195 100644
--- a/arch/arm/dts/zynq-zc706.dts
+++ b/arch/arm/dts/zynq-zc706.dts
@@ -11,4 +11,13 @@
 / {
 	model = "Zynq ZC706 Board";
 	compatible = "xlnx,zynq-zc706", "xlnx,zynq-7000";
+
+	aliases {
+		serial0 = &uart1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x40000000>;
+	};
 };
diff --git a/arch/arm/dts/zynq-zc770-xm010.dts b/arch/arm/dts/zynq-zc770-xm010.dts
index 8b542a1..5e661749 100644
--- a/arch/arm/dts/zynq-zc770-xm010.dts
+++ b/arch/arm/dts/zynq-zc770-xm010.dts
@@ -11,4 +11,13 @@
 / {
 	model = "Zynq ZC770 XM010 Board";
 	compatible = "xlnx,zynq-zc770-xm010", "xlnx,zynq-7000";
+
+	aliases {
+		serial0 = &uart1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x40000000>;
+	};
 };
diff --git a/arch/arm/dts/zynq-zc770-xm012.dts b/arch/arm/dts/zynq-zc770-xm012.dts
index 0379a07..127a661 100644
--- a/arch/arm/dts/zynq-zc770-xm012.dts
+++ b/arch/arm/dts/zynq-zc770-xm012.dts
@@ -11,4 +11,13 @@
 / {
 	model = "Zynq ZC770 XM012 Board";
 	compatible = "xlnx,zynq-zc770-xm012", "xlnx,zynq-7000";
+
+	aliases {
+		serial0 = &uart1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x40000000>;
+	};
 };
diff --git a/arch/arm/dts/zynq-zc770-xm013.dts b/arch/arm/dts/zynq-zc770-xm013.dts
index a4f9e05..c61c7e7 100644
--- a/arch/arm/dts/zynq-zc770-xm013.dts
+++ b/arch/arm/dts/zynq-zc770-xm013.dts
@@ -11,4 +11,13 @@
 / {
 	model = "Zynq ZC770 XM013 Board";
 	compatible = "xlnx,zynq-zc770-xm013", "xlnx,zynq-7000";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x40000000>;
+	};
 };
diff --git a/arch/arm/dts/zynq-zed.dts b/arch/arm/dts/zynq-zed.dts
index 91a5deb..70cc8a6 100644
--- a/arch/arm/dts/zynq-zed.dts
+++ b/arch/arm/dts/zynq-zed.dts
@@ -11,4 +11,13 @@
 / {
 	model = "Zynq ZED Board";
 	compatible = "xlnx,zynq-zed", "xlnx,zynq-7000";
+
+	aliases {
+		serial0 = &uart1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x20000000>;
+	};
 };
diff --git a/arch/arm/include/asm/arch-rmobile/r8a7790-gpio.h b/arch/arm/include/asm/arch-rmobile/r8a7790-gpio.h
index 444e361..74b5f1d 100644
--- a/arch/arm/include/asm/arch-rmobile/r8a7790-gpio.h
+++ b/arch/arm/include/asm/arch-rmobile/r8a7790-gpio.h
@@ -1,5 +1,5 @@
-#ifndef __ASM_R8A7790_H__
-#define __ASM_R8A7790_H__
+#ifndef __ASM_R8A7790_GPIO_H__
+#define __ASM_R8A7790_GPIO_H__
 
 /* Pin Function Controller:
  * GPIO_FN_xx - GPIO used to select pin function
@@ -384,4 +384,4 @@
 	GPIO_FN_TCLK1_B,
 };
 
-#endif /* __ASM_R8A7790_H__ */
+#endif /* __ASM_R8A7790_GPIO_H__ */
diff --git a/arch/arm/include/asm/arch-rmobile/r8a7791-gpio.h b/arch/arm/include/asm/arch-rmobile/r8a7791-gpio.h
index d3cf0c1..42e8259 100644
--- a/arch/arm/include/asm/arch-rmobile/r8a7791-gpio.h
+++ b/arch/arm/include/asm/arch-rmobile/r8a7791-gpio.h
@@ -1,5 +1,5 @@
-#ifndef __ASM_R8A7791_H__
-#define __ASM_R8A7791_H__
+#ifndef __ASM_R8A7791_GPIO_H__
+#define __ASM_R8A7791_GPIO_H__
 
 /* Pin Function Controller:
  * GPIO_FN_xx - GPIO used to select pin function
@@ -435,4 +435,4 @@
 	GPIO_FN_MLB_DAT, GPIO_FN_CAN1_RX_B,
 };
 
-#endif /* __ASM_R8A7791_H__ */
+#endif /* __ASM_R8A7791_GPIO_H__ */
diff --git a/arch/arm/include/asm/arch-rmobile/r8a7791.h b/arch/arm/include/asm/arch-rmobile/r8a7791.h
index 4791825..592c524 100644
--- a/arch/arm/include/asm/arch-rmobile/r8a7791.h
+++ b/arch/arm/include/asm/arch-rmobile/r8a7791.h
@@ -45,6 +45,7 @@
 #define DBSC3_1_QOS_W13_BASE	0xE67A2D00
 #define DBSC3_1_QOS_W14_BASE	0xE67A2E00
 #define DBSC3_1_QOS_W15_BASE	0xE67A2F00
+#define DBSC3_1_DBADJ2		0xE67A00C8
 
 #define R8A7791_CUT_ES2X	2
 #define IS_R8A7791_ES2()	\
diff --git a/arch/arm/include/asm/arch-rmobile/rcar-base.h b/arch/arm/include/asm/arch-rmobile/rcar-base.h
index 4331d31..41240f3 100644
--- a/arch/arm/include/asm/arch-rmobile/rcar-base.h
+++ b/arch/arm/include/asm/arch-rmobile/rcar-base.h
@@ -21,6 +21,14 @@
 #define GPIO5_BASE		0xE6055000
 #define SH_QSPI_BASE		0xE6B10000
 
+/* SCIF */
+#define SCIF0_BASE		0xE6E60000
+#define SCIF1_BASE		0xE6E68000
+#define SCIF2_BASE		0xE6E58000
+#define SCIF3_BASE		0xE6EA8000
+#define SCIF4_BASE		0xE6EE0000
+#define SCIF5_BASE		0xE6EE8000
+
 #define S3C_BASE		0xE6784000
 #define S3C_INT_BASE		0xE6784A00
 #define S3C_MEDIA_BASE		0xE6784B00
diff --git a/arch/arm/include/asm/arch-tegra/usb.h b/arch/arm/include/asm/arch-tegra/usb.h
index ceb7bcd..c817088 100644
--- a/arch/arm/include/asm/arch-tegra/usb.h
+++ b/arch/arm/include/asm/arch-tegra/usb.h
@@ -349,6 +349,8 @@
 
 /* USB3_IF_USB_PHY_VBUS_SENSORS_0 */
 #define VBUS_VLD_STS			(1 << 26)
+#define VBUS_B_SESS_VLD_SW_VALUE	(1 << 12)
+#define VBUS_B_SESS_VLD_SW_EN		(1 << 11)
 
 /* Setup USB on the board */
 int usb_process_devicetree(const void *blob);
diff --git a/arch/arm/include/asm/arch-zynq/hardware.h b/arch/arm/include/asm/arch-zynq/hardware.h
index 39184da..2aede0c 100644
--- a/arch/arm/include/asm/arch-zynq/hardware.h
+++ b/arch/arm/include/asm/arch-zynq/hardware.h
@@ -22,9 +22,12 @@
 #define ZYNQ_SPI_BASEADDR0		0xE0006000
 #define ZYNQ_SPI_BASEADDR1		0xE0007000
 #define ZYNQ_DDRC_BASEADDR		0xF8006000
+#define ZYNQ_EFUSE_BASEADDR		0xF800D000
+#define ZYNQ_USB_BASEADDR0		0xE0002000
+#define ZYNQ_USB_BASEADDR1		0xE0003000
 
 /* Bootmode setting values */
-#define ZYNQ_BM_MASK		0xF
+#define ZYNQ_BM_MASK		0x7
 #define ZYNQ_BM_NOR		0x2
 #define ZYNQ_BM_SD		0x5
 #define ZYNQ_BM_JTAG		0x0
@@ -130,4 +133,12 @@
 };
 #define ddrc_base ((struct ddrc_regs *)ZYNQ_DDRC_BASEADDR)
 
+struct efuse_reg {
+	u32 reserved1[4];
+	u32 status;
+	u32 reserved2[3];
+};
+
+#define efuse_base ((struct efuse_reg *)ZYNQ_EFUSE_BASEADDR)
+
 #endif /* _ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/include/asm/arch-zynq/sys_proto.h b/arch/arm/include/asm/arch-zynq/sys_proto.h
index a68e1b3..53c30ec 100644
--- a/arch/arm/include/asm/arch-zynq/sys_proto.h
+++ b/arch/arm/include/asm/arch-zynq/sys_proto.h
@@ -15,7 +15,9 @@
 extern void zynq_slcr_devcfg_enable(void);
 extern u32 zynq_slcr_get_boot_mode(void);
 extern u32 zynq_slcr_get_idcode(void);
+extern int zynq_slcr_get_mio_pin_status(const char *periph);
 extern void zynq_ddrc_init(void);
+extern unsigned int zynq_get_silicon_version(void);
 
 /* Driver extern functions */
 extern int zynq_sdhci_init(u32 regbase);
diff --git a/board/BuR/common/common.c b/board/BuR/common/common.c
index 4c926ce..25cbe62 100644
--- a/board/BuR/common/common.c
+++ b/board/BuR/common/common.c
@@ -19,6 +19,7 @@
 #include <asm/arch/clock.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/arch/mmc_host_def.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <i2c.h>
@@ -214,3 +215,9 @@
 	return rv;
 }
 #endif /* CONFIG_DRIVER_TI_CPSW */
+#if defined(CONFIG_GENERIC_MMC) && !defined(CONFIG_SPL_BUILD)
+int board_mmc_init(bd_t *bis)
+{
+	return omap_mmc_init(1, 0, 0, -1, -1);
+}
+#endif
diff --git a/board/matrix_vision/common/mv_common.c b/board/matrix_vision/common/mv_common.c
index 70133b5..1be5aba 100644
--- a/board/matrix_vision/common/mv_common.c
+++ b/board/matrix_vision/common/mv_common.c
@@ -77,7 +77,7 @@
 		return -1;
 	}
 
-	result = fpga_load(0, fpga_data, data_size);
+	result = fpga_load(0, fpga_data, data_size, BIT_FULL);
 	if (!result)
 		bootstage_mark(BOOTSTAGE_ID_START);
 
diff --git a/board/renesas/koelsch/qos.c b/board/renesas/koelsch/qos.c
index e6c5e48..55a0420 100644
--- a/board/renesas/koelsch/qos.c
+++ b/board/renesas/koelsch/qos.c
@@ -111,6 +111,7 @@
 
 	/* DBSC DBADJ2 */
 	writel(0x20042004, DBSC3_0_DBADJ2);
+	writel(0x20042004, DBSC3_1_DBADJ2);
 
 	/* S3C -QoS */
 	s3c = (struct rcar_s3c *)S3C_BASE;
diff --git a/board/samsung/common/Makefile b/board/samsung/common/Makefile
index 7d2bb8c..41d0cc3 100644
--- a/board/samsung/common/Makefile
+++ b/board/samsung/common/Makefile
@@ -7,7 +7,6 @@
 
 obj-$(CONFIG_SOFT_I2C_MULTI_BUS) += multi_i2c.o
 obj-$(CONFIG_THOR_FUNCTION) += thor.o
-obj-$(CONFIG_CMD_USB_MASS_STORAGE) += ums.o
 obj-$(CONFIG_MISC_COMMON) += misc.o
 
 ifndef CONFIG_SPL_BUILD
diff --git a/board/samsung/common/ums.c b/board/samsung/common/ums.c
deleted file mode 100644
index cebabe9..0000000
--- a/board/samsung/common/ums.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2013 Samsung Electronics
- * Lukasz Majewski <l.majewski@samsung.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <usb_mass_storage.h>
-#include <part.h>
-
-static int ums_read_sector(struct ums *ums_dev,
-			   ulong start, lbaint_t blkcnt, void *buf)
-{
-	block_dev_desc_t *block_dev = &ums_dev->mmc->block_dev;
-	lbaint_t blkstart = start + ums_dev->start_sector;
-	int dev_num = block_dev->dev;
-
-	return block_dev->block_read(dev_num, blkstart, blkcnt, buf);
-}
-
-static int ums_write_sector(struct ums *ums_dev,
-			    ulong start, lbaint_t blkcnt, const void *buf)
-{
-	block_dev_desc_t *block_dev = &ums_dev->mmc->block_dev;
-	lbaint_t blkstart = start + ums_dev->start_sector;
-	int dev_num = block_dev->dev;
-
-	return block_dev->block_write(dev_num, blkstart, blkcnt, buf);
-}
-
-static struct ums ums_dev = {
-	.read_sector = ums_read_sector,
-	.write_sector = ums_write_sector,
-	.name = "UMS disk",
-};
-
-static struct ums *ums_disk_init(struct mmc *mmc)
-{
-	uint64_t mmc_end_sector = mmc->capacity / SECTOR_SIZE;
-	uint64_t ums_end_sector = UMS_NUM_SECTORS + UMS_START_SECTOR;
-
-	if (!mmc_end_sector) {
-		error("MMC capacity is not valid");
-		return NULL;
-	}
-
-	ums_dev.mmc = mmc;
-
-	if (ums_end_sector <= mmc_end_sector) {
-		ums_dev.start_sector = UMS_START_SECTOR;
-		if (UMS_NUM_SECTORS)
-			ums_dev.num_sectors = UMS_NUM_SECTORS;
-		else
-			ums_dev.num_sectors = mmc_end_sector - UMS_START_SECTOR;
-	} else {
-		ums_dev.num_sectors = mmc_end_sector;
-		puts("UMS: defined bad disk parameters. Using default.\n");
-	}
-
-	printf("UMS: disk start sector: %#x, count: %#x\n",
-	       ums_dev.start_sector, ums_dev.num_sectors);
-
-	return &ums_dev;
-}
-
-struct ums *ums_init(unsigned int dev_num)
-{
-	struct mmc *mmc = find_mmc_device(dev_num);
-
-	if (!mmc || mmc_init(mmc))
-		return NULL;
-	return ums_disk_init(mmc);
-}
diff --git a/board/xilinx/zynq/.gitignore b/board/xilinx/zynq/.gitignore
new file mode 100644
index 0000000..68b8edd
--- /dev/null
+++ b/board/xilinx/zynq/.gitignore
@@ -0,0 +1 @@
+ps7_init.[ch]
diff --git a/board/xilinx/zynq/Makefile b/board/xilinx/zynq/Makefile
index 3f19a1c..fd93f63 100644
--- a/board/xilinx/zynq/Makefile
+++ b/board/xilinx/zynq/Makefile
@@ -6,4 +6,7 @@
 #
 
 obj-y	:= board.o
-obj-$(CONFIG_SPL_BUILD)	+= ps7_init.o
+
+# Please copy ps7_init.c/h from hw project to this directory
+obj-$(CONFIG_SPL_BUILD) += \
+		$(if $(wildcard $(srctree)/$(src)/ps7_init.c), ps7_init.o)
diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c
index c8cc2bc..258632e 100644
--- a/board/xilinx/zynq/board.c
+++ b/board/xilinx/zynq/board.c
@@ -6,6 +6,8 @@
 
 #include <common.h>
 #include <fdtdec.h>
+#include <fpga.h>
+#include <mmc.h>
 #include <netdev.h>
 #include <zynqpl.h>
 #include <asm/arch/hardware.h>
@@ -13,21 +15,23 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#ifdef CONFIG_FPGA
-xilinx_desc fpga;
+#if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \
+    (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD))
+static xilinx_desc fpga;
 
 /* It can be done differently */
-xilinx_desc fpga010 = XILINX_XC7Z010_DESC(0x10);
-xilinx_desc fpga015 = XILINX_XC7Z015_DESC(0x15);
-xilinx_desc fpga020 = XILINX_XC7Z020_DESC(0x20);
-xilinx_desc fpga030 = XILINX_XC7Z030_DESC(0x30);
-xilinx_desc fpga045 = XILINX_XC7Z045_DESC(0x45);
-xilinx_desc fpga100 = XILINX_XC7Z100_DESC(0x100);
+static xilinx_desc fpga010 = XILINX_XC7Z010_DESC(0x10);
+static xilinx_desc fpga015 = XILINX_XC7Z015_DESC(0x15);
+static xilinx_desc fpga020 = XILINX_XC7Z020_DESC(0x20);
+static xilinx_desc fpga030 = XILINX_XC7Z030_DESC(0x30);
+static xilinx_desc fpga045 = XILINX_XC7Z045_DESC(0x45);
+static xilinx_desc fpga100 = XILINX_XC7Z100_DESC(0x100);
 #endif
 
 int board_init(void)
 {
-#ifdef CONFIG_FPGA
+#if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \
+    (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD))
 	u32 idcode;
 
 	idcode = zynq_slcr_get_idcode();
@@ -54,7 +58,8 @@
 	}
 #endif
 
-#ifdef CONFIG_FPGA
+#if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \
+    (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD))
 	fpga_init();
 	fpga_add(fpga_xilinx, &fpga);
 #endif
diff --git a/board/xilinx/zynq/ps7_init.c b/board/xilinx/zynq/ps7_init.c
deleted file mode 100644
index c47da09..0000000
--- a/board/xilinx/zynq/ps7_init.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * (C) Copyright 2014 Xilinx, Inc. Michal Simek
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-#include <common.h>
-#include <asm/arch/spl.h>
-
-__weak void ps7_init(void)
-{
-	puts("Please copy ps7_init.c/h from hw project\n");
-}
diff --git a/board/xilinx/zynq/xil_io.h b/board/xilinx/zynq/xil_io.h
new file mode 100644
index 0000000..e59a977
--- /dev/null
+++ b/board/xilinx/zynq/xil_io.h
@@ -0,0 +1,13 @@
+/*
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef XIL_IO_H           /* prevent circular inclusions */
+#define XIL_IO_H
+
+/*
+ * This empty file is here because ps7_init.c exported by hw project
+ * has #include "xil_io.h" line.
+ */
+
+#endif /* XIL_IO_H */
diff --git a/common/Makefile b/common/Makefile
index 7c853ae..219cb51 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -168,6 +168,8 @@
 obj-y += usb.o usb_hub.o
 obj-$(CONFIG_USB_STORAGE) += usb_storage.o
 endif
+obj-$(CONFIG_CMD_FASTBOOT) += cmd_fastboot.o
+
 obj-$(CONFIG_CMD_USB_MASS_STORAGE) += cmd_usb_mass_storage.o
 obj-$(CONFIG_CMD_THOR_DOWNLOAD) += cmd_thordown.o
 obj-$(CONFIG_CMD_XIMG) += cmd_ximg.o
@@ -237,6 +239,7 @@
 obj-$(CONFIG_CROS_EC) += cros_ec.o
 obj-y += dlmalloc.o
 obj-y += image.o
+obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
 obj-$(CONFIG_OF_LIBFDT) += image-fdt.o
 obj-$(CONFIG_FIT) += image-fit.o
 obj-$(CONFIG_FIT_SIGNATURE) += image-sig.o
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index e683af3..34b4b58 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -222,6 +222,7 @@
 			 char * const argv[])
 {
 	const void *os_hdr;
+	bool ep_found = false;
 
 	/* get kernel image header, start address and length */
 	os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
@@ -274,6 +275,18 @@
 		}
 		break;
 #endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+	case IMAGE_FORMAT_ANDROID:
+		images.os.type = IH_TYPE_KERNEL;
+		images.os.comp = IH_COMP_NONE;
+		images.os.os = IH_OS_LINUX;
+		images.ep = images.os.load;
+		ep_found = true;
+
+		images.os.end = android_image_get_end(os_hdr);
+		images.os.load = android_image_get_kload(os_hdr);
+		break;
+#endif
 	default:
 		puts("ERROR: unknown image format type!\n");
 		return 1;
@@ -293,7 +306,7 @@
 			return 1;
 		}
 #endif
-	} else {
+	} else if (!ep_found) {
 		puts("Could not find kernel entry point!\n");
 		return 1;
 	}
@@ -1002,6 +1015,14 @@
 		images->fit_noffset_os = os_noffset;
 		break;
 #endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+	case IMAGE_FORMAT_ANDROID:
+		printf("## Booting Android Image at 0x%08lx ...\n", img_addr);
+		if (android_image_get_kernel((void *)img_addr, images->verify,
+					     os_data, os_len))
+			return NULL;
+		break;
+#endif
 	default:
 		printf("Wrong Image Format for %s command\n", cmdtp->name);
 		bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO);
diff --git a/common/cmd_fastboot.c b/common/cmd_fastboot.c
new file mode 100644
index 0000000..83fa7bd
--- /dev/null
+++ b/common/cmd_fastboot.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 - 2009 Windriver, <www.windriver.com>
+ * Author: Tom Rix <Tom.Rix@windriver.com>
+ *
+ * (C) Copyright 2014 Linaro, Ltd.
+ * Rob Herring <robh@kernel.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <command.h>
+#include <g_dnl.h>
+
+static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	int ret;
+
+	ret = g_dnl_register("usb_dnl_fastboot");
+	if (ret)
+		return ret;
+
+	while (1) {
+		if (ctrlc())
+			break;
+		usb_gadget_handle_interrupts();
+	}
+
+	g_dnl_unregister();
+	return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+	fastboot,	1,	1,	do_fastboot,
+	"fastboot - enter USB Fastboot protocol",
+	""
+);
diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c
index 010cd24..bda5c8f 100644
--- a/common/cmd_fpga.c
+++ b/common/cmd_fpga.c
@@ -11,6 +11,7 @@
 #include <common.h>
 #include <command.h>
 #include <fpga.h>
+#include <fs.h>
 #include <malloc.h>
 
 /* Local functions */
@@ -23,6 +24,9 @@
 #define FPGA_LOADB  2
 #define FPGA_DUMP   3
 #define FPGA_LOADMK 4
+#define FPGA_LOADP  5
+#define FPGA_LOADBP 6
+#define FPGA_LOADFS 7
 
 /* ------------------------------------------------------------------------- */
 /* command form:
@@ -45,6 +49,10 @@
 	const char *fit_uname = NULL;
 	ulong fit_addr;
 #endif
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+	fpga_fs_info fpga_fsinfo;
+	fpga_fsinfo.fstype = FS_TYPE_ANY;
+#endif
 
 	if (devstr)
 		dev = (int) simple_strtoul(devstr, NULL, 16);
@@ -52,6 +60,14 @@
 		fpga_data = (void *)simple_strtoul(datastr, NULL, 16);
 
 	switch (argc) {
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+	case 9:
+		fpga_fsinfo.blocksize = (unsigned int)
+					     simple_strtoul(argv[5], NULL, 16);
+		fpga_fsinfo.interface = argv[6];
+		fpga_fsinfo.dev_part = argv[7];
+		fpga_fsinfo.filename = argv[8];
+#endif
 	case 5:		/* fpga <op> <dev> <data> <datasize> */
 		data_size = simple_strtoul(argv[4], NULL, 16);
 
@@ -120,16 +136,27 @@
 	case FPGA_NONE:
 	case FPGA_INFO:
 		break;
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+	case FPGA_LOADFS:
+		/* Blocksize can be zero */
+		if (!fpga_fsinfo.interface || !fpga_fsinfo.dev_part ||
+		    !fpga_fsinfo.filename)
+			wrong_parms = 1;
+#endif
 	case FPGA_LOAD:
+	case FPGA_LOADP:
 	case FPGA_LOADB:
+	case FPGA_LOADBP:
 	case FPGA_DUMP:
 		if (!fpga_data || !data_size)
 			wrong_parms = 1;
 		break;
+#if defined(CONFIG_CMD_FPGA_LOADMK)
 	case FPGA_LOADMK:
 		if (!fpga_data)
 			wrong_parms = 1;
 		break;
+#endif
 	}
 
 	if (wrong_parms) {
@@ -146,13 +173,32 @@
 		break;
 
 	case FPGA_LOAD:
-		rc = fpga_load(dev, fpga_data, data_size);
+		rc = fpga_load(dev, fpga_data, data_size, BIT_FULL);
+		break;
+
+#if defined(CONFIG_CMD_FPGA_LOADP)
+	case FPGA_LOADP:
+		rc = fpga_load(dev, fpga_data, data_size, BIT_PARTIAL);
 		break;
+#endif
 
 	case FPGA_LOADB:
-		rc = fpga_loadbitstream(dev, fpga_data, data_size);
+		rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_FULL);
+		break;
+
+#if defined(CONFIG_CMD_FPGA_LOADBP)
+	case FPGA_LOADBP:
+		rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_PARTIAL);
+		break;
+#endif
+
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+	case FPGA_LOADFS:
+		rc = fpga_fsload(dev, fpga_data, data_size, &fpga_fsinfo);
 		break;
+#endif
 
+#if defined(CONFIG_CMD_FPGA_LOADMK)
 	case FPGA_LOADMK:
 		switch (genimg_get_format(fpga_data)) {
 		case IMAGE_FORMAT_LEGACY:
@@ -179,7 +225,8 @@
 					data = (ulong)image_get_data(hdr);
 					data_size = image_get_data_size(hdr);
 				}
-				rc = fpga_load(dev, (void *)data, data_size);
+				rc = fpga_load(dev, (void *)data, data_size,
+					       BIT_FULL);
 			}
 			break;
 #if defined(CONFIG_FIT)
@@ -221,7 +268,8 @@
 					return 1;
 				}
 
-				rc = fpga_load(dev, fit_data, data_size);
+				rc = fpga_load(dev, fit_data, data_size,
+					       BIT_FULL);
 			}
 			break;
 #endif
@@ -231,6 +279,7 @@
 			break;
 		}
 		break;
+#endif
 
 	case FPGA_DUMP:
 		rc = fpga_dump(dev, fpga_data, data_size);
@@ -257,8 +306,22 @@
 		op = FPGA_LOADB;
 	else if (!strcmp("load", opstr))
 		op = FPGA_LOAD;
+#if defined(CONFIG_CMD_FPGA_LOADP)
+	else if (!strcmp("loadp", opstr))
+		op = FPGA_LOADP;
+#endif
+#if defined(CONFIG_CMD_FPGA_LOADBP)
+	else if (!strcmp("loadbp", opstr))
+		op = FPGA_LOADBP;
+#endif
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+	else if (!strcmp("loadfs", opstr))
+		op = FPGA_LOADFS;
+#endif
+#if defined(CONFIG_CMD_FPGA_LOADMK)
 	else if (!strcmp("loadmk", opstr))
 		op = FPGA_LOADMK;
+#endif
 	else if (!strcmp("dump", opstr))
 		op = FPGA_DUMP;
 
@@ -268,19 +331,39 @@
 	return op;
 }
 
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+U_BOOT_CMD(fpga, 9, 1, do_fpga,
+#else
 U_BOOT_CMD(fpga, 6, 1, do_fpga,
+#endif
 	   "loadable FPGA image support",
 	   "[operation type] [device number] [image address] [image size]\n"
 	   "fpga operations:\n"
 	   "  dump\t[dev]\t\t\tLoad device to memory buffer\n"
 	   "  info\t[dev]\t\t\tlist known device information\n"
 	   "  load\t[dev] [address] [size]\tLoad device from memory buffer\n"
+#if defined(CONFIG_CMD_FPGA_LOADP)
+	   "  loadp\t[dev] [address] [size]\t"
+	   "Load device from memory buffer with partial bitstream\n"
+#endif
 	   "  loadb\t[dev] [address] [size]\t"
 	   "Load device from bitstream buffer (Xilinx only)\n"
+#if defined(CONFIG_CMD_FPGA_LOADBP)
+	   "  loadbp\t[dev] [address] [size]\t"
+	   "Load device from bitstream buffer with partial bitstream"
+	   "(Xilinx only)\n"
+#endif
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+	   "Load device from filesystem (FAT by default) (Xilinx only)\n"
+	   "  loadfs [dev] [address] [image size] [blocksize] <interface>\n"
+	   "        [<dev[:part]>] <filename>\n"
+#endif
+#if defined(CONFIG_CMD_FPGA_LOADMK)
 	   "  loadmk [dev] [address]\tLoad device generated with mkimage"
 #if defined(CONFIG_FIT)
 	   "\n"
 	   "\tFor loadmk operating on FIT format uImage address must include\n"
 	   "\tsubimage unit name in the form of addr:<subimg_uname>"
 #endif
+#endif
 );
diff --git a/common/cmd_fuse.c b/common/cmd_fuse.c
index 0df57db..abab978 100644
--- a/common/cmd_fuse.c
+++ b/common/cmd_fuse.c
@@ -33,15 +33,8 @@
 					"what you are doing!\n"
 			"\nReally perform this fuse programming? <y/N>\n");
 
-	if (getc() == 'y') {
-		int c;
-
-		putc('y');
-		c = getc();
-		putc('\n');
-		if (c == '\r')
-			return 1;
-	}
+	if (confirm_yesno())
+		return 1;
 
 	puts("Fuse programming aborted\n");
 	return 0;
diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index c1916c9..eea3375 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -71,12 +71,6 @@
 );
 #else /* !CONFIG_GENERIC_MMC */
 
-enum mmc_state {
-	MMC_INVALID,
-	MMC_READ,
-	MMC_WRITE,
-	MMC_ERASE,
-};
 static void print_mmcinfo(struct mmc *mmc)
 {
 	printf("Device: %s\n", mmc->cfg->name);
@@ -98,7 +92,18 @@
 
 	printf("Bus Width: %d-bit\n", mmc->bus_width);
 }
-
+static struct mmc *init_mmc_device(int dev)
+{
+	struct mmc *mmc;
+	mmc = find_mmc_device(dev);
+	if (!mmc) {
+		printf("no mmc device at slot %x\n", dev);
+		return NULL;
+	}
+	if (mmc_init(mmc))
+		return NULL;
+	return mmc;
+}
 static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	struct mmc *mmc;
@@ -112,351 +117,537 @@
 		}
 	}
 
-	mmc = find_mmc_device(curr_device);
+	mmc = init_mmc_device(curr_device);
+	if (!mmc)
+		return CMD_RET_FAILURE;
 
-	if (mmc) {
-		mmc_init(mmc);
+	print_mmcinfo(mmc);
+	return CMD_RET_SUCCESS;
+}
 
-		print_mmcinfo(mmc);
-		return 0;
-	} else {
-		printf("no mmc device at slot %x\n", curr_device);
+#ifdef CONFIG_SUPPORT_EMMC_RPMB
+static int confirm_key_prog(void)
+{
+	puts("Warning: Programming authentication key can be done only once !\n"
+	     "         Use this command only if you are sure of what you are doing,\n"
+	     "Really perform the key programming? <y/N> ");
+	if (confirm_yesno())
 		return 1;
+
+	puts("Authentication key programming aborted\n");
+	return 0;
+}
+static int do_mmcrpmb_key(cmd_tbl_t *cmdtp, int flag,
+			  int argc, char * const argv[])
+{
+	void *key_addr;
+	struct mmc *mmc = find_mmc_device(curr_device);
+
+	if (argc != 2)
+		return CMD_RET_USAGE;
+
+	key_addr = (void *)simple_strtoul(argv[1], NULL, 16);
+	if (!confirm_key_prog())
+		return CMD_RET_FAILURE;
+	if (mmc_rpmb_set_key(mmc, key_addr)) {
+		printf("ERROR - Key already programmed ?\n");
+		return CMD_RET_FAILURE;
 	}
+	return CMD_RET_SUCCESS;
 }
+static int do_mmcrpmb_read(cmd_tbl_t *cmdtp, int flag,
+			   int argc, char * const argv[])
+{
+	u16 blk, cnt;
+	void *addr;
+	int n;
+	void *key_addr = NULL;
+	struct mmc *mmc = find_mmc_device(curr_device);
 
-U_BOOT_CMD(
-	mmcinfo, 1, 0, do_mmcinfo,
-	"display MMC info",
-	"- display info of the current MMC device"
-);
+	if (argc < 4)
+		return CMD_RET_USAGE;
 
-static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+	addr = (void *)simple_strtoul(argv[1], NULL, 16);
+	blk = simple_strtoul(argv[2], NULL, 16);
+	cnt = simple_strtoul(argv[3], NULL, 16);
+
+	if (argc == 5)
+		key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
+
+	printf("\nMMC RPMB read: dev # %d, block # %d, count %d ... ",
+	       curr_device, blk, cnt);
+	n =  mmc_rpmb_read(mmc, addr, blk, cnt, key_addr);
+
+	printf("%d RPMB blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
+	if (n != cnt)
+		return CMD_RET_FAILURE;
+	return CMD_RET_SUCCESS;
+}
+static int do_mmcrpmb_write(cmd_tbl_t *cmdtp, int flag,
+			    int argc, char * const argv[])
 {
-	enum mmc_state state;
+	u16 blk, cnt;
+	void *addr;
+	int n;
+	void *key_addr;
+	struct mmc *mmc = find_mmc_device(curr_device);
 
-	if (argc < 2)
+	if (argc != 5)
 		return CMD_RET_USAGE;
 
-	if (curr_device < 0) {
-		if (get_mmc_num() > 0)
-			curr_device = 0;
-		else {
-			puts("No MMC device available\n");
-			return 1;
-		}
+	addr = (void *)simple_strtoul(argv[1], NULL, 16);
+	blk = simple_strtoul(argv[2], NULL, 16);
+	cnt = simple_strtoul(argv[3], NULL, 16);
+	key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
+
+	printf("\nMMC RPMB write: dev # %d, block # %d, count %d ... ",
+	       curr_device, blk, cnt);
+	n =  mmc_rpmb_write(mmc, addr, blk, cnt, key_addr);
+
+	printf("%d RPMB blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
+	if (n != cnt)
+		return CMD_RET_FAILURE;
+	return CMD_RET_SUCCESS;
+}
+static int do_mmcrpmb_counter(cmd_tbl_t *cmdtp, int flag,
+			      int argc, char * const argv[])
+{
+	unsigned long counter;
+	struct mmc *mmc = find_mmc_device(curr_device);
+
+	if (mmc_rpmb_get_counter(mmc, &counter))
+		return CMD_RET_FAILURE;
+	printf("RPMB Write counter= %lx\n", counter);
+	return CMD_RET_SUCCESS;
+}
+
+static cmd_tbl_t cmd_rpmb[] = {
+	U_BOOT_CMD_MKENT(key, 2, 0, do_mmcrpmb_key, "", ""),
+	U_BOOT_CMD_MKENT(read, 5, 1, do_mmcrpmb_read, "", ""),
+	U_BOOT_CMD_MKENT(write, 5, 0, do_mmcrpmb_write, "", ""),
+	U_BOOT_CMD_MKENT(counter, 1, 1, do_mmcrpmb_counter, "", ""),
+};
+
+static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag,
+		      int argc, char * const argv[])
+{
+	cmd_tbl_t *cp;
+	struct mmc *mmc;
+	char original_part;
+	int ret;
+
+	cp = find_cmd_tbl(argv[1], cmd_rpmb, ARRAY_SIZE(cmd_rpmb));
+
+	/* Drop the rpmb subcommand */
+	argc--;
+	argv++;
+
+	if (cp == NULL || argc > cp->maxargs)
+		return CMD_RET_USAGE;
+	if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
+		return CMD_RET_SUCCESS;
+
+	mmc = init_mmc_device(curr_device);
+	if (!mmc)
+		return CMD_RET_FAILURE;
+
+	if (!(mmc->version & MMC_VERSION_MMC)) {
+		printf("It is not a EMMC device\n");
+		return CMD_RET_FAILURE;
+	}
+	if (mmc->version < MMC_VERSION_4_41) {
+		printf("RPMB not supported before version 4.41\n");
+		return CMD_RET_FAILURE;
 	}
+	/* Switch to the RPMB partition */
+	original_part = mmc->part_num;
+	if (mmc->part_num != MMC_PART_RPMB) {
+		if (mmc_switch_part(curr_device, MMC_PART_RPMB) != 0)
+			return CMD_RET_FAILURE;
+		mmc->part_num = MMC_PART_RPMB;
+	}
+	ret = cp->cmd(cmdtp, flag, argc, argv);
 
-	if (strcmp(argv[1], "rescan") == 0) {
-		struct mmc *mmc;
+	/* Return to original partition */
+	if (mmc->part_num != original_part) {
+		if (mmc_switch_part(curr_device, original_part) != 0)
+			return CMD_RET_FAILURE;
+		mmc->part_num = original_part;
+	}
+	return ret;
+}
+#endif
 
-		if (argc != 2)
-			return CMD_RET_USAGE;
+static int do_mmc_read(cmd_tbl_t *cmdtp, int flag,
+		       int argc, char * const argv[])
+{
+	struct mmc *mmc;
+	u32 blk, cnt, n;
+	void *addr;
 
-		mmc = find_mmc_device(curr_device);
-		if (!mmc) {
-			printf("no mmc device at slot %x\n", curr_device);
-			return 1;
-		}
+	if (argc != 4)
+		return CMD_RET_USAGE;
 
-		mmc->has_init = 0;
+	addr = (void *)simple_strtoul(argv[1], NULL, 16);
+	blk = simple_strtoul(argv[2], NULL, 16);
+	cnt = simple_strtoul(argv[3], NULL, 16);
 
-		if (mmc_init(mmc))
-			return 1;
-		else
-			return 0;
-	} else if (strcmp(argv[1], "part") == 0) {
-		block_dev_desc_t *mmc_dev;
-		struct mmc *mmc;
+	mmc = init_mmc_device(curr_device);
+	if (!mmc)
+		return CMD_RET_FAILURE;
 
-		if (argc != 2)
-			return CMD_RET_USAGE;
+	printf("\nMMC read: dev # %d, block # %d, count %d ... ",
+	       curr_device, blk, cnt);
 
-		mmc = find_mmc_device(curr_device);
-		if (!mmc) {
-			printf("no mmc device at slot %x\n", curr_device);
-			return 1;
-		}
-		mmc_init(mmc);
-		mmc_dev = mmc_get_dev(curr_device);
-		if (mmc_dev != NULL &&
-				mmc_dev->type != DEV_TYPE_UNKNOWN) {
-			print_part(mmc_dev);
-			return 0;
-		}
+	n = mmc->block_dev.block_read(curr_device, blk, cnt, addr);
+	/* flush cache after read */
+	flush_cache((ulong)addr, cnt * 512); /* FIXME */
+	printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
 
-		puts("get mmc type error!\n");
-		return 1;
-	} else if (strcmp(argv[1], "list") == 0) {
-		if (argc != 2)
-			return CMD_RET_USAGE;
-		print_mmc_devices('\n');
-		return 0;
-	} else if (strcmp(argv[1], "dev") == 0) {
-		int dev, part = -1;
-		struct mmc *mmc;
+	return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+}
+static int do_mmc_write(cmd_tbl_t *cmdtp, int flag,
+			int argc, char * const argv[])
+{
+	struct mmc *mmc;
+	u32 blk, cnt, n;
+	void *addr;
 
-		if (argc == 2)
-			dev = curr_device;
-		else if (argc == 3)
-			dev = simple_strtoul(argv[2], NULL, 10);
-		else if (argc == 4) {
-			dev = (int)simple_strtoul(argv[2], NULL, 10);
-			part = (int)simple_strtoul(argv[3], NULL, 10);
-			if (part > PART_ACCESS_MASK) {
-				printf("#part_num shouldn't be larger"
-					" than %d\n", PART_ACCESS_MASK);
-				return 1;
-			}
-		} else
-			return CMD_RET_USAGE;
+	if (argc != 4)
+		return CMD_RET_USAGE;
 
-		mmc = find_mmc_device(dev);
-		if (!mmc) {
-			printf("no mmc device at slot %x\n", dev);
-			return 1;
-		}
+	addr = (void *)simple_strtoul(argv[1], NULL, 16);
+	blk = simple_strtoul(argv[2], NULL, 16);
+	cnt = simple_strtoul(argv[3], NULL, 16);
 
-		mmc_init(mmc);
-		if (part != -1) {
-			int ret;
-			if (mmc->part_config == MMCPART_NOAVAILABLE) {
-				printf("Card doesn't support part_switch\n");
-				return 1;
-			}
+	mmc = init_mmc_device(curr_device);
+	if (!mmc)
+		return CMD_RET_FAILURE;
 
-			if (part != mmc->part_num) {
-				ret = mmc_switch_part(dev, part);
-				if (!ret)
-					mmc->part_num = part;
+	printf("\nMMC write: dev # %d, block # %d, count %d ... ",
+	       curr_device, blk, cnt);
 
-				printf("switch to partitions #%d, %s\n",
-						part, (!ret) ? "OK" : "ERROR");
-			}
-		}
-		curr_device = dev;
-		if (mmc->part_config == MMCPART_NOAVAILABLE)
-			printf("mmc%d is current device\n", curr_device);
-		else
-			printf("mmc%d(part %d) is current device\n",
-				curr_device, mmc->part_num);
+	if (mmc_getwp(mmc) == 1) {
+		printf("Error: card is write protected!\n");
+		return CMD_RET_FAILURE;
+	}
+	n = mmc->block_dev.block_write(curr_device, blk, cnt, addr);
+	printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
 
-		return 0;
-#ifdef CONFIG_SUPPORT_EMMC_BOOT
-	} else if (strcmp(argv[1], "partconf") == 0) {
-		int dev;
-		struct mmc *mmc;
-		u8 ack, part_num, access;
+	return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+}
+static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag,
+			int argc, char * const argv[])
+{
+	struct mmc *mmc;
+	u32 blk, cnt, n;
 
-		if (argc == 6) {
-			dev = simple_strtoul(argv[2], NULL, 10);
-			ack = simple_strtoul(argv[3], NULL, 10);
-			part_num = simple_strtoul(argv[4], NULL, 10);
-			access = simple_strtoul(argv[5], NULL, 10);
-		} else {
-			return CMD_RET_USAGE;
-		}
+	if (argc != 3)
+		return CMD_RET_USAGE;
 
-		mmc = find_mmc_device(dev);
-		if (!mmc) {
-			printf("no mmc device at slot %x\n", dev);
-			return 1;
-		}
+	blk = simple_strtoul(argv[1], NULL, 16);
+	cnt = simple_strtoul(argv[2], NULL, 16);
 
-		if (IS_SD(mmc)) {
-			puts("PARTITION_CONFIG only exists on eMMC\n");
-			return 1;
-		}
+	mmc = init_mmc_device(curr_device);
+	if (!mmc)
+		return CMD_RET_FAILURE;
 
-		/* acknowledge to be sent during boot operation */
-		return mmc_set_part_conf(mmc, ack, part_num, access);
-	} else if (strcmp(argv[1], "bootbus") == 0) {
-		int dev;
-		struct mmc *mmc;
-		u8 width, reset, mode;
+	printf("\nMMC erase: dev # %d, block # %d, count %d ... ",
+	       curr_device, blk, cnt);
 
-		if (argc == 6) {
-			dev = simple_strtoul(argv[2], NULL, 10);
-			width = simple_strtoul(argv[3], NULL, 10);
-			reset = simple_strtoul(argv[4], NULL, 10);
-			mode = simple_strtoul(argv[5], NULL, 10);
-		} else {
-			return CMD_RET_USAGE;
-		}
+	if (mmc_getwp(mmc) == 1) {
+		printf("Error: card is write protected!\n");
+		return CMD_RET_FAILURE;
+	}
+	n = mmc->block_dev.block_erase(curr_device, blk, cnt);
+	printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR");
 
-		mmc = find_mmc_device(dev);
-		if (!mmc) {
-			printf("no mmc device at slot %x\n", dev);
-			return 1;
-		}
+	return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+}
+static int do_mmc_rescan(cmd_tbl_t *cmdtp, int flag,
+			 int argc, char * const argv[])
+{
+	struct mmc *mmc;
 
-		if (IS_SD(mmc)) {
-			puts("BOOT_BUS_WIDTH only exists on eMMC\n");
-			return 1;
-		}
+	mmc = find_mmc_device(curr_device);
+	if (!mmc) {
+		printf("no mmc device at slot %x\n", curr_device);
+		return CMD_RET_FAILURE;
+	}
 
-		/* acknowledge to be sent during boot operation */
-		return mmc_set_boot_bus_width(mmc, width, reset, mode);
-	} else if (strcmp(argv[1], "bootpart-resize") == 0) {
-		int dev;
-		struct mmc *mmc;
-		u32 bootsize, rpmbsize;
+	mmc->has_init = 0;
 
-		if (argc == 5) {
-			dev = simple_strtoul(argv[2], NULL, 10);
-			bootsize = simple_strtoul(argv[3], NULL, 10);
-			rpmbsize = simple_strtoul(argv[4], NULL, 10);
-		} else {
-			return CMD_RET_USAGE;
-		}
+	if (mmc_init(mmc))
+		return CMD_RET_FAILURE;
+	return CMD_RET_SUCCESS;
+}
+static int do_mmc_part(cmd_tbl_t *cmdtp, int flag,
+		       int argc, char * const argv[])
+{
+	block_dev_desc_t *mmc_dev;
+	struct mmc *mmc;
 
-		mmc = find_mmc_device(dev);
-		if (!mmc) {
-			printf("no mmc device at slot %x\n", dev);
-			return 1;
-		}
+	mmc = init_mmc_device(curr_device);
+	if (!mmc)
+		return CMD_RET_FAILURE;
 
-		if (IS_SD(mmc)) {
-			printf("It is not a EMMC device\n");
-			return 1;
-		}
+	mmc_dev = mmc_get_dev(curr_device);
+	if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) {
+		print_part(mmc_dev);
+		return CMD_RET_SUCCESS;
+	}
 
-		if (0 == mmc_boot_partition_size_change(mmc,
-							bootsize, rpmbsize)) {
-			printf("EMMC boot partition Size %d MB\n", bootsize);
-			printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
-			return 0;
-		} else {
-			printf("EMMC boot partition Size change Failed.\n");
-			return 1;
-		}
-	} else if (strcmp(argv[1], "rst-function") == 0) {
-		/*
-		 * Set the RST_n_ENABLE bit of RST_n_FUNCTION
-		 * The only valid values are 0x0, 0x1 and 0x2 and writing
-		 * a value of 0x1 or 0x2 sets the value permanently.
-		 */
-		int dev;
-		struct mmc *mmc;
-		u8 enable;
+	puts("get mmc type error!\n");
+	return CMD_RET_FAILURE;
+}
+static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag,
+		      int argc, char * const argv[])
+{
+	int dev, part = -1, ret;
+	struct mmc *mmc;
 
-		if (argc == 4) {
-			dev = simple_strtoul(argv[2], NULL, 10);
-			enable = simple_strtoul(argv[3], NULL, 10);
-		} else {
-			return CMD_RET_USAGE;
+	if (argc == 1) {
+		dev = curr_device;
+	} else if (argc == 2) {
+		dev = simple_strtoul(argv[1], NULL, 10);
+	} else if (argc == 3) {
+		dev = (int)simple_strtoul(argv[1], NULL, 10);
+		part = (int)simple_strtoul(argv[2], NULL, 10);
+		if (part > PART_ACCESS_MASK) {
+			printf("#part_num shouldn't be larger than %d\n",
+			       PART_ACCESS_MASK);
+			return CMD_RET_FAILURE;
 		}
+	} else {
+		return CMD_RET_USAGE;
+	}
 
-		if (enable > 2 || enable < 0) {
-			puts("Invalid RST_n_ENABLE value\n");
-			return CMD_RET_USAGE;
-		}
+	mmc = init_mmc_device(dev);
+	if (!mmc)
+		return CMD_RET_FAILURE;
 
-		mmc = find_mmc_device(dev);
-		if (!mmc) {
-			printf("no mmc device at slot %x\n", dev);
+	if (part != -1) {
+		ret = mmc_select_hwpart(dev, part);
+		printf("switch to partitions #%d, %s\n",
+			part, (!ret) ? "OK" : "ERROR");
+		if (ret)
 			return 1;
-		}
+	}
+	curr_device = dev;
+	if (mmc->part_config == MMCPART_NOAVAILABLE)
+		printf("mmc%d is current device\n", curr_device);
+	else
+		printf("mmc%d(part %d) is current device\n",
+		       curr_device, mmc->part_num);
 
-		if (IS_SD(mmc)) {
-			puts("RST_n_FUNCTION only exists on eMMC\n");
-			return 1;
-		}
+	return CMD_RET_SUCCESS;
+}
+static int do_mmc_list(cmd_tbl_t *cmdtp, int flag,
+		       int argc, char * const argv[])
+{
+	print_mmc_devices('\n');
+	return CMD_RET_SUCCESS;
+}
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+static int do_mmc_bootbus(cmd_tbl_t *cmdtp, int flag,
+			  int argc, char * const argv[])
+{
+	int dev;
+	struct mmc *mmc;
+	u8 width, reset, mode;
+
+	if (argc != 5)
+		return CMD_RET_USAGE;
+	dev = simple_strtoul(argv[1], NULL, 10);
+	width = simple_strtoul(argv[2], NULL, 10);
+	reset = simple_strtoul(argv[3], NULL, 10);
+	mode = simple_strtoul(argv[4], NULL, 10);
 
-		return mmc_set_rst_n_function(mmc, enable);
-#endif /* CONFIG_SUPPORT_EMMC_BOOT */
+	mmc = init_mmc_device(dev);
+	if (!mmc)
+		return CMD_RET_FAILURE;
+
+	if (IS_SD(mmc)) {
+		puts("BOOT_BUS_WIDTH only exists on eMMC\n");
+		return CMD_RET_FAILURE;
 	}
 
-	else if (argc == 3 && strcmp(argv[1], "setdsr") == 0) {
-		struct mmc *mmc = find_mmc_device(curr_device);
-		u32 val = simple_strtoul(argv[2], NULL, 16);
-		int ret;
+	/* acknowledge to be sent during boot operation */
+	return mmc_set_boot_bus_width(mmc, width, reset, mode);
+}
+static int do_mmc_boot_resize(cmd_tbl_t *cmdtp, int flag,
+			      int argc, char * const argv[])
+{
+	int dev;
+	struct mmc *mmc;
+	u32 bootsize, rpmbsize;
 
-		if (!mmc) {
-			printf("no mmc device at slot %x\n", curr_device);
-			return 1;
-		}
-		ret = mmc_set_dsr(mmc, val);
-		printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR");
-		if (!ret) {
-			mmc->has_init = 0;
-			if (mmc_init(mmc))
-				return 1;
-			else
-				return 0;
-		}
-		return ret;
+	if (argc != 4)
+		return CMD_RET_USAGE;
+	dev = simple_strtoul(argv[1], NULL, 10);
+	bootsize = simple_strtoul(argv[2], NULL, 10);
+	rpmbsize = simple_strtoul(argv[3], NULL, 10);
+
+	mmc = init_mmc_device(dev);
+	if (!mmc)
+		return CMD_RET_FAILURE;
+
+	if (IS_SD(mmc)) {
+		printf("It is not a EMMC device\n");
+		return CMD_RET_FAILURE;
 	}
 
-	state = MMC_INVALID;
-	if (argc == 5 && strcmp(argv[1], "read") == 0)
-		state = MMC_READ;
-	else if (argc == 5 && strcmp(argv[1], "write") == 0)
-		state = MMC_WRITE;
-	else if (argc == 4 && strcmp(argv[1], "erase") == 0)
-		state = MMC_ERASE;
+	if (mmc_boot_partition_size_change(mmc, bootsize, rpmbsize)) {
+		printf("EMMC boot partition Size change Failed.\n");
+		return CMD_RET_FAILURE;
+	}
 
-	if (state != MMC_INVALID) {
-		struct mmc *mmc = find_mmc_device(curr_device);
-		int idx = 2;
-		u32 blk, cnt, n;
-		void *addr;
+	printf("EMMC boot partition Size %d MB\n", bootsize);
+	printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
+	return CMD_RET_SUCCESS;
+}
+static int do_mmc_partconf(cmd_tbl_t *cmdtp, int flag,
+			   int argc, char * const argv[])
+{
+	int dev;
+	struct mmc *mmc;
+	u8 ack, part_num, access;
 
-		if (state != MMC_ERASE) {
-			addr = (void *)simple_strtoul(argv[idx], NULL, 16);
-			++idx;
-		} else
-			addr = NULL;
-		blk = simple_strtoul(argv[idx], NULL, 16);
-		cnt = simple_strtoul(argv[idx + 1], NULL, 16);
+	if (argc != 5)
+		return CMD_RET_USAGE;
 
-		if (!mmc) {
-			printf("no mmc device at slot %x\n", curr_device);
-			return 1;
-		}
+	dev = simple_strtoul(argv[1], NULL, 10);
+	ack = simple_strtoul(argv[2], NULL, 10);
+	part_num = simple_strtoul(argv[3], NULL, 10);
+	access = simple_strtoul(argv[4], NULL, 10);
 
-		printf("\nMMC %s: dev # %d, block # %d, count %d ... ",
-				argv[1], curr_device, blk, cnt);
+	mmc = init_mmc_device(dev);
+	if (!mmc)
+		return CMD_RET_FAILURE;
 
-		mmc_init(mmc);
+	if (IS_SD(mmc)) {
+		puts("PARTITION_CONFIG only exists on eMMC\n");
+		return CMD_RET_FAILURE;
+	}
 
-		if ((state == MMC_WRITE || state == MMC_ERASE)) {
-			if (mmc_getwp(mmc) == 1) {
-				printf("Error: card is write protected!\n");
-				return 1;
-			}
-		}
+	/* acknowledge to be sent during boot operation */
+	return mmc_set_part_conf(mmc, ack, part_num, access);
+}
+static int do_mmc_rst_func(cmd_tbl_t *cmdtp, int flag,
+			   int argc, char * const argv[])
+{
+	int dev;
+	struct mmc *mmc;
+	u8 enable;
 
-		switch (state) {
-		case MMC_READ:
-			n = mmc->block_dev.block_read(curr_device, blk,
-						      cnt, addr);
-			/* flush cache after read */
-			flush_cache((ulong)addr, cnt * 512); /* FIXME */
-			break;
-		case MMC_WRITE:
-			n = mmc->block_dev.block_write(curr_device, blk,
-						      cnt, addr);
-			break;
-		case MMC_ERASE:
-			n = mmc->block_dev.block_erase(curr_device, blk, cnt);
-			break;
-		default:
-			BUG();
-		}
+	/*
+	 * Set the RST_n_ENABLE bit of RST_n_FUNCTION
+	 * The only valid values are 0x0, 0x1 and 0x2 and writing
+	 * a value of 0x1 or 0x2 sets the value permanently.
+	 */
+	if (argc != 3)
+		return CMD_RET_USAGE;
+
+	dev = simple_strtoul(argv[1], NULL, 10);
+	enable = simple_strtoul(argv[2], NULL, 10);
+
+	if (enable > 2 || enable < 0) {
+		puts("Invalid RST_n_ENABLE value\n");
+		return CMD_RET_USAGE;
+	}
+
+	mmc = init_mmc_device(dev);
+	if (!mmc)
+		return CMD_RET_FAILURE;
+
+	if (IS_SD(mmc)) {
+		puts("RST_n_FUNCTION only exists on eMMC\n");
+		return CMD_RET_FAILURE;
+	}
+
+	return mmc_set_rst_n_function(mmc, enable);
+}
+#endif
+static int do_mmc_setdsr(cmd_tbl_t *cmdtp, int flag,
+			 int argc, char * const argv[])
+{
+	struct mmc *mmc;
+	u32 val;
+	int ret;
 
-		printf("%d blocks %s: %s\n",
-				n, argv[1], (n == cnt) ? "OK" : "ERROR");
-		return (n == cnt) ? 0 : 1;
+	if (argc != 2)
+		return CMD_RET_USAGE;
+	val = simple_strtoul(argv[2], NULL, 16);
+
+	mmc = find_mmc_device(curr_device);
+	if (!mmc) {
+		printf("no mmc device at slot %x\n", curr_device);
+		return CMD_RET_FAILURE;
+	}
+	ret = mmc_set_dsr(mmc, val);
+	printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR");
+	if (!ret) {
+		mmc->has_init = 0;
+		if (mmc_init(mmc))
+			return CMD_RET_FAILURE;
+		else
+			return CMD_RET_SUCCESS;
 	}
+	return ret;
+}
 
-	return CMD_RET_USAGE;
+static cmd_tbl_t cmd_mmc[] = {
+	U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""),
+	U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""),
+	U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""),
+	U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""),
+	U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""),
+	U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""),
+	U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""),
+	U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""),
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+	U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""),
+	U_BOOT_CMD_MKENT(bootpart-resize, 3, 0, do_mmc_boot_resize, "", ""),
+	U_BOOT_CMD_MKENT(partconf, 5, 0, do_mmc_partconf, "", ""),
+	U_BOOT_CMD_MKENT(rst-function, 3, 0, do_mmc_rst_func, "", ""),
+#endif
+#ifdef CONFIG_SUPPORT_EMMC_RPMB
+	U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""),
+#endif
+	U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""),
+};
+
+static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	cmd_tbl_t *cp;
+
+	cp = find_cmd_tbl(argv[1], cmd_mmc, ARRAY_SIZE(cmd_mmc));
+
+	/* Drop the mmc command */
+	argc--;
+	argv++;
+
+	if (cp == NULL || argc > cp->maxargs)
+		return CMD_RET_USAGE;
+	if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
+		return CMD_RET_SUCCESS;
+
+	if (curr_device < 0) {
+		if (get_mmc_num() > 0) {
+			curr_device = 0;
+		} else {
+			puts("No MMC device available\n");
+			return CMD_RET_FAILURE;
+		}
+	}
+	return cp->cmd(cmdtp, flag, argc, argv);
 }
 
 U_BOOT_CMD(
-	mmc, 6, 1, do_mmcops,
+	mmc, 7, 1, do_mmcops,
 	"MMC sub system",
-	"read addr blk# cnt\n"
+	"info - display info of the current MMC device\n"
+	"mmc read addr blk# cnt\n"
 	"mmc write addr blk# cnt\n"
 	"mmc erase blk# cnt\n"
 	"mmc rescan\n"
@@ -474,6 +665,20 @@
 	" - Change the RST_n_FUNCTION field of the specified device\n"
 	"   WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n"
 #endif
-	"mmc setdsr - set DSR register value\n"
+#ifdef CONFIG_SUPPORT_EMMC_RPMB
+	"mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n"
+	"mmc rpmb write addr blk# cnt <address of auth-key> - block size is 256 bytes\n"
+	"mmc rpmb key <address of auth-key> - program the RPMB authentication key.\n"
+	"mmc rpmb counter - read the value of the write counter\n"
+#endif
+	"mmc setdsr <value> - set DSR register value\n"
 	);
+
+/* Old command kept for compatibility. Same as 'mmc info' */
+U_BOOT_CMD(
+	mmcinfo, 1, 0, do_mmcinfo,
+	"display MMC info",
+	"- display info of the current MMC device"
+);
+
 #endif /* !CONFIG_GENERIC_MMC */
diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index 04ab0f1..a84f7dc 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -605,22 +605,16 @@
 		opts.spread = spread;
 
 		if (scrub) {
-			if (!scrub_yes)
-				puts(scrub_warn);
-
-			if (scrub_yes)
+			if (scrub_yes) {
 				opts.scrub = 1;
-			else if (getc() == 'y') {
-				puts("y");
-				if (getc() == '\r')
+			} else {
+				puts(scrub_warn);
+				if (confirm_yesno()) {
 					opts.scrub = 1;
-				else {
+				} else {
 					puts("scrub aborted\n");
 					return 1;
 				}
-			} else {
-				puts("scrub aborted\n");
-				return 1;
 			}
 		}
 		ret = nand_erase_opts(nand, &opts);
diff --git a/common/cmd_otp.c b/common/cmd_otp.c
index 67808aa..593bb8c 100644
--- a/common/cmd_otp.c
+++ b/common/cmd_otp.c
@@ -158,21 +158,9 @@
 			lowup(half + count - 1), page + (half + count - 1) / 2,
 			half + count
 		);
-
-		i = 0;
-		while (1) {
-			if (tstc()) {
-				const char exp_ans[] = "YES\r";
-				char c;
-				putc(c = getc());
-				if (exp_ans[i++] != c) {
-					printf(" Aborting\n");
-					return 1;
-				} else if (!exp_ans[i]) {
-					puts("\n");
-					break;
-				}
-			}
+		if (!confirm_yesno()) {
+			printf(" Aborting\n");
+			return 1;
 		}
 	}
 
diff --git a/common/cmd_part.c b/common/cmd_part.c
index 1424854..c84bc27 100644
--- a/common/cmd_part.c
+++ b/common/cmd_part.c
@@ -82,7 +82,7 @@
 U_BOOT_CMD(
 	part,	5,	1,	do_part,
 	"disk partition related commands",
-	"uuid <interface> <dev>:<part>\n"
+	"part uuid <interface> <dev>:<part>\n"
 	"    - print partition UUID\n"
 	"part uuid <interface> <dev>:<part> <varname>\n"
 	"    - set environment variable to partition UUID\n"
diff --git a/common/cmd_usb_mass_storage.c b/common/cmd_usb_mass_storage.c
index d8d9efd..2c879ea 100644
--- a/common/cmd_usb_mass_storage.c
+++ b/common/cmd_usb_mass_storage.c
@@ -9,41 +9,107 @@
 #include <common.h>
 #include <command.h>
 #include <g_dnl.h>
+#include <part.h>
 #include <usb.h>
 #include <usb_mass_storage.h>
 
+static int ums_read_sector(struct ums *ums_dev,
+			   ulong start, lbaint_t blkcnt, void *buf)
+{
+	block_dev_desc_t *block_dev = ums_dev->block_dev;
+	lbaint_t blkstart = start + ums_dev->start_sector;
+	int dev_num = block_dev->dev;
+
+	return block_dev->block_read(dev_num, blkstart, blkcnt, buf);
+}
+
+static int ums_write_sector(struct ums *ums_dev,
+			    ulong start, lbaint_t blkcnt, const void *buf)
+{
+	block_dev_desc_t *block_dev = ums_dev->block_dev;
+	lbaint_t blkstart = start + ums_dev->start_sector;
+	int dev_num = block_dev->dev;
+
+	return block_dev->block_write(dev_num, blkstart, blkcnt, buf);
+}
+
+static struct ums ums_dev = {
+	.read_sector = ums_read_sector,
+	.write_sector = ums_write_sector,
+	.name = "UMS disk",
+};
+
+struct ums *ums_init(const char *devtype, const char *devnum)
+{
+	block_dev_desc_t *block_dev;
+	int ret;
+
+	ret = get_device(devtype, devnum, &block_dev);
+	if (ret < 0)
+		return NULL;
+
+	/* f_mass_storage.c assumes SECTOR_SIZE sectors */
+	if (block_dev->blksz != SECTOR_SIZE)
+		return NULL;
+
+	ums_dev.block_dev = block_dev;
+	ums_dev.start_sector = 0;
+	ums_dev.num_sectors = block_dev->lba;
+
+	printf("UMS: disk start sector: %#x, count: %#x\n",
+	       ums_dev.start_sector, ums_dev.num_sectors);
+
+	return &ums_dev;
+}
+
 int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag,
 			       int argc, char * const argv[])
 {
+	const char *usb_controller;
+	const char *devtype;
+	const char *devnum;
+	struct ums *ums;
+	unsigned int controller_index;
+	int rc;
+	int cable_ready_timeout __maybe_unused;
+
 	if (argc < 3)
 		return CMD_RET_USAGE;
 
-	const char *usb_controller = argv[1];
-	const char *mmc_devstring  = argv[2];
-
-	unsigned int dev_num = simple_strtoul(mmc_devstring, NULL, 0);
+	usb_controller = argv[1];
+	if (argc >= 4) {
+		devtype = argv[2];
+		devnum  = argv[3];
+	} else {
+		devtype = "mmc";
+		devnum  = argv[2];
+	}
 
-	struct ums *ums = ums_init(dev_num);
+	ums = ums_init(devtype, devnum);
 	if (!ums)
 		return CMD_RET_FAILURE;
 
-	unsigned int controller_index = (unsigned int)(simple_strtoul(
-					usb_controller,	NULL, 0));
+	controller_index = (unsigned int)(simple_strtoul(
+				usb_controller,	NULL, 0));
 	if (board_usb_init(controller_index, USB_INIT_DEVICE)) {
 		error("Couldn't init USB controller.");
 		return CMD_RET_FAILURE;
 	}
 
-	int rc = fsg_init(ums);
+	rc = fsg_init(ums);
 	if (rc) {
 		error("fsg_init failed");
 		return CMD_RET_FAILURE;
 	}
 
-	g_dnl_register("usb_dnl_ums");
+	rc = g_dnl_register("usb_dnl_ums");
+	if (rc) {
+		error("g_dnl_register failed");
+		return CMD_RET_FAILURE;
+	}
 
 	/* Timeout unit: seconds */
-	int cable_ready_timeout = UMS_CABLE_READY_TIMEOUT;
+	cable_ready_timeout = UMS_CABLE_READY_TIMEOUT;
 
 	if (!g_dnl_board_usb_cable_connected()) {
 		/*
@@ -91,7 +157,8 @@
 	return CMD_RET_SUCCESS;
 }
 
-U_BOOT_CMD(ums, CONFIG_SYS_MAXARGS, 1, do_usb_mass_storage,
+U_BOOT_CMD(ums, 4, 1, do_usb_mass_storage,
 	"Use the UMS [User Mass Storage]",
-	"ums <USB_controller> <mmc_dev>  e.g. ums 0 0"
+	"ums <USB_controller> [<devtype>] <devnum>  e.g. ums 0 mmc 0\n"
+	"    devtype defaults to mmc"
 );
diff --git a/common/console.c b/common/console.c
index 2dfb788..5453726 100644
--- a/common/console.c
+++ b/common/console.c
@@ -537,7 +537,33 @@
 	}
 	return 0;
 }
+/* Reads user's confirmation.
+   Returns 1 if user's input is "y", "Y", "yes" or "YES"
+*/
+int confirm_yesno(void)
+{
+	int i;
+	char str_input[5];
 
+	/* Flush input */
+	while (tstc())
+		getc();
+	i = 0;
+	while (i < sizeof(str_input)) {
+		str_input[i] = getc();
+		putc(str_input[i]);
+		if (str_input[i] == '\r')
+			break;
+		i++;
+	}
+	putc('\n');
+	if (strncmp(str_input, "y\r", 2) == 0 ||
+	    strncmp(str_input, "Y\r", 2) == 0 ||
+	    strncmp(str_input, "yes\r", 4) == 0 ||
+	    strncmp(str_input, "YES\r", 4) == 0)
+		return 1;
+	return 0;
+}
 /* pass 1 to disable ctrlc() checking, 0 to enable.
  * returns previous state
  */
diff --git a/common/image-android.c b/common/image-android.c
new file mode 100644
index 0000000..6ded7e2
--- /dev/null
+++ b/common/image-android.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <image.h>
+#include <android_image.h>
+
+static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1];
+
+int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
+			     ulong *os_data, ulong *os_len)
+{
+	/*
+	 * Not all Android tools use the id field for signing the image with
+	 * sha1 (or anything) so we don't check it. It is not obvious that the
+	 * string is null terminated so we take care of this.
+	 */
+	strncpy(andr_tmp_str, hdr->name, ANDR_BOOT_NAME_SIZE);
+	andr_tmp_str[ANDR_BOOT_NAME_SIZE] = '\0';
+	if (strlen(andr_tmp_str))
+		printf("Android's image name: %s\n", andr_tmp_str);
+
+	printf("Kernel load addr 0x%08x size %u KiB\n",
+	       hdr->kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024));
+	strncpy(andr_tmp_str, hdr->cmdline, ANDR_BOOT_ARGS_SIZE);
+	andr_tmp_str[ANDR_BOOT_ARGS_SIZE] = '\0';
+	if (strlen(andr_tmp_str)) {
+		printf("Kernel command line: %s\n", andr_tmp_str);
+		setenv("bootargs", andr_tmp_str);
+	}
+	if (hdr->ramdisk_size)
+		printf("RAM disk load addr 0x%08x size %u KiB\n",
+		       hdr->ramdisk_addr,
+		       DIV_ROUND_UP(hdr->ramdisk_size, 1024));
+
+	if (os_data) {
+		*os_data = (ulong)hdr;
+		*os_data += hdr->page_size;
+	}
+	if (os_len)
+		*os_len = hdr->kernel_size;
+	return 0;
+}
+
+int android_image_check_header(const struct andr_img_hdr *hdr)
+{
+	return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE);
+}
+
+ulong android_image_get_end(const struct andr_img_hdr *hdr)
+{
+	u32 size = 0;
+	/*
+	 * The header takes a full page, the remaining components are aligned
+	 * on page boundary
+	 */
+	size += hdr->page_size;
+	size += ALIGN(hdr->kernel_size, hdr->page_size);
+	size += ALIGN(hdr->ramdisk_size, hdr->page_size);
+	size += ALIGN(hdr->second_size, hdr->page_size);
+
+	return size;
+}
+
+ulong android_image_get_kload(const struct andr_img_hdr *hdr)
+{
+	return hdr->kernel_addr;
+}
+
+int android_image_get_ramdisk(const struct andr_img_hdr *hdr,
+			      ulong *rd_data, ulong *rd_len)
+{
+	if (!hdr->ramdisk_size)
+		return -1;
+	*rd_data = (unsigned long)hdr;
+	*rd_data += hdr->page_size;
+	*rd_data += ALIGN(hdr->kernel_size, hdr->page_size);
+
+	*rd_len = hdr->ramdisk_size;
+	return 0;
+}
diff --git a/common/image.c b/common/image.c
index fcc5a9c..fa4864d 100644
--- a/common/image.c
+++ b/common/image.c
@@ -660,10 +660,12 @@
 	if (image_check_magic(hdr))
 		format = IMAGE_FORMAT_LEGACY;
 #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
-	else {
-		if (fdt_check_header(img_addr) == 0)
-			format = IMAGE_FORMAT_FIT;
-	}
+	else if (fdt_check_header(img_addr) == 0)
+		format = IMAGE_FORMAT_FIT;
+#endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+	else if (android_image_check_header(img_addr) == 0)
+		format = IMAGE_FORMAT_ANDROID;
 #endif
 
 	return format;
@@ -933,7 +935,15 @@
 				(ulong)images->legacy_hdr_os);
 
 		image_multi_getimg(images->legacy_hdr_os, 1, &rd_data, &rd_len);
-	} else {
+	}
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+	else if ((genimg_get_format(images) == IMAGE_FORMAT_ANDROID) &&
+		 (!android_image_get_ramdisk((void *)images->os.start,
+		 &rd_data, &rd_len))) {
+		/* empty */
+	}
+#endif
+	else {
 		/*
 		 * no initrd image
 		 */
diff --git a/disk/part.c b/disk/part.c
index b8c6aac..2827089 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -22,6 +22,7 @@
 struct block_drvr {
 	char *name;
 	block_dev_desc_t* (*get_dev)(int dev);
+	int (*select_hwpart)(int dev_num, int hwpart);
 };
 
 static const struct block_drvr block_drvr[] = {
@@ -38,7 +39,11 @@
 	{ .name = "usb", .get_dev = usb_stor_get_dev, },
 #endif
 #if defined(CONFIG_MMC)
-	{ .name = "mmc", .get_dev = mmc_get_dev, },
+	{
+		.name = "mmc",
+		.get_dev = mmc_get_dev,
+		.select_hwpart = mmc_select_hwpart,
+	},
 #endif
 #if defined(CONFIG_SYSTEMACE)
 	{ .name = "ace", .get_dev = systemace_get_dev, },
@@ -52,11 +57,13 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 #ifdef HAVE_BLOCK_DEVICE
-block_dev_desc_t *get_dev(const char *ifname, int dev)
+block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
 {
 	const struct block_drvr *drvr = block_drvr;
 	block_dev_desc_t* (*reloc_get_dev)(int dev);
+	int (*select_hwpart)(int dev_num, int hwpart);
 	char *name;
+	int ret;
 
 	if (!ifname)
 		return NULL;
@@ -68,17 +75,41 @@
 	while (drvr->name) {
 		name = drvr->name;
 		reloc_get_dev = drvr->get_dev;
+		select_hwpart = drvr->select_hwpart;
 #ifdef CONFIG_NEEDS_MANUAL_RELOC
 		name += gd->reloc_off;
 		reloc_get_dev += gd->reloc_off;
+		if (select_hwpart)
+			select_hwpart += gd->reloc_off;
 #endif
-		if (strncmp(ifname, name, strlen(name)) == 0)
-			return reloc_get_dev(dev);
+		if (strncmp(ifname, name, strlen(name)) == 0) {
+			block_dev_desc_t *dev_desc = reloc_get_dev(dev);
+			if (!dev_desc)
+				return NULL;
+			if (hwpart == -1)
+				return dev_desc;
+			if (!select_hwpart)
+				return NULL;
+			ret = select_hwpart(dev_desc->dev, hwpart);
+			if (ret < 0)
+				return NULL;
+			return dev_desc;
+		}
 		drvr++;
 	}
 	return NULL;
 }
+
+block_dev_desc_t *get_dev(const char *ifname, int dev)
+{
+	return get_dev_hwpart(ifname, dev, -1);
+}
 #else
+block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
+{
+	return NULL;
+}
+
 block_dev_desc_t *get_dev(const char *ifname, int dev)
 {
 	return NULL;
@@ -413,25 +444,52 @@
 	return -1;
 }
 
-int get_device(const char *ifname, const char *dev_str,
+int get_device(const char *ifname, const char *dev_hwpart_str,
 	       block_dev_desc_t **dev_desc)
 {
 	char *ep;
-	int dev;
+	char *dup_str = NULL;
+	const char *dev_str, *hwpart_str;
+	int dev, hwpart;
+
+	hwpart_str = strchr(dev_hwpart_str, '.');
+	if (hwpart_str) {
+		dup_str = strdup(dev_hwpart_str);
+		dup_str[hwpart_str - dev_hwpart_str] = 0;
+		dev_str = dup_str;
+		hwpart_str++;
+	} else {
+		dev_str = dev_hwpart_str;
+		hwpart = -1;
+	}
 
 	dev = simple_strtoul(dev_str, &ep, 16);
 	if (*ep) {
 		printf("** Bad device specification %s %s **\n",
 		       ifname, dev_str);
-		return -1;
+		dev = -1;
+		goto cleanup;
+	}
+
+	if (hwpart_str) {
+		hwpart = simple_strtoul(hwpart_str, &ep, 16);
+		if (*ep) {
+			printf("** Bad HW partition specification %s %s **\n",
+			    ifname, hwpart_str);
+			dev = -1;
+			goto cleanup;
+		}
 	}
 
-	*dev_desc = get_dev(ifname, dev);
+	*dev_desc = get_dev_hwpart(ifname, dev, hwpart);
 	if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
-		printf("** Bad device %s %s **\n", ifname, dev_str);
-		return -1;
+		printf("** Bad device %s %s **\n", ifname, dev_hwpart_str);
+		dev = -1;
+		goto cleanup;
 	}
 
+cleanup:
+	free(dup_str);
 	return dev;
 }
 
diff --git a/doc/README.android-fastboot b/doc/README.android-fastboot
new file mode 100644
index 0000000..f1d128c
--- /dev/null
+++ b/doc/README.android-fastboot
@@ -0,0 +1,91 @@
+Android Fastboot
+~~~~~~~~~~~~~~~~
+
+Overview
+========
+The protocol that is used over USB is described in
+README.android-fastboot-protocol in same directory.
+
+The current implementation does not yet support the flash and erase
+commands.
+
+Client installation
+===================
+The counterpart to this gadget is the fastboot client which can
+be found in Android's platform/system/core repository in the fastboot
+folder. It runs on Windows, Linux and even OSX. Linux user are lucky since
+they only need libusb.
+Windows users need to bring some time until they have Android SDK (currently
+http://dl.google.com/android/installer_r12-windows.exe) installed. You
+need to install ADB package which contains the required glue libraries for
+accessing USB. Also you need "Google USB driver package" and "SDK platform
+tools". Once installed the usb driver is placed in your SDK folder under
+extras\google\usb_driver. The android_winusb.inf needs a line like
+
+   %SingleBootLoaderInterface% = USB_Install, USB\VID_0451&PID_D022
+
+either in the [Google.NTx86] section for 32bit Windows or [Google.NTamd64]
+for 64bit Windows. VID and PID should match whatever the fastboot is
+advertising.
+
+Board specific
+==============
+The fastboot gadget relies on the USB download gadget, so the following
+options must be configured:
+
+CONFIG_USBDOWNLOAD_GADGET
+CONFIG_G_DNL_VENDOR_NUM
+CONFIG_G_DNL_PRODUCT_NUM
+CONFIG_G_DNL_MANUFACTURER
+
+The fastboot function is enabled by defining CONFIG_CMD_FASTBOOT and
+CONFIG_ANDROID_BOOT_IMAGE.
+
+The fastboot protocol requires a large memory buffer for downloads. This
+buffer should be as large as possible for a platform. The location of the
+buffer and size are set with CONFIG_USB_FASTBOOT_BUF_ADDR and
+CONFIG_USB_FASTBOOT_BUF_SIZE.
+
+In Action
+=========
+Enter into fastboot by executing the fastboot command in u-boot and you
+should see:
+|GADGET DRIVER: usb_dnl_fastboot
+
+On the client side you can fetch the bootloader version for instance:
+|>fastboot getvar bootloader-version
+|bootloader-version: U-Boot 2014.04-00005-gd24cabc
+|finished. total time: 0.000s
+
+or initiate a reboot:
+|>fastboot reboot
+
+and once the client comes back, the board should reset.
+
+You can also specify a kernel image to boot. You have to either specify
+the an image in Android format _or_ pass a binary kernel and let the
+fastboot client wrap the Android suite around it. On OMAP for instance you
+take zImage kernel and pass it to the fastboot client:
+
+|>fastboot -b 0x80000000 -c "console=ttyO2 earlyprintk root=/dev/ram0
+|	mem=128M" boot zImage
+|creating boot image...
+|creating boot image - 1847296 bytes
+|downloading 'boot.img'...
+|OKAY [  2.766s]
+|booting...
+|OKAY [ -0.000s]
+|finished. total time: 2.766s
+
+and on the gadget side you should see:
+|Starting download of 1847296 bytes
+|........................................................
+|downloading of 1847296 bytes finished
+|Booting kernel..
+|## Booting Android Image at 0x81000000 ...
+|Kernel load addr 0x80008000 size 1801 KiB
+|Kernel command line: console=ttyO2 earlyprintk root=/dev/ram0 mem=128M
+|   Loading Kernel Image ... OK
+|OK
+|
+|Starting kernel ...
diff --git a/doc/README.android-fastboot-protocol b/doc/README.android-fastboot-protocol
new file mode 100644
index 0000000..e9e7166
--- /dev/null
+++ b/doc/README.android-fastboot-protocol
@@ -0,0 +1,170 @@
+FastBoot  Version  0.4
+----------------------
+
+The fastboot protocol is a mechanism for communicating with bootloaders
+over USB.  It is designed to be very straightforward to implement, to
+allow it to be used across a wide range of devices and from hosts running
+Linux, Windows, or OSX.
+
+
+Basic Requirements
+------------------
+
+* Two bulk endpoints (in, out) are required
+* Max packet size must be 64 bytes for full-speed and 512 bytes for
+  high-speed USB
+* The protocol is entirely host-driven and synchronous (unlike the
+  multi-channel, bi-directional, asynchronous ADB protocol)
+
+
+Transport and Framing
+---------------------
+
+1. Host sends a command, which is an ascii string in a single
+   packet no greater than 64 bytes.
+
+2. Client response with a single packet no greater than 64 bytes.
+   The first four bytes of the response are "OKAY", "FAIL", "DATA",
+   or "INFO".  Additional bytes may contain an (ascii) informative
+   message.
+
+   a. INFO -> the remaining 60 bytes are an informative message
+      (providing progress or diagnostic messages).  They should
+      be displayed and then step #2 repeats
+
+   b. FAIL -> the requested command failed.  The remaining 60 bytes
+      of the response (if present) provide a textual failure message
+      to present to the user.  Stop.
+
+   c. OKAY -> the requested command completed successfully.  Go to #5
+
+   d. DATA -> the requested command is ready for the data phase.
+      A DATA response packet will be 12 bytes long, in the form of
+      DATA00000000 where the 8 digit hexidecimal number represents
+      the total data size to transfer.
+
+3. Data phase.  Depending on the command, the host or client will
+   send the indicated amount of data.  Short packets are always
+   acceptable and zero-length packets are ignored.  This phase continues
+   until the client has sent or received the number of bytes indicated
+   in the "DATA" response above.
+
+4. Client responds with a single packet no greater than 64 bytes.
+   The first four bytes of the response are "OKAY", "FAIL", or "INFO".
+   Similar to #2:
+
+   a. INFO -> display the remaining 60 bytes and return to #4
+
+   b. FAIL -> display the remaining 60 bytes (if present) as a failure
+      reason and consider the command failed.  Stop.
+
+   c. OKAY -> success.  Go to #5
+
+5. Success.  Stop.
+
+
+Example Session
+---------------
+
+Host:    "getvar:version"        request version variable
+
+Client:  "OKAY0.4"               return version "0.4"
+
+Host:    "getvar:nonexistant"    request some undefined variable
+
+Client:  "OKAY"                  return value ""
+
+Host:    "download:00001234"     request to send 0x1234 bytes of data
+
+Client:  "DATA00001234"          ready to accept data
+
+Host:    < 0x1234 bytes >        send data
+
+Client:  "OKAY"                  success
+
+Host:    "flash:bootloader"      request to flash the data to the bootloader
+
+Client:  "INFOerasing flash"     indicate status / progress
+         "INFOwriting flash"
+         "OKAY"                  indicate success
+
+Host:    "powerdown"             send a command
+
+Client:  "FAILunknown command"   indicate failure
+
+
+Command Reference
+-----------------
+
+* Command parameters are indicated by printf-style escape sequences.
+
+* Commands are ascii strings and sent without the quotes (which are
+  for illustration only here) and without a trailing 0 byte.
+
+* Commands that begin with a lowercase letter are reserved for this
+  specification.  OEM-specific commands should not begin with a
+  lowercase letter, to prevent incompatibilities with future specs.
+
+ "getvar:%s"           Read a config/version variable from the bootloader.
+                       The variable contents will be returned after the
+                       OKAY response.
+
+ "download:%08x"       Write data to memory which will be later used
+                       by "boot", "ramdisk", "flash", etc.  The client
+                       will reply with "DATA%08x" if it has enough
+                       space in RAM or "FAIL" if not.  The size of
+                       the download is remembered.
+
+  "verify:%08x"        Send a digital signature to verify the downloaded
+                       data.  Required if the bootloader is "secure"
+                       otherwise "flash" and "boot" will be ignored.
+
+  "flash:%s"           Write the previously downloaded image to the
+                       named partition (if possible).
+
+  "erase:%s"           Erase the indicated partition (clear to 0xFFs)
+
+  "boot"               The previously downloaded data is a boot.img
+                       and should be booted according to the normal
+                       procedure for a boot.img
+
+  "continue"           Continue booting as normal (if possible)
+
+  "reboot"             Reboot the device.
+
+  "reboot-bootloader"  Reboot back into the bootloader.
+                       Useful for upgrade processes that require upgrading
+                       the bootloader and then upgrading other partitions
+                       using the new bootloader.
+
+  "powerdown"          Power off the device.
+
+
+
+Client Variables
+----------------
+
+The "getvar:%s" command is used to read client variables which
+represent various information about the device and the software
+on it.
+
+The various currently defined names are:
+
+  version             Version of FastBoot protocol supported.
+                      It should be "0.3" for this document.
+
+  version-bootloader  Version string for the Bootloader.
+
+  version-baseband    Version string of the Baseband Software
+
+  product             Name of the product
+
+  serialno            Product serial number
+
+  secure              If the value is "yes", this is a secure
+                      bootloader requiring a signature before
+                      it will install or boot images.
+
+Names starting with a lowercase character are reserved by this
+specification.  OEM-specific names should not start with lowercase
+characters.
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index 51b1026..a938109 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -131,6 +131,10 @@
 {
 	int ret = 0;
 
+	ret = dfu_write_buffer_drain(dfu);
+	if (ret)
+		return ret;
+
 	if (dfu->flush_medium)
 		ret = dfu->flush_medium(dfu);
 
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index 5e10ea7..63cc876 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -18,11 +18,29 @@
 				dfu_file_buf[CONFIG_SYS_DFU_MAX_FILE_SIZE];
 static long dfu_file_buf_len;
 
+static int mmc_access_part(struct dfu_entity *dfu, struct mmc *mmc, int part)
+{
+	int ret;
+
+	if (part == mmc->part_num)
+		return 0;
+
+	ret = mmc_switch_part(dfu->dev_num, part);
+	if (ret) {
+		error("Cannot switch to partition %d\n", part);
+		return ret;
+	}
+	mmc->part_num = part;
+
+	return 0;
+}
+
 static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
 			u64 offset, void *buf, long *len)
 {
 	struct mmc *mmc = find_mmc_device(dfu->dev_num);
 	u32 blk_start, blk_count, n = 0;
+	int ret, part_num_bkp = 0;
 
 	/*
 	 * We must ensure that we work in lba_blk_size chunks, so ALIGN
@@ -39,6 +57,13 @@
 		return -EINVAL;
 	}
 
+	if (dfu->data.mmc.hw_partition >= 0) {
+		part_num_bkp = mmc->part_num;
+		ret = mmc_access_part(dfu, mmc, dfu->data.mmc.hw_partition);
+		if (ret)
+			return ret;
+	}
+
 	debug("%s: %s dev: %d start: %d cnt: %d buf: 0x%p\n", __func__,
 	      op == DFU_OP_READ ? "MMC READ" : "MMC WRITE", dfu->dev_num,
 	      blk_start, blk_count, buf);
@@ -57,9 +82,17 @@
 
 	if (n != blk_count) {
 		error("MMC operation failed");
+		if (dfu->data.mmc.hw_partition >= 0)
+			mmc_access_part(dfu, mmc, part_num_bkp);
 		return -EIO;
 	}
 
+	if (dfu->data.mmc.hw_partition >= 0) {
+		ret = mmc_access_part(dfu, mmc, part_num_bkp);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
@@ -194,6 +227,8 @@
  *	2nd and 3rd:
  *		lba_start and lba_size, for raw write
  *		mmc_dev and mmc_part, for filesystems and part
+ *	4th (optional):
+ *		mmcpart <num> (access to HW eMMC partitions)
  */
 int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
 {
@@ -233,11 +268,22 @@
 		return -ENODEV;
 	}
 
+	dfu->data.mmc.hw_partition = -EINVAL;
 	if (!strcmp(entity_type, "raw")) {
 		dfu->layout			= DFU_RAW_ADDR;
 		dfu->data.mmc.lba_start		= second_arg;
 		dfu->data.mmc.lba_size		= third_arg;
 		dfu->data.mmc.lba_blk_size	= mmc->read_bl_len;
+
+		/*
+		 * Check for an extra entry at dfu_alt_info env variable
+		 * specifying the mmc HW defined partition number
+		 */
+		if (s)
+			if (!strcmp(strsep(&s, " "), "mmcpart"))
+				dfu->data.mmc.hw_partition =
+					simple_strtoul(s, NULL, 0);
+
 	} else if (!strcmp(entity_type, "part")) {
 		disk_partition_t partinfo;
 		block_dev_desc_t *blk_dev = &mmc->block_dev;
diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c
index 2d07097..ccdbef6 100644
--- a/drivers/dfu/dfu_nand.c
+++ b/drivers/dfu/dfu_nand.c
@@ -163,6 +163,18 @@
 	return ret;
 }
 
+unsigned int dfu_polltimeout_nand(struct dfu_entity *dfu)
+{
+	/*
+	 * Currently, Poll Timeout != 0 is only needed on nand
+	 * ubi partition, as the not used sectors need an erase
+	 */
+	if (dfu->data.nand.ubi)
+		return DFU_MANIFEST_POLL_TIMEOUT;
+
+	return DFU_DEFAULT_POLL_TIMEOUT;
+}
+
 int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s)
 {
 	char *st;
@@ -211,6 +223,7 @@
 	dfu->read_medium = dfu_read_medium_nand;
 	dfu->write_medium = dfu_write_medium_nand;
 	dfu->flush_medium = dfu_flush_medium_nand;
+	dfu->poll_timeout = dfu_polltimeout_nand;
 
 	/* initial state */
 	dfu->inited = 0;
diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c
index b940d9b..37946d5 100644
--- a/drivers/fpga/fpga.c
+++ b/drivers/fpga/fpga.c
@@ -173,16 +173,45 @@
 /*
  * Convert bitstream data and load into the fpga
  */
-int __weak fpga_loadbitstream(int devnum, char *fpgadata, size_t size)
+int __weak fpga_loadbitstream(int devnum, char *fpgadata, size_t size,
+			      bitstream_type bstype)
 {
 	printf("Bitstream support not implemented for this FPGA device\n");
 	return FPGA_FAIL;
 }
 
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+int fpga_fsload(int devnum, const void *buf, size_t size,
+		 fpga_fs_info *fpga_fsinfo)
+{
+	int ret_val = FPGA_FAIL;           /* assume failure */
+	const fpga_desc *desc = fpga_validate(devnum, buf, size,
+					      (char *)__func__);
+
+	if (desc) {
+		switch (desc->devtype) {
+		case fpga_xilinx:
+#if defined(CONFIG_FPGA_XILINX)
+			ret_val = xilinx_loadfs(desc->devdesc, buf, size,
+						fpga_fsinfo);
+#else
+			fpga_no_sup((char *)__func__, "Xilinx devices");
+#endif
+			break;
+		default:
+			printf("%s: Invalid or unsupported device type %d\n",
+			       __func__, desc->devtype);
+		}
+	}
+
+	return ret_val;
+}
+#endif
+
 /*
  * Generic multiplexing code
  */
-int fpga_load(int devnum, const void *buf, size_t bsize)
+int fpga_load(int devnum, const void *buf, size_t bsize, bitstream_type bstype)
 {
 	int ret_val = FPGA_FAIL;           /* assume failure */
 	const fpga_desc *desc = fpga_validate(devnum, buf, bsize,
@@ -192,7 +221,8 @@
 		switch (desc->devtype) {
 		case fpga_xilinx:
 #if defined(CONFIG_FPGA_XILINX)
-			ret_val = xilinx_load(desc->devdesc, buf, bsize);
+			ret_val = xilinx_load(desc->devdesc, buf, bsize,
+					      bstype);
 #else
 			fpga_no_sup((char *)__func__, "Xilinx devices");
 #endif
diff --git a/drivers/fpga/spartan2.c b/drivers/fpga/spartan2.c
index 7054056..859fb3c 100644
--- a/drivers/fpga/spartan2.c
+++ b/drivers/fpga/spartan2.c
@@ -41,7 +41,8 @@
 
 /* ------------------------------------------------------------------------- */
 /* Spartan-II Generic Implementation */
-static int spartan2_load(xilinx_desc *desc, const void *buf, size_t bsize)
+static int spartan2_load(xilinx_desc *desc, const void *buf, size_t bsize,
+			 bitstream_type bstype)
 {
 	int ret_val = FPGA_FAIL;
 
diff --git a/drivers/fpga/spartan3.c b/drivers/fpga/spartan3.c
index 5c9412c..b0213e6 100644
--- a/drivers/fpga/spartan3.c
+++ b/drivers/fpga/spartan3.c
@@ -45,7 +45,8 @@
 
 /* ------------------------------------------------------------------------- */
 /* Spartan-II Generic Implementation */
-static int spartan3_load(xilinx_desc *desc, const void *buf, size_t bsize)
+static int spartan3_load(xilinx_desc *desc, const void *buf, size_t bsize,
+			 bitstream_type bstype)
 {
 	int ret_val = FPGA_FAIL;
 
diff --git a/drivers/fpga/virtex2.c b/drivers/fpga/virtex2.c
index e092147..0d2d9a4 100644
--- a/drivers/fpga/virtex2.c
+++ b/drivers/fpga/virtex2.c
@@ -90,7 +90,8 @@
 static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
 static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
 
-static int virtex2_load(xilinx_desc *desc, const void *buf, size_t bsize)
+static int virtex2_load(xilinx_desc *desc, const void *buf, size_t bsize,
+			bitstream_type bstype)
 {
 	int ret_val = FPGA_FAIL;
 
diff --git a/drivers/fpga/xilinx.c b/drivers/fpga/xilinx.c
index 8837f5c..3795c1a 100644
--- a/drivers/fpga/xilinx.c
+++ b/drivers/fpga/xilinx.c
@@ -24,7 +24,8 @@
 
 /* ------------------------------------------------------------------------- */
 
-int fpga_loadbitstream(int devnum, char *fpgadata, size_t size)
+int fpga_loadbitstream(int devnum, char *fpgadata, size_t size,
+		       bitstream_type bstype)
 {
 	unsigned int length;
 	unsigned int swapsize;
@@ -127,18 +128,35 @@
 	dataptr += 4;
 	printf("  bytes in bitstream = %d\n", swapsize);
 
-	return fpga_load(devnum, dataptr, swapsize);
+	return fpga_load(devnum, dataptr, swapsize, bstype);
 }
 
-int xilinx_load(xilinx_desc *desc, const void *buf, size_t bsize)
+int xilinx_load(xilinx_desc *desc, const void *buf, size_t bsize,
+		bitstream_type bstype)
 {
 	if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
 		printf ("%s: Invalid device descriptor\n", __FUNCTION__);
 		return FPGA_FAIL;
 	}
 
-	return desc->operations->load(desc, buf, bsize);
+	return desc->operations->load(desc, buf, bsize, bstype);
+}
+
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+int xilinx_loadfs(xilinx_desc *desc, const void *buf, size_t bsize,
+		   fpga_fs_info *fpga_fsinfo)
+{
+	if (!xilinx_validate(desc, (char *)__func__)) {
+		printf("%s: Invalid device descriptor\n", __func__);
+		return FPGA_FAIL;
+	}
+
+	if (!desc->operations->loadfs)
+		return FPGA_FAIL;
+
+	return desc->operations->loadfs(desc, buf, bsize, fpga_fsinfo);
 }
+#endif
 
 int xilinx_dump(xilinx_desc *desc, const void *buf, size_t bsize)
 {
diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c
index c066f21..68fe0f3 100644
--- a/drivers/fpga/zynqpl.c
+++ b/drivers/fpga/zynqpl.c
@@ -9,6 +9,7 @@
 
 #include <common.h>
 #include <asm/io.h>
+#include <fs.h>
 #include <zynqpl.h>
 #include <linux/sizes.h>
 #include <asm/arch/hardware.h>
@@ -194,7 +195,7 @@
 	return FPGA_SUCCESS;
 }
 
-static int zynq_dma_xfer_init(u32 partialbit)
+static int zynq_dma_xfer_init(bitstream_type bstype)
 {
 	u32 status, control, isr_status;
 	unsigned long ts;
@@ -202,7 +203,7 @@
 	/* Clear loopback bit */
 	clrbits_le32(&devcfg_base->mctrl, DEVCFG_MCTRL_PCAP_LPBK);
 
-	if (!partialbit) {
+	if (bstype != BIT_PARTIAL) {
 		zynq_slcr_devcfg_disable();
 
 		/* Setting PCFG_PROG_B signal to high */
@@ -322,16 +323,11 @@
 
 static int zynq_validate_bitstream(xilinx_desc *desc, const void *buf,
 				   size_t bsize, u32 blocksize, u32 *swap,
-				   u32 *partialbit)
+				   bitstream_type *bstype)
 {
 	u32 *buf_start;
 	u32 diff;
 
-	/* Detect if we are going working with partial or full bitstream */
-	if (bsize != desc->size) {
-		printf("%s: Working with partial bitstream\n", __func__);
-		*partialbit = 1;
-	}
 	buf_start = check_data((u8 *)buf, blocksize, swap);
 
 	if (!buf_start)
@@ -351,17 +347,16 @@
 		return FPGA_FAIL;
 	}
 
-	if (zynq_dma_xfer_init(*partialbit))
+	if (zynq_dma_xfer_init(*bstype))
 		return FPGA_FAIL;
 
 	return 0;
 }
 
-
-static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize)
+static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize,
+		     bitstream_type bstype)
 {
 	unsigned long ts; /* Timestamp */
-	u32 partialbit = 0;
 	u32 isr_status, swap;
 
 	/*
@@ -369,7 +364,7 @@
 	 * in chunks
 	 */
 	if (zynq_validate_bitstream(desc, buf, bsize, bsize, &swap,
-				    &partialbit))
+				    &bstype))
 		return FPGA_FAIL;
 
 	buf = zynq_align_dma_buffer((u32 *)buf, bsize, swap);
@@ -384,7 +379,87 @@
 	if (zynq_dma_transfer((u32)buf | 1, bsize >> 2, 0xffffffff, 0))
 		return FPGA_FAIL;
 
+	isr_status = readl(&devcfg_base->int_sts);
+	/* Check FPGA configuration completion */
+	ts = get_timer(0);
+	while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) {
+		if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) {
+			printf("%s: Timeout wait for FPGA to config\n",
+			       __func__);
+			return FPGA_FAIL;
+		}
+		isr_status = readl(&devcfg_base->int_sts);
+	}
+
+	debug("%s: FPGA config done\n", __func__);
+
+	if (bstype != BIT_PARTIAL)
+		zynq_slcr_devcfg_enable();
+
+	return FPGA_SUCCESS;
+}
+
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+static int zynq_loadfs(xilinx_desc *desc, const void *buf, size_t bsize,
+		       fpga_fs_info *fsinfo)
+{
+	unsigned long ts; /* Timestamp */
+	u32 isr_status, swap;
+	u32 partialbit = 0;
+	u32 blocksize;
+	u32 pos = 0;
+	int fstype;
+	char *interface, *dev_part, *filename;
+
+	blocksize = fsinfo->blocksize;
+	interface = fsinfo->interface;
+	dev_part = fsinfo->dev_part;
+	filename = fsinfo->filename;
+	fstype = fsinfo->fstype;
+
+	if (fs_set_blk_dev(interface, dev_part, fstype))
+		return FPGA_FAIL;
+
+	if (fs_read(filename, (u32) buf, pos, blocksize) < 0)
+		return FPGA_FAIL;
+
+	if (zynq_validate_bitstream(desc, buf, bsize, blocksize, &swap,
+				    &partialbit))
+		return FPGA_FAIL;
+
+	dcache_disable();
+
+	do {
+		buf = zynq_align_dma_buffer((u32 *)buf, blocksize, swap);
+
+		if (zynq_dma_transfer((u32)buf | 1, blocksize >> 2,
+				      0xffffffff, 0))
+			return FPGA_FAIL;
+
+		bsize -= blocksize;
+		pos   += blocksize;
+
+		if (fs_set_blk_dev(interface, dev_part, fstype))
+			return FPGA_FAIL;
+
+		if (bsize > blocksize) {
+			if (fs_read(filename, (u32) buf, pos, blocksize) < 0)
+				return FPGA_FAIL;
+		} else {
+			if (fs_read(filename, (u32) buf, pos, bsize) < 0)
+				return FPGA_FAIL;
+		}
+	} while (bsize > blocksize);
+
+	buf = zynq_align_dma_buffer((u32 *)buf, blocksize, swap);
+
+	if (zynq_dma_transfer((u32)buf | 1, bsize >> 2, 0xffffffff, 0))
+		return FPGA_FAIL;
+
+	dcache_enable();
+
 	isr_status = readl(&devcfg_base->int_sts);
+
 	/* Check FPGA configuration completion */
 	ts = get_timer(0);
 	while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) {
@@ -403,6 +478,7 @@
 
 	return FPGA_SUCCESS;
 }
+#endif
 
 static int zynq_dump(xilinx_desc *desc, const void *buf, size_t bsize)
 {
@@ -411,6 +487,9 @@
 
 struct xilinx_fpga_op zynq_op = {
 	.load = zynq_load,
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+	.loadfs = zynq_loadfs,
+#endif
 	.dump = zynq_dump,
 	.info = zynq_info,
 };
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 931922b..4c6ab9e 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -30,6 +30,7 @@
 obj-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
 obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
 obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o
+obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
 else
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 50cba64..5541613 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -174,7 +174,7 @@
 	int timeout;
 	struct fsl_esdhc_cfg *cfg = mmc->priv;
 	struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
-#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
+
 	uint wml_value;
 
 	wml_value = data->blocksize/4;
@@ -184,12 +184,15 @@
 			wml_value = WML_RD_WML_MAX_VAL;
 
 		esdhc_clrsetbits32(&regs->wml, WML_RD_WML_MASK, wml_value);
+#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
 		esdhc_write32(&regs->dsaddr, (u32)data->dest);
+#endif
 	} else {
+#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
 		flush_dcache_range((ulong)data->src,
 				   (ulong)data->src+data->blocks
 					 *data->blocksize);
-
+#endif
 		if (wml_value > WML_WR_WML_MAX)
 			wml_value = WML_WR_WML_MAX_VAL;
 		if ((esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL) == 0) {
@@ -199,19 +202,10 @@
 
 		esdhc_clrsetbits32(&regs->wml, WML_WR_WML_MASK,
 					wml_value << 16);
+#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
 		esdhc_write32(&regs->dsaddr, (u32)data->src);
+#endif
 	}
-#else	/* CONFIG_SYS_FSL_ESDHC_USE_PIO */
-	if (!(data->flags & MMC_DATA_READ)) {
-		if ((esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL) == 0) {
-			printf("\nThe SD card is locked. "
-				"Can not write to a locked card.\n\n");
-			return TIMEOUT;
-		}
-		esdhc_write32(&regs->dsaddr, (u32)data->src);
-	} else
-		esdhc_write32(&regs->dsaddr, (u32)data->dest);
-#endif	/* CONFIG_SYS_FSL_ESDHC_USE_PIO */
 
 	esdhc_write32(&regs->blkattr, data->blocks << 16 | data->blocksize);
 
@@ -252,6 +246,7 @@
 	return 0;
 }
 
+#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
 static void check_and_invalidate_dcache_range
 	(struct mmc_cmd *cmd,
 	 struct mmc_data *data) {
@@ -261,6 +256,8 @@
 	unsigned end = start+size ;
 	invalidate_dcache_range(start, end);
 }
+#endif
+
 /*
  * Sends a command out on the bus.  Takes the mmc pointer,
  * a command pointer, and an optional data pointer.
@@ -388,9 +385,10 @@
 				goto out;
 			}
 		} while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
-#endif
+
 		if (data->flags & MMC_DATA_READ)
 			check_and_invalidate_dcache_range(cmd, data);
+#endif
 	}
 
 out:
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 16051e5..8b53ead 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -150,6 +150,8 @@
 #endif
 		return TIMEOUT;
 	}
+	if (cmd.response[0] & MMC_STATUS_SWITCH_ERROR)
+		return SWITCH_ERR;
 
 	return 0;
 }
@@ -501,7 +503,7 @@
 	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
 
 	if (err)
-		return err;
+		return err == SWITCH_ERR ? 0 : err;
 
 	/* Now check to see that it worked */
 	err = mmc_send_ext_csd(mmc, ext_csd);
@@ -550,6 +552,32 @@
 	return 0;
 }
 
+int mmc_select_hwpart(int dev_num, int hwpart)
+{
+	struct mmc *mmc = find_mmc_device(dev_num);
+	int ret;
+
+	if (!mmc)
+		return -1;
+
+	if (mmc->part_num == hwpart)
+		return 0;
+
+	if (mmc->part_config == MMCPART_NOAVAILABLE) {
+		printf("Card doesn't support part_switch\n");
+		return -1;
+	}
+
+	ret = mmc_switch_part(dev_num, hwpart);
+	if (ret)
+		return -1;
+
+	mmc->part_num = hwpart;
+
+	return 0;
+}
+
+
 int mmc_switch_part(int dev_num, unsigned int part_num)
 {
 	struct mmc *mmc = find_mmc_device(dev_num);
@@ -1310,10 +1338,13 @@
 int mmc_init(struct mmc *mmc)
 {
 	int err = IN_PROGRESS;
-	unsigned start = get_timer(0);
+	unsigned start;
 
 	if (mmc->has_init)
 		return 0;
+
+	start = get_timer(0);
+
 	if (!mmc->init_in_progress)
 		err = mmc_start_init(mmc);
 
diff --git a/drivers/mmc/rpmb.c b/drivers/mmc/rpmb.c
new file mode 100644
index 0000000..05936f5
--- /dev/null
+++ b/drivers/mmc/rpmb.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright 2014, Staubli Faverges
+ * Pierre Aubert
+ *
+ * eMMC- Replay Protected Memory Block
+ * According to JEDEC Standard No. 84-A441
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <mmc.h>
+#include <sha256.h>
+#include "mmc_private.h"
+
+/* Request codes */
+#define RPMB_REQ_KEY		1
+#define RPMB_REQ_WCOUNTER	2
+#define RPMB_REQ_WRITE_DATA	3
+#define RPMB_REQ_READ_DATA	4
+#define RPMB_REQ_STATUS		5
+
+/* Response code */
+#define RPMB_RESP_KEY		0x0100
+#define RPMB_RESP_WCOUNTER	0x0200
+#define RPMB_RESP_WRITE_DATA	0x0300
+#define RPMB_RESP_READ_DATA	0x0400
+
+/* Error codes */
+#define RPMB_OK			0
+#define RPMB_ERR_GENERAL	1
+#define RPMB_ERR_AUTH	2
+#define RPMB_ERR_COUNTER	3
+#define RPMB_ERR_ADDRESS	4
+#define RPMB_ERR_WRITE		5
+#define RPMB_ERR_READ		6
+#define RPMB_ERR_KEY		7
+#define RPMB_ERR_CNT_EXPIRED	0x80
+#define RPMB_ERR_MSK		0x7
+
+/* Sizes of RPMB data frame */
+#define RPMB_SZ_STUFF		196
+#define RPMB_SZ_MAC		32
+#define RPMB_SZ_DATA		256
+#define RPMB_SZ_NONCE		16
+
+#define SHA256_BLOCK_SIZE	64
+
+/* Error messages */
+static const char * const rpmb_err_msg[] = {
+	"",
+	"General failure",
+	"Authentication failure",
+	"Counter failure",
+	"Address failure",
+	"Write failure",
+	"Read failure",
+	"Authentication key not yet programmed",
+};
+
+
+/* Structure of RPMB data frame. */
+struct s_rpmb {
+	unsigned char stuff[RPMB_SZ_STUFF];
+	unsigned char mac[RPMB_SZ_MAC];
+	unsigned char data[RPMB_SZ_DATA];
+	unsigned char nonce[RPMB_SZ_NONCE];
+	unsigned long write_counter;
+	unsigned short address;
+	unsigned short block_count;
+	unsigned short result;
+	unsigned short request;
+};
+
+static int mmc_set_blockcount(struct mmc *mmc, unsigned int blockcount,
+			      bool is_rel_write)
+{
+	struct mmc_cmd cmd = {0};
+
+	cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
+	cmd.cmdarg = blockcount & 0x0000FFFF;
+	if (is_rel_write)
+		cmd.cmdarg |= 1 << 31;
+	cmd.resp_type = MMC_RSP_R1;
+
+	return mmc_send_cmd(mmc, &cmd, NULL);
+}
+static int mmc_rpmb_request(struct mmc *mmc, const struct s_rpmb *s,
+			    unsigned int count, bool is_rel_write)
+{
+	struct mmc_cmd cmd = {0};
+	struct mmc_data data;
+	int ret;
+
+	ret = mmc_set_blockcount(mmc, count, is_rel_write);
+	if (ret) {
+#ifdef CONFIG_MMC_RPMB_TRACE
+		printf("%s:mmc_set_blockcount-> %d\n", __func__, ret);
+#endif
+		return 1;
+	}
+
+	cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
+	cmd.cmdarg = 0;
+	cmd.resp_type = MMC_RSP_R1b;
+
+	data.src = (const char *)s;
+	data.blocks = 1;
+	data.blocksize = MMC_MAX_BLOCK_LEN;
+	data.flags = MMC_DATA_WRITE;
+
+	ret = mmc_send_cmd(mmc, &cmd, &data);
+	if (ret) {
+#ifdef CONFIG_MMC_RPMB_TRACE
+		printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
+#endif
+		return 1;
+	}
+	return 0;
+}
+static int mmc_rpmb_response(struct mmc *mmc, struct s_rpmb *s,
+			     unsigned short expected)
+{
+	struct mmc_cmd cmd = {0};
+	struct mmc_data data;
+	int ret;
+
+	ret = mmc_set_blockcount(mmc, 1, false);
+	if (ret) {
+#ifdef CONFIG_MMC_RPMB_TRACE
+		printf("%s:mmc_set_blockcount-> %d\n", __func__, ret);
+#endif
+		return -1;
+	}
+	cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
+	cmd.cmdarg = 0;
+	cmd.resp_type = MMC_RSP_R1;
+
+	data.dest = (char *)s;
+	data.blocks = 1;
+	data.blocksize = MMC_MAX_BLOCK_LEN;
+	data.flags = MMC_DATA_READ;
+
+	ret = mmc_send_cmd(mmc, &cmd, &data);
+	if (ret) {
+#ifdef CONFIG_MMC_RPMB_TRACE
+		printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
+#endif
+		return -1;
+	}
+	/* Check the response and the status */
+	if (be16_to_cpu(s->request) != expected) {
+#ifdef CONFIG_MMC_RPMB_TRACE
+		printf("%s:response= %x\n", __func__,
+		       be16_to_cpu(s->request));
+#endif
+		return -1;
+	}
+	ret = be16_to_cpu(s->result);
+	if (ret) {
+		printf("%s %s\n", rpmb_err_msg[ret & RPMB_ERR_MSK],
+		       (ret & RPMB_ERR_CNT_EXPIRED) ?
+		       "Write counter has expired" : "");
+	}
+
+	/* Return the status of the command */
+	return ret;
+}
+static int mmc_rpmb_status(struct mmc *mmc, unsigned short expected)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
+
+	memset(rpmb_frame, 0, sizeof(struct s_rpmb));
+	rpmb_frame->request = cpu_to_be16(RPMB_REQ_STATUS);
+	if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
+		return -1;
+
+	/* Read the result */
+	return mmc_rpmb_response(mmc, rpmb_frame, expected);
+}
+static void rpmb_hmac(unsigned char *key, unsigned char *buff, int len,
+		      unsigned char *output)
+{
+	sha256_context ctx;
+	int i;
+	unsigned char k_ipad[SHA256_BLOCK_SIZE];
+	unsigned char k_opad[SHA256_BLOCK_SIZE];
+
+	sha256_starts(&ctx);
+
+	/* According to RFC 4634, the HMAC transform looks like:
+	   SHA(K XOR opad, SHA(K XOR ipad, text))
+
+	   where K is an n byte key.
+	   ipad is the byte 0x36 repeated blocksize times
+	   opad is the byte 0x5c repeated blocksize times
+	   and text is the data being protected.
+	*/
+
+	for (i = 0; i < RPMB_SZ_MAC; i++) {
+		k_ipad[i] = key[i] ^ 0x36;
+		k_opad[i] = key[i] ^ 0x5c;
+	}
+	/* remaining pad bytes are '\0' XOR'd with ipad and opad values */
+	for ( ; i < SHA256_BLOCK_SIZE; i++) {
+		k_ipad[i] = 0x36;
+		k_opad[i] = 0x5c;
+	}
+	sha256_update(&ctx, k_ipad, SHA256_BLOCK_SIZE);
+	sha256_update(&ctx, buff, len);
+	sha256_finish(&ctx, output);
+
+	/* Init context for second pass */
+	sha256_starts(&ctx);
+
+	/* start with outer pad */
+	sha256_update(&ctx, k_opad, SHA256_BLOCK_SIZE);
+
+	/* then results of 1st hash */
+	sha256_update(&ctx, output, RPMB_SZ_MAC);
+
+	/* finish up 2nd pass */
+	sha256_finish(&ctx, output);
+}
+int mmc_rpmb_get_counter(struct mmc *mmc, unsigned long *pcounter)
+{
+	int ret;
+	ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
+
+	/* Fill the request */
+	memset(rpmb_frame, 0, sizeof(struct s_rpmb));
+	rpmb_frame->request = cpu_to_be16(RPMB_REQ_WCOUNTER);
+	if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
+		return -1;
+
+	/* Read the result */
+	ret = mmc_rpmb_response(mmc, rpmb_frame, RPMB_RESP_WCOUNTER);
+	if (ret)
+		return ret;
+
+	*pcounter = be32_to_cpu(rpmb_frame->write_counter);
+	return 0;
+}
+int mmc_rpmb_set_key(struct mmc *mmc, void *key)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
+	/* Fill the request */
+	memset(rpmb_frame, 0, sizeof(struct s_rpmb));
+	rpmb_frame->request = cpu_to_be16(RPMB_REQ_KEY);
+	memcpy(rpmb_frame->mac, key, RPMB_SZ_MAC);
+
+	if (mmc_rpmb_request(mmc, rpmb_frame, 1, true))
+		return -1;
+
+	/* read the operation status */
+	return mmc_rpmb_status(mmc, RPMB_RESP_KEY);
+}
+int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk,
+		  unsigned short cnt, unsigned char *key)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
+	int i;
+
+	for (i = 0; i < cnt; i++) {
+		/* Fill the request */
+		memset(rpmb_frame, 0, sizeof(struct s_rpmb));
+		rpmb_frame->address = cpu_to_be16(blk + i);
+		rpmb_frame->request = cpu_to_be16(RPMB_REQ_READ_DATA);
+		if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
+			break;
+
+		/* Read the result */
+		if (mmc_rpmb_response(mmc, rpmb_frame, RPMB_RESP_READ_DATA))
+			break;
+
+		/* Check the HMAC if key is provided */
+		if (key) {
+			unsigned char ret_hmac[RPMB_SZ_MAC];
+
+			rpmb_hmac(key, rpmb_frame->data, 284, ret_hmac);
+			if (memcmp(ret_hmac, rpmb_frame->mac, RPMB_SZ_MAC)) {
+				printf("MAC error on block #%d\n", i);
+				break;
+			}
+		}
+		/* Copy data */
+		memcpy(addr + i * RPMB_SZ_DATA, rpmb_frame->data, RPMB_SZ_DATA);
+	}
+	return i;
+}
+int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
+		  unsigned short cnt, unsigned char *key)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
+	unsigned long wcount;
+	int i;
+
+	for (i = 0; i < cnt; i++) {
+		if (mmc_rpmb_get_counter(mmc, &wcount)) {
+			printf("Cannot read RPMB write counter\n");
+			break;
+		}
+
+		/* Fill the request */
+		memset(rpmb_frame, 0, sizeof(struct s_rpmb));
+		memcpy(rpmb_frame->data, addr + i * RPMB_SZ_DATA, RPMB_SZ_DATA);
+		rpmb_frame->address = cpu_to_be16(blk + i);
+		rpmb_frame->block_count = cpu_to_be16(1);
+		rpmb_frame->write_counter = cpu_to_be32(wcount);
+		rpmb_frame->request = cpu_to_be16(RPMB_REQ_WRITE_DATA);
+		/* Computes HMAC */
+		rpmb_hmac(key, rpmb_frame->data, 284, rpmb_frame->mac);
+
+		if (mmc_rpmb_request(mmc, rpmb_frame, 1, true))
+			break;
+
+		/* Get status */
+		if (mmc_rpmb_status(mmc, RPMB_RESP_WRITE_DATA))
+			break;
+	}
+	return i;
+}
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 896c8d4..66becdc 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -18,6 +18,7 @@
 obj-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
 obj-$(CONFIG_DFU_FUNCTION) += f_dfu.o
 obj-$(CONFIG_USB_GADGET_MASS_STORAGE) += f_mass_storage.o
+obj-$(CONFIG_CMD_FASTBOOT) += f_fastboot.o
 endif
 ifdef CONFIG_USB_ETHER
 obj-y += ether.o
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 02d3fda..9cd0036 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -205,13 +205,26 @@
 static struct usb_request *
 ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags)
 {
-	struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep);
-	return &ci_ep->req;
+	struct ci_req *ci_req;
+
+	ci_req = memalign(ARCH_DMA_MINALIGN, sizeof(*ci_req));
+	if (!ci_req)
+		return NULL;
+
+	INIT_LIST_HEAD(&ci_req->queue);
+	ci_req->b_buf = 0;
+
+	return &ci_req->req;
 }
 
-static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *_req)
+static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *req)
 {
-	return;
+	struct ci_req *ci_req;
+
+	ci_req = container_of(req, struct ci_req, req);
+	if (ci_req->b_buf)
+		free(ci_req->b_buf);
+	free(ci_req);
 }
 
 static void ep_enable(int num, int in, int maxpacket)
@@ -267,99 +280,102 @@
 	return 0;
 }
 
-static int ci_bounce(struct ci_ep *ep, int in)
+static int ci_bounce(struct ci_req *ci_req, int in)
 {
-	uint32_t addr = (uint32_t)ep->req.buf;
-	uint32_t ba;
+	struct usb_request *req = &ci_req->req;
+	uint32_t addr = (uint32_t)req->buf;
+	uint32_t hwaddr;
+	uint32_t aligned_used_len;
 
 	/* Input buffer address is not aligned. */
 	if (addr & (ARCH_DMA_MINALIGN - 1))
 		goto align;
 
 	/* Input buffer length is not aligned. */
-	if (ep->req.length & (ARCH_DMA_MINALIGN - 1))
+	if (req->length & (ARCH_DMA_MINALIGN - 1))
 		goto align;
 
 	/* The buffer is well aligned, only flush cache. */
-	ep->b_len = ep->req.length;
-	ep->b_buf = ep->req.buf;
+	ci_req->hw_len = req->length;
+	ci_req->hw_buf = req->buf;
 	goto flush;
 
 align:
-	/* Use internal buffer for small payloads. */
-	if (ep->req.length <= 64) {
-		ep->b_len = 64;
-		ep->b_buf = ep->b_fast;
-	} else {
-		ep->b_len = roundup(ep->req.length, ARCH_DMA_MINALIGN);
-		ep->b_buf = memalign(ARCH_DMA_MINALIGN, ep->b_len);
-		if (!ep->b_buf)
+	if (ci_req->b_buf && req->length > ci_req->b_len) {
+		free(ci_req->b_buf);
+		ci_req->b_buf = 0;
+	}
+	if (!ci_req->b_buf) {
+		ci_req->b_len = roundup(req->length, ARCH_DMA_MINALIGN);
+		ci_req->b_buf = memalign(ARCH_DMA_MINALIGN, ci_req->b_len);
+		if (!ci_req->b_buf)
 			return -ENOMEM;
 	}
+	ci_req->hw_len = ci_req->b_len;
+	ci_req->hw_buf = ci_req->b_buf;
+
 	if (in)
-		memcpy(ep->b_buf, ep->req.buf, ep->req.length);
+		memcpy(ci_req->hw_buf, req->buf, req->length);
 
 flush:
-	ba = (uint32_t)ep->b_buf;
-	flush_dcache_range(ba, ba + ep->b_len);
+	hwaddr = (uint32_t)ci_req->hw_buf;
+	aligned_used_len = roundup(req->length, ARCH_DMA_MINALIGN);
+	flush_dcache_range(hwaddr, hwaddr + aligned_used_len);
 
 	return 0;
 }
 
-static void ci_debounce(struct ci_ep *ep, int in)
+static void ci_debounce(struct ci_req *ci_req, int in)
 {
-	uint32_t addr = (uint32_t)ep->req.buf;
-	uint32_t ba = (uint32_t)ep->b_buf;
+	struct usb_request *req = &ci_req->req;
+	uint32_t addr = (uint32_t)req->buf;
+	uint32_t hwaddr = (uint32_t)ci_req->hw_buf;
+	uint32_t aligned_used_len;
 
-	if (in) {
-		if (addr == ba)
-			return;		/* not a bounce */
-		goto free;
-	}
-	invalidate_dcache_range(ba, ba + ep->b_len);
+	if (in)
+		return;
+
+	aligned_used_len = roundup(req->actual, ARCH_DMA_MINALIGN);
+	invalidate_dcache_range(hwaddr, hwaddr + aligned_used_len);
 
-	if (addr == ba)
-		return;		/* not a bounce */
+	if (addr == hwaddr)
+		return; /* not a bounce */
 
-	memcpy(ep->req.buf, ep->b_buf, ep->req.actual);
-free:
-	/* Large payloads use allocated buffer, free it. */
-	if (ep->b_buf != ep->b_fast)
-		free(ep->b_buf);
+	memcpy(req->buf, ci_req->hw_buf, req->actual);
 }
 
-static int ci_ep_queue(struct usb_ep *ep,
-		struct usb_request *req, gfp_t gfp_flags)
+static void ci_ep_submit_next_request(struct ci_ep *ci_ep)
 {
-	struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep);
 	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
 	struct ept_queue_item *item;
 	struct ept_queue_head *head;
-	int bit, num, len, in, ret;
+	int bit, num, len, in;
+	struct ci_req *ci_req;
+
+	ci_ep->req_primed = true;
+
 	num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
 	in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0;
 	item = ci_get_qtd(num, in);
 	head = ci_get_qh(num, in);
-	len = req->length;
 
-	ret = ci_bounce(ci_ep, in);
-	if (ret)
-		return ret;
+	ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
+	len = ci_req->req.length;
 
 	item->next = TERMINATE;
 	item->info = INFO_BYTES(len) | INFO_IOC | INFO_ACTIVE;
-	item->page0 = (uint32_t)ci_ep->b_buf;
-	item->page1 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x1000;
-	item->page2 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x2000;
-	item->page3 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x3000;
-	item->page4 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x4000;
+	item->page0 = (uint32_t)ci_req->hw_buf;
+	item->page1 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x1000;
+	item->page2 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x2000;
+	item->page3 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x3000;
+	item->page4 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x4000;
 	ci_flush_qtd(num);
 
 	head->next = (unsigned) item;
 	head->info = 0;
 
-	DBG("ept%d %s queue len %x, buffer %p\n",
-	    num, in ? "in" : "out", len, ci_ep->b_buf);
+	DBG("ept%d %s queue len %x, req %p, buffer %p\n",
+	    num, in ? "in" : "out", len, ci_req, ci_req->hw_buf);
 	ci_flush_qh(num);
 
 	if (in)
@@ -368,6 +384,29 @@
 		bit = EPT_RX(num);
 
 	writel(bit, &udc->epprime);
+}
+
+static int ci_ep_queue(struct usb_ep *ep,
+		struct usb_request *req, gfp_t gfp_flags)
+{
+	struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep);
+	struct ci_req *ci_req = container_of(req, struct ci_req, req);
+	int in, ret;
+	int __maybe_unused num;
+
+	num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0;
+
+	ret = ci_bounce(ci_req, in);
+	if (ret)
+		return ret;
+
+	DBG("ept%d %s pre-queue req %p, buffer %p\n",
+	    num, in ? "in" : "out", ci_req, ci_req->hw_buf);
+	list_add_tail(&ci_req->queue, &ci_ep->queue);
+
+	if (!ci_ep->req_primed)
+		ci_ep_submit_next_request(ci_ep);
 
 	return 0;
 }
@@ -376,6 +415,8 @@
 {
 	struct ept_queue_item *item;
 	int num, in, len;
+	struct ci_req *ci_req;
+
 	num = ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
 	in = (ep->desc->bEndpointAddress & USB_DIR_IN) != 0;
 	if (num == 0)
@@ -383,20 +424,27 @@
 	item = ci_get_qtd(num, in);
 	ci_invalidate_qtd(num);
 
+	len = (item->info >> 16) & 0x7fff;
 	if (item->info & 0xff)
 		printf("EP%d/%s FAIL info=%x pg0=%x\n",
 		       num, in ? "in" : "out", item->info, item->page0);
 
-	len = (item->info >> 16) & 0x7fff;
-	ep->req.actual = ep->req.length - len;
-	ci_debounce(ep, in);
+	ci_req = list_first_entry(&ep->queue, struct ci_req, queue);
+	list_del_init(&ci_req->queue);
+	ep->req_primed = false;
+
+	if (!list_empty(&ep->queue))
+		ci_ep_submit_next_request(ep);
 
-	DBG("ept%d %s complete %x\n",
-			num, in ? "in" : "out", len);
-	ep->req.complete(&ep->ep, &ep->req);
+	ci_req->req.actual = ci_req->req.length - len;
+	ci_debounce(ci_req, in);
+
+	DBG("ept%d %s req %p, complete %x\n",
+	    num, in ? "in" : "out", ci_req, len);
+	ci_req->req.complete(&ep->ep, &ci_req->req);
 	if (num == 0) {
-		ep->req.length = 0;
-		usb_ep_queue(&ep->ep, &ep->req, 0);
+		ci_req->req.length = 0;
+		usb_ep_queue(&ep->ep, &ci_req->req, 0);
 		ep->desc = &ep0_in_desc;
 	}
 }
@@ -405,13 +453,18 @@
 
 static void handle_setup(void)
 {
-	struct usb_request *req = &controller.ep[0].req;
+	struct ci_ep *ci_ep = &controller.ep[0];
+	struct ci_req *ci_req;
+	struct usb_request *req;
 	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
 	struct ept_queue_head *head;
 	struct usb_ctrlrequest r;
 	int status = 0;
 	int num, in, _num, _in, i;
 	char *buf;
+
+	ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
+	req = &ci_req->req;
 	head = ci_get_qh(0, 0);	/* EP0 OUT */
 
 	ci_invalidate_qh(0);
@@ -424,6 +477,9 @@
 	DBG("handle setup %s, %x, %x index %x value %x\n", reqname(r.bRequest),
 	    r.bRequestType, r.bRequest, r.wIndex, r.wValue);
 
+	list_del_init(&ci_req->queue);
+	ci_ep->req_primed = false;
+
 	switch (SETUP(r.bRequestType, r.bRequest)) {
 	case SETUP(USB_RECIP_ENDPOINT, USB_REQ_CLEAR_FEATURE):
 		_num = r.wIndex & 15;
@@ -701,6 +757,8 @@
 	/* Init EP 0 */
 	memcpy(&controller.ep[0].ep, &ci_ep_init[0], sizeof(*ci_ep_init));
 	controller.ep[0].desc = &ep0_in_desc;
+	INIT_LIST_HEAD(&controller.ep[0].queue);
+	controller.ep[0].req_primed = false;
 	controller.gadget.ep0 = &controller.ep[0].ep;
 	INIT_LIST_HEAD(&controller.gadget.ep0->ep_list);
 
@@ -708,6 +766,8 @@
 	for (i = 1; i < NUM_ENDPOINTS; i++) {
 		memcpy(&controller.ep[i].ep, &ci_ep_init[1],
 		       sizeof(*ci_ep_init));
+		INIT_LIST_HEAD(&controller.ep[i].queue);
+		controller.ep[i].req_primed = false;
 		list_add_tail(&controller.ep[i].ep.ep_list,
 			      &controller.gadget.ep_list);
 	}
diff --git a/drivers/usb/gadget/ci_udc.h b/drivers/usb/gadget/ci_udc.h
index 4425fd9..23cff56 100644
--- a/drivers/usb/gadget/ci_udc.h
+++ b/drivers/usb/gadget/ci_udc.h
@@ -77,15 +77,22 @@
 #define CTRL_TXT_BULK	(2 << 18)
 #define CTRL_RXT_BULK	(2 << 2)
 
+struct ci_req {
+	struct usb_request	req;
+	struct list_head	queue;
+	/* Bounce buffer allocated if needed to align the transfer */
+	uint8_t *b_buf;
+	uint32_t b_len;
+	/* Buffer for the current transfer. Either req.buf/len or b_buf/len */
+	uint8_t *hw_buf;
+	uint32_t hw_len;
+};
+
 struct ci_ep {
 	struct usb_ep ep;
 	struct list_head queue;
+	bool req_primed;
 	const struct usb_endpoint_descriptor *desc;
-
-	struct usb_request req;
-	uint8_t *b_buf;
-	uint32_t b_len;
-	uint8_t b_fast[64] __aligned(ARCH_DMA_MINALIGN);
 };
 
 struct ci_drv {
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index 1b1e179..859fe82 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -175,10 +175,17 @@
 		  req->length, f_dfu->blk_seq_num);
 }
 
+static inline int dfu_get_manifest_timeout(struct dfu_entity *dfu)
+{
+	return dfu->poll_timeout ? dfu->poll_timeout(dfu) :
+		DFU_MANIFEST_POLL_TIMEOUT;
+}
+
 static void handle_getstatus(struct usb_request *req)
 {
 	struct dfu_status *dstat = (struct dfu_status *)req->buf;
 	struct f_dfu *f_dfu = req->context;
+	struct dfu_entity *dfu = dfu_get_entity(f_dfu->altsetting);
 
 	dfu_set_poll_timeout(dstat, 0);
 
@@ -191,7 +198,8 @@
 		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
 		break;
 	case DFU_STATE_dfuMANIFEST:
-		dfu_set_poll_timeout(dstat, DFU_MANIFEST_POLL_TIMEOUT);
+		dfu_set_poll_timeout(dstat, dfu_get_manifest_timeout(dfu));
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
new file mode 100644
index 0000000..9dd85b6
--- /dev/null
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -0,0 +1,513 @@
+/*
+ * (C) Copyright 2008 - 2009
+ * Windriver, <www.windriver.com>
+ * Tom Rix <Tom.Rix@windriver.com>
+ *
+ * Copyright 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ *
+ * Copyright 2014 Linaro, Ltd.
+ * Rob Herring <robh@kernel.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/composite.h>
+#include <linux/compiler.h>
+#include <version.h>
+#include <g_dnl.h>
+
+#define FASTBOOT_VERSION		"0.4"
+
+#define FASTBOOT_INTERFACE_CLASS	0xff
+#define FASTBOOT_INTERFACE_SUB_CLASS	0x42
+#define FASTBOOT_INTERFACE_PROTOCOL	0x03
+
+#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0  (0x0200)
+#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1  (0x0040)
+#define TX_ENDPOINT_MAXIMUM_PACKET_SIZE      (0x0040)
+
+/* The 64 defined bytes plus \0 */
+#define RESPONSE_LEN	(64 + 1)
+
+#define EP_BUFFER_SIZE			4096
+
+struct f_fastboot {
+	struct usb_function usb_function;
+
+	/* IN/OUT EP's and correspoinding requests */
+	struct usb_ep *in_ep, *out_ep;
+	struct usb_request *in_req, *out_req;
+};
+
+static inline struct f_fastboot *func_to_fastboot(struct usb_function *f)
+{
+	return container_of(f, struct f_fastboot, usb_function);
+}
+
+static struct f_fastboot *fastboot_func;
+static unsigned int download_size;
+static unsigned int download_bytes;
+
+static struct usb_endpoint_descriptor fs_ep_in = {
+	.bLength            = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType    = USB_DT_ENDPOINT,
+	.bEndpointAddress   = USB_DIR_IN,
+	.bmAttributes       = USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize     = TX_ENDPOINT_MAXIMUM_PACKET_SIZE,
+	.bInterval          = 0x00,
+};
+
+static struct usb_endpoint_descriptor fs_ep_out = {
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
+	.bEndpointAddress	= USB_DIR_OUT,
+	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize		= RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1,
+	.bInterval		= 0x00,
+};
+
+static struct usb_endpoint_descriptor hs_ep_out = {
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
+	.bEndpointAddress	= USB_DIR_OUT,
+	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize		= RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0,
+	.bInterval		= 0x00,
+};
+
+static struct usb_interface_descriptor interface_desc = {
+	.bLength		= USB_DT_INTERFACE_SIZE,
+	.bDescriptorType	= USB_DT_INTERFACE,
+	.bInterfaceNumber	= 0x00,
+	.bAlternateSetting	= 0x00,
+	.bNumEndpoints		= 0x02,
+	.bInterfaceClass	= FASTBOOT_INTERFACE_CLASS,
+	.bInterfaceSubClass	= FASTBOOT_INTERFACE_SUB_CLASS,
+	.bInterfaceProtocol	= FASTBOOT_INTERFACE_PROTOCOL,
+};
+
+static struct usb_descriptor_header *fb_runtime_descs[] = {
+	(struct usb_descriptor_header *)&interface_desc,
+	(struct usb_descriptor_header *)&fs_ep_in,
+	(struct usb_descriptor_header *)&hs_ep_out,
+	NULL,
+};
+
+/*
+ * static strings, in UTF-8
+ */
+static const char fastboot_name[] = "Android Fastboot";
+
+static struct usb_string fastboot_string_defs[] = {
+	[0].s = fastboot_name,
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab_fastboot = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= fastboot_string_defs,
+};
+
+static struct usb_gadget_strings *fastboot_strings[] = {
+	&stringtab_fastboot,
+	NULL,
+};
+
+static void rx_handler_command(struct usb_ep *ep, struct usb_request *req);
+
+static void fastboot_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	int status = req->status;
+	if (!status)
+		return;
+	printf("status: %d ep '%s' trans: %d\n", status, ep->name, req->actual);
+}
+
+static int fastboot_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	int id;
+	struct usb_gadget *gadget = c->cdev->gadget;
+	struct f_fastboot *f_fb = func_to_fastboot(f);
+
+	/* DYNAMIC interface numbers assignments */
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	interface_desc.bInterfaceNumber = id;
+
+	id = usb_string_id(c->cdev);
+	if (id < 0)
+		return id;
+	fastboot_string_defs[0].id = id;
+	interface_desc.iInterface = id;
+
+	f_fb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in);
+	if (!f_fb->in_ep)
+		return -ENODEV;
+	f_fb->in_ep->driver_data = c->cdev;
+
+	f_fb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out);
+	if (!f_fb->out_ep)
+		return -ENODEV;
+	f_fb->out_ep->driver_data = c->cdev;
+
+	hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress;
+
+	return 0;
+}
+
+static void fastboot_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	memset(fastboot_func, 0, sizeof(*fastboot_func));
+}
+
+static void fastboot_disable(struct usb_function *f)
+{
+	struct f_fastboot *f_fb = func_to_fastboot(f);
+
+	usb_ep_disable(f_fb->out_ep);
+	usb_ep_disable(f_fb->in_ep);
+
+	if (f_fb->out_req) {
+		free(f_fb->out_req->buf);
+		usb_ep_free_request(f_fb->out_ep, f_fb->out_req);
+		f_fb->out_req = NULL;
+	}
+	if (f_fb->in_req) {
+		free(f_fb->in_req->buf);
+		usb_ep_free_request(f_fb->in_ep, f_fb->in_req);
+		f_fb->in_req = NULL;
+	}
+}
+
+static struct usb_request *fastboot_start_ep(struct usb_ep *ep)
+{
+	struct usb_request *req;
+
+	req = usb_ep_alloc_request(ep, 0);
+	if (!req)
+		return NULL;
+
+	req->length = EP_BUFFER_SIZE;
+	req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE);
+	if (!req->buf) {
+		usb_ep_free_request(ep, req);
+		return NULL;
+	}
+
+	memset(req->buf, 0, req->length);
+	return req;
+}
+
+static int fastboot_set_alt(struct usb_function *f,
+			    unsigned interface, unsigned alt)
+{
+	int ret;
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct usb_gadget *gadget = cdev->gadget;
+	struct f_fastboot *f_fb = func_to_fastboot(f);
+
+	debug("%s: func: %s intf: %d alt: %d\n",
+	      __func__, f->name, interface, alt);
+
+	/* make sure we don't enable the ep twice */
+	if (gadget->speed == USB_SPEED_HIGH)
+		ret = usb_ep_enable(f_fb->out_ep, &hs_ep_out);
+	else
+		ret = usb_ep_enable(f_fb->out_ep, &fs_ep_out);
+	if (ret) {
+		puts("failed to enable out ep\n");
+		return ret;
+	}
+
+	f_fb->out_req = fastboot_start_ep(f_fb->out_ep);
+	if (!f_fb->out_req) {
+		puts("failed to alloc out req\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	f_fb->out_req->complete = rx_handler_command;
+
+	ret = usb_ep_enable(f_fb->in_ep, &fs_ep_in);
+	if (ret) {
+		puts("failed to enable in ep\n");
+		goto err;
+	}
+
+	f_fb->in_req = fastboot_start_ep(f_fb->in_ep);
+	if (!f_fb->in_req) {
+		puts("failed alloc req in\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	f_fb->in_req->complete = fastboot_complete;
+
+	ret = usb_ep_queue(f_fb->out_ep, f_fb->out_req, 0);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	fastboot_disable(f);
+	return ret;
+}
+
+static int fastboot_add(struct usb_configuration *c)
+{
+	struct f_fastboot *f_fb = fastboot_func;
+	int status;
+
+	debug("%s: cdev: 0x%p\n", __func__, c->cdev);
+
+	if (!f_fb) {
+		f_fb = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_fb));
+		if (!f_fb)
+			return -ENOMEM;
+
+		fastboot_func = f_fb;
+		memset(f_fb, 0, sizeof(*f_fb));
+	}
+
+	f_fb->usb_function.name = "f_fastboot";
+	f_fb->usb_function.hs_descriptors = fb_runtime_descs;
+	f_fb->usb_function.bind = fastboot_bind;
+	f_fb->usb_function.unbind = fastboot_unbind;
+	f_fb->usb_function.set_alt = fastboot_set_alt;
+	f_fb->usb_function.disable = fastboot_disable;
+	f_fb->usb_function.strings = fastboot_strings;
+
+	status = usb_add_function(c, &f_fb->usb_function);
+	if (status) {
+		free(f_fb);
+		fastboot_func = f_fb;
+	}
+
+	return status;
+}
+DECLARE_GADGET_BIND_CALLBACK(usb_dnl_fastboot, fastboot_add);
+
+int fastboot_tx_write(const char *buffer, unsigned int buffer_size)
+{
+	struct usb_request *in_req = fastboot_func->in_req;
+	int ret;
+
+	memcpy(in_req->buf, buffer, buffer_size);
+	in_req->length = buffer_size;
+	ret = usb_ep_queue(fastboot_func->in_ep, in_req, 0);
+	if (ret)
+		printf("Error %d on queue\n", ret);
+	return 0;
+}
+
+static int fastboot_tx_write_str(const char *buffer)
+{
+	return fastboot_tx_write(buffer, strlen(buffer));
+}
+
+static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
+{
+	do_reset(NULL, 0, 0, NULL);
+}
+
+static void cb_reboot(struct usb_ep *ep, struct usb_request *req)
+{
+	fastboot_func->in_req->complete = compl_do_reset;
+	fastboot_tx_write_str("OKAY");
+}
+
+static int strcmp_l1(const char *s1, const char *s2)
+{
+	if (!s1 || !s2)
+		return -1;
+	return strncmp(s1, s2, strlen(s1));
+}
+
+static void cb_getvar(struct usb_ep *ep, struct usb_request *req)
+{
+	char *cmd = req->buf;
+	char response[RESPONSE_LEN];
+	const char *s;
+
+	strcpy(response, "OKAY");
+	strsep(&cmd, ":");
+	if (!cmd) {
+		fastboot_tx_write_str("FAILmissing var");
+		return;
+	}
+
+	if (!strcmp_l1("version", cmd)) {
+		strncat(response, FASTBOOT_VERSION, sizeof(response));
+	} else if (!strcmp_l1("bootloader-version", cmd)) {
+		strncat(response, U_BOOT_VERSION, sizeof(response));
+	} else if (!strcmp_l1("downloadsize", cmd)) {
+		char str_num[12];
+
+		sprintf(str_num, "%08x", CONFIG_USB_FASTBOOT_BUF_SIZE);
+		strncat(response, str_num, sizeof(response));
+	} else if (!strcmp_l1("serialno", cmd)) {
+		s = getenv("serial#");
+		if (s)
+			strncat(response, s, sizeof(response));
+		else
+			strcpy(response, "FAILValue not set");
+	} else {
+		strcpy(response, "FAILVariable not implemented");
+	}
+	fastboot_tx_write_str(response);
+}
+
+static unsigned int rx_bytes_expected(void)
+{
+	int rx_remain = download_size - download_bytes;
+	if (rx_remain < 0)
+		return 0;
+	if (rx_remain > EP_BUFFER_SIZE)
+		return EP_BUFFER_SIZE;
+	return rx_remain;
+}
+
+#define BYTES_PER_DOT	0x20000
+static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
+{
+	char response[RESPONSE_LEN];
+	unsigned int transfer_size = download_size - download_bytes;
+	const unsigned char *buffer = req->buf;
+	unsigned int buffer_size = req->actual;
+
+	if (req->status != 0) {
+		printf("Bad status: %d\n", req->status);
+		return;
+	}
+
+	if (buffer_size < transfer_size)
+		transfer_size = buffer_size;
+
+	memcpy((void *)CONFIG_USB_FASTBOOT_BUF_ADDR + download_bytes,
+	       buffer, transfer_size);
+
+	download_bytes += transfer_size;
+
+	/* Check if transfer is done */
+	if (download_bytes >= download_size) {
+		/*
+		 * Reset global transfer variable, keep download_bytes because
+		 * it will be used in the next possible flashing command
+		 */
+		download_size = 0;
+		req->complete = rx_handler_command;
+		req->length = EP_BUFFER_SIZE;
+
+		sprintf(response, "OKAY");
+		fastboot_tx_write_str(response);
+
+		printf("\ndownloading of %d bytes finished\n", download_bytes);
+	} else {
+		req->length = rx_bytes_expected();
+		if (req->length < ep->maxpacket)
+			req->length = ep->maxpacket;
+	}
+
+	if (download_bytes && !(download_bytes % BYTES_PER_DOT)) {
+		putc('.');
+		if (!(download_bytes % (74 * BYTES_PER_DOT)))
+			putc('\n');
+	}
+	req->actual = 0;
+	usb_ep_queue(ep, req, 0);
+}
+
+static void cb_download(struct usb_ep *ep, struct usb_request *req)
+{
+	char *cmd = req->buf;
+	char response[RESPONSE_LEN];
+
+	strsep(&cmd, ":");
+	download_size = simple_strtoul(cmd, NULL, 16);
+	download_bytes = 0;
+
+	printf("Starting download of %d bytes\n", download_size);
+
+	if (0 == download_size) {
+		sprintf(response, "FAILdata invalid size");
+	} else if (download_size > CONFIG_USB_FASTBOOT_BUF_SIZE) {
+		download_size = 0;
+		sprintf(response, "FAILdata too large");
+	} else {
+		sprintf(response, "DATA%08x", download_size);
+		req->complete = rx_handler_dl_image;
+		req->length = rx_bytes_expected();
+		if (req->length < ep->maxpacket)
+			req->length = ep->maxpacket;
+	}
+	fastboot_tx_write_str(response);
+}
+
+static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	char boot_addr_start[12];
+	char *bootm_args[] = { "bootm", boot_addr_start, NULL };
+
+	puts("Booting kernel..\n");
+
+	sprintf(boot_addr_start, "0x%lx", load_addr);
+	do_bootm(NULL, 0, 2, bootm_args);
+
+	/* This only happens if image is somehow faulty so we start over */
+	do_reset(NULL, 0, 0, NULL);
+}
+
+static void cb_boot(struct usb_ep *ep, struct usb_request *req)
+{
+	fastboot_func->in_req->complete = do_bootm_on_complete;
+	fastboot_tx_write_str("OKAY");
+}
+
+struct cmd_dispatch_info {
+	char *cmd;
+	void (*cb)(struct usb_ep *ep, struct usb_request *req);
+};
+
+static const struct cmd_dispatch_info cmd_dispatch_info[] = {
+	{
+		.cmd = "reboot",
+		.cb = cb_reboot,
+	}, {
+		.cmd = "getvar:",
+		.cb = cb_getvar,
+	}, {
+		.cmd = "download:",
+		.cb = cb_download,
+	}, {
+		.cmd = "boot",
+		.cb = cb_boot,
+	},
+};
+
+static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
+{
+	char *cmdbuf = req->buf;
+	void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) {
+		if (!strcmp_l1(cmd_dispatch_info[i].cmd, cmdbuf)) {
+			func_cb = cmd_dispatch_info[i].cb;
+			break;
+		}
+	}
+
+	if (!func_cb)
+		fastboot_tx_write_str("FAILunknown command");
+	else
+		func_cb(ep, req);
+
+	if (req->status == 0) {
+		*cmdbuf = '\0';
+		req->actual = 0;
+		usb_ep_queue(ep, req, 0);
+	}
+}
diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
index feef9e4..28f215e 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -219,21 +219,15 @@
 	}
 
 	/*
-	 * To store last "packet" DFU storage backend requires dfu_write with
-	 * size parameter equal to 0
+	 * To store last "packet" or write file from buffer to filesystem
+	 * DFU storage backend requires dfu_flush
 	 *
 	 * This also frees memory malloc'ed by dfu_get_buf(), so no explicit
 	 * need fo call dfu_free_buf() is needed.
 	 */
-	ret = dfu_write(dfu_entity, transfer_buffer, 0, cnt);
-	if (ret)
-		error("DFU write failed [%d] cnt: %d", ret, cnt);
-
 	ret = dfu_flush(dfu_entity, transfer_buffer, 0, cnt);
-	if (ret) {
+	if (ret)
 		error("DFU flush failed!");
-		return ret;
-	}
 
 	return ret;
 }
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 7430074..02803df 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -311,11 +311,7 @@
 #define DELAYED_STATUS	(EP0_BUFSIZE + 999)	/* An impossibly large value */
 
 /* Number of buffers we will use.  2 is enough for double-buffering */
-#ifndef CONFIG_CI_UDC
 #define FSG_NUM_BUFFERS	2
-#else
-#define FSG_NUM_BUFFERS	1 /* ci_udc only allows 1 req per ep at present */
-#endif
 
 /* Default size of buffer length. */
 #define FSG_BUFLEN	((u32)16384)
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index b301e28..7211c6a 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -37,6 +37,7 @@
 obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o
 obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o
 obj-$(CONFIG_USB_EHCI_RMOBILE) += ehci-rmobile.o
+obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o
 
 # xhci
 obj-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 38db18e..33e5ea9 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -69,6 +69,7 @@
 	unsigned enabled:1;	/* 1 to enable, 0 to disable */
 	unsigned has_legacy_mode:1; /* 1 if this port has legacy mode */
 	unsigned initialized:1; /* has this port already been initialized? */
+	enum usb_init_type init_type;
 	enum dr_mode dr_mode;	/* dual role mode */
 	enum periph_id periph_id;/* peripheral id */
 	struct fdt_gpio_state vbus_gpio;	/* GPIO for vbus enable */
@@ -237,29 +238,31 @@
 		return PORTSC_PSPD(reg);
 }
 
-/* Put the port into host mode */
-static void set_host_mode(struct fdt_usb *config)
+/* Set up VBUS for host/device mode */
+static void set_up_vbus(struct fdt_usb *config, enum usb_init_type init)
 {
 	/*
-	 * If we are an OTG port, check if remote host is driving VBus and
-	 * bail out in this case.
+	 * If we are an OTG port initializing in host mode,
+	 * check if remote host is driving VBus and bail out in this case.
 	 */
-	if (config->dr_mode == DR_MODE_OTG &&
-		(readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS))
+	if (init == USB_INIT_HOST &&
+	    config->dr_mode == DR_MODE_OTG &&
+	    (readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS)) {
+		printf("tegrausb: VBUS input active; not enabling as host\n");
 		return;
+	}
 
-	/*
-	 * If not driving, we set the GPIO to enable VBUS. We assume
-	 * that the pinmux is set up correctly for this.
-	 */
 	if (fdt_gpio_isvalid(&config->vbus_gpio)) {
+		int vbus_value;
+
 		fdtdec_setup_gpio(&config->vbus_gpio);
-		gpio_direction_output(config->vbus_gpio.gpio,
-			(config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ?
-				 0 : 1);
-		debug("set_host_mode: GPIO %d %s\n", config->vbus_gpio.gpio,
-			(config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ?
-				"low" : "high");
+
+		vbus_value = (init == USB_INIT_HOST) ^
+			     !!(config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW);
+		gpio_direction_output(config->vbus_gpio.gpio, vbus_value);
+
+		debug("set_up_vbus: GPIO %d %d\n", config->vbus_gpio.gpio,
+		      vbus_value);
 	}
 }
 
@@ -293,10 +296,44 @@
 	return timing;
 }
 
+/* select the PHY to use with a USB controller */
+static void init_phy_mux(struct fdt_usb *config, uint pts,
+			 enum usb_init_type init)
+{
+	struct usb_ctlr *usbctlr = config->reg;
+
+#if defined(CONFIG_TEGRA20)
+	if (config->periph_id == PERIPH_ID_USBD) {
+		clrsetbits_le32(&usbctlr->port_sc1, PTS1_MASK,
+				PTS_UTMI << PTS1_SHIFT);
+		clrbits_le32(&usbctlr->port_sc1, STS1);
+	} else {
+		clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK,
+				PTS_UTMI << PTS_SHIFT);
+		clrbits_le32(&usbctlr->port_sc1, STS);
+	}
+#else
+	/* Set to Host mode (if applicable) after Controller Reset was done */
+	clrsetbits_le32(&usbctlr->usb_mode, USBMODE_CM_HC,
+			(init == USB_INIT_HOST) ? USBMODE_CM_HC : 0);
+	/*
+	 * Select PHY interface after setting host mode.
+	 * For device mode, the ordering requirement is not an issue, since
+	 * only the first USB controller supports device mode, and that USB
+	 * controller can only talk to a UTMI PHY, so the PHY selection is
+	 * already made at reset time, so this write is a no-op.
+	 */
+	clrsetbits_le32(&usbctlr->hostpc1_devlc, PTS_MASK,
+			pts << PTS_SHIFT);
+	clrbits_le32(&usbctlr->hostpc1_devlc, STS);
+#endif
+}
+
 /* set up the UTMI USB controller with the parameters provided */
-static int init_utmi_usb_controller(struct fdt_usb *config)
+static int init_utmi_usb_controller(struct fdt_usb *config,
+				    enum usb_init_type init)
 {
-	u32 val;
+	u32 b_sess_valid_mask, val;
 	int loop_count;
 	const unsigned *timing;
 	struct usb_ctlr *usbctlr = config->reg;
@@ -314,6 +351,10 @@
 	/* Follow the crystal clock disable by >100ns delay */
 	udelay(1);
 
+	b_sess_valid_mask = (VBUS_B_SESS_VLD_SW_VALUE | VBUS_B_SESS_VLD_SW_EN);
+	clrsetbits_le32(&usbctlr->phy_vbus_sensors, b_sess_valid_mask,
+			(init == USB_INIT_DEVICE) ? b_sess_valid_mask : 0);
+
 	/*
 	 * To Use the A Session Valid for cable detection logic, VBUS_WAKEUP
 	 * mux must be switched to actually use a_sess_vld threshold.
@@ -485,21 +526,7 @@
 	clrbits_le32(&usbctlr->icusb_ctrl, IC_ENB1);
 
 	/* Select UTMI parallel interface */
-#if defined(CONFIG_TEGRA20)
-	if (config->periph_id == PERIPH_ID_USBD) {
-		clrsetbits_le32(&usbctlr->port_sc1, PTS1_MASK,
-				PTS_UTMI << PTS1_SHIFT);
-		clrbits_le32(&usbctlr->port_sc1, STS1);
-	} else {
-		clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK,
-				PTS_UTMI << PTS_SHIFT);
-		clrbits_le32(&usbctlr->port_sc1, STS);
-	}
-#else
-	clrsetbits_le32(&usbctlr->hostpc1_devlc, PTS_MASK,
-			PTS_UTMI << PTS_SHIFT);
-	clrbits_le32(&usbctlr->hostpc1_devlc, STS);
-#endif
+	init_phy_mux(config, PTS_UTMI, init);
 
 	/* Deassert power down state */
 	clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_FORCE_PD_POWERDOWN |
@@ -529,7 +556,8 @@
 #endif
 
 /* set up the ULPI USB controller with the parameters provided */
-static int init_ulpi_usb_controller(struct fdt_usb *config)
+static int init_ulpi_usb_controller(struct fdt_usb *config,
+				    enum usb_init_type init)
 {
 	u32 val;
 	int loop_count;
@@ -557,13 +585,7 @@
 			ULPI_CLKOUT_PINMUX_BYP | ULPI_OUTPUT_PINMUX_BYP);
 
 	/* Select ULPI parallel interface */
-#if defined(CONFIG_TEGRA20)
-	clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK,
-			PTS_ULPI << PTS_SHIFT);
-#else
-	clrsetbits_le32(&usbctlr->hostpc1_devlc, PTS_MASK,
-			PTS_ULPI << PTS_SHIFT);
-#endif
+	init_phy_mux(config, PTS_ULPI, init);
 
 	/* enable ULPI transceiver */
 	setbits_le32(&usbctlr->susp_ctrl, ULPI_PHY_ENB);
@@ -612,7 +634,8 @@
 	return 0;
 }
 #else
-static int init_ulpi_usb_controller(struct fdt_usb *config)
+static int init_ulpi_usb_controller(struct fdt_usb *config,
+				    enum usb_init_type init)
 {
 	printf("No code to set up ULPI controller, please enable"
 			"CONFIG_USB_ULPI and CONFIG_USB_ULPI_VIEWPORT");
@@ -765,42 +788,66 @@
 
 	config = &port[index];
 
+	switch (init) {
+	case USB_INIT_HOST:
+		switch (config->dr_mode) {
+		case DR_MODE_HOST:
+		case DR_MODE_OTG:
+			break;
+		default:
+			printf("tegrausb: Invalid dr_mode %d for host mode\n",
+			       config->dr_mode);
+			return -1;
+		}
+		break;
+	case USB_INIT_DEVICE:
+		if (config->periph_id != PERIPH_ID_USBD) {
+			printf("tegrausb: Device mode only supported on first USB controller\n");
+			return -1;
+		}
+		if (!config->utmi) {
+			printf("tegrausb: Device mode only supported with UTMI PHY\n");
+			return -1;
+		}
+		switch (config->dr_mode) {
+		case DR_MODE_DEVICE:
+		case DR_MODE_OTG:
+			break;
+		default:
+			printf("tegrausb: Invalid dr_mode %d for device mode\n",
+			       config->dr_mode);
+			return -1;
+		}
+		break;
+	default:
+		printf("tegrausb: Unknown USB_INIT_* %d\n", init);
+		return -1;
+	}
+
 	/* skip init, if the port is already initialized */
-	if (config->initialized)
+	if (config->initialized && config->init_type == init)
 		goto success;
 
-	if (config->utmi && init_utmi_usb_controller(config)) {
+	if (config->utmi && init_utmi_usb_controller(config, init)) {
 		printf("tegrausb: Cannot init port %d\n", index);
 		return -1;
 	}
 
-	if (config->ulpi && init_ulpi_usb_controller(config)) {
+	if (config->ulpi && init_ulpi_usb_controller(config, init)) {
 		printf("tegrausb: Cannot init port %d\n", index);
 		return -1;
 	}
 
-	set_host_mode(config);
+	set_up_vbus(config, init);
 
 	config->initialized = 1;
+	config->init_type = init;
 
 success:
 	usbctlr = config->reg;
 	*hccr = (struct ehci_hccr *)&usbctlr->cap_length;
 	*hcor = (struct ehci_hcor *)&usbctlr->usb_cmd;
 
-	if (controller->has_hostpc) {
-		/* Set to Host mode after Controller Reset was done */
-		clrsetbits_le32(&usbctlr->usb_mode, USBMODE_CM_HC,
-				USBMODE_CM_HC);
-		/* Select UTMI parallel interface after setting host mode */
-		if (config->utmi) {
-			clrsetbits_le32((char *)&usbctlr->usb_cmd +
-					HOSTPC1_DEVLC, PTS_MASK,
-					PTS_UTMI << PTS_SHIFT);
-			clrbits_le32((char *)&usbctlr->usb_cmd +
-				     HOSTPC1_DEVLC, STS);
-		}
-	}
 	return 0;
 }
 
diff --git a/drivers/usb/host/ehci-zynq.c b/drivers/usb/host/ehci-zynq.c
new file mode 100644
index 0000000..7770d05
--- /dev/null
+++ b/drivers/usb/host/ehci-zynq.c
@@ -0,0 +1,104 @@
+/*
+ * (C) Copyright 2014, Xilinx, Inc
+ *
+ * USB Low level initialization(Specific to zynq)
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/io.h>
+#include <usb.h>
+#include <usb/ehci-fsl.h>
+#include <usb/ulpi.h>
+
+#include "ehci.h"
+
+#define ZYNQ_USB_USBCMD_RST			0x0000002
+#define ZYNQ_USB_USBCMD_STOP			0x0000000
+#define ZYNQ_USB_NUM_MIO			12
+
+/*
+ * Create the appropriate control structures to manage
+ * a new EHCI host controller.
+ */
+int ehci_hcd_init(int index,  enum usb_init_type init, struct ehci_hccr **hccr,
+		  struct ehci_hcor **hcor)
+{
+	struct usb_ehci *ehci;
+	struct ulpi_viewport ulpi_vp;
+	int ret, mio_usb;
+	/* Used for writing the ULPI data address */
+	struct ulpi_regs *ulpi = (struct ulpi_regs *)0;
+
+	if (!index) {
+		mio_usb = zynq_slcr_get_mio_pin_status("usb0");
+		if (mio_usb != ZYNQ_USB_NUM_MIO) {
+			printf("usb0 wrong num MIO: %d, Index %d\n", mio_usb,
+			       index);
+			return -1;
+		}
+		ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR0;
+	} else {
+		mio_usb = zynq_slcr_get_mio_pin_status("usb1");
+		if (mio_usb != ZYNQ_USB_NUM_MIO) {
+			printf("usb1 wrong num MIO: %d, Index %d\n", mio_usb,
+			       index);
+			return -1;
+		}
+		ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR1;
+	}
+
+	*hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
+	*hcor = (struct ehci_hcor *)((uint32_t) *hccr +
+			HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
+
+	ulpi_vp.viewport_addr = (u32)&ehci->ulpi_viewpoint;
+	ulpi_vp.port_num = 0;
+
+	ret = ulpi_init(&ulpi_vp);
+	if (ret) {
+		puts("zynq ULPI viewport init failed\n");
+		return -1;
+	}
+
+	/* ULPI set flags */
+	ulpi_write(&ulpi_vp, &ulpi->otg_ctrl,
+		   ULPI_OTG_DP_PULLDOWN | ULPI_OTG_DM_PULLDOWN |
+		   ULPI_OTG_EXTVBUSIND);
+	ulpi_write(&ulpi_vp, &ulpi->function_ctrl,
+		   ULPI_FC_FULL_SPEED | ULPI_FC_OPMODE_NORMAL |
+		   ULPI_FC_SUSPENDM);
+	ulpi_write(&ulpi_vp, &ulpi->iface_ctrl, 0);
+
+	/* Set VBus */
+	ulpi_write(&ulpi_vp, &ulpi->otg_ctrl_set,
+		   ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+
+	return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding
+ * the the EHCI host controller.
+ */
+int ehci_hcd_stop(int index)
+{
+	struct usb_ehci *ehci;
+
+	if (!index)
+		ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR0;
+	else
+		ehci = (struct usb_ehci *)ZYNQ_USB_BASEADDR1;
+
+	/* Stop controller */
+	writel(ZYNQ_USB_USBCMD_STOP, &ehci->usbcmd);
+	udelay(1000);
+
+	/* Initiate controller reset */
+	writel(ZYNQ_USB_USBCMD_RST, &ehci->usbcmd);
+
+	return 0;
+}
diff --git a/drivers/usb/musb-new/musb_gadget_ep0.c b/drivers/usb/musb-new/musb_gadget_ep0.c
index 6599d38..8c3b0a1 100644
--- a/drivers/usb/musb-new/musb_gadget_ep0.c
+++ b/drivers/usb/musb-new/musb_gadget_ep0.c
@@ -576,6 +576,10 @@
 	} else
 		request = NULL;
 
+	/* send it out, triggering a "txpktrdy cleared" irq */
+	musb_ep_select(musb->mregs, 0);
+	musb_writew(regs, MUSB_CSR0, csr);
+
 	/* report completions as soon as the fifo's loaded; there's no
 	 * win in waiting till this last packet gets acked.  (other than
 	 * very precise fault reporting, needed by USB TMC; possible with
@@ -588,10 +592,6 @@
 			return;
 		musb->ackpend = 0;
 	}
-
-	/* send it out, triggering a "txpktrdy cleared" irq */
-	musb_ep_select(musb->mregs, 0);
-	musb_writew(regs, MUSB_CSR0, csr);
 }
 
 /*
diff --git a/include/android_image.h b/include/android_image.h
new file mode 100644
index 0000000..094d60a
--- /dev/null
+++ b/include/android_image.h
@@ -0,0 +1,69 @@
+/*
+ * This is from the Android Project,
+ * Repository: https://android.googlesource.com/platform/bootable/bootloader/legacy
+ * File: include/boot/bootimg.h
+ * Commit: 4205b865141ff2e255fe1d3bd16de18e217ef06a
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _ANDROID_IMAGE_H_
+#define _ANDROID_IMAGE_H_
+
+#define ANDR_BOOT_MAGIC "ANDROID!"
+#define ANDR_BOOT_MAGIC_SIZE 8
+#define ANDR_BOOT_NAME_SIZE 16
+#define ANDR_BOOT_ARGS_SIZE 512
+
+struct andr_img_hdr {
+	char magic[ANDR_BOOT_MAGIC_SIZE];
+
+	u32 kernel_size;	/* size in bytes */
+	u32 kernel_addr;	/* physical load addr */
+
+	u32 ramdisk_size;	/* size in bytes */
+	u32 ramdisk_addr;	/* physical load addr */
+
+	u32 second_size;	/* size in bytes */
+	u32 second_addr;	/* physical load addr */
+
+	u32 tags_addr;		/* physical addr for kernel tags */
+	u32 page_size;		/* flash page size we assume */
+	u32 unused[2];		/* future expansion: should be 0 */
+
+	char name[ANDR_BOOT_NAME_SIZE]; /* asciiz product name */
+
+	char cmdline[ANDR_BOOT_ARGS_SIZE];
+
+	u32 id[8]; /* timestamp / checksum / sha1 / etc */
+};
+
+/*
+ * +-----------------+
+ * | boot header     | 1 page
+ * +-----------------+
+ * | kernel          | n pages
+ * +-----------------+
+ * | ramdisk         | m pages
+ * +-----------------+
+ * | second stage    | o pages
+ * +-----------------+
+ *
+ * n = (kernel_size + page_size - 1) / page_size
+ * m = (ramdisk_size + page_size - 1) / page_size
+ * o = (second_size + page_size - 1) / page_size
+ *
+ * 0. all entities are page_size aligned in flash
+ * 1. kernel and ramdisk are required (size != 0)
+ * 2. second is optional (second_size == 0 -> no second)
+ * 3. load each element (kernel, ramdisk, second) at
+ *    the specified physical address (kernel_addr, etc)
+ * 4. prepare tags at tag_addr.  kernel_args[] is
+ *    appended to the kernel commandline in the tags.
+ * 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
+ * 6. if second_size != 0: jump to second_addr
+ *    else: jump to kernel_addr
+ */
+#endif
diff --git a/include/common.h b/include/common.h
index 13e5dc7..232136c 100644
--- a/include/common.h
+++ b/include/common.h
@@ -836,7 +836,7 @@
 int	had_ctrlc (void);	/* have we had a Control-C since last clear? */
 void	clear_ctrlc (void);	/* clear the Control-C condition */
 int	disable_ctrlc (int);	/* 1 to disable, 0 to enable Control-C detect */
-
+int confirm_yesno(void);        /*  1 if input is "y", "Y", "yes" or "YES" */
 /*
  * STDIO based functions (can always be used)
  */
diff --git a/include/configs/GEN860T.h b/include/configs/GEN860T.h
index 2822a08..fd6c976 100644
--- a/include/configs/GEN860T.h
+++ b/include/configs/GEN860T.h
@@ -219,6 +219,7 @@
 #define CONFIG_CMD_ELF
 #define CONFIG_CMD_DATE
 #define CONFIG_CMD_FPGA
+#define CONFIG_CMD_FPGA_LOADMK
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_BEDBUG
 
diff --git a/include/configs/MVBC_P.h b/include/configs/MVBC_P.h
index 036396c..1ab2b3d 100644
--- a/include/configs/MVBC_P.h
+++ b/include/configs/MVBC_P.h
@@ -89,6 +89,7 @@
 #define CONFIG_CMD_SDRAM
 #define CONFIG_CMD_PCI
 #define CONFIG_CMD_FPGA
+#define CONFIG_CMD_FPGA_LOADMK
 #define CONFIG_CMD_I2C
 
 #undef CONFIG_WATCHDOG
diff --git a/include/configs/MVBLM7.h b/include/configs/MVBLM7.h
index 27c2fa0..1ee4d7c 100644
--- a/include/configs/MVBLM7.h
+++ b/include/configs/MVBLM7.h
@@ -267,6 +267,7 @@
 #define CONFIG_CMD_PCI
 #define CONFIG_CMD_I2C
 #define CONFIG_CMD_FPGA
+#define CONFIG_CMD_FPGA_LOADMK
 #define CONFIG_CMD_USB
 #define CONFIG_DOS_PARTITION
 
diff --git a/include/configs/MVSMR.h b/include/configs/MVSMR.h
index ad15506..27f730d 100644
--- a/include/configs/MVSMR.h
+++ b/include/configs/MVSMR.h
@@ -74,6 +74,7 @@
 #define CONFIG_CMD_CACHE
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_FPGA
+#define CONFIG_CMD_FPGA_LOADMK
 #define CONFIG_CMD_I2C
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_NET
diff --git a/include/configs/alpr.h b/include/configs/alpr.h
index 7849b22..2782e55 100644
--- a/include/configs/alpr.h
+++ b/include/configs/alpr.h
@@ -222,6 +222,7 @@
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_EEPROM
 #define CONFIG_CMD_FPGA
+#define CONFIG_CMD_FPGA_LOADMK
 #define CONFIG_CMD_I2C
 #undef CONFIG_CMD_LOADB
 #undef CONFIG_CMD_LOADS
diff --git a/include/configs/armadillo-800eva.h b/include/configs/armadillo-800eva.h
index 17a2da0..8bb932c 100644
--- a/include/configs/armadillo-800eva.h
+++ b/include/configs/armadillo-800eva.h
@@ -48,6 +48,7 @@
 #define CONFIG_USE_ARCH_MEMCPY
 #define CONFIG_TMU_TIMER
 #define CONFIG_SYS_DCACHE_OFF
+#define CONFIG_SYS_GENERIC_BOARD
 
 /* STACK */
 #define CONFIG_SYS_INIT_SP_ADDR		0xE8083000
diff --git a/include/configs/astro_mcf5373l.h b/include/configs/astro_mcf5373l.h
index d875753..fa64a68 100644
--- a/include/configs/astro_mcf5373l.h
+++ b/include/configs/astro_mcf5373l.h
@@ -88,6 +88,7 @@
 #define CONFIG_CMD_LOADS
 #define CONFIG_CMD_LOADB
 #define CONFIG_CMD_FPGA
+#define CONFIG_CMD_FPGA_LOADMK
 #define CONFIG_CMDLINE_EDITING
 
 #define CONFIG_SYS_HUSH_PARSER
diff --git a/include/configs/balloon3.h b/include/configs/balloon3.h
index 5228ba6..2f5a660 100644
--- a/include/configs/balloon3.h
+++ b/include/configs/balloon3.h
@@ -54,6 +54,7 @@
 #undef	CONFIG_CMD_IMLS
 #define	CONFIG_CMD_USB
 #define	CONFIG_CMD_FPGA
+#define	CONFIG_CMD_FPGA_LOADMK
 #undef	CONFIG_LCD
 
 /*
diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h
index d1d732f..a1a63a0 100644
--- a/include/configs/coreboot.h
+++ b/include/configs/coreboot.h
@@ -167,6 +167,7 @@
 #define CONFIG_CMD_ECHO
 #undef CONFIG_CMD_FLASH
 #define CONFIG_CMD_FPGA
+#define CONFIG_CMD_FPGA_LOADMK
 #define CONFIG_CMD_GPIO
 #define CONFIG_CMD_IMI
 #undef CONFIG_CMD_IMLS
diff --git a/include/configs/grsim.h b/include/configs/grsim.h
index 556c749..1e089a9 100644
--- a/include/configs/grsim.h
+++ b/include/configs/grsim.h
@@ -53,6 +53,7 @@
 #define CONFIG_CMD_DIAG
 #define CONFIG_CMD_ECHO		/* echo arguments		*/
 #define CONFIG_CMD_FPGA		/* FPGA configuration Support	*/
+#define CONFIG_CMD_FPGA_LOADMK
 #define CONFIG_CMD_IRQ
 #define CONFIG_CMD_ITEST	/* Integer (and string) test	*/
 #define CONFIG_CMD_LOADB	/* loadb			*/
diff --git a/include/configs/grsim_leon2.h b/include/configs/grsim_leon2.h
index 8be9898..66194a8 100644
--- a/include/configs/grsim_leon2.h
+++ b/include/configs/grsim_leon2.h
@@ -51,6 +51,7 @@
 #define CONFIG_CMD_DIAG
 #define CONFIG_CMD_ECHO		/* echo arguments		*/
 #define CONFIG_CMD_FPGA		/* FPGA configuration Support	*/
+#define CONFIG_CMD_FPGA_LOADMK
 #define CONFIG_CMD_IRQ
 #define CONFIG_CMD_ITEST	/* Integer (and string) test	*/
 #define CONFIG_CMD_LOADB	/* loadb			*/
diff --git a/include/configs/iocon.h b/include/configs/iocon.h
index f36c2a3..79c4736 100644
--- a/include/configs/iocon.h
+++ b/include/configs/iocon.h
@@ -62,7 +62,8 @@
  * Commands additional to the ones defined in amcc-common.h
  */
 #define CONFIG_CMD_CACHE
-#define CONFIG_CMD_FPGAD
+#define CONFIG_CMD_FPGA
+#define CONFIG_CMD_FPGA_LOADMK
 #undef CONFIG_CMD_EEPROM
 
 /*
diff --git a/include/configs/koelsch.h b/include/configs/koelsch.h
index 1a93d17..6795f28 100644
--- a/include/configs/koelsch.h
+++ b/include/configs/koelsch.h
@@ -31,10 +31,22 @@
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_NFS
 #define CONFIG_CMD_BOOTZ
-
+#define CONFIG_CMD_USB
+#define CONFIG_CMD_FAT
 #define CONFIG_CMD_SF
 #define CONFIG_CMD_SPI
+
+#define CONFIG_FAT_WRITE
+#define CONFIG_EXT4_WRITE
+
 #define CONFIG_SYS_TEXT_BASE	0xE6304000
+#define CONFIG_SYS_THUMB_BUILD
+#define CONFIG_SYS_GENERIC_BOARD
+
+/* Support File sytems */
+#define CONFIG_DOS_PARTITION
+#define CONFIG_SUPPORT_VFAT
+
 
 #define	CONFIG_CMDLINE_TAG
 #define	CONFIG_SETUP_MEMORY_TAGS
@@ -55,8 +67,6 @@
 #define CONFIG_DISPLAY_CPUINFO
 #define CONFIG_DISPLAY_BOARDINFO
 #define CONFIG_BOARD_EARLY_INIT_F
-#define CONFIG_USE_ARCH_MEMSET
-#define CONFIG_USE_ARCH_MEMCPY
 #define CONFIG_TMU_TIMER
 
 /* STACK */
@@ -80,7 +90,6 @@
 /* SCIF */
 #define CONFIG_SCIF_CONSOLE
 #define CONFIG_CONS_SCIF0
-#define SCIF0_BASE		0xe6e60000
 #undef	CONFIG_SYS_CONSOLE_INFO_QUIET
 #undef	CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
 #undef	CONFIG_SYS_CONSOLE_ENV_OVERWRITE
@@ -159,4 +168,10 @@
 
 #define CONFIG_SYS_I2C_POWERIC_ADDR 0x58 /* da9063 */
 
+/* USB */
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_RMOBILE
+#define CONFIG_USB_MAX_CONTROLLER_COUNT	3
+#define CONFIG_USB_STORAGE
+
 #endif	/* __KOELSCH_H */
diff --git a/include/configs/kwb.h b/include/configs/kwb.h
index 0f631c0..0860434 100644
--- a/include/configs/kwb.h
+++ b/include/configs/kwb.h
@@ -109,7 +109,7 @@
 
 #undef CONFIG_ENV_IS_NOWHERE
 #define CONFIG_ENV_IS_IN_MMC
-#define CONFIG_SYS_MMC_ENV_DEV		1
+#define CONFIG_SYS_MMC_ENV_DEV		0
 #define CONFIG_SYS_MMC_ENV_PART		2
 #define CONFIG_ENV_OFFSET		0x40000	/* TODO: Adresse definieren */
 #define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
diff --git a/include/configs/lager.h b/include/configs/lager.h
index ac31128..f39a788 100644
--- a/include/configs/lager.h
+++ b/include/configs/lager.h
@@ -32,10 +32,21 @@
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_NFS
 #define CONFIG_CMD_BOOTZ
-
+#define CONFIG_CMD_USB
+#define CONFIG_CMD_FAT
 #define CONFIG_CMD_SF
 #define CONFIG_CMD_SPI
+
+#define CONFIG_FAT_WRITE
+#define CONFIG_EXT4_WRITE
+
 #define CONFIG_SYS_TEXT_BASE	0xE8080000
+#define CONFIG_SYS_THUMB_BUILD
+#define CONFIG_SYS_GENERIC_BOARD
+
+/* Support File sytems */
+#define CONFIG_DOS_PARTITION
+#define CONFIG_SUPPORT_VFAT
 
 #define	CONFIG_CMDLINE_TAG
 #define	CONFIG_SETUP_MEMORY_TAGS
@@ -57,8 +68,6 @@
 #define CONFIG_DISPLAY_CPUINFO
 #define CONFIG_DISPLAY_BOARDINFO
 #define CONFIG_BOARD_EARLY_INIT_F
-#define CONFIG_USE_ARCH_MEMSET
-#define CONFIG_USE_ARCH_MEMCPY
 #define CONFIG_TMU_TIMER
 
 /* STACK */
@@ -82,7 +91,6 @@
 /* SCIF */
 #define CONFIG_SCIF_CONSOLE
 #define CONFIG_CONS_SCIF0
-#define SCIF0_BASE		0xe6e60000
 #undef	CONFIG_SYS_CONSOLE_INFO_QUIET
 #undef	CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
 #undef	CONFIG_SYS_CONSOLE_ENV_OVERWRITE
@@ -164,4 +172,10 @@
 
 #define CONFIG_SYS_TMU_CLK_DIV	4
 
+/* USB */
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_RMOBILE
+#define CONFIG_USB_MAX_CONTROLLER_COUNT	4
+#define CONFIG_USB_STORAGE
+
 #endif	/* __LAGER_H */
diff --git a/include/configs/mt_ventoux.h b/include/configs/mt_ventoux.h
index e7afd07..01e395a 100644
--- a/include/configs/mt_ventoux.h
+++ b/include/configs/mt_ventoux.h
@@ -49,6 +49,7 @@
  * FPGA
  */
 #define CONFIG_CMD_FPGA
+#define CONFIG_CMD_FPGA_LOADMK
 #define CONFIG_FPGA
 #define CONFIG_FPGA_XILINX
 #define CONFIG_FPGA_SPARTAN3
diff --git a/include/configs/omap3_beagle.h b/include/configs/omap3_beagle.h
index d07e52df..0a7df60 100644
--- a/include/configs/omap3_beagle.h
+++ b/include/configs/omap3_beagle.h
@@ -66,6 +66,16 @@
 #define CONFIG_TWL4030_USB		1
 #define CONFIG_USB_ETHER
 #define CONFIG_USB_ETHER_RNDIS
+#define CONFIG_USB_GADGET
+#define CONFIG_USB_GADGET_VBUS_DRAW	0
+#define CONFIG_USBDOWNLOAD_GADGET
+#define CONFIG_G_DNL_VENDOR_NUM		0x0451
+#define CONFIG_G_DNL_PRODUCT_NUM	0xd022
+#define CONFIG_G_DNL_MANUFACTURER	"TI"
+#define CONFIG_CMD_FASTBOOT
+#define CONFIG_ANDROID_BOOT_IMAGE
+#define CONFIG_USB_FASTBOOT_BUF_ADDR	CONFIG_SYS_LOAD_ADDR
+#define CONFIG_USB_FASTBOOT_BUF_SIZE	0x07000000
 
 /* USB EHCI */
 #define CONFIG_CMD_USB
diff --git a/include/configs/omap3_mvblx.h b/include/configs/omap3_mvblx.h
index 8d11010..a3dcb15 100644
--- a/include/configs/omap3_mvblx.h
+++ b/include/configs/omap3_mvblx.h
@@ -127,6 +127,7 @@
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_PING
 #define CONFIG_CMD_FPGA
+#define CONFIG_CMD_FPGA_LOADMK
 
 #define CONFIG_SYS_I2C
 #define CONFIG_SYS_OMAP24_I2C_SPEED	100000
diff --git a/include/configs/tseries.h b/include/configs/tseries.h
index 8fb87ac..e550afa 100644
--- a/include/configs/tseries.h
+++ b/include/configs/tseries.h
@@ -237,7 +237,7 @@
 #elif defined(CONFIG_EMMC_BOOT)
 #undef CONFIG_ENV_IS_NOWHERE
 #define CONFIG_ENV_IS_IN_MMC
-#define CONFIG_SYS_MMC_ENV_DEV		1
+#define CONFIG_SYS_MMC_ENV_DEV		0
 #define CONFIG_SYS_MMC_ENV_PART		2
 #define CONFIG_ENV_OFFSET		0x40000	/* TODO: Adresse definieren */
 #define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
diff --git a/include/configs/x600.h b/include/configs/x600.h
index 7405419..eae85d6 100644
--- a/include/configs/x600.h
+++ b/include/configs/x600.h
@@ -107,6 +107,7 @@
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_ENV
 #define CONFIG_CMD_FPGA
+#define CONFIG_CMD_FPGA_LOADMK
 #define CONFIG_CMD_GPIO
 #define CONFIG_CMD_I2C
 #define CONFIG_CMD_MEMORY
diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h
index 731e69b..dc5bc22 100644
--- a/include/configs/zynq-common.h
+++ b/include/configs/zynq-common.h
@@ -83,10 +83,27 @@
 # define CONFIG_SDHCI
 # define CONFIG_ZYNQ_SDHCI
 # define CONFIG_CMD_MMC
-# define CONFIG_CMD_FAT
+#endif
+
+#ifdef CONFIG_ZYNQ_USB
+# define CONFIG_USB_EHCI
+# define CONFIG_CMD_USB
+# define CONFIG_USB_STORAGE
+# define CONFIG_USB_EHCI_ZYNQ
+# define CONFIG_USB_ULPI_VIEWPORT
+# define CONFIG_USB_ULPI
+# define CONFIG_EHCI_IS_TDI
+# define CONFIG_USB_MAX_CONTROLLER_COUNT	2
+#endif
+
+#if defined(CONFIG_ZYNQ_SDHCI) || defined(CONFIG_ZYNQ_USB)
 # define CONFIG_SUPPORT_VFAT
+# define CONFIG_CMD_FAT
 # define CONFIG_CMD_EXT2
+# define CONFIG_FAT_WRITE
 # define CONFIG_DOS_PARTITION
+# define CONFIG_CMD_EXT4
+# define CONFIG_CMD_EXT4_WRITE
 #endif
 
 #define CONFIG_SYS_I2C_ZYNQ
@@ -150,7 +167,13 @@
 		"bootm ${load_addr}\0" \
 	"jtagboot=echo TFTPing FIT to RAM... && " \
 		"tftpboot ${load_addr} ${fit_image} && " \
-		"bootm ${load_addr}\0"
+		"bootm ${load_addr}\0" \
+	"usbboot=if usb start; then " \
+			"echo Copying FIT from USB to RAM... && " \
+			"fatload usb 0 ${load_addr} ${fit_image} && " \
+			"bootm ${load_addr}\0" \
+		"fi\0"
+
 #define CONFIG_BOOTCOMMAND		"run $modeboot"
 #define CONFIG_BOOTDELAY		3 /* -1 to Disable autoboot */
 #define CONFIG_SYS_LOAD_ADDR		0 /* default? */
@@ -165,7 +188,7 @@
 #define CONFIG_SYS_LONGHELP
 #define CONFIG_CLOCKS
 #define CONFIG_CMD_CLK
-#define CONFIG_SYS_MAXARGS		15 /* max number of command args */
+#define CONFIG_SYS_MAXARGS		32 /* max number of command args */
 #define CONFIG_SYS_CBSIZE		256 /* Console I/O Buffer Size */
 #define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
 					sizeof(CONFIG_SYS_PROMPT) + 16)
@@ -191,6 +214,10 @@
 #define CONFIG_FPGA_XILINX
 #define CONFIG_FPGA_ZYNQPL
 #define CONFIG_CMD_FPGA
+#define CONFIG_CMD_FPGA_LOADMK
+#define CONFIG_CMD_FPGA_LOADP
+#define CONFIG_CMD_FPGA_LOADBP
+#define CONFIG_CMD_FPGA_LOADFS
 
 /* Open Firmware flat tree */
 #define CONFIG_OF_LIBFDT
@@ -209,7 +236,7 @@
 #define CONFIG_RSA
 
 /* Extend size of kernel image for uncompression */
-#define CONFIG_SYS_BOOTM_LEN	(20 * 1024 * 1024)
+#define CONFIG_SYS_BOOTM_LEN	(60 * 1024 * 1024)
 
 /* Boot FreeBSD/vxWorks from an ELF image */
 #if defined(CONFIG_ZYNQ_BOOT_FREEBSD)
@@ -235,16 +262,10 @@
 #define CONFIG_SPL_LIBCOMMON_SUPPORT
 #define CONFIG_SPL_LIBGENERIC_SUPPORT
 #define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_BOARD_INIT
 
 #define CONFIG_SPL_LDSCRIPT	"arch/arm/cpu/armv7/zynq/u-boot-spl.lds"
 
-/* Disable dcache for SPL just for sure */
-#ifdef CONFIG_SPL_BUILD
-#define CONFIG_SYS_DCACHE_OFF
-#undef CONFIG_FPGA
-#undef CONFIG_OF_CONTROL
-#endif
-
 /* MMC support */
 #ifdef CONFIG_ZYNQ_SDHCI0
 #define CONFIG_SPL_MMC_SUPPORT
@@ -253,7 +274,18 @@
 #define CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION    1
 #define CONFIG_SPL_LIBDISK_SUPPORT
 #define CONFIG_SPL_FAT_SUPPORT
-#define CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME     "u-boot.img"
+#if defined(CONFIG_OF_CONTROL) && defined(CONFIG_OF_SEPARATE)
+# define CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME     "u-boot-dtb.img"
+#else
+# define CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME     "u-boot.img"
+#endif
+#endif
+
+/* Disable dcache for SPL just for sure */
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_DCACHE_OFF
+#undef CONFIG_FPGA
+#undef CONFIG_OF_CONTROL
 #endif
 
 /* Address in RAM where the parameters must be copied by SPL. */
diff --git a/include/configs/zynq_zc70x.h b/include/configs/zynq_zc70x.h
index de0e241..291a5fe 100644
--- a/include/configs/zynq_zc70x.h
+++ b/include/configs/zynq_zc70x.h
@@ -19,6 +19,7 @@
 #define CONFIG_SYS_NO_FLASH
 
 #define CONFIG_ZYNQ_SDHCI0
+#define CONFIG_ZYNQ_USB
 #define CONFIG_ZYNQ_I2C0
 #define CONFIG_ZYNQ_EEPROM
 #define CONFIG_ZYNQ_BOOT_FREEBSD
diff --git a/include/configs/zynq_zed.h b/include/configs/zynq_zed.h
index 274140c..ce17d40 100644
--- a/include/configs/zynq_zed.h
+++ b/include/configs/zynq_zed.h
@@ -18,6 +18,7 @@
 
 #define CONFIG_SYS_NO_FLASH
 
+#define CONFIG_ZYNQ_USB
 #define CONFIG_ZYNQ_SDHCI0
 #define CONFIG_ZYNQ_BOOT_FREEBSD
 #define CONFIG_DEFAULT_DEVICE_TREE	zynq-zed
diff --git a/include/dfu.h b/include/dfu.h
index 2409168..26ffbc8 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -43,6 +43,9 @@
 	unsigned int lba_size;
 	unsigned int lba_blk_size;
 
+	/* eMMC HW partition access */
+	int hw_partition;
+
 	/* FAT/EXT */
 	unsigned int dev;
 	unsigned int part;
@@ -100,6 +103,7 @@
 			u64 offset, void *buf, long *len);
 
 	int (*flush_medium)(struct dfu_entity *dfu);
+	unsigned int (*poll_timeout)(struct dfu_entity *dfu);
 
 	struct list_head list;
 
diff --git a/include/fpga.h b/include/fpga.h
index 15e603a..914024c 100644
--- a/include/fpga.h
+++ b/include/fpga.h
@@ -35,13 +35,29 @@
 	void *devdesc;		/* real device descriptor */
 } fpga_desc;			/* end, typedef fpga_desc */
 
+typedef struct {                /* typedef fpga_desc */
+	unsigned int blocksize;
+	char *interface;
+	char *dev_part;
+	char *filename;
+	int fstype;
+} fpga_fs_info;
+
+typedef enum {
+	BIT_FULL = 0,
+	BIT_PARTIAL,
+} bitstream_type;
 
 /* root function definitions */
 extern void fpga_init(void);
 extern int fpga_add(fpga_type devtype, void *desc);
 extern int fpga_count(void);
-extern int fpga_load(int devnum, const void *buf, size_t bsize);
-extern int fpga_loadbitstream(int devnum, char *fpgadata, size_t size);
+extern int fpga_load(int devnum, const void *buf, size_t bsize,
+		     bitstream_type bstype);
+extern int fpga_fsload(int devnum, const void *buf, size_t size,
+		       fpga_fs_info *fpga_fsinfo);
+extern int fpga_loadbitstream(int devnum, char *fpgadata, size_t size,
+			      bitstream_type bstype);
 extern int fpga_dump(int devnum, const void *buf, size_t bsize);
 extern int fpga_info(int devnum);
 extern const fpga_desc *const fpga_validate(int devnum, const void *buf,
diff --git a/include/image.h b/include/image.h
index b278778..1886168 100644
--- a/include/image.h
+++ b/include/image.h
@@ -413,6 +413,7 @@
 #define IMAGE_FORMAT_INVALID	0x00
 #define IMAGE_FORMAT_LEGACY	0x01	/* legacy image_header based format */
 #define IMAGE_FORMAT_FIT	0x02	/* new, libfdt based format */
+#define IMAGE_FORMAT_ANDROID	0x03	/* Android boot image */
 
 int genimg_get_format(const void *img_addr);
 int genimg_has_config(bootm_headers_t *images);
@@ -1031,4 +1032,16 @@
 #endif /* CONFIG_FIT_VERBOSE */
 #endif /* CONFIG_FIT */
 
+#if defined(CONFIG_ANDROID_BOOT_IMAGE)
+struct andr_img_hdr;
+int android_image_check_header(const struct andr_img_hdr *hdr);
+int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
+			     ulong *os_data, ulong *os_len);
+int android_image_get_ramdisk(const struct andr_img_hdr *hdr,
+			      ulong *rd_data, ulong *rd_len);
+ulong android_image_get_end(const struct andr_img_hdr *hdr);
+ulong android_image_get_kload(const struct andr_img_hdr *hdr);
+
+#endif /* CONFIG_ANDROID_BOOT_IMAGE */
+
 #endif	/* __IMAGE_H__ */
diff --git a/include/mmc.h b/include/mmc.h
index bc11f45..a3a100b 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -54,6 +54,7 @@
 #define COMM_ERR		-18 /* Communications Error */
 #define TIMEOUT			-19
 #define IN_PROGRESS		-20 /* operation is in progress */
+#define SWITCH_ERR		-21 /* Card reports failure to switch mode */
 
 #define MMC_CMD_GO_IDLE_STATE		0
 #define MMC_CMD_SEND_OP_COND		1
@@ -70,6 +71,7 @@
 #define MMC_CMD_SET_BLOCKLEN		16
 #define MMC_CMD_READ_SINGLE_BLOCK	17
 #define MMC_CMD_READ_MULTIPLE_BLOCK	18
+#define MMC_CMD_SET_BLOCK_COUNT         23
 #define MMC_CMD_WRITE_SINGLE_BLOCK	24
 #define MMC_CMD_WRITE_MULTIPLE_BLOCK	25
 #define MMC_CMD_ERASE_GROUP_START	35
@@ -109,6 +111,7 @@
 #define SECURE_ERASE		0x80000000
 
 #define MMC_STATUS_MASK		(~0x0206BF7F)
+#define MMC_STATUS_SWITCH_ERROR	(1 << 7)
 #define MMC_STATUS_RDY_FOR_DATA (1 << 8)
 #define MMC_STATUS_CURR_STATE	(0xf << 9)
 #define MMC_STATUS_ERROR	(1 << 19)
@@ -225,6 +228,7 @@
  * boot partitions (2), general purpose partitions (4) in MMC v4.4.
  */
 #define MMC_NUM_BOOT_PARTITION	2
+#define MMC_PART_RPMB           3       /* RPMB partition number */
 
 struct mmc_cid {
 	unsigned long psn;
@@ -336,7 +340,13 @@
 int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode);
 /* Function to modify the RST_n_FUNCTION field of EXT_CSD */
 int mmc_set_rst_n_function(struct mmc *mmc, u8 enable);
-
+/* Functions to read / write the RPMB partition */
+int mmc_rpmb_set_key(struct mmc *mmc, void *key);
+int mmc_rpmb_get_counter(struct mmc *mmc, unsigned long *counter);
+int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk,
+		  unsigned short cnt, unsigned char *key);
+int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
+		   unsigned short cnt, unsigned char *key);
 /**
  * Start device initialization and return immediately; it does not block on
  * polling OCR (operation condition register) status.  Then you should call
diff --git a/include/part.h b/include/part.h
index 53532dc..f2c8c64 100644
--- a/include/part.h
+++ b/include/part.h
@@ -103,6 +103,7 @@
 block_dev_desc_t* scsi_get_dev(int dev);
 block_dev_desc_t* usb_stor_get_dev(int dev);
 block_dev_desc_t* mmc_get_dev(int dev);
+int mmc_select_hwpart(int dev_num, int hwpart);
 block_dev_desc_t* systemace_get_dev(int dev);
 block_dev_desc_t* mg_disk_get_dev(int dev);
 block_dev_desc_t *host_get_dev(int dev);
@@ -126,6 +127,7 @@
 static inline block_dev_desc_t* scsi_get_dev(int dev) { return NULL; }
 static inline block_dev_desc_t* usb_stor_get_dev(int dev) { return NULL; }
 static inline block_dev_desc_t* mmc_get_dev(int dev) { return NULL; }
+static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; }
 static inline block_dev_desc_t* systemace_get_dev(int dev) { return NULL; }
 static inline block_dev_desc_t* mg_disk_get_dev(int dev) { return NULL; }
 static inline block_dev_desc_t *host_get_dev(int dev) { return NULL; }
diff --git a/include/usb_mass_storage.h b/include/usb_mass_storage.h
index ed46064..69b80cd 100644
--- a/include/usb_mass_storage.h
+++ b/include/usb_mass_storage.h
@@ -9,17 +9,9 @@
 #define __USB_MASS_STORAGE_H__
 
 #define SECTOR_SIZE		0x200
-#include <mmc.h>
+#include <part.h>
 #include <linux/usb/composite.h>
 
-#ifndef UMS_START_SECTOR
-#define UMS_START_SECTOR	0
-#endif
-
-#ifndef UMS_NUM_SECTORS
-#define UMS_NUM_SECTORS		0
-#endif
-
 /* Wait at maximum 60 seconds for cable connection */
 #define UMS_CABLE_READY_TIMEOUT	60
 
@@ -31,14 +23,13 @@
 	unsigned int start_sector;
 	unsigned int num_sectors;
 	const char *name;
-	struct mmc *mmc;
+	block_dev_desc_t *block_dev;
 };
 
 extern struct ums *ums;
 
 int fsg_init(struct ums *);
 void fsg_cleanup(void);
-struct ums *ums_init(unsigned int);
 int fsg_main_thread(void *);
 int fsg_add(struct usb_configuration *c);
 #endif /* __USB_MASS_STORAGE_H__ */
diff --git a/include/xilinx.h b/include/xilinx.h
index 9801267..aebcb3b 100644
--- a/include/xilinx.h
+++ b/include/xilinx.h
@@ -45,16 +45,20 @@
 } xilinx_desc;			/* end, typedef xilinx_desc */
 
 struct xilinx_fpga_op {
-	int (*load)(xilinx_desc *, const void *, size_t);
+	int (*load)(xilinx_desc *, const void *, size_t, bitstream_type);
+	int (*loadfs)(xilinx_desc *, const void *, size_t, fpga_fs_info *);
 	int (*dump)(xilinx_desc *, const void *, size_t);
 	int (*info)(xilinx_desc *);
 };
 
 /* Generic Xilinx Functions
  *********************************************************************/
-int xilinx_load(xilinx_desc *desc, const void *image, size_t size);
+int xilinx_load(xilinx_desc *desc, const void *image, size_t size,
+		bitstream_type bstype);
 int xilinx_dump(xilinx_desc *desc, const void *buf, size_t bsize);
 int xilinx_info(xilinx_desc *desc);
+int xilinx_loadfs(xilinx_desc *desc, const void *buf, size_t bsize,
+		  fpga_fs_info *fpga_fsinfo);
 
 /* Board specific implementation specific function types
  *********************************************************************/
diff --git a/lib/Makefile b/lib/Makefile
index 27e4f78..377ab13 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -35,6 +35,7 @@
 obj-$(CONFIG_PHYSMEM) += physmem.o
 obj-y += qsort.o
 obj-$(CONFIG_SHA1) += sha1.o
+obj-$(CONFIG_SUPPORT_EMMC_RPMB) += sha256.o
 obj-$(CONFIG_SHA256) += sha256.o
 obj-y	+= strmhz.o
 obj-$(CONFIG_TPM) += tpm.o