Merge git://git.denx.de/u-boot-video
diff --git a/.travis.yml b/.travis.yml
index 00b2a73..0b7a062 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -138,6 +138,12 @@
     - env:
         - BUILDMAN="aries"
     - env:
+        - JOB="Boundary Devices"
+          BUILDMAN="boundary"
+    - env:
+        - JOB="engicam"
+          BUILDMAN="engicam"
+    - env:
         - JOB="Freescale ARM32"
           BUILDMAN="freescale -x powerpc,m68k,aarch64"
     - env:
@@ -145,13 +151,17 @@
           BUILDMAN="freescale&aarch64"
     - env:
         - JOB="i.MX6 (non-Freescale)"
-          BUILDMAN="mx6 -x freescale"
+          BUILDMAN="mx6 -x freescale,toradex,boundary,engicam"
     - env:
         - JOB="i.MX (non-Freescale, non-i.MX6)"
-          BUILDMAN="mx -x freescale,mx6"
+          BUILDMAN="mx -x freescale,mx6,toradex"
+    - env:
+        - BUILDMAN="k2"
     - env:
         - BUILDMAN="samsung"
     - env:
+        - BUILDMAN="socfpga"
+    - env:
         - BUILDMAN="sun4i"
     - env:
         - BUILDMAN="sun5i"
@@ -167,16 +177,19 @@
         - BUILDMAN="sun50i"
     - env:
         - JOB="Catch-all ARM"
-          BUILDMAN="arm -x arm11,arm7,arm9,aarch64,atmel,aries,freescale,kirkwood,mvebu,siemens,tegra,uniphier,mx,samsung,sunxi,am33xx,omap3,omap4,omap5,pxa,rockchip"
+          BUILDMAN="arm -x arm11,arm7,arm9,aarch64,atmel,aries,freescale,kirkwood,mvebu,siemens,tegra,uniphier,mx,samsung,sunxi,am33xx,omap3,omap4,omap5,pxa,rockchip,toradex,socfpga,k2,xilinx"
     - env:
         - BUILDMAN="sandbox x86"
           TOOLCHAIN="x86_64"
     - env:
+        - BUILDMAN="toradex"
+    - env:
         - BUILDMAN="kirkwood"
     - env:
         - BUILDMAN="mvebu"
     - env:
-        - BUILDMAN="pxa"
+        - JOB="PXA"
+        - BUILDMAN="pxa -x toradex"
     - env:
         - BUILDMAN="m68k"
           TOOLCHAIN="m68k"
@@ -207,7 +220,8 @@
     - env:
         - BUILDMAN="siemens"
     - env:
-        - BUILDMAN="tegra"
+        - JOB="tegra"
+          BUILDMAN="tegra -x toradex"
     - env:
         - JOB="am33xx"
           BUILDMAN="am33xx -x siemens"
@@ -220,13 +234,17 @@
     - env:
         - BUILDMAN="uniphier"
     - env:
-        - BUILDMAN="aarch64 -x tegra,freescale,mvebu,uniphier,sunxi,samsung,rockchip"
+        - JOB="aarch64"
+          BUILDMAN="aarch64 -x tegra,freescale,mvebu,uniphier,sunxi,samsung,rockchip"
     - env:
         - BUILDMAN="rockchip"
     - env:
         - BUILDMAN="sh4"
           TOOLCHAIN="sh4"
     - env:
+        - JOB="Xilinx (ARM)"
+          BUILDMAN="xilinx -x microblaze"
+    - env:
         - BUILDMAN="xtensa"
           TOOLCHAIN="xtensa"
 
@@ -286,6 +304,11 @@
           QEMU_TARGET="arm-softmmu"
           BUILDMAN="^integratorcp_cm926ejs$"
     - env:
+        - TEST_PY_BD="qemu_arm"
+          TEST_PY_TEST_SPEC="not sleep"
+          QEMU_TARGET="arm-softmmu"
+          BUILDMAN="^qemu_arm$"
+    - env:
         - TEST_PY_BD="qemu_mips"
           TEST_PY_TEST_SPEC="not sleep"
           QEMU_TARGET="mips-softmmu"
diff --git a/Kconfig b/Kconfig
index 238fa3e..d951e9f 100644
--- a/Kconfig
+++ b/Kconfig
@@ -398,5 +398,3 @@
 source "lib/Kconfig"
 
 source "test/Kconfig"
-
-source "scripts/Kconfig"
diff --git a/MAINTAINERS b/MAINTAINERS
index 04acf2b..b167b02 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -259,8 +259,9 @@
 M:	Alexander Graf <agraf@suse.de>
 S:	Maintained
 T:	git git://github.com/agraf/u-boot.git
-F:	include/efi_loader.h
-F:	lib/efi_loader/
+F:	include/efi*
+F:	lib/efi*
+F:	test/py/tests/test_efi*
 F:	cmd/bootefi.c
 
 FLATTENED DEVICE TREE
@@ -419,6 +420,7 @@
 F:	arch/arm/mach-omap2/sec-common.c
 F:	arch/arm/mach-omap2/config_secure.mk
 F:	configs/am335x_hs_evm_defconfig
+F:	configs/am335x_hs_evm_uart_defconfig
 F:	configs/am43xx_hs_evm_defconfig
 F:	configs/am57xx_hs_evm_defconfig
 F:	configs/dra7xx_hs_evm_defconfig
diff --git a/Makefile b/Makefile
index b7d5cbb..888486b 100644
--- a/Makefile
+++ b/Makefile
@@ -3,9 +3,9 @@
 #
 
 VERSION = 2017
-PATCHLEVEL = 09
+PATCHLEVEL = 11
 SUBLEVEL =
-EXTRAVERSION =
+EXTRAVERSION = -rc1
 NAME =
 
 # *DOCUMENTATION*
@@ -878,7 +878,7 @@
 quiet_cmd_copy = COPY    $@
       cmd_copy = cp $< $@
 
-ifeq ($(CONFIG_FIT_EMBED),y)
+ifeq ($(CONFIG_MULTI_DTB_FIT),y)
 
 fit-dtb.blob: dts/dt.dtb FORCE
 	$(call if_changed,mkimage)
diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
index 42e7f22..a12303b 100644
--- a/arch/arc/include/asm/io.h
+++ b/arch/arc/include/asm/io.h
@@ -50,30 +50,6 @@
 #define __iowmb()		do { } while (0)
 #endif
 
-/*
- * Given a physical address and a length, return a virtual address
- * that can be used to access the memory range with the caching
- * properties specified by "flags".
- */
-#define MAP_NOCACHE	(0)
-#define MAP_WRCOMBINE	(0)
-#define MAP_WRBACK	(0)
-#define MAP_WRTHROUGH	(0)
-
-static inline void *
-map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
-{
-	return (void *)((unsigned long)paddr);
-}
-
-/*
- * Take down a mapping set up by map_physmem().
- */
-static inline void unmap_physmem(void *vaddr, unsigned long flags)
-{
-
-}
-
 static inline void sync(void)
 {
 	/* Not yet implemented */
@@ -302,9 +278,6 @@
 #define setbits_8(addr, set) setbits(8, addr, set)
 #define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
 
-static inline phys_addr_t virt_to_phys(void *vaddr)
-{
-	return (phys_addr_t)((unsigned long)vaddr);
-}
+#include <asm-generic/io.h>
 
 #endif	/* __ASM_ARC_IO_H */
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index bb64b9c..64e0ee4 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -588,6 +588,7 @@
 	bool "TI OMAP2+"
 	select CPU_V7
 	select SPL_BOARD_INIT if SPL
+	select SPL_STACK_R if SPL
 	select SUPPORT_SPL
 	imply FIT
 
@@ -630,6 +631,14 @@
 	select CPU_V7
 	select BOARD_EARLY_INIT_F
 
+config ARCH_QEMU
+	bool "QEMU Virtual Platform"
+	select CPU_V7
+	select ARCH_SUPPORT_PSCI
+	select DM
+	select DM_SERIAL
+	select OF_CONTROL
+
 config ARCH_RMOBILE
 	bool "Renesas ARM SoCs"
 	select DM
@@ -693,8 +702,7 @@
 	select USB_STORAGE if DISTRO_DEFAULTS
 	select USB_KEYBOARD if DISTRO_DEFAULTS
 	select USE_TINY_PRINTF
-	imply CMD_FASTBOOT
-	imply FASTBOOT
+	imply CMD_GPT
 	imply FAT_WRITE
 	imply PRE_CONSOLE_BUFFER
 	imply SPL_GPIO_SUPPORT
@@ -704,7 +712,7 @@
 	imply SPL_MMC_SUPPORT if MMC
 	imply SPL_POWER_SUPPORT
 	imply SPL_SERIAL_SUPPORT
-	imply USB_FUNCTION_FASTBOOT
+	imply USB_GADGET
 
 config TARGET_TS4600
 	bool "Support TS4600"
@@ -1114,6 +1122,9 @@
 	imply FAT_WRITE
 	imply USB_FUNCTION_FASTBOOT
 	imply SPL_SYSRESET
+	imply TPL_SYSRESET
+	imply ADC
+	imply SARADC_ROCKCHIP
 
 config TARGET_THUNDERX_88XX
 	bool "Support ThunderX 88xx"
@@ -1168,6 +1179,8 @@
 
 source "arch/arm/mach-meson/Kconfig"
 
+source "arch/arm/mach-qemu/Kconfig"
+
 source "arch/arm/mach-rockchip/Kconfig"
 
 source "arch/arm/mach-s5pc1xx/Kconfig"
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 7c062f0..5b90280 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -313,8 +313,8 @@
 	sun8i-r16-parrot.dtb
 dtb-$(CONFIG_MACH_SUN8I_A83T) += \
 	sun8i-a83t-allwinner-h8homlet-v2.dtb \
-	sun8i-a83t-cubietruck-plus.dtb \
-	sun8i-a83t-sinovoip-bpi-m3.dtb
+	sun8i-a83t-bananapi-m3.dtb \
+	sun8i-a83t-cubietruck-plus.dtb
 dtb-$(CONFIG_MACH_SUN8I_H3) += \
 	sun8i-h2-plus-orangepi-zero.dtb \
 	sun8i-h3-bananapi-m2-plus.dtb \
diff --git a/arch/arm/dts/am3517-evm-u-boot.dtsi b/arch/arm/dts/am3517-evm-u-boot.dtsi
new file mode 100644
index 0000000..24a67db
--- /dev/null
+++ b/arch/arm/dts/am3517-evm-u-boot.dtsi
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2017
+ * Logic PD - http://www.logicpd.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/ {
+	chosen {
+		stdout-path = &uart3;
+	};
+};
diff --git a/arch/arm/dts/am3517-evm.dts b/arch/arm/dts/am3517-evm.dts
new file mode 100644
index 0000000..0e4a125
--- /dev/null
+++ b/arch/arm/dts/am3517-evm.dts
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am3517.dtsi"
+
+/ {
+	model = "TI AM3517 EVM (AM3517/05 TMDSEVM3517)";
+	compatible = "ti,am3517-evm", "ti,am3517", "ti,omap3";
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+        vmmc_fixed: vmmc {
+                compatible = "regulator-fixed";
+                regulator-name = "vmmc_fixed";
+                regulator-min-microvolt = <3300000>;
+                regulator-max-microvolt = <3300000>;
+        };
+};
+
+&davinci_emac {
+	     status = "okay";
+};
+
+&davinci_mdio {
+	     status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <400000>;
+};
+
+&i2c2 {
+	clock-frequency = <400000>;
+};
+
+&i2c3 {
+	clock-frequency = <400000>;
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmc_fixed>;
+	bus-width = <4>;
+};
+
+&mmc2 {
+      status = "disabled";
+};
+
+&mmc3 {
+      status = "disabled";
+};
+
diff --git a/arch/arm/dts/am3517-u-boot.dtsi b/arch/arm/dts/am3517-u-boot.dtsi
new file mode 100644
index 0000000..2190052
--- /dev/null
+++ b/arch/arm/dts/am3517-u-boot.dtsi
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2017
+ * Logic PD - http://www.logicpd.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+&uart4 {
+	reg-shift = <2>;
+};
diff --git a/arch/arm/dts/am3517.dtsi b/arch/arm/dts/am3517.dtsi
new file mode 100644
index 0000000..00da3f2
--- /dev/null
+++ b/arch/arm/dts/am3517.dtsi
@@ -0,0 +1,107 @@
+/*
+ * Device Tree Source for am3517 SoC
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include "omap3.dtsi"
+
+/ {
+	aliases {
+		serial3 = &uart4;
+		can = &hecc;
+	};
+
+	ocp@68000000 {
+		am35x_otg_hs: am35x_otg_hs@5c040000 {
+			compatible = "ti,omap3-musb";
+			ti,hwmods = "am35x_otg_hs";
+			status = "disabled";
+			reg = <0x5c040000 0x1000>;
+			interrupts = <71>;
+			interrupt-names = "mc";
+		};
+
+		davinci_emac: ethernet@0x5c000000 {
+			compatible = "ti,am3517-emac";
+			ti,hwmods = "davinci_emac";
+			status = "disabled";
+			reg = <0x5c000000 0x30000>;
+			interrupts = <67 68 69 70>;
+			syscon = <&scm_conf>;
+			ti,davinci-ctrl-reg-offset = <0x10000>;
+			ti,davinci-ctrl-mod-reg-offset = <0>;
+			ti,davinci-ctrl-ram-offset = <0x20000>;
+			ti,davinci-ctrl-ram-size = <0x2000>;
+			ti,davinci-rmii-en = /bits/ 8 <1>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+		};
+
+		davinci_mdio: ethernet@0x5c030000 {
+			compatible = "ti,davinci_mdio";
+			ti,hwmods = "davinci_mdio";
+			status = "disabled";
+			reg = <0x5c030000 0x1000>;
+			bus_freq = <1000000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		uart4: serial@4809e000 {
+			compatible = "ti,omap3-uart";
+			ti,hwmods = "uart4";
+			status = "disabled";
+			reg = <0x4809e000 0x400>;
+			interrupts = <84>;
+			dmas = <&sdma 55 &sdma 54>;
+			dma-names = "tx", "rx";
+			clock-frequency = <48000000>;
+		};
+
+		omap3_pmx_core2: pinmux@480025d8 {
+			compatible = "ti,omap3-padconf", "pinctrl-single";
+			reg = <0x480025d8 0x24>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			#pinctrl-cells = <1>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			pinctrl-single,register-width = <16>;
+			pinctrl-single,function-mask = <0xff1f>;
+		};
+
+		hecc: can@5c050000 {
+			compatible = "ti,am3517-hecc";
+			status = "disabled";
+			reg = <0x5c050000 0x80>,
+			      <0x5c053000 0x180>,
+			      <0x5c052000 0x200>;
+			reg-names = "hecc", "hecc-ram", "mbx";
+			interrupts = <24>;
+			clocks = <&hecc_ck>;
+		};
+	};
+};
+
+&iva {
+	status = "disabled";
+};
+
+&mailbox {
+	status = "disabled";
+};
+
+&mmu_isp {
+	status = "disabled";
+};
+
+&smartreflex_mpu_iva {
+	status = "disabled";
+};
+
+/include/ "am35xx-clocks.dtsi"
+/include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
diff --git a/arch/arm/dts/am35xx-clocks.dtsi b/arch/arm/dts/am35xx-clocks.dtsi
new file mode 100644
index 0000000..00dd1f0
--- /dev/null
+++ b/arch/arm/dts/am35xx-clocks.dtsi
@@ -0,0 +1,128 @@
+/*
+ * Device Tree Source for OMAP3 clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+&scm_clocks {
+	emac_ick: emac_ick@32c {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-gate-clock";
+		clocks = <&ipss_ick>;
+		reg = <0x032c>;
+		ti,bit-shift = <1>;
+	};
+
+	emac_fck: emac_fck@32c {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&rmii_ck>;
+		reg = <0x032c>;
+		ti,bit-shift = <9>;
+	};
+
+	vpfe_ick: vpfe_ick@32c {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-gate-clock";
+		clocks = <&ipss_ick>;
+		reg = <0x032c>;
+		ti,bit-shift = <2>;
+	};
+
+	vpfe_fck: vpfe_fck@32c {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&pclk_ck>;
+		reg = <0x032c>;
+		ti,bit-shift = <10>;
+	};
+
+	hsotgusb_ick_am35xx: hsotgusb_ick_am35xx@32c {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-gate-clock";
+		clocks = <&ipss_ick>;
+		reg = <0x032c>;
+		ti,bit-shift = <0>;
+	};
+
+	hsotgusb_fck_am35xx: hsotgusb_fck_am35xx@32c {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&sys_ck>;
+		reg = <0x032c>;
+		ti,bit-shift = <8>;
+	};
+
+	hecc_ck: hecc_ck@32c {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-gate-clock";
+		clocks = <&sys_ck>;
+		reg = <0x032c>;
+		ti,bit-shift = <3>;
+	};
+};
+&cm_clocks {
+	ipss_ick: ipss_ick@a10 {
+		#clock-cells = <0>;
+		compatible = "ti,am35xx-interface-clock";
+		clocks = <&core_l3_ick>;
+		reg = <0x0a10>;
+		ti,bit-shift = <4>;
+	};
+
+	rmii_ck: rmii_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <50000000>;
+	};
+
+	pclk_ck: pclk_ck {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <27000000>;
+	};
+
+	uart4_ick_am35xx: uart4_ick_am35xx@a10 {
+		#clock-cells = <0>;
+		compatible = "ti,omap3-interface-clock";
+		clocks = <&core_l4_ick>;
+		reg = <0x0a10>;
+		ti,bit-shift = <23>;
+	};
+
+	uart4_fck_am35xx: uart4_fck_am35xx@a00 {
+		#clock-cells = <0>;
+		compatible = "ti,wait-gate-clock";
+		clocks = <&core_48m_fck>;
+		reg = <0x0a00>;
+		ti,bit-shift = <23>;
+	};
+};
+
+&cm_clockdomains {
+	core_l3_clkdm: core_l3_clkdm {
+		compatible = "ti,clockdomain";
+		clocks = <&sdrc_ick>, <&ipss_ick>, <&emac_ick>, <&vpfe_ick>,
+			 <&hsotgusb_ick_am35xx>, <&hsotgusb_fck_am35xx>,
+			 <&hecc_ck>;
+	};
+
+	core_l4_clkdm: core_l4_clkdm {
+		compatible = "ti,clockdomain";
+		clocks = <&cpefuse_fck>, <&ts_fck>, <&usbtll_fck>,
+			 <&usbtll_ick>, <&mmchs3_ick>, <&mmchs3_fck>,
+			 <&mmchs2_fck>, <&mmchs1_fck>, <&i2c3_fck>, <&i2c2_fck>,
+			 <&i2c1_fck>, <&mcspi4_fck>, <&mcspi3_fck>,
+			 <&mcspi2_fck>, <&mcspi1_fck>, <&uart2_fck>,
+			 <&uart1_fck>, <&hdq_fck>, <&mmchs2_ick>, <&mmchs1_ick>,
+			 <&hdq_ick>, <&mcspi4_ick>, <&mcspi3_ick>,
+			 <&mcspi2_ick>, <&mcspi1_ick>, <&i2c3_ick>, <&i2c2_ick>,
+			 <&i2c1_ick>, <&uart2_ick>, <&uart1_ick>, <&gpt11_ick>,
+			 <&gpt10_ick>, <&mcbsp5_ick>, <&mcbsp1_ick>,
+			 <&omapctrl_ick>, <&aes2_ick>, <&sha12_ick>,
+			 <&uart4_ick_am35xx>, <&uart4_fck_am35xx>;
+	};
+};
diff --git a/arch/arm/dts/axp223.dtsi b/arch/arm/dts/axp223.dtsi
new file mode 100644
index 0000000..b91b6c1
--- /dev/null
+++ b/arch/arm/dts/axp223.dtsi
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016 Free Electrons
+ *
+ * Quentin Schulz <quentin.schulz@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * AXP223 Integrated Power Management Chip
+ * http://www.x-powers.com/product/AXP22X.php
+ * http://dl.linux-sunxi.org/AXP/AXP223-en.pdf
+ *
+ * The AXP223 shares most of its logic with the AXP221 but it has some
+ * differences, for the VBUS driver for example.
+ */
+
+#include "axp22x.dtsi"
+
+&usb_power_supply {
+	compatible = "x-powers,axp223-usb-power-supply";
+};
diff --git a/arch/arm/dts/axp22x.dtsi b/arch/arm/dts/axp22x.dtsi
index 458b668..87fb08e 100644
--- a/arch/arm/dts/axp22x.dtsi
+++ b/arch/arm/dts/axp22x.dtsi
@@ -52,6 +52,16 @@
 	interrupt-controller;
 	#interrupt-cells = <1>;
 
+	ac_power_supply: ac-power-supply {
+		compatible = "x-powers,axp221-ac-power-supply";
+		status = "disabled";
+	};
+
+	battery_power_supply: battery-power-supply {
+		compatible = "x-powers,axp221-battery-power-supply";
+		status = "disabled";
+	};
+
 	regulators {
 		/* Default work frequency for buck regulators */
 		x-powers,dcdc-freq = <3000>;
diff --git a/arch/arm/dts/da850-evm-u-boot.dtsi b/arch/arm/dts/da850-evm-u-boot.dtsi
new file mode 100644
index 0000000..5cc5a81
--- /dev/null
+++ b/arch/arm/dts/da850-evm-u-boot.dtsi
@@ -0,0 +1,23 @@
+/*
+ * da850-evm U-Boot Additions
+ *
+ * Copyright (C) 2017 Logic PD, Inc.
+ * Copyright (C) Adam Ford
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/ {
+	chosen {
+		stdout-path = &serial2;
+	};
+
+	aliases {
+		i2c0 = &i2c0;
+		spi0 = &spi1;
+	};
+};
+
+&flash {
+	compatible = "m25p64", "spi-flash";
+};
diff --git a/arch/arm/dts/da850-evm.dts b/arch/arm/dts/da850-evm.dts
new file mode 100644
index 0000000..67e72bc
--- /dev/null
+++ b/arch/arm/dts/da850-evm.dts
@@ -0,0 +1,304 @@
+/*
+ * Device Tree for DA850 EVM board
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation, version 2.
+ */
+/dts-v1/;
+#include "da850.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	compatible = "ti,da850-evm", "ti,da850";
+	model = "DA850/AM1808/OMAP-L138 EVM";
+
+	soc@1c00000 {
+		pmx_core: pinmux@14120 {
+			status = "okay";
+
+			mcasp0_pins: pinmux_mcasp0_pins {
+				pinctrl-single,bits = <
+					/*
+					 * AHCLKX, ACLKX, AFSX, AHCLKR, ACLKR,
+					 * AFSR, AMUTE
+					 */
+					0x00 0x11111111 0xffffffff
+					/* AXR11, AXR12 */
+					0x04 0x00011000 0x000ff000
+				>;
+			};
+			nand_pins: nand_pins {
+				pinctrl-single,bits = <
+					/* EMA_WAIT[0], EMA_OE, EMA_WE, EMA_CS[4], EMA_CS[3] */
+					0x1c 0x10110110  0xf0ff0ff0
+					/*
+					 * EMA_D[0], EMA_D[1], EMA_D[2],
+					 * EMA_D[3], EMA_D[4], EMA_D[5],
+					 * EMA_D[6], EMA_D[7]
+					 */
+					0x24 0x11111111  0xffffffff
+					/* EMA_A[1], EMA_A[2] */
+					0x30 0x01100000  0x0ff00000
+				>;
+			};
+		};
+		serial0: serial@42000 {
+			status = "okay";
+		};
+		serial1: serial@10c000 {
+			status = "okay";
+		};
+		serial2: serial@10d000 {
+			status = "okay";
+		};
+		rtc0: rtc@23000 {
+			status = "okay";
+		};
+		i2c0: i2c@22000 {
+			status = "okay";
+			clock-frequency = <100000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins>;
+
+			tps: tps@48 {
+				reg = <0x48>;
+			};
+			tlv320aic3106: tlv320aic3106@18 {
+				#sound-dai-cells = <0>;
+				compatible = "ti,tlv320aic3106";
+				reg = <0x18>;
+				status = "okay";
+
+				/* Regulators */
+				IOVDD-supply = <&vdcdc2_reg>;
+				/* Derived from VBAT: Baseboard 3.3V / 1.8V */
+				AVDD-supply = <&vbat>;
+				DRVDD-supply = <&vbat>;
+				DVDD-supply = <&vbat>;
+			};
+			tca6416: gpio@20 {
+				compatible = "ti,tca6416";
+				reg = <0x20>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+		};
+		wdt: wdt@21000 {
+			status = "okay";
+		};
+		mmc0: mmc@40000 {
+			max-frequency = <50000000>;
+			bus-width = <4>;
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&mmc0_pins>;
+		};
+		spi1: spi@30e000 {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi1_pins &spi1_cs0_pin>;
+			flash: m25p80@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "m25p64";
+				spi-max-frequency = <30000000>;
+				m25p,fast-read;
+				reg = <0>;
+				partition@0 {
+					label = "U-Boot-SPL";
+					reg = <0x00000000 0x00010000>;
+					read-only;
+				};
+				partition@1 {
+					label = "U-Boot";
+					reg = <0x00010000 0x00080000>;
+					read-only;
+				};
+				partition@2 {
+					label = "U-Boot-Env";
+					reg = <0x00090000 0x00010000>;
+					read-only;
+				};
+				partition@3 {
+					label = "Kernel";
+					reg = <0x000a0000 0x00280000>;
+				};
+				partition@4 {
+					label = "Filesystem";
+					reg = <0x00320000 0x00400000>;
+				};
+				partition@5 {
+					label = "MAC-Address";
+					reg = <0x007f0000 0x00010000>;
+					read-only;
+				};
+			};
+		};
+		mdio: mdio@224000 {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&mdio_pins>;
+			bus_freq = <2200000>;
+		};
+		eth0: ethernet@220000 {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&mii_pins>;
+		};
+		gpio: gpio@226000 {
+			status = "okay";
+		};
+	};
+	vbat: fixedregulator0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "DA850/OMAP-L138 EVM";
+		simple-audio-card,widgets =
+			"Line", "Line In",
+			"Line", "Line Out";
+		simple-audio-card,routing =
+			"LINE1L", "Line In",
+			"LINE1R", "Line In",
+			"Line Out", "LLOUT",
+			"Line Out", "RLOUT";
+		simple-audio-card,format = "dsp_b";
+		simple-audio-card,bitclock-master = <&link0_codec>;
+		simple-audio-card,frame-master = <&link0_codec>;
+		simple-audio-card,bitclock-inversion;
+
+		simple-audio-card,cpu {
+			sound-dai = <&mcasp0>;
+			system-clock-frequency = <24576000>;
+		};
+
+		link0_codec: simple-audio-card,codec {
+			sound-dai = <&tlv320aic3106>;
+			system-clock-frequency = <24576000>;
+		};
+	};
+};
+
+/include/ "tps6507x.dtsi"
+
+&tps {
+	vdcdc1_2-supply = <&vbat>;
+	vdcdc3-supply = <&vbat>;
+	vldo1_2-supply = <&vbat>;
+
+	regulators {
+		vdcdc1_reg: regulator@0 {
+			regulator-name = "VDCDC1_3.3V";
+			regulator-min-microvolt = <3150000>;
+			regulator-max-microvolt = <3450000>;
+			regulator-always-on;
+			regulator-boot-on;
+		};
+
+		vdcdc2_reg: regulator@1 {
+			regulator-name = "VDCDC2_3.3V";
+			regulator-min-microvolt = <1710000>;
+			regulator-max-microvolt = <3450000>;
+			regulator-always-on;
+			regulator-boot-on;
+			ti,defdcdc_default = <1>;
+		};
+
+		vdcdc3_reg: regulator@2 {
+			regulator-name = "VDCDC3_1.2V";
+			regulator-min-microvolt = <950000>;
+			regulator-max-microvolt = <1350000>;
+			regulator-always-on;
+			regulator-boot-on;
+			ti,defdcdc_default = <1>;
+		};
+
+		ldo1_reg: regulator@3 {
+			regulator-name = "LDO1_1.8V";
+			regulator-min-microvolt = <1710000>;
+			regulator-max-microvolt = <1890000>;
+			regulator-always-on;
+			regulator-boot-on;
+		};
+
+		ldo2_reg: regulator@4 {
+			regulator-name = "LDO2_1.2V";
+			regulator-min-microvolt = <1140000>;
+			regulator-max-microvolt = <1320000>;
+			regulator-always-on;
+			regulator-boot-on;
+		};
+	};
+};
+
+&mcasp0 {
+	#sound-dai-cells = <0>;
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcasp0_pins>;
+
+	op-mode = <0>;          /* MCASP_IIS_MODE */
+	tdm-slots = <2>;
+	/* 4 serializer */
+	serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+		0 0 0 0
+		0 0 0 0
+		0 0 0 1
+		2 0 0 0
+	>;
+	tx-num-evt = <32>;
+	rx-num-evt = <32>;
+};
+
+&edma0 {
+	ti,edma-reserved-slot-ranges = <32 50>;
+};
+
+&edma1 {
+	ti,edma-reserved-slot-ranges = <32 90>;
+};
+
+&aemif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&nand_pins>;
+	status = "ok";
+	cs3 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		clock-ranges;
+		ranges;
+
+		ti,cs-chipselect = <3>;
+
+		nand@2000000,0 {
+			compatible = "ti,davinci-nand";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0 0x02000000 0x02000000
+			       1 0x00000000 0x00008000>;
+
+			ti,davinci-chipselect = <1>;
+			ti,davinci-mask-ale = <0>;
+			ti,davinci-mask-cle = <0>;
+			ti,davinci-mask-chipsel = <0>;
+			ti,davinci-ecc-mode = "hw";
+			ti,davinci-ecc-bits = <4>;
+			ti,davinci-nand-use-bbt;
+		};
+	};
+};
+
+&vpif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&vpif_capture_pins>, <&vpif_display_pins>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/da850.dtsi b/arch/arm/dts/da850.dtsi
new file mode 100644
index 0000000..02e2f8f
--- /dev/null
+++ b/arch/arm/dts/da850.dtsi
@@ -0,0 +1,581 @@
+/*
+ * Copyright 2012 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include "skeleton.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	arm {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		intc: interrupt-controller@fffee000 {
+			compatible = "ti,cp-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			ti,intc-size = <101>;
+			reg = <0xfffee000 0x2000>;
+		};
+	};
+
+	aliases {
+		spi0 = &spi0;
+	};
+
+	soc@1c00000 {
+		compatible = "simple-bus";
+		model = "da850";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x0 0x01c00000 0x400000>;
+		interrupt-parent = <&intc>;
+
+		pmx_core: pinmux@14120 {
+			compatible = "pinctrl-single";
+			reg = <0x14120 0x50>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			#pinctrl-cells = <2>;
+			pinctrl-single,bit-per-mux;
+			pinctrl-single,register-width = <32>;
+			pinctrl-single,function-mask = <0xf>;
+			status = "disabled";
+
+			serial0_rtscts_pins: pinmux_serial0_rtscts_pins {
+				pinctrl-single,bits = <
+					/* UART0_RTS UART0_CTS */
+					0x0c 0x22000000 0xff000000
+				>;
+			};
+			serial0_rxtx_pins: pinmux_serial0_rxtx_pins {
+				pinctrl-single,bits = <
+					/* UART0_TXD UART0_RXD */
+					0x0c 0x00220000 0x00ff0000
+				>;
+			};
+			serial1_rtscts_pins: pinmux_serial1_rtscts_pins {
+				pinctrl-single,bits = <
+					/* UART1_CTS UART1_RTS */
+					0x00 0x00440000 0x00ff0000
+				>;
+			};
+			serial1_rxtx_pins: pinmux_serial1_rxtx_pins {
+				pinctrl-single,bits = <
+					/* UART1_TXD UART1_RXD */
+					0x10 0x22000000 0xff000000
+				>;
+			};
+			serial2_rtscts_pins: pinmux_serial2_rtscts_pins {
+				pinctrl-single,bits = <
+					/* UART2_CTS UART2_RTS */
+					0x00 0x44000000 0xff000000
+				>;
+			};
+			serial2_rxtx_pins: pinmux_serial2_rxtx_pins {
+				pinctrl-single,bits = <
+					/* UART2_TXD UART2_RXD */
+					0x10 0x00220000 0x00ff0000
+				>;
+			};
+			i2c0_pins: pinmux_i2c0_pins {
+				pinctrl-single,bits = <
+					/* I2C0_SDA,I2C0_SCL */
+					0x10 0x00002200 0x0000ff00
+				>;
+			};
+			i2c1_pins: pinmux_i2c1_pins {
+				pinctrl-single,bits = <
+					/* I2C1_SDA, I2C1_SCL */
+					0x10 0x00440000 0x00ff0000
+				>;
+			};
+			mmc0_pins: pinmux_mmc_pins {
+				pinctrl-single,bits = <
+					/* MMCSD0_DAT[3] MMCSD0_DAT[2]
+					 * MMCSD0_DAT[1] MMCSD0_DAT[0]
+					 * MMCSD0_CMD    MMCSD0_CLK
+					 */
+					0x28 0x00222222  0x00ffffff
+				>;
+			};
+			ehrpwm0a_pins: pinmux_ehrpwm0a_pins {
+				pinctrl-single,bits = <
+					/* EPWM0A */
+					0xc 0x00000002 0x0000000f
+				>;
+			};
+			ehrpwm0b_pins: pinmux_ehrpwm0b_pins {
+				pinctrl-single,bits = <
+					/* EPWM0B */
+					0xc 0x00000020 0x000000f0
+				>;
+			};
+			ehrpwm1a_pins: pinmux_ehrpwm1a_pins {
+				pinctrl-single,bits = <
+					/* EPWM1A */
+					0x14 0x00000002 0x0000000f
+				>;
+			};
+			ehrpwm1b_pins: pinmux_ehrpwm1b_pins {
+				pinctrl-single,bits = <
+					/* EPWM1B */
+					0x14 0x00000020 0x000000f0
+				>;
+			};
+			ecap0_pins: pinmux_ecap0_pins {
+				pinctrl-single,bits = <
+					/* ECAP0_APWM0 */
+					0x8 0x20000000 0xf0000000
+				>;
+			};
+			ecap1_pins: pinmux_ecap1_pins {
+				pinctrl-single,bits = <
+					/* ECAP1_APWM1 */
+					0x4 0x40000000 0xf0000000
+				>;
+			};
+			ecap2_pins: pinmux_ecap2_pins {
+				pinctrl-single,bits = <
+					/* ECAP2_APWM2 */
+					0x4 0x00000004 0x0000000f
+				>;
+			};
+			spi0_pins: pinmux_spi0_pins {
+				pinctrl-single,bits = <
+					/* SIMO, SOMI, CLK */
+					0xc 0x00001101 0x0000ff0f
+				>;
+			};
+			spi0_cs0_pin: pinmux_spi0_cs0 {
+				pinctrl-single,bits = <
+					/* CS0 */
+					0x10 0x00000010 0x000000f0
+				>;
+			};
+			spi0_cs3_pin: pinmux_spi0_cs3_pin {
+				pinctrl-single,bits = <
+					/* CS3 */
+					0xc 0x01000000 0x0f000000
+				>;
+			};
+			spi1_pins: pinmux_spi1_pins {
+				pinctrl-single,bits = <
+					/* SIMO, SOMI, CLK */
+					0x14 0x00110100 0x00ff0f00
+				>;
+			};
+			spi1_cs0_pin: pinmux_spi1_cs0 {
+				pinctrl-single,bits = <
+					/* CS0 */
+					0x14 0x00000010 0x000000f0
+				>;
+			};
+			mdio_pins: pinmux_mdio_pins {
+				pinctrl-single,bits = <
+					/* MDIO_CLK, MDIO_D */
+					0x10 0x00000088 0x000000ff
+				>;
+			};
+			mii_pins: pinmux_mii_pins {
+				pinctrl-single,bits = <
+					/*
+					 * MII_TXEN, MII_TXCLK, MII_COL
+					 * MII_TXD_3, MII_TXD_2, MII_TXD_1
+					 * MII_TXD_0
+					 */
+					0x8 0x88888880 0xfffffff0
+					/*
+					 * MII_RXER, MII_CRS, MII_RXCLK
+					 * MII_RXDV, MII_RXD_3, MII_RXD_2
+					 * MII_RXD_1, MII_RXD_0
+					 */
+					0xc 0x88888888 0xffffffff
+				>;
+			};
+			lcd_pins: pinmux_lcd_pins {
+				pinctrl-single,bits = <
+					/*
+					 * LCD_D[2], LCD_D[3], LCD_D[4], LCD_D[5],
+					 * LCD_D[6], LCD_D[7]
+					 */
+					0x40 0x22222200 0xffffff00
+					/*
+					 * LCD_D[10], LCD_D[11], LCD_D[12], LCD_D[13],
+					 * LCD_D[14], LCD_D[15], LCD_D[0], LCD_D[1]
+					 */
+					0x44 0x22222222 0xffffffff
+					/* LCD_D[8], LCD_D[9] */
+					0x48 0x00000022 0x000000ff
+
+					/* LCD_PCLK */
+					0x48 0x02000000 0x0f000000
+					/* LCD_AC_ENB_CS, LCD_VSYNC, LCD_HSYNC */
+					0x4c 0x02000022 0x0f0000ff
+				>;
+			};
+			vpif_capture_pins: vpif_capture_pins {
+				pinctrl-single,bits = <
+					/* VP_DIN[2..7], VP_CLKIN1, VP_CLKIN0 */
+					0x38 0x11111111 0xffffffff
+					/* VP_DIN[10..15,0..1] */
+					0x3c 0x11111111 0xffffffff
+					/* VP_DIN[8..9] */
+					0x40 0x00000011 0x000000ff
+				>;
+			};
+			vpif_display_pins: vpif_display_pins {
+				pinctrl-single,bits = <
+					/* VP_DOUT[2..7] */
+					0x40 0x11111100 0xffffff00
+					/* VP_DOUT[10..15,0..1] */
+					0x44 0x11111111 0xffffffff
+					/*  VP_DOUT[8..9] */
+					0x48 0x00000011 0x000000ff
+					/*
+					 * VP_CLKOUT3, VP_CLKIN3,
+					 * VP_CLKOUT2, VP_CLKIN2
+					 */
+					0x4c 0x00111100 0x00ffff00
+				>;
+			};
+		};
+		prictrl: priority-controller@14110 {
+			compatible = "ti,da850-mstpri";
+			reg = <0x14110 0x0c>;
+			status = "disabled";
+		};
+		cfgchip: chip-controller@1417c {
+			compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
+			reg = <0x1417c 0x14>;
+
+			usb_phy: usb-phy {
+				compatible = "ti,da830-usb-phy";
+				#phy-cells = <1>;
+				status = "disabled";
+			};
+		};
+		edma0: edma@0 {
+			compatible = "ti,edma3-tpcc";
+			/* eDMA3 CC0: 0x01c0 0000 - 0x01c0 7fff */
+			reg =	<0x0 0x8000>;
+			reg-names = "edma3_cc";
+			interrupts = <11 12>;
+			interrupt-names = "edma3_ccint", "edma3_ccerrint";
+			#dma-cells = <2>;
+
+			ti,tptcs = <&edma0_tptc0 7>, <&edma0_tptc1 0>;
+		};
+		edma0_tptc0: tptc@8000 {
+			compatible = "ti,edma3-tptc";
+			reg =	<0x8000 0x400>;
+			interrupts = <13>;
+			interrupt-names = "edm3_tcerrint";
+		};
+		edma0_tptc1: tptc@8400 {
+			compatible = "ti,edma3-tptc";
+			reg =	<0x8400 0x400>;
+			interrupts = <32>;
+			interrupt-names = "edm3_tcerrint";
+		};
+		edma1: edma@230000 {
+			compatible = "ti,edma3-tpcc";
+			/* eDMA3 CC1: 0x01e3 0000 - 0x01e3 7fff */
+			reg =	<0x230000 0x8000>;
+			reg-names = "edma3_cc";
+			interrupts = <93 94>;
+			interrupt-names = "edma3_ccint", "edma3_ccerrint";
+			#dma-cells = <2>;
+
+			ti,tptcs = <&edma1_tptc0 7>;
+		};
+		edma1_tptc0: tptc@238000 {
+			compatible = "ti,edma3-tptc";
+			reg =	<0x238000 0x400>;
+			interrupts = <95>;
+			interrupt-names = "edm3_tcerrint";
+		};
+		serial0: serial@42000 {
+			compatible = "ti,da830-uart", "ns16550a";
+			reg = <0x42000 0x100>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			interrupts = <25>;
+			status = "disabled";
+		};
+		serial1: serial@10c000 {
+			compatible = "ti,da830-uart", "ns16550a";
+			reg = <0x10c000 0x100>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			interrupts = <53>;
+			status = "disabled";
+		};
+		serial2: serial@10d000 {
+			compatible = "ti,da830-uart", "ns16550a";
+			reg = <0x10d000 0x100>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			interrupts = <61>;
+			status = "disabled";
+		};
+		rtc0: rtc@23000 {
+			compatible = "ti,da830-rtc";
+			reg = <0x23000 0x1000>;
+			interrupts = <19
+				      19>;
+			status = "disabled";
+		};
+		i2c0: i2c@22000 {
+			compatible = "ti,davinci-i2c";
+			reg = <0x22000 0x1000>;
+			interrupts = <15>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+		i2c1: i2c@228000 {
+			compatible = "ti,davinci-i2c";
+			reg = <0x228000 0x1000>;
+			interrupts = <51>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+		wdt: wdt@21000 {
+			compatible = "ti,davinci-wdt";
+			reg = <0x21000 0x1000>;
+			status = "disabled";
+		};
+		mmc0: mmc@40000 {
+			compatible = "ti,da830-mmc";
+			reg = <0x40000 0x1000>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			interrupts = <16>;
+			dmas = <&edma0 16 0>, <&edma0 17 0>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+		vpif: video@217000 {
+			compatible = "ti,da850-vpif";
+			reg = <0x217000 0x1000>;
+			interrupts = <92>;
+			status = "disabled";
+
+			/* VPIF capture port */
+			port@0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+
+			/* VPIF display port */
+			port@1 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+		};
+		mmc1: mmc@21b000 {
+			compatible = "ti,da830-mmc";
+			reg = <0x21b000 0x1000>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			interrupts = <72>;
+			dmas = <&edma1 28 0>, <&edma1 29 0>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+		ehrpwm0: pwm@300000 {
+			compatible = "ti,da850-ehrpwm", "ti,am3352-ehrpwm",
+				     "ti,am33xx-ehrpwm";
+			#pwm-cells = <3>;
+			reg = <0x300000 0x2000>;
+			status = "disabled";
+		};
+		ehrpwm1: pwm@302000 {
+			compatible = "ti,da850-ehrpwm", "ti,am3352-ehrpwm",
+				     "ti,am33xx-ehrpwm";
+			#pwm-cells = <3>;
+			reg = <0x302000 0x2000>;
+			status = "disabled";
+		};
+		ecap0: ecap@306000 {
+			compatible = "ti,da850-ecap", "ti,am3352-ecap",
+				     "ti,am33xx-ecap";
+			#pwm-cells = <3>;
+			reg = <0x306000 0x80>;
+			status = "disabled";
+		};
+		ecap1: ecap@307000 {
+			compatible = "ti,da850-ecap", "ti,am3352-ecap",
+				     "ti,am33xx-ecap";
+			#pwm-cells = <3>;
+			reg = <0x307000 0x80>;
+			status = "disabled";
+		};
+		ecap2: ecap@308000 {
+			compatible = "ti,da850-ecap", "ti,am3352-ecap",
+				     "ti,am33xx-ecap";
+			#pwm-cells = <3>;
+			reg = <0x308000 0x80>;
+			status = "disabled";
+		};
+		spi0: spi@41000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "ti,da830-spi";
+			reg = <0x41000 0x1000>;
+			num-cs = <6>;
+			ti,davinci-spi-intr-line = <1>;
+			interrupts = <20>;
+			dmas = <&edma0 14 0>, <&edma0 15 0>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+		spi1: spi@30e000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "ti,da830-spi";
+			reg = <0x30e000 0x1000>;
+			num-cs = <4>;
+			ti,davinci-spi-intr-line = <1>;
+			interrupts = <56>;
+			dmas = <&edma0 18 0>, <&edma0 19 0>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+		usb0: usb@200000 {
+			compatible = "ti,da830-musb";
+			reg = <0x200000 0x1000>;
+			ranges;
+			interrupts = <58>;
+			interrupt-names = "mc";
+			dr_mode = "otg";
+			phys = <&usb_phy 0>;
+			phy-names = "usb-phy";
+			status = "disabled";
+
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			dmas = <&cppi41dma 0 0 &cppi41dma 1 0
+				&cppi41dma 2 0 &cppi41dma 3 0
+				&cppi41dma 0 1 &cppi41dma 1 1
+				&cppi41dma 2 1 &cppi41dma 3 1>;
+			dma-names =
+				"rx1", "rx2", "rx3", "rx4",
+				"tx1", "tx2", "tx3", "tx4";
+
+			cppi41dma: dma-controller@201000 {
+				compatible = "ti,da830-cppi41";
+				reg =  <0x201000 0x1000
+					0x202000 0x1000
+					0x204000 0x4000>;
+				reg-names = "controller",
+					    "scheduler", "queuemgr";
+				interrupts = <58>;
+				#dma-cells = <2>;
+				#dma-channels = <4>;
+				status = "okay";
+			};
+		};
+		sata: sata@218000 {
+			compatible = "ti,da850-ahci";
+			reg = <0x218000 0x2000>, <0x22c018 0x4>;
+			interrupts = <67>;
+			status = "disabled";
+		};
+		mdio: mdio@224000 {
+			compatible = "ti,davinci_mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x224000 0x1000>;
+			status = "disabled";
+		};
+		eth0: ethernet@220000 {
+			compatible = "ti,davinci-dm6467-emac";
+			reg = <0x220000 0x4000>;
+			ti,davinci-ctrl-reg-offset = <0x3000>;
+			ti,davinci-ctrl-mod-reg-offset = <0x2000>;
+			ti,davinci-ctrl-ram-offset = <0>;
+			ti,davinci-ctrl-ram-size = <0x2000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <33
+					34
+					35
+					36
+					>;
+			status = "disabled";
+		};
+		usb1: usb@225000 {
+			compatible = "ti,da830-ohci";
+			reg = <0x225000 0x1000>;
+			interrupts = <59>;
+			phys = <&usb_phy 1>;
+			phy-names = "usb-phy";
+			status = "disabled";
+		};
+		gpio: gpio@226000 {
+			compatible = "ti,dm6441-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			reg = <0x226000 0x1000>;
+			interrupts = <42 IRQ_TYPE_EDGE_BOTH
+				43 IRQ_TYPE_EDGE_BOTH 44 IRQ_TYPE_EDGE_BOTH
+				45 IRQ_TYPE_EDGE_BOTH 46 IRQ_TYPE_EDGE_BOTH
+				47 IRQ_TYPE_EDGE_BOTH 48 IRQ_TYPE_EDGE_BOTH
+				49 IRQ_TYPE_EDGE_BOTH 50 IRQ_TYPE_EDGE_BOTH>;
+			ti,ngpio = <144>;
+			ti,davinci-gpio-unbanked = <0>;
+			status = "disabled";
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+		pinconf: pin-controller@22c00c {
+			compatible = "ti,da850-pupd";
+			reg = <0x22c00c 0x8>;
+			status = "disabled";
+		};
+
+		mcasp0: mcasp@100000 {
+			compatible = "ti,da830-mcasp-audio";
+			reg = <0x100000 0x2000>,
+			      <0x102000 0x400000>;
+			reg-names = "mpu", "dat";
+			interrupts = <54>;
+			interrupt-names = "common";
+			status = "disabled";
+			dmas = <&edma0 1 1>,
+				<&edma0 0 1>;
+			dma-names = "tx", "rx";
+		};
+
+		lcdc: display@213000 {
+			compatible = "ti,da850-tilcdc";
+			reg = <0x213000 0x1000>;
+			interrupts = <52>;
+			max-pixelclock = <37500>;
+			status = "disabled";
+		};
+	};
+	aemif: aemif@68000000 {
+		compatible = "ti,da850-aemif";
+		#address-cells = <2>;
+		#size-cells = <1>;
+
+		reg = <0x68000000 0x00008000>;
+		ranges = <0 0 0x60000000 0x08000000
+			  1 0 0x68000000 0x00008000>;
+		status = "disabled";
+	};
+	memctrl: memory-controller@b0000000 {
+		compatible = "ti,da850-ddr-controller";
+		reg = <0xb0000000 0xe8>;
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/dts/omap3.dtsi b/arch/arm/dts/omap3.dtsi
index e6f9c9a..56c9472 100644
--- a/arch/arm/dts/omap3.dtsi
+++ b/arch/arm/dts/omap3.dtsi
@@ -716,14 +716,12 @@
 			usbhsohci: ohci@48064400 {
 				compatible = "ti,ohci-omap3";
 				reg = <0x48064400 0x400>;
-				interrupt-parent = <&intc>;
 				interrupts = <76>;
 			};
 
 			usbhsehci: ehci@48064800 {
 				compatible = "ti,ehci-omap";
 				reg = <0x48064800 0x400>;
-				interrupt-parent = <&intc>;
 				interrupts = <77>;
 			};
 		};
@@ -834,7 +832,6 @@
 				reg-names = "tx",
 					    "rx";
 
-				interrupt-parent = <&intc>;
 				interrupts = <67>,
 					     <68>;
 			};
@@ -847,7 +844,6 @@
 				reg-names = "tx",
 					    "rx";
 
-				interrupt-parent = <&intc>;
 				interrupts = <69>,
 					     <70>;
 			};
diff --git a/arch/arm/dts/omap5-u-boot.dtsi b/arch/arm/dts/omap5-u-boot.dtsi
index 2eeed6f..fdaa692 100644
--- a/arch/arm/dts/omap5-u-boot.dtsi
+++ b/arch/arm/dts/omap5-u-boot.dtsi
@@ -60,10 +60,30 @@
 	};
 };
 
+&gpio1 {
+	u-boot,dm-spl;
+};
+
 &gpio2 {
 	u-boot,dm-spl;
 };
 
+&gpio3 {
+	u-boot,dm-spl;
+};
+
+&gpio4 {
+	u-boot,dm-spl;
+};
+
+&gpio5 {
+	u-boot,dm-spl;
+};
+
+&gpio6 {
+	u-boot,dm-spl;
+};
+
 &gpio7 {
 	u-boot,dm-spl;
 };
diff --git a/arch/arm/dts/rk3229-evb.dts b/arch/arm/dts/rk3229-evb.dts
index 64f1c2d..ae0b0a4 100644
--- a/arch/arm/dts/rk3229-evb.dts
+++ b/arch/arm/dts/rk3229-evb.dts
@@ -40,7 +40,6 @@
 };
 
 &dmc {
-	rockchip,sdram-channel = /bits/ 8 <1 10 3 2 1 0 15 15>;
 	rockchip,pctl-timing = <0x96 0xC8 0x1F3 0xF 0x8000004D 0x4 0x4E 0x6 0x3
 		0x0 0x6 0x5 0xC 0x10 0x6 0x4 0x4
 		0x5 0x4 0x200 0x3 0xA 0x40 0x0 0x1
diff --git a/arch/arm/dts/rk3288-popmetal.dtsi b/arch/arm/dts/rk3288-popmetal.dtsi
index dd6ce8b..63785eb 100644
--- a/arch/arm/dts/rk3288-popmetal.dtsi
+++ b/arch/arm/dts/rk3288-popmetal.dtsi
@@ -491,6 +491,10 @@
 	};
 };
 
+&saradc {
+	status = "okay";
+};
+
 &tsadc {
 	rockchip,hw-tshut-mode = <0>;
 	rockchip,hw-tshut-polarity = <0>;
diff --git a/arch/arm/dts/rk3328-evb.dts b/arch/arm/dts/rk3328-evb.dts
index 8a14c65..3dd9d81 100644
--- a/arch/arm/dts/rk3328-evb.dts
+++ b/arch/arm/dts/rk3328-evb.dts
@@ -42,6 +42,10 @@
 	};
 };
 
+&saradc {
+	status = "okay";
+};
+
 &uart2 {
 	status = "okay";
 };
@@ -87,3 +91,121 @@
 	vbus-supply = <&vcc5v0_host_xhci>;
 	status = "okay";
 };
+
+&i2c1 {
+	clock-frequency = <400000>;
+	i2c-scl-rising-time-ns = <168>;
+	i2c-scl-falling-time-ns = <4>;
+	status = "okay";
+
+	rk805: pmic@18 {
+		compatible = "rockchip,rk805";
+		status = "okay";
+		reg = <0x18>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_int_l>;
+		rockchip,system-power-controller;
+		wakeup-source;
+		gpio-controller;
+		#gpio-cells = <2>;
+		#clock-cells = <1>;
+		clock-output-names = "xin32k", "rk805-clkout2";
+
+		regulators {
+			vdd_logic: DCDC_REG1 {
+				regulator-name = "vdd_logic";
+				regulator-min-microvolt = <712500>;
+				regulator-max-microvolt = <1450000>;
+				regulator-ramp-delay = <6001>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vdd_arm: DCDC_REG2 {
+				regulator-name = "vdd_arm";
+				regulator-min-microvolt = <712500>;
+				regulator-max-microvolt = <1450000>;
+				regulator-ramp-delay = <6001>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vcc_ddr: DCDC_REG3 {
+				regulator-name = "vcc_ddr";
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+
+			vcc_io: DCDC_REG4 {
+				regulator-name = "vcc_io";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vdd_18: LDO_REG1 {
+				regulator-name = "vdd_18";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vcc_18emmc: LDO_REG2 {
+				regulator-name = "vcc_18emmc";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1800000>;
+				};
+			};
+
+			vdd_10: LDO_REG3 {
+				regulator-name = "vdd_10";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+		};
+	};
+};
+
+&pinctrl {
+	pmic {
+		pmic_int_l: pmic-int-l {
+		rockchip,pins =
+			<2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>;	/* gpio2_a6 */
+		};
+	};
+};
+
diff --git a/arch/arm/dts/rk3368-px5-evb.dts b/arch/arm/dts/rk3368-px5-evb.dts
index c7478f7..e9c5eba 100644
--- a/arch/arm/dts/rk3368-px5-evb.dts
+++ b/arch/arm/dts/rk3368-px5-evb.dts
@@ -296,6 +296,10 @@
 	};
 };
 
+&saradc {
+	status = "okay";
+};
+
 &tsadc {
 	status = "okay";
 	rockchip,hw-tshut-mode = <0>; /* CRU */
diff --git a/arch/arm/dts/rk3368-sheep.dts b/arch/arm/dts/rk3368-sheep.dts
index 7c190f7..27befad 100644
--- a/arch/arm/dts/rk3368-sheep.dts
+++ b/arch/arm/dts/rk3368-sheep.dts
@@ -260,6 +260,10 @@
 	};
 };
 
+&saradc {
+	status = "okay";
+};
+
 &tsadc {
 	status = "okay";
 	rockchip,hw-tshut-mode = <0>; /* CRU */
diff --git a/arch/arm/dts/rk3399-evb.dts b/arch/arm/dts/rk3399-evb.dts
index be0c6d9..0e5d8d7 100644
--- a/arch/arm/dts/rk3399-evb.dts
+++ b/arch/arm/dts/rk3399-evb.dts
@@ -149,6 +149,10 @@
 	status = "okay";
 };
 
+&saradc {
+	status = "okay";
+};
+
 &sdmmc {
 	bus-width = <4>;
 	status = "okay";
diff --git a/arch/arm/dts/rk3399-puma.dtsi b/arch/arm/dts/rk3399-puma.dtsi
index a04878e..65ab380 100644
--- a/arch/arm/dts/rk3399-puma.dtsi
+++ b/arch/arm/dts/rk3399-puma.dtsi
@@ -20,7 +20,8 @@
 
 	chosen {
 		stdout-path = "serial0:115200n8";
-		u-boot,spl-boot-order = &spiflash, &sdhci, &sdmmc;
+		u-boot,spl-boot-order = \
+			"same-as-spl", &spiflash, &sdhci, &sdmmc;
 	};
 
 	aliases {
@@ -100,6 +101,24 @@
 		regulator-max-microvolt = <3300000>;
 	};
 
+	/*
+	 * The Qseven BIOS_DISABLE signal on the RK3399-Q7 keeps the on-module
+	 * eMMC and SPI flash powered-down initially (in fact it keeps the
+	 * reset signal asserted).  Even though it is an enable signal, we
+	 * model this as a regulator.
+	 */
+	bios_enable: bios_enable {
+		compatible = "regulator-fixed";
+		u-boot,dm-pre-reloc;
+		regulator-name = "bios_enable";
+		enable-active-low;
+		gpio = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
 	vccadc_ref: vccadc-ref {
 		compatible = "regulator-fixed";
 		regulator-name = "vcc1v8_sys";
@@ -458,7 +477,7 @@
 };
 
 &pcie_phy {
-	        status = "okay";
+		status = "okay";
 };
 
 &pmu_io_domains {
@@ -485,7 +504,7 @@
 };
 
 &sdmmc {
-        u-boot,dm-pre-reloc;
+	u-boot,dm-pre-reloc;
 	clock-frequency = <150000000>;
 	clock-freq-min-max = <100000 150000000>;
 	supports-sd;
@@ -532,10 +551,15 @@
 	status = "okay";
 };
 
+&gpio3 {
+	u-boot,dm-pre-reloc;
+};
+
 &pinctrl {
 	/* Pins that are not explicitely used by any devices */
 	pinctrl-names = "default";
 	pinctrl-0 = <&puma_pin_hog>;
+
 	hog {
 		puma_pin_hog: puma_pin_hog {
 			rockchip,pins =
@@ -575,7 +599,7 @@
 	i2c8 {
 		i2c8_xfer_a: i2c8-xfer {
 			rockchip,pins = <1 21 RK_FUNC_1 &pcfg_pull_up>,
-			                <1 20 RK_FUNC_1 &pcfg_pull_up>;
+					<1 20 RK_FUNC_1 &pcfg_pull_up>;
 		};
 	};
 };
@@ -651,4 +675,3 @@
 &spi5 {
 	status = "okay";
 };
-
diff --git a/arch/arm/dts/rv1108-evb.dts b/arch/arm/dts/rv1108-evb.dts
index 2b221b6..8e857b2 100644
--- a/arch/arm/dts/rv1108-evb.dts
+++ b/arch/arm/dts/rv1108-evb.dts
@@ -39,6 +39,10 @@
 	snps,reset-gpio = <&gpio1 RK_PC1 GPIO_ACTIVE_LOW>;
 };
 
+&saradc {
+	status = "okay";
+};
+
 &sfc {
 	status = "okay";
 	flash@0 {
diff --git a/arch/arm/dts/rv1108.dtsi b/arch/arm/dts/rv1108.dtsi
index 3153dfe..31b4d93 100644
--- a/arch/arm/dts/rv1108.dtsi
+++ b/arch/arm/dts/rv1108.dtsi
@@ -126,6 +126,17 @@
 		reg = <0x10300000 0x1000>;
 	};
 
+	saradc: saradc@1038c000 {
+		compatible = "rockchip,rv1108-saradc", "rockchip,rk3399-saradc";
+		reg = <0x1038c000 0x100>;
+		interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+		#io-channel-cells = <1>;
+		clock-frequency = <1000000>;
+		clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
+		clock-names = "saradc", "apb_pclk";
+		status = "disabled";
+	};
+
 	pmugrf: syscon@20060000 {
 		compatible = "rockchip,rv1108-pmugrf", "syscon";
 		reg = <0x20060000 0x1000>;
diff --git a/arch/arm/dts/stm32h743-pinctrl.dtsi b/arch/arm/dts/stm32h743-pinctrl.dtsi
index d3e11d5..e4f4aa5 100644
--- a/arch/arm/dts/stm32h743-pinctrl.dtsi
+++ b/arch/arm/dts/stm32h743-pinctrl.dtsi
@@ -244,6 +244,32 @@
 					  slew-rate = <3>;
 				};
 			};
+
+			sdmmc1_pins: sdmmc@0 {
+				pins {
+					pinmux = <STM32H7_PC8_FUNC_SDMMC1_D0>,
+						 <STM32H7_PC9_FUNC_SDMMC1_D1>,
+						 <STM32H7_PC10_FUNC_SDMMC1_D2>,
+						 <STM32H7_PC11_FUNC_SDMMC1_D3>,
+						 <STM32H7_PC12_FUNC_SDMMC1_CK>,
+						 <STM32H7_PD2_FUNC_SDMMC1_CMD>;
+
+					slew-rate = <3>;
+					drive-push-pull;
+					bias-disable;
+				};
+			};
+
+			pinctrl_sdmmc1_level_shifter: sdmmc0_ls@0 {
+				pins {
+					pinmux = <STM32H7_PB8_FUNC_SDMMC1_CKIN>,
+						 <STM32H7_PB9_FUNC_SDMMC1_CDIR>,
+						 <STM32H7_PC6_FUNC_SDMMC1_D0DIR>,
+						 <STM32H7_PC7_FUNC_SDMMC1_D123DIR>;
+					drive-push-pull;
+					slew-rate = <3>;
+				};
+			};
 		};
 	};
 };
diff --git a/arch/arm/dts/stm32h743.dtsi b/arch/arm/dts/stm32h743.dtsi
index 16e9308..d5b8d87 100644
--- a/arch/arm/dts/stm32h743.dtsi
+++ b/arch/arm/dts/stm32h743.dtsi
@@ -43,6 +43,7 @@
 #include "skeleton.dtsi"
 #include "armv7-m.dtsi"
 #include <dt-bindings/clock/stm32h7-clks.h>
+#include <dt-bindings/mfd/stm32h7-rcc.h>
 
 / {
 	clocks {
@@ -76,7 +77,7 @@
 		};
 
 		usart1: serial@40011000 {
-			compatible = "st,stm32h7-usart", "st,stm32h7-uart";
+			compatible = "st,stm32h7-uart";
 			reg = <0x40011000 0x400>;
 			interrupts = <37>;
 			status = "disabled";
@@ -84,7 +85,7 @@
 		};
 
 		usart2: serial@40004400 {
-			compatible = "st,stm32h7-usart", "st,stm32h7-uart";
+			compatible = "st,stm32h7-uart";
 			reg = <0x40004400 0x400>;
 			interrupts = <38>;
 			status = "disabled";
@@ -120,6 +121,18 @@
 			compatible = "fixed-clock";
 			clock-frequency = <4000000>;
 		};
+
+		sdmmc1: sdmmc@52007000 {
+			compatible = "st,stm32-sdmmc2";
+			reg = <0x52007000 0x1000>;
+			interrupts = <49>;
+			clocks = <&rcc SDMMC1_CK>;
+			resets = <&rcc STM32H7_AHB3_RESET(SDMMC1)>;
+			st,idma = <1>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			status = "disabled";
+		};
 	};
 };
 
diff --git a/arch/arm/dts/stm32h743i-disco.dts b/arch/arm/dts/stm32h743i-disco.dts
index bef7e90..917a859 100644
--- a/arch/arm/dts/stm32h743i-disco.dts
+++ b/arch/arm/dts/stm32h743i-disco.dts
@@ -60,6 +60,7 @@
 
 	aliases {
 		serial0 = &usart2;
+		mmc0 = &sdmmc1;
 		gpio0 = &gpioa;
 		gpio1 = &gpiob;
 		gpio2 = &gpioc;
@@ -98,3 +99,11 @@
 		st,sdram-refcount = <1539>;
 	};
 };
+
+&sdmmc1 {
+	status = "okay";
+	pinctrl-0 = <&sdmmc1_pins>;
+	pinctrl-names = "default";
+	bus-width = <4>;
+	cd-gpios = <&gpioi 8 1>;
+};
diff --git a/arch/arm/dts/stm32h743i-eval.dts b/arch/arm/dts/stm32h743i-eval.dts
index 0e01ce5..28c876b 100644
--- a/arch/arm/dts/stm32h743i-eval.dts
+++ b/arch/arm/dts/stm32h743i-eval.dts
@@ -98,3 +98,12 @@
 		st,sdram-refcount = <1539>;
 	};
 };
+
+&sdmmc1 {
+	status = "okay";
+	pinctrl-0 = <&sdmmc1_pins>,
+		    <&pinctrl_sdmmc1_level_shifter>;
+	pinctrl-names = "default";
+	bus-width = <4>;
+	st,dirpol;
+};
diff --git a/arch/arm/dts/sun7i-a20-bananapi-m1-plus.dts b/arch/arm/dts/sun7i-a20-bananapi-m1-plus.dts
index ba5bca0..4c03cc3 100644
--- a/arch/arm/dts/sun7i-a20-bananapi-m1-plus.dts
+++ b/arch/arm/dts/sun7i-a20-bananapi-m1-plus.dts
@@ -105,6 +105,10 @@
 	status = "okay";
 };
 
+&cpu0 {
+	cpu-supply = <&reg_dcdc2>;
+};
+
 &ehci0 {
 	status = "okay";
 };
@@ -132,16 +136,14 @@
 	status = "okay";
 
 	axp209: pmic@34 {
-		compatible = "x-powers,axp209";
 		reg = <0x34>;
 		interrupt-parent = <&nmi_intc>;
 		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
-
-		interrupt-controller;
-		#interrupt-cells = <1>;
 	};
 };
 
+#include "axp209.dtsi"
+
 &ir0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&ir0_rx_pins_a>;
@@ -167,10 +169,10 @@
 	mmc-pwrseq = <&mmc3_pwrseq>;
 	bus-width = <4>;
 	non-removable;
-	enable-sdio-wakeup;
+	wakeup-source;
 	status = "okay";
 
-	brcmf: bcrmf@1 {
+	brcmf: wifi@1 {
 		reg = <1>;
 		compatible = "brcm,bcm4329-fmac";
 		interrupt-parent = <&pio>;
@@ -181,7 +183,7 @@
 
 &mmc3_pins_a {
 	/* AP6210 requires pull-up */
-	allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+	bias-pull-up;
 };
 
 &ohci0 {
@@ -192,38 +194,81 @@
 	status = "okay";
 };
 
+&otg_sram {
+	status = "okay";
+};
+
 &pio {
 	gmac_power_pin_bpi_m1p: gmac_power_pin@0 {
-		allwinner,pins = "PH23";
-		allwinner,function = "gpio_out";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+		pins = "PH23";
+		function = "gpio_out";
 	};
 
 	led_pins_bpi_m1p: led_pins@0 {
-		allwinner,pins = "PH24", "PH25";
-		allwinner,function = "gpio_out";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+		pins = "PH24", "PH25";
+		function = "gpio_out";
 	};
 
 	mmc0_cd_pin_bpi_m1p: mmc0_cd_pin@0 {
-		allwinner,pins = "PH10";
-		allwinner,function = "gpio_in";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+		pins = "PH10";
+		function = "gpio_in";
+		bias-pull-up;
 	};
 
 	mmc3_pwrseq_pin_bpi_m1p: mmc3_pwrseq_pin@0 {
-		allwinner,pins = "PH22";
-		allwinner,function = "gpio_out";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+		pins = "PH22";
+		function = "gpio_out";
 	};
 };
 
+&reg_dcdc2 {
+	regulator-always-on;
+	regulator-min-microvolt = <1000000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc3 {
+	regulator-always-on;
+	regulator-min-microvolt = <1000000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-int-dll";
+};
+
+&reg_ldo1 {
+	regulator-name = "vdd-rtc";
+};
+
+&reg_ldo2 {
+	regulator-always-on;
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-name = "avcc";
+};
+
+&reg_usb0_vbus {
+	status = "okay";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
 	status = "okay";
 };
+
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usb_power_supply {
+	status = "okay";
+};
+
+&usbphy {
+	usb0_id_det-gpios = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+	usb0_vbus_power-supply = <&usb_power_supply>;
+	usb0_vbus-supply = <&reg_usb0_vbus>;
+	/* VBUS on usb host ports are tied to DC5V and therefore always on */
+	status = "okay";
+};
diff --git a/arch/arm/dts/sun7i-a20-olinuxino-micro-emmc.dts b/arch/arm/dts/sun7i-a20-olinuxino-micro-emmc.dts
new file mode 100644
index 0000000..d99e7b1
--- /dev/null
+++ b/arch/arm/dts/sun7i-a20-olinuxino-micro-emmc.dts
@@ -0,0 +1,70 @@
+ /*
+ * Copyright 2017 Olimex Ltd.
+ * Stefan Mavrodiev <stefan@olimex.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "sun7i-a20-olinuxino-micro.dts"
+
+/ {
+	model = "Olimex A20-OLinuXino-MICRO-eMMC";
+	compatible = "olimex,a20-olinuxino-micro-emmc", "allwinner,sun7i-a20";
+
+	mmc2_pwrseq: pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&pio 2 16 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins_a>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	non-removable;
+	mmc-pwrseq = <&mmc2_pwrseq>;
+	status = "okay";
+
+	emmc: emmc@0 {
+		reg = <0>;
+		compatible = "mmc-card";
+		broken-hpi;
+	};
+};
diff --git a/arch/arm/dts/sun8i-a23-a33.dtsi b/arch/arm/dts/sun8i-a23-a33.dtsi
index f97c38f..ea50dda 100644
--- a/arch/arm/dts/sun8i-a23-a33.dtsi
+++ b/arch/arm/dts/sun8i-a23-a33.dtsi
@@ -46,7 +46,8 @@
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-#include <dt-bindings/pinctrl/sun4i-a10.h>
+#include <dt-bindings/clock/sun8i-a23-a33-ccu.h>
+#include <dt-bindings/reset/sun8i-a23-a33-ccu.h>
 
 / {
 	interrupt-parent = <&gic>;
@@ -60,7 +61,9 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0";
-			clocks = <&pll6 0>;
+			clocks = <&ccu CLK_BUS_LCD>, <&ccu CLK_BUS_DE_BE>,
+				 <&ccu CLK_LCD_CH0>, <&ccu CLK_DE_BE>,
+				 <&ccu CLK_DRAM_DE_BE>, <&ccu CLK_DRC>;
 			status = "disabled";
 		};
 	};
@@ -80,7 +83,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		cpu@0 {
+		cpu0: cpu@0 {
 			compatible = "arm,cortex-a7";
 			device_type = "cpu";
 			reg = <0>;
@@ -102,151 +105,16 @@
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <24000000>;
+			clock-accuracy = <50000>;
 			clock-output-names = "osc24M";
 		};
 
-		osc32k: osc32k_clk {
+		ext_osc32k: ext_osc32k_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <32768>;
-			clock-output-names = "osc32k";
-		};
-
-		pll1: clk@01c20000 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun8i-a23-pll1-clk";
-			reg = <0x01c20000 0x4>;
-			clocks = <&osc24M>;
-			clock-output-names = "pll1";
-		};
-
-		/* dummy clock until actually implemented */
-		pll5: pll5_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <0>;
-			clock-output-names = "pll5";
-		};
-
-		pll6: clk@01c20028 {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun6i-a31-pll6-clk";
-			reg = <0x01c20028 0x4>;
-			clocks = <&osc24M>;
-			clock-output-names = "pll6", "pll6x2";
-		};
-
-		cpu: cpu_clk@01c20050 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-cpu-clk";
-			reg = <0x01c20050 0x4>;
-
-			/*
-			 * PLL1 is listed twice here.
-			 * While it looks suspicious, it's actually documented
-			 * that way both in the datasheet and in the code from
-			 * Allwinner.
-			 */
-			clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>;
-			clock-output-names = "cpu";
-		};
-
-		axi: axi_clk@01c20050 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun8i-a23-axi-clk";
-			reg = <0x01c20050 0x4>;
-			clocks = <&cpu>;
-			clock-output-names = "axi";
-		};
-
-		ahb1: ahb1_clk@01c20054 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun6i-a31-ahb1-clk";
-			reg = <0x01c20054 0x4>;
-			clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>;
-			clock-output-names = "ahb1";
-		};
-
-		apb1: apb1_clk@01c20054 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-apb0-clk";
-			reg = <0x01c20054 0x4>;
-			clocks = <&ahb1>;
-			clock-output-names = "apb1";
-		};
-
-		apb1_gates: clk@01c20068 {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun8i-a23-apb1-gates-clk";
-			reg = <0x01c20068 0x4>;
-			clocks = <&apb1>;
-			clock-indices = <0>, <5>,
-					<12>, <13>;
-			clock-output-names = "apb1_codec", "apb1_pio",
-					"apb1_daudio0",	"apb1_daudio1";
-		};
-
-		apb2: clk@01c20058 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-apb1-clk";
-			reg = <0x01c20058 0x4>;
-			clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>;
-			clock-output-names = "apb2";
-		};
-
-		apb2_gates: clk@01c2006c {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun8i-a23-apb2-gates-clk";
-			reg = <0x01c2006c 0x4>;
-			clocks = <&apb2>;
-			clock-indices = <0>, <1>,
-					<2>, <16>,
-					<17>, <18>,
-					<19>, <20>;
-			clock-output-names = "apb2_i2c0", "apb2_i2c1",
-					"apb2_i2c2", "apb2_uart0",
-					"apb2_uart1", "apb2_uart2",
-					"apb2_uart3", "apb2_uart4";
-		};
-
-		mmc0_clk: clk@01c20088 {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun4i-a10-mmc-clk";
-			reg = <0x01c20088 0x4>;
-			clocks = <&osc24M>, <&pll6 0>;
-			clock-output-names = "mmc0",
-					     "mmc0_output",
-					     "mmc0_sample";
-		};
-
-		mmc1_clk: clk@01c2008c {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun4i-a10-mmc-clk";
-			reg = <0x01c2008c 0x4>;
-			clocks = <&osc24M>, <&pll6 0>;
-			clock-output-names = "mmc1",
-					     "mmc1_output",
-					     "mmc1_sample";
-		};
-
-		mmc2_clk: clk@01c20090 {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun4i-a10-mmc-clk";
-			reg = <0x01c20090 0x4>;
-			clocks = <&osc24M>, <&pll6 0>;
-			clock-output-names = "mmc2",
-					     "mmc2_output",
-					     "mmc2_sample";
-		};
-
-		usb_clk: clk@01c200cc {
-			#clock-cells = <1>;
-			#reset-cells = <1>;
-			compatible = "allwinner,sun8i-a23-usb-clk";
-			reg = <0x01c200cc 0x4>;
-			clocks = <&osc24M>;
-			clock-output-names = "usb_phy0", "usb_phy1", "usb_hsic",
-					     "usb_hsic_12M", "usb_ohci0";
+			clock-accuracy = <50000>;
+			clock-output-names = "ext-osc32k";
 		};
 	};
 
@@ -260,24 +128,23 @@
 			compatible = "allwinner,sun8i-a23-dma";
 			reg = <0x01c02000 0x1000>;
 			interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&ahb1_gates 6>;
-			resets = <&ahb1_rst 6>;
+			clocks = <&ccu CLK_BUS_DMA>;
+			resets = <&ccu RST_BUS_DMA>;
 			#dma-cells = <1>;
 		};
 
 		mmc0: mmc@01c0f000 {
-			compatible = "allwinner,sun7i-a20-mmc",
-				     "allwinner,sun5i-a13-mmc";
+			compatible = "allwinner,sun7i-a20-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb1_gates 8>,
-				 <&mmc0_clk 0>,
-				 <&mmc0_clk 1>,
-				 <&mmc0_clk 2>;
+			clocks = <&ccu CLK_BUS_MMC0>,
+				 <&ccu CLK_MMC0>,
+				 <&ccu CLK_MMC0_OUTPUT>,
+				 <&ccu CLK_MMC0_SAMPLE>;
 			clock-names = "ahb",
 				      "mmc",
 				      "output",
 				      "sample";
-			resets = <&ahb1_rst 8>;
+			resets = <&ccu RST_BUS_MMC0>;
 			reset-names = "ahb";
 			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
@@ -286,18 +153,17 @@
 		};
 
 		mmc1: mmc@01c10000 {
-			compatible = "allwinner,sun7i-a20-mmc",
-				     "allwinner,sun5i-a13-mmc";
+			compatible = "allwinner,sun7i-a20-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb1_gates 9>,
-				 <&mmc1_clk 0>,
-				 <&mmc1_clk 1>,
-				 <&mmc1_clk 2>;
+			clocks = <&ccu CLK_BUS_MMC1>,
+				 <&ccu CLK_MMC1>,
+				 <&ccu CLK_MMC1_OUTPUT>,
+				 <&ccu CLK_MMC1_SAMPLE>;
 			clock-names = "ahb",
 				      "mmc",
 				      "output",
 				      "sample";
-			resets = <&ahb1_rst 9>;
+			resets = <&ccu RST_BUS_MMC1>;
 			reset-names = "ahb";
 			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
@@ -306,18 +172,17 @@
 		};
 
 		mmc2: mmc@01c11000 {
-			compatible = "allwinner,sun7i-a20-mmc",
-				     "allwinner,sun5i-a13-mmc";
+			compatible = "allwinner,sun7i-a20-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb1_gates 10>,
-				 <&mmc2_clk 0>,
-				 <&mmc2_clk 1>,
-				 <&mmc2_clk 2>;
+			clocks = <&ccu CLK_BUS_MMC2>,
+				 <&ccu CLK_MMC2>,
+				 <&ccu CLK_MMC2_OUTPUT>,
+				 <&ccu CLK_MMC2_SAMPLE>;
 			clock-names = "ahb",
 				      "mmc",
 				      "output",
 				      "sample";
-			resets = <&ahb1_rst 10>;
+			resets = <&ccu RST_BUS_MMC2>;
 			reset-names = "ahb";
 			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
@@ -325,12 +190,55 @@
 			#size-cells = <0>;
 		};
 
+		nfc: nand@01c03000 {
+			compatible = "allwinner,sun4i-a10-nand";
+			reg = <0x01c03000 0x1000>;
+			interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_NAND>, <&ccu CLK_NAND>;
+			clock-names = "ahb", "mod";
+			resets = <&ccu RST_BUS_NAND>;
+			reset-names = "ahb";
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		usb_otg: usb@01c19000 {
+			/* compatible gets set in SoC specific dtsi file */
+			reg = <0x01c19000 0x0400>;
+			clocks = <&ccu CLK_BUS_OTG>;
+			resets = <&ccu RST_BUS_OTG>;
+			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "mc";
+			phys = <&usbphy 0>;
+			phy-names = "usb";
+			extcon = <&usbphy 0>;
+			status = "disabled";
+		};
+
+		usbphy: phy@01c19400 {
+			/*
+			 * compatible and address regions get set in
+			 * SoC specific dtsi file
+			 */
+			clocks = <&ccu CLK_USB_PHY0>,
+				 <&ccu CLK_USB_PHY1>;
+			clock-names = "usb0_phy",
+				      "usb1_phy";
+			resets = <&ccu RST_USB_PHY0>,
+				 <&ccu RST_USB_PHY1>;
+			reset-names = "usb0_reset",
+				      "usb1_reset";
+			status = "disabled";
+			#phy-cells = <1>;
+		};
+
 		ehci0: usb@01c1a000 {
 			compatible = "allwinner,sun8i-a23-ehci", "generic-ehci";
 			reg = <0x01c1a000 0x100>;
 			interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&ahb1_gates 26>;
-			resets = <&ahb1_rst 26>;
+			clocks = <&ccu CLK_BUS_EHCI>;
+			resets = <&ccu RST_BUS_EHCI>;
 			phys = <&usbphy 1>;
 			phy-names = "usb";
 			status = "disabled";
@@ -340,101 +248,100 @@
 			compatible = "allwinner,sun8i-a23-ohci", "generic-ohci";
 			reg = <0x01c1a400 0x100>;
 			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&ahb1_gates 29>, <&usb_clk 16>;
-			resets = <&ahb1_rst 29>;
+			clocks = <&ccu CLK_BUS_OHCI>, <&ccu CLK_USB_OHCI>;
+			resets = <&ccu RST_BUS_OHCI>;
 			phys = <&usbphy 1>;
 			phy-names = "usb";
 			status = "disabled";
 		};
 
+		ccu: clock@01c20000 {
+			reg = <0x01c20000 0x400>;
+			clocks = <&osc24M>, <&rtc 0>;
+			clock-names = "hosc", "losc";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
 		pio: pinctrl@01c20800 {
 			/* compatible gets set in SoC specific dtsi file */
 			reg = <0x01c20800 0x400>;
 			/* interrupts get set in SoC specific dtsi file */
-			clocks = <&apb1_gates 5>;
+			clocks = <&ccu CLK_BUS_PIO>, <&osc24M>, <&rtc 0>;
+			clock-names = "apb", "hosc", "losc";
 			gpio-controller;
 			interrupt-controller;
 			#interrupt-cells = <3>;
 			#gpio-cells = <3>;
 
 			uart0_pins_a: uart0@0 {
-				allwinner,pins = "PF2", "PF4";
-				allwinner,function = "uart0";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+				pins = "PF2", "PF4";
+				function = "uart0";
+			};
+
+			uart1_pins_a: uart1@0 {
+				pins = "PG6", "PG7";
+				function = "uart1";
+			};
+
+			uart1_pins_cts_rts_a: uart1-cts-rts@0 {
+				pins = "PG8", "PG9";
+				function = "uart1";
 			};
 
 			mmc0_pins_a: mmc0@0 {
-				allwinner,pins = "PF0", "PF1", "PF2",
-						 "PF3", "PF4", "PF5";
-				allwinner,function = "mmc0";
-				allwinner,drive = <SUN4I_PINCTRL_30_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+				pins = "PF0", "PF1", "PF2",
+				       "PF3", "PF4", "PF5";
+				function = "mmc0";
+				drive-strength = <30>;
+				bias-pull-up;
 			};
 
 			mmc1_pins_a: mmc1@0 {
-				allwinner,pins = "PG0", "PG1", "PG2",
-						 "PG3", "PG4", "PG5";
-				allwinner,function = "mmc1";
-				allwinner,drive = <SUN4I_PINCTRL_30_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+				pins = "PG0", "PG1", "PG2",
+				       "PG3", "PG4", "PG5";
+				function = "mmc1";
+				drive-strength = <30>;
+				bias-pull-up;
 			};
 
 			mmc2_8bit_pins: mmc2_8bit {
-				allwinner,pins = "PC5", "PC6", "PC8",
-						 "PC9", "PC10", "PC11",
-						 "PC12", "PC13", "PC14",
-						 "PC15", "PC16";
-				allwinner,function = "mmc2";
-				allwinner,drive = <SUN4I_PINCTRL_30_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+				pins = "PC5", "PC6", "PC8",
+				       "PC9", "PC10", "PC11",
+				       "PC12", "PC13", "PC14",
+				       "PC15", "PC16";
+				function = "mmc2";
+				drive-strength = <30>;
+				bias-pull-up;
 			};
 
 			pwm0_pins: pwm0 {
-				allwinner,pins = "PH0";
-				allwinner,function = "pwm0";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+				pins = "PH0";
+				function = "pwm0";
 			};
 
 			i2c0_pins_a: i2c0@0 {
-				allwinner,pins = "PH2", "PH3";
-				allwinner,function = "i2c0";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+				pins = "PH2", "PH3";
+				function = "i2c0";
 			};
 
 			i2c1_pins_a: i2c1@0 {
-				allwinner,pins = "PH4", "PH5";
-				allwinner,function = "i2c1";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+				pins = "PH4", "PH5";
+				function = "i2c1";
 			};
 
 			i2c2_pins_a: i2c2@0 {
-				allwinner,pins = "PE12", "PE13";
-				allwinner,function = "i2c2";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+				pins = "PE12", "PE13";
+				function = "i2c2";
 			};
-		};
 
-		ahb1_rst: reset@01c202c0 {
-			#reset-cells = <1>;
-			compatible = "allwinner,sun6i-a31-clock-reset";
-			reg = <0x01c202c0 0xc>;
-		};
-
-		apb1_rst: reset@01c202d0 {
-			#reset-cells = <1>;
-			compatible = "allwinner,sun6i-a31-clock-reset";
-			reg = <0x01c202d0 0x4>;
-		};
-
-		apb2_rst: reset@01c202d8 {
-			#reset-cells = <1>;
-			compatible = "allwinner,sun6i-a31-clock-reset";
-			reg = <0x01c202d8 0x4>;
+			lcd_rgb666_pins: lcd-rgb666@0 {
+				pins = "PD2", "PD3", "PD4", "PD5", "PD6", "PD7",
+				       "PD10", "PD11", "PD12", "PD13", "PD14", "PD15",
+				       "PD18", "PD19", "PD20", "PD21", "PD22", "PD23",
+				       "PD24", "PD25", "PD26", "PD27";
+				function = "lcd0";
+			};
 		};
 
 		timer@01c20c00 {
@@ -472,8 +379,8 @@
 			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&apb2_gates 16>;
-			resets = <&apb2_rst 16>;
+			clocks = <&ccu CLK_BUS_UART0>;
+			resets = <&ccu RST_BUS_UART0>;
 			dmas = <&dma 6>, <&dma 6>;
 			dma-names = "rx", "tx";
 			status = "disabled";
@@ -485,8 +392,8 @@
 			interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&apb2_gates 17>;
-			resets = <&apb2_rst 17>;
+			clocks = <&ccu CLK_BUS_UART1>;
+			resets = <&ccu RST_BUS_UART1>;
 			dmas = <&dma 7>, <&dma 7>;
 			dma-names = "rx", "tx";
 			status = "disabled";
@@ -498,8 +405,8 @@
 			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&apb2_gates 18>;
-			resets = <&apb2_rst 18>;
+			clocks = <&ccu CLK_BUS_UART2>;
+			resets = <&ccu RST_BUS_UART2>;
 			dmas = <&dma 8>, <&dma 8>;
 			dma-names = "rx", "tx";
 			status = "disabled";
@@ -511,8 +418,8 @@
 			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&apb2_gates 19>;
-			resets = <&apb2_rst 19>;
+			clocks = <&ccu CLK_BUS_UART3>;
+			resets = <&ccu RST_BUS_UART3>;
 			dmas = <&dma 9>, <&dma 9>;
 			dma-names = "rx", "tx";
 			status = "disabled";
@@ -524,8 +431,8 @@
 			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&apb2_gates 20>;
-			resets = <&apb2_rst 20>;
+			clocks = <&ccu CLK_BUS_UART4>;
+			resets = <&ccu RST_BUS_UART4>;
 			dmas = <&dma 10>, <&dma 10>;
 			dma-names = "rx", "tx";
 			status = "disabled";
@@ -535,8 +442,8 @@
 			compatible = "allwinner,sun6i-a31-i2c";
 			reg = <0x01c2ac00 0x400>;
 			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&apb2_gates 0>;
-			resets = <&apb2_rst 0>;
+			clocks = <&ccu CLK_BUS_I2C0>;
+			resets = <&ccu RST_BUS_I2C0>;
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -546,8 +453,8 @@
 			compatible = "allwinner,sun6i-a31-i2c";
 			reg = <0x01c2b000 0x400>;
 			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&apb2_gates 1>;
-			resets = <&apb2_rst 1>;
+			clocks = <&ccu CLK_BUS_I2C1>;
+			resets = <&ccu RST_BUS_I2C1>;
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -557,17 +464,44 @@
 			compatible = "allwinner,sun6i-a31-i2c";
 			reg = <0x01c2b400 0x400>;
 			interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&apb2_gates 2>;
-			resets = <&apb2_rst 2>;
+			clocks = <&ccu CLK_BUS_I2C2>;
+			resets = <&ccu RST_BUS_I2C2>;
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
 		};
 
+		mali: gpu@1c40000 {
+			compatible = "allwinner,sun8i-a23-mali",
+				     "allwinner,sun7i-a20-mali", "arm,mali-400";
+			reg = <0x01c40000 0x10000>;
+			interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "gp",
+					  "gpmmu",
+					  "pp0",
+					  "ppmmu0",
+					  "pp1",
+					  "ppmmu1",
+					  "pmu";
+			clocks = <&ccu CLK_BUS_GPU>, <&ccu CLK_GPU>;
+			clock-names = "bus", "core";
+			resets = <&ccu RST_BUS_GPU>;
+			#cooling-cells = <2>;
+
+			assigned-clocks = <&ccu CLK_GPU>;
+			assigned-clock-rates = <384000000>;
+		};
+
 		gic: interrupt-controller@01c81000 {
 			compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
 			reg = <0x01c81000 0x1000>,
-			      <0x01c82000 0x1000>,
+			      <0x01c82000 0x2000>,
 			      <0x01c84000 0x2000>,
 			      <0x01c86000 0x2000>;
 			interrupt-controller;
@@ -580,13 +514,16 @@
 			reg = <0x01f00000 0x54>;
 			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+			clock-output-names = "osc32k";
+			clocks = <&ext_osc32k>;
+			#clock-cells = <1>;
 		};
 
-		nmi_intc: interrupt-controller@01f00c0c {
-			compatible = "allwinner,sun6i-a31-sc-nmi";
+		nmi_intc: interrupt-controller@1f00c00 {
+			compatible = "allwinner,sun6i-a31-r-intc";
 			interrupt-controller;
 			#interrupt-cells = <2>;
-			reg = <0x01f00c0c 0x38>;
+			reg = <0x01f00c00 0x400>;
 			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
@@ -632,6 +569,10 @@
 				compatible = "allwinner,sun6i-a31-clock-reset";
 				#reset-cells = <1>;
 			};
+
+			codec_analog: codec-analog {
+				compatible = "allwinner,sun8i-a23-codec-analog";
+			};
 		};
 
 		cpucfg@01f01c00 {
@@ -654,7 +595,8 @@
 			compatible = "allwinner,sun8i-a23-r-pinctrl";
 			reg = <0x01f02c00 0x400>;
 			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&apb0_gates 0>;
+			clocks = <&apb0_gates 0>, <&osc24M>, <&rtc 0>;
+			clock-names = "apb", "hosc", "losc";
 			resets = <&apb0_rst 0>;
 			gpio-controller;
 			interrupt-controller;
@@ -664,17 +606,15 @@
 			#gpio-cells = <3>;
 
 			r_rsb_pins: r_rsb {
-				allwinner,pins = "PL0", "PL1";
-				allwinner,function = "s_rsb";
-				allwinner,drive = <SUN4I_PINCTRL_20_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+				pins = "PL0", "PL1";
+				function = "s_rsb";
+				drive-strength = <20>;
+				bias-pull-up;
 			};
 
 			r_uart_pins_a: r_uart@0 {
-				allwinner,pins = "PL2", "PL3";
-				allwinner,function = "s_uart";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+				pins = "PL2", "PL3";
+				function = "s_uart";
 			};
 		};
 
diff --git a/arch/arm/dts/sun8i-a23.dtsi b/arch/arm/dts/sun8i-a23.dtsi
index 92e6616..4d1f929 100644
--- a/arch/arm/dts/sun8i-a23.dtsi
+++ b/arch/arm/dts/sun8i-a23.dtsi
@@ -49,78 +49,40 @@
 		reg = <0x40000000 0x40000000>;
 	};
 
-	clocks {
-		ahb1_gates: clk@01c20060 {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun8i-a23-ahb1-gates-clk";
-			reg = <0x01c20060 0x8>;
-			clocks = <&ahb1>;
-			clock-indices = <1>, <6>,
-					<8>, <9>, <10>,
-					<13>, <14>,
-					<19>, <20>,
-					<21>, <24>, <26>,
-					<29>, <32>, <36>,
-					<40>, <44>, <46>,
-					<52>, <53>,
-					<54>, <57>;
-			clock-output-names = "ahb1_mipidsi", "ahb1_dma",
-					"ahb1_mmc0", "ahb1_mmc1", "ahb1_mmc2",
-					"ahb1_nand", "ahb1_sdram",
-					"ahb1_hstimer", "ahb1_spi0",
-					"ahb1_spi1", "ahb1_otg", "ahb1_ehci",
-					"ahb1_ohci", "ahb1_ve", "ahb1_lcd",
-					"ahb1_csi", "ahb1_be",	"ahb1_fe",
-					"ahb1_gpu", "ahb1_msgbox",
-					"ahb1_spinlock", "ahb1_drc";
-		};
-
-		mbus_clk: clk@01c2015c {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun8i-a23-mbus-clk";
-			reg = <0x01c2015c 0x4>;
-			clocks = <&osc24M>, <&pll6 1>, <&pll5>;
-			clock-output-names = "mbus";
-		};
-	};
-
 	soc@01c00000 {
-		usb_otg: usb@01c19000 {
-			compatible = "allwinner,sun6i-a31-musb";
-			reg = <0x01c19000 0x0400>;
-			clocks = <&ahb1_gates 24>;
-			resets = <&ahb1_rst 24>;
-			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names = "mc";
-			phys = <&usbphy 0>;
-			phy-names = "usb";
-			extcon = <&usbphy 0>;
+		codec: codec@01c22c00 {
+			#sound-dai-cells = <0>;
+			compatible = "allwinner,sun8i-a23-codec";
+			reg = <0x01c22c00 0x400>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>;
+			clock-names = "apb", "codec";
+			resets = <&ccu RST_BUS_CODEC>;
+			dmas = <&dma 15>, <&dma 15>;
+			dma-names = "rx", "tx";
+			allwinner,codec-analog-controls = <&codec_analog>;
 			status = "disabled";
 		};
-
-		usbphy: phy@01c19400 {
-			compatible = "allwinner,sun8i-a23-usb-phy";
-			reg = <0x01c19400 0x10>,
-			      <0x01c1a800 0x4>;
-			reg-names = "phy_ctrl",
-				    "pmu1";
-			clocks = <&usb_clk 8>,
-				 <&usb_clk 9>;
-			clock-names = "usb0_phy",
-				      "usb1_phy";
-			resets = <&usb_clk 0>,
-				 <&usb_clk 1>;
-			reset-names = "usb0_reset",
-				      "usb1_reset";
-			status = "disabled";
-			#phy-cells = <1>;
-		};
 	};
 };
 
+&ccu {
+	compatible = "allwinner,sun8i-a23-ccu";
+};
+
 &pio {
 	compatible = "allwinner,sun8i-a23-pinctrl";
 	interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
 		     <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
 		     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
 };
+
+&usb_otg {
+	compatible = "allwinner,sun6i-a31-musb";
+};
+
+&usbphy {
+	compatible = "allwinner,sun8i-a23-usb-phy";
+	reg = <0x01c19400 0x10>, <0x01c1a800 0x4>;
+	reg-names = "phy_ctrl", "pmu1";
+};
diff --git a/arch/arm/dts/sun8i-a33-sinlinx-sina33.dts b/arch/arm/dts/sun8i-a33-sinlinx-sina33.dts
index fef6abc..b1bc88c 100644
--- a/arch/arm/dts/sun8i-a33-sinlinx-sina33.dts
+++ b/arch/arm/dts/sun8i-a33-sinlinx-sina33.dts
@@ -61,6 +61,31 @@
 	chosen {
 		stdout-path = "serial0:115200n8";
 	};
+
+	panel {
+		compatible = "netron-dy,e231732";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			panel_input: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&tcon0_out_panel>;
+			};
+		};
+	};
+};
+
+&de {
+	status = "okay";
+};
+
+&cpu0 {
+	cpu-supply = <&reg_dcdc3>;
 };
 
 &ehci0 {
@@ -207,12 +232,30 @@
 	regulator-name = "vcc-rtc";
 };
 
+&tcon0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_rgb666_pins>;
+	status = "okay";
+};
+
+&tcon0_out {
+	tcon0_out_panel: endpoint@0 {
+		reg = <0>;
+		remote-endpoint = <&panel_input>;
+	};
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_b>;
 	status = "okay";
 };
 
+&usb_otg {
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
 &usbphy {
 	status = "okay";
 	usb1_vbus-supply = <&reg_vcc5v0>; /* USB1 VBUS is always on */
diff --git a/arch/arm/dts/sun8i-a33.dtsi b/arch/arm/dts/sun8i-a33.dtsi
index 001d840..2266091 100644
--- a/arch/arm/dts/sun8i-a33.dtsi
+++ b/arch/arm/dts/sun8i-a33.dtsi
@@ -43,19 +43,137 @@
  */
 
 #include "sun8i-a23-a33.dtsi"
+#include <dt-bindings/thermal/thermal.h>
 
 / {
+	cpu0_opp_table: opp_table0 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp-120000000 {
+			opp-hz = /bits/ 64 <120000000>;
+			opp-microvolt = <1040000>;
+			clock-latency-ns = <244144>; /* 8 32k periods */
+		};
+
+		opp-240000000 {
+			opp-hz = /bits/ 64 <240000000>;
+			opp-microvolt = <1040000>;
+			clock-latency-ns = <244144>; /* 8 32k periods */
+		};
+
+		opp-312000000 {
+			opp-hz = /bits/ 64 <312000000>;
+			opp-microvolt = <1040000>;
+			clock-latency-ns = <244144>; /* 8 32k periods */
+		};
+
+		opp-408000000 {
+			opp-hz = /bits/ 64 <408000000>;
+			opp-microvolt = <1040000>;
+			clock-latency-ns = <244144>; /* 8 32k periods */
+		};
+
+		opp-480000000 {
+			opp-hz = /bits/ 64 <480000000>;
+			opp-microvolt = <1040000>;
+			clock-latency-ns = <244144>; /* 8 32k periods */
+		};
+
+		opp-504000000 {
+			opp-hz = /bits/ 64 <504000000>;
+			opp-microvolt = <1040000>;
+			clock-latency-ns = <244144>; /* 8 32k periods */
+		};
+
+		opp-600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-microvolt = <1040000>;
+			clock-latency-ns = <244144>; /* 8 32k periods */
+		};
+
+		opp-648000000 {
+			opp-hz = /bits/ 64 <648000000>;
+			opp-microvolt = <1040000>;
+			clock-latency-ns = <244144>; /* 8 32k periods */
+		};
+
+		opp-720000000 {
+			opp-hz = /bits/ 64 <720000000>;
+			opp-microvolt = <1100000>;
+			clock-latency-ns = <244144>; /* 8 32k periods */
+		};
+
+		opp-816000000 {
+			opp-hz = /bits/ 64 <816000000>;
+			opp-microvolt = <1100000>;
+			clock-latency-ns = <244144>; /* 8 32k periods */
+		};
+
+		opp-912000000 {
+			opp-hz = /bits/ 64 <912000000>;
+			opp-microvolt = <1200000>;
+			clock-latency-ns = <244144>; /* 8 32k periods */
+		};
+
+		opp-1008000000 {
+			opp-hz = /bits/ 64 <1008000000>;
+			opp-microvolt = <1200000>;
+			clock-latency-ns = <244144>; /* 8 32k periods */
+		};
+	};
+
 	cpus {
+		cpu@0 {
+			clocks = <&ccu CLK_CPUX>;
+			clock-names = "cpu";
+			operating-points-v2 = <&cpu0_opp_table>;
+			#cooling-cells = <2>;
+		};
+
+		cpu@1 {
+			operating-points-v2 = <&cpu0_opp_table>;
+		};
+
 		cpu@2 {
 			compatible = "arm,cortex-a7";
 			device_type = "cpu";
 			reg = <2>;
+			operating-points-v2 = <&cpu0_opp_table>;
 		};
 
 		cpu@3 {
 			compatible = "arm,cortex-a7";
 			device_type = "cpu";
 			reg = <3>;
+			operating-points-v2 = <&cpu0_opp_table>;
+		};
+	};
+
+	de: display-engine {
+		compatible = "allwinner,sun8i-a33-display-engine";
+		allwinner,pipelines = <&fe0>;
+		status = "disabled";
+	};
+
+	iio-hwmon {
+		compatible = "iio-hwmon";
+		io-channels = <&ths>;
+	};
+
+	mali_opp_table: gpu-opp-table {
+		compatible = "operating-points-v2";
+
+		opp-144000000 {
+			opp-hz = /bits/ 64 <144000000>;
+		};
+
+		opp-240000000 {
+			opp-hz = /bits/ 64 <240000000>;
+		};
+
+		opp-384000000 {
+			opp-hz = /bits/ 64 <384000000>;
 		};
 	};
 
@@ -63,101 +181,290 @@
 		reg = <0x40000000 0x80000000>;
 	};
 
-	clocks {
-		/* Dummy clock for pll11 (DDR1) until actually implemented */
-		pll11: pll11_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <0>;
-			clock-output-names = "pll11";
+	sound: sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "sun8i-a33-audio";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,frame-master = <&link_codec>;
+		simple-audio-card,bitclock-master = <&link_codec>;
+		simple-audio-card,mclk-fs = <512>;
+		simple-audio-card,aux-devs = <&codec_analog>;
+		simple-audio-card,routing =
+			"Left DAC", "AIF1 Slot 0 Left",
+			"Right DAC", "AIF1 Slot 0 Right";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&dai>;
 		};
 
-		ahb1_gates: clk@01c20060 {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun8i-a33-ahb1-gates-clk";
-			reg = <0x01c20060 0x8>;
-			clocks = <&ahb1>;
-			clock-indices = <1>, <5>,
-				        <6>, <8>, <9>,
-				        <10>, <13>, <14>,
-					<19>, <20>,
-					<21>, <24>, <26>,
-					<29>, <32>, <36>,
-					<40>, <44>, <46>,
-					<52>, <53>,
-					<54>, <57>,
-					<58>;
-			clock-output-names = "ahb1_mipidsi", "ahb1_ss",
-					"ahb1_dma","ahb1_mmc0", "ahb1_mmc1",
-					"ahb1_mmc2", "ahb1_nand", "ahb1_sdram",
-					"ahb1_hstimer", "ahb1_spi0",
-					"ahb1_spi1", "ahb1_otg", "ahb1_ehci",
-					"ahb1_ohci", "ahb1_ve", "ahb1_lcd",
-					"ahb1_csi", "ahb1_be",	"ahb1_fe",
-					"ahb1_gpu", "ahb1_msgbox",
-					"ahb1_spinlock", "ahb1_drc",
-					"ahb1_sat";
-		};
-
-		ss_clk: clk@01c2009c {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
-			reg = <0x01c2009c 0x4>;
-			clocks = <&osc24M>, <&pll6 0>;
-			clock-output-names = "ss";
-		};
-
-		mbus_clk: clk@01c2015c {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun8i-a23-mbus-clk";
-			reg = <0x01c2015c 0x4>;
-			clocks = <&osc24M>, <&pll6 1>, <&pll5>, <&pll11>;
-			clock-output-names = "mbus";
+		link_codec: simple-audio-card,codec {
+			sound-dai = <&codec>;
 		};
 	};
 
 	soc@01c00000 {
+		tcon0: lcd-controller@01c0c000 {
+			compatible = "allwinner,sun8i-a33-tcon";
+			reg = <0x01c0c000 0x1000>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_LCD>,
+				 <&ccu CLK_LCD_CH0>;
+			clock-names = "ahb",
+				      "tcon-ch0";
+			clock-output-names = "tcon-pixel-clock";
+			resets = <&ccu RST_BUS_LCD>;
+			reset-names = "lcd";
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon0_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					tcon0_in_drc0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&drc0_out_tcon0>;
+					};
+				};
+
+				tcon0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+			};
+		};
+
 		crypto: crypto-engine@01c15000 {
 			compatible = "allwinner,sun4i-a10-crypto";
 			reg = <0x01c15000 0x1000>;
 			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&ahb1_gates 5>, <&ss_clk>;
+			clocks = <&ccu CLK_BUS_SS>, <&ccu CLK_SS>;
 			clock-names = "ahb", "mod";
-			resets = <&ahb1_rst 5>;
+			resets = <&ccu RST_BUS_SS>;
 			reset-names = "ahb";
 		};
 
-		usb_otg: usb@01c19000 {
-			compatible = "allwinner,sun8i-a33-musb";
-			reg = <0x01c19000 0x0400>;
-			clocks = <&ahb1_gates 24>;
-			resets = <&ahb1_rst 24>;
-			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names = "mc";
-			phys = <&usbphy 0>;
-			phy-names = "usb";
-			extcon = <&usbphy 0>;
+		dai: dai@01c22c00 {
+			#sound-dai-cells = <0>;
+			compatible = "allwinner,sun6i-a31-i2s";
+			reg = <0x01c22c00 0x200>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>;
+			clock-names = "apb", "mod";
+			resets = <&ccu RST_BUS_CODEC>;
+			dmas = <&dma 15>, <&dma 15>;
+			dma-names = "rx", "tx";
 			status = "disabled";
 		};
 
-		usbphy: phy@01c19400 {
-			compatible = "allwinner,sun8i-a33-usb-phy";
-			reg = <0x01c19400 0x14>,
-			      <0x01c1a800 0x4>;
-			reg-names = "phy_ctrl",
-				    "pmu1";
-			clocks = <&usb_clk 8>,
-				 <&usb_clk 9>;
-			clock-names = "usb0_phy",
-				      "usb1_phy";
-			resets = <&usb_clk 0>,
-				 <&usb_clk 1>;
-			reset-names = "usb0_reset",
-				      "usb1_reset";
+		codec: codec@01c22e00 {
+			#sound-dai-cells = <0>;
+			compatible = "allwinner,sun8i-a33-codec";
+			reg = <0x01c22e00 0x400>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>;
+			clock-names = "bus", "mod";
 			status = "disabled";
-			#phy-cells = <1>;
+		};
+
+		ths: ths@01c25000 {
+			compatible = "allwinner,sun8i-a33-ths";
+			reg = <0x01c25000 0x100>;
+			#thermal-sensor-cells = <0>;
+			#io-channel-cells = <0>;
+		};
+
+		fe0: display-frontend@01e00000 {
+			compatible = "allwinner,sun8i-a33-display-frontend";
+			reg = <0x01e00000 0x20000>;
+			interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_DE_FE>, <&ccu CLK_DE_FE>,
+				 <&ccu CLK_DRAM_DE_FE>;
+			clock-names = "ahb", "mod",
+				      "ram";
+			resets = <&ccu RST_BUS_DE_FE>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				fe0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					fe0_out_be0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&be0_in_fe0>;
+					};
+				};
+			};
+		};
+
+		be0: display-backend@01e60000 {
+			compatible = "allwinner,sun8i-a33-display-backend";
+			reg = <0x01e60000 0x10000>, <0x01e80000 0x1000>;
+			reg-names = "be", "sat";
+			interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_DE_BE>, <&ccu CLK_DE_BE>,
+				 <&ccu CLK_DRAM_DE_BE>, <&ccu CLK_BUS_SAT>;
+			clock-names = "ahb", "mod",
+				      "ram", "sat";
+			resets = <&ccu RST_BUS_DE_BE>, <&ccu RST_BUS_SAT>;
+			reset-names = "be", "sat";
+			assigned-clocks = <&ccu CLK_DE_BE>;
+			assigned-clock-rates = <300000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				be0_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					be0_in_fe0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&fe0_out_be0>;
+					};
+				};
+
+				be0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					be0_out_drc0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&drc0_in_be0>;
+					};
+				};
+			};
+		};
+
+		drc0: drc@01e70000 {
+			compatible = "allwinner,sun8i-a33-drc";
+			reg = <0x01e70000 0x10000>;
+			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_DRC>, <&ccu CLK_DRC>,
+				 <&ccu CLK_DRAM_DRC>;
+			clock-names = "ahb", "mod", "ram";
+			resets = <&ccu RST_BUS_DRC>;
+
+			assigned-clocks = <&ccu CLK_DRC>;
+			assigned-clock-rates = <300000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				drc0_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					drc0_in_be0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&be0_out_drc0>;
+					};
+				};
+
+				drc0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					drc0_out_tcon0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&tcon0_in_drc0>;
+					};
+				};
+			};
 		};
 	};
+
+	thermal-zones {
+		cpu_thermal {
+			/* milliseconds */
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+			thermal-sensors = <&ths>;
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert0>;
+					cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+				map1 {
+					trip = <&cpu_alert1>;
+					cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+
+				map2 {
+					trip = <&gpu_alert0>;
+					cooling-device = <&mali 1 THERMAL_NO_LIMIT>;
+				};
+
+				map3 {
+					trip = <&gpu_alert1>;
+					cooling-device = <&mali 2 THERMAL_NO_LIMIT>;
+				};
+			};
+
+			trips {
+				cpu_alert0: cpu_alert0 {
+					/* milliCelsius */
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				gpu_alert0: gpu_alert0 {
+					/* milliCelsius */
+					temperature = <85000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				cpu_alert1: cpu_alert1 {
+					/* milliCelsius */
+					temperature = <90000>;
+					hysteresis = <2000>;
+					type = "hot";
+				};
+
+				gpu_alert1: gpu_alert1 {
+					/* milliCelsius */
+					temperature = <95000>;
+					hysteresis = <2000>;
+					type = "hot";
+				};
+
+				cpu_crit: cpu_crit {
+					/* milliCelsius */
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+	};
+};
+
+&ccu {
+	compatible = "allwinner,sun8i-a33-ccu";
+};
+
+&mali {
+	operating-points-v2 = <&mali_opp_table>;
 };
 
 &pio {
@@ -166,10 +473,18 @@
 		     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
 
 	uart0_pins_b: uart0@1 {
-		allwinner,pins = "PB0", "PB1";
-		allwinner,function = "uart0";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+		pins = "PB0", "PB1";
+		function = "uart0";
 	};
 
 };
+
+&usb_otg {
+	compatible = "allwinner,sun8i-a33-musb";
+};
+
+&usbphy {
+	compatible = "allwinner,sun8i-a33-usb-phy";
+	reg = <0x01c19400 0x14>, <0x01c1a800 0x4>;
+	reg-names = "phy_ctrl", "pmu1";
+};
diff --git a/arch/arm/dts/sun8i-a83t-sinovoip-bpi-m3.dts b/arch/arm/dts/sun8i-a83t-bananapi-m3.dts
similarity index 100%
rename from arch/arm/dts/sun8i-a83t-sinovoip-bpi-m3.dts
rename to arch/arm/dts/sun8i-a83t-bananapi-m3.dts
diff --git a/arch/arm/dts/tps6507x.dtsi b/arch/arm/dts/tps6507x.dtsi
new file mode 100644
index 0000000..4c326e5
--- /dev/null
+++ b/arch/arm/dts/tps6507x.dtsi
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Integrated Power Management Chip
+ * http://www.ti.com/lit/ds/symlink/tps65070.pdf
+ */
+
+&tps {
+	compatible = "ti,tps6507x";
+
+	regulators {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdcdc1_reg: regulator@0 {
+			reg = <0>;
+			regulator-compatible = "VDCDC1";
+		};
+
+		vdcdc2_reg: regulator@1 {
+			reg = <1>;
+			regulator-compatible = "VDCDC2";
+		};
+
+		vdcdc3_reg: regulator@2 {
+			reg = <2>;
+			regulator-compatible = "VDCDC3";
+		};
+
+		ldo1_reg: regulator@3 {
+			reg = <3>;
+			regulator-compatible = "LDO1";
+		};
+
+		ldo2_reg: regulator@4 {
+			reg = <4>;
+			regulator-compatible = "LDO2";
+		};
+
+	};
+};
diff --git a/arch/arm/include/asm/arch-rockchip/bootrom.h b/arch/arm/include/asm/arch-rockchip/bootrom.h
index 92eb878..169cc5e 100644
--- a/arch/arm/include/asm/arch-rockchip/bootrom.h
+++ b/arch/arm/include/asm/arch-rockchip/bootrom.h
@@ -24,4 +24,22 @@
  */
 void _back_to_bootrom_s(void);
 
+/**
+ * Boot-device identifiers as used by the BROM
+ */
+enum {
+	BROM_BOOTSOURCE_NAND = 1,
+	BROM_BOOTSOURCE_EMMC = 2,
+	BROM_BOOTSOURCE_SPINOR = 3,
+	BROM_BOOTSOURCE_SPINAND = 4,
+	BROM_BOOTSOURCE_SD = 5,
+	BROM_BOOTSOURCE_USB = 10,
+	BROM_LAST_BOOTSOURCE = BROM_BOOTSOURCE_USB
+};
+
+/**
+ * Locations of the boot-device identifier in SRAM
+ */
+#define RK3399_BROM_BOOTSOURCE_ID_ADDR   0xff8c0010
+
 #endif
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3368.h b/arch/arm/include/asm/arch-rockchip/cru_rk3368.h
index 2b1197f..5f6a5fb 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3368.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3368.h
@@ -89,6 +89,11 @@
 	MCU_CLK_DIV_SHIFT		= 0,
 	MCU_CLK_DIV_MASK		= GENMASK(4, 0),
 
+	/* CLKSEL_CON25 */
+	CLK_SARADC_DIV_CON_SHIFT	= 8,
+	CLK_SARADC_DIV_CON_MASK		= GENMASK(15, 8),
+	CLK_SARADC_DIV_CON_WIDTH	= 8,
+
 	/* CLKSEL43_CON */
 	GMAC_MUX_SEL_EXTCLK             = BIT(8),
 
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rv1108.h b/arch/arm/include/asm/arch-rockchip/cru_rv1108.h
index 2a1ae69..ad2dc96 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rv1108.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rv1108.h
@@ -90,6 +90,11 @@
 	CORE_CLK_DIV_SHIFT	= 0,
 	CORE_CLK_DIV_MASK	= 0x1f << CORE_CLK_DIV_SHIFT,
 
+	/* CLKSEL_CON22 */
+	CLK_SARADC_DIV_CON_SHIFT= 0,
+	CLK_SARADC_DIV_CON_MASK	= GENMASK(9, 0),
+	CLK_SARADC_DIV_CON_WIDTH= 10,
+
 	/* CLKSEL24_CON */
 	MAC_PLL_SEL_SHIFT	= 12,
 	MAC_PLL_SEL_MASK	= 1 << MAC_PLL_SEL_SHIFT,
diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3036.h b/arch/arm/include/asm/arch-rockchip/grf_rk3036.h
index 7625f24..d995b7d 100644
--- a/arch/arm/include/asm/arch-rockchip/grf_rk3036.h
+++ b/arch/arm/include/asm/arch-rockchip/grf_rk3036.h
@@ -209,10 +209,10 @@
 	GPIO1A3_I2S_LRCKTX,
 
 	GPIO1A2_SHIFT		= 4,
-	GPIO1A2_MASK		= 6 << GPIO1A2_SHIFT,
+	GPIO1A2_MASK		= 3 << GPIO1A2_SHIFT,
 	GPIO1A2_GPIO		= 0,
 	GPIO1A2_I2S_LRCKRX,
-	GPIO1A2_I2S_PWM1_0,
+	GPIO1A2_PWM1_0,
 
 	GPIO1A1_SHIFT		= 2,
 	GPIO1A1_MASK		= 1 << GPIO1A1_SHIFT,
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h b/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h
new file mode 100644
index 0000000..b40da40
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h
@@ -0,0 +1,581 @@
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+#ifndef _ASM_ARCH_SDRAM_RK322X_H
+#define _ASM_ARCH_SDRAM_RK322X_H
+
+#include <common.h>
+
+enum {
+	DDR3		= 3,
+	LPDDR2		= 5,
+	LPDDR3		= 6,
+	UNUSED		= 0xFF,
+};
+
+struct rk322x_sdram_channel {
+	/*
+	 * bit width in address, eg:
+	 * 8 banks using 3 bit to address,
+	 * 2 cs using 1 bit to address.
+	 */
+	u8 rank;
+	u8 col;
+	u8 bk;
+	u8 bw;
+	u8 dbw;
+	u8 row_3_4;
+	u8 cs0_row;
+	u8 cs1_row;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	/*
+	 * For of-platdata, which would otherwise convert this into two
+	 * byte-swapped integers. With a size of 9 bytes, this struct will
+	 * appear in of-platdata as a byte array.
+	 *
+	 * If OF_PLATDATA enabled, need to add a dummy byte in dts.(i.e 0xff)
+	 */
+	u8 dummy;
+#endif
+};
+
+struct rk322x_ddr_pctl {
+	u32 scfg;
+	u32 sctl;
+	u32 stat;
+	u32 intrstat;
+	u32 reserved0[(0x40 - 0x10) / 4];
+	u32 mcmd;
+	u32 powctl;
+	u32 powstat;
+	u32 cmdtstat;
+	u32 cmdtstaten;
+	u32 reserved1[(0x60 - 0x54) / 4];
+	u32 mrrcfg0;
+	u32 mrrstat0;
+	u32 mrrstat1;
+	u32 reserved2[(0x7c - 0x6c) / 4];
+
+	u32 mcfg1;
+	u32 mcfg;
+	u32 ppcfg;
+	u32 mstat;
+	u32 lpddr2zqcfg;
+	u32 reserved3;
+
+	u32 dtupdes;
+	u32 dtuna;
+	u32 dtune;
+	u32 dtuprd0;
+	u32 dtuprd1;
+	u32 dtuprd2;
+	u32 dtuprd3;
+	u32 dtuawdt;
+	u32 reserved4[(0xc0 - 0xb4) / 4];
+
+	u32 togcnt1u;
+	u32 tinit;
+	u32 trsth;
+	u32 togcnt100n;
+	u32 trefi;
+	u32 tmrd;
+	u32 trfc;
+	u32 trp;
+	u32 trtw;
+	u32 tal;
+	u32 tcl;
+	u32 tcwl;
+	u32 tras;
+	u32 trc;
+	u32 trcd;
+	u32 trrd;
+	u32 trtp;
+	u32 twr;
+	u32 twtr;
+	u32 texsr;
+	u32 txp;
+	u32 txpdll;
+	u32 tzqcs;
+	u32 tzqcsi;
+	u32 tdqs;
+	u32 tcksre;
+	u32 tcksrx;
+	u32 tcke;
+	u32 tmod;
+	u32 trstl;
+	u32 tzqcl;
+	u32 tmrr;
+	u32 tckesr;
+	u32 tdpd;
+	u32 tref_mem_ddr3;
+	u32 reserved5[(0x180 - 0x14c) / 4];
+	u32 ecccfg;
+	u32 ecctst;
+	u32 eccclr;
+	u32 ecclog;
+	u32 reserved6[(0x200 - 0x190) / 4];
+	u32 dtuwactl;
+	u32 dturactl;
+	u32 dtucfg;
+	u32 dtuectl;
+	u32 dtuwd0;
+	u32 dtuwd1;
+	u32 dtuwd2;
+	u32 dtuwd3;
+	u32 dtuwdm;
+	u32 dturd0;
+	u32 dturd1;
+	u32 dturd2;
+	u32 dturd3;
+	u32 dtulfsrwd;
+	u32 dtulfsrrd;
+	u32 dtueaf;
+	/* dfi control registers */
+	u32 dfitctrldelay;
+	u32 dfiodtcfg;
+	u32 dfiodtcfg1;
+	u32 dfiodtrankmap;
+	/* dfi write data registers */
+	u32 dfitphywrdata;
+	u32 dfitphywrlat;
+	u32 reserved7[(0x260 - 0x258) / 4];
+	u32 dfitrddataen;
+	u32 dfitphyrdlat;
+	u32 reserved8[(0x270 - 0x268) / 4];
+	u32 dfitphyupdtype0;
+	u32 dfitphyupdtype1;
+	u32 dfitphyupdtype2;
+	u32 dfitphyupdtype3;
+	u32 dfitctrlupdmin;
+	u32 dfitctrlupdmax;
+	u32 dfitctrlupddly;
+	u32 reserved9;
+	u32 dfiupdcfg;
+	u32 dfitrefmski;
+	u32 dfitctrlupdi;
+	u32 reserved10[(0x2ac - 0x29c) / 4];
+	u32 dfitrcfg0;
+	u32 dfitrstat0;
+	u32 dfitrwrlvlen;
+	u32 dfitrrdlvlen;
+	u32 dfitrrdlvlgateen;
+	u32 dfiststat0;
+	u32 dfistcfg0;
+	u32 dfistcfg1;
+	u32 reserved11;
+	u32 dfitdramclken;
+	u32 dfitdramclkdis;
+	u32 dfistcfg2;
+	u32 dfistparclr;
+	u32 dfistparlog;
+	u32 reserved12[(0x2f0 - 0x2e4) / 4];
+
+	u32 dfilpcfg0;
+	u32 reserved13[(0x300 - 0x2f4) / 4];
+	u32 dfitrwrlvlresp0;
+	u32 dfitrwrlvlresp1;
+	u32 dfitrwrlvlresp2;
+	u32 dfitrrdlvlresp0;
+	u32 dfitrrdlvlresp1;
+	u32 dfitrrdlvlresp2;
+	u32 dfitrwrlvldelay0;
+	u32 dfitrwrlvldelay1;
+	u32 dfitrwrlvldelay2;
+	u32 dfitrrdlvldelay0;
+	u32 dfitrrdlvldelay1;
+	u32 dfitrrdlvldelay2;
+	u32 dfitrrdlvlgatedelay0;
+	u32 dfitrrdlvlgatedelay1;
+	u32 dfitrrdlvlgatedelay2;
+	u32 dfitrcmd;
+	u32 reserved14[(0x3f8 - 0x340) / 4];
+	u32 ipvr;
+	u32 iptr;
+};
+check_member(rk322x_ddr_pctl, iptr, 0x03fc);
+
+struct rk322x_ddr_phy {
+	u32 ddrphy_reg[0x100];
+};
+
+struct rk322x_pctl_timing {
+	u32 togcnt1u;
+	u32 tinit;
+	u32 trsth;
+	u32 togcnt100n;
+	u32 trefi;
+	u32 tmrd;
+	u32 trfc;
+	u32 trp;
+	u32 trtw;
+	u32 tal;
+	u32 tcl;
+	u32 tcwl;
+	u32 tras;
+	u32 trc;
+	u32 trcd;
+	u32 trrd;
+	u32 trtp;
+	u32 twr;
+	u32 twtr;
+	u32 texsr;
+	u32 txp;
+	u32 txpdll;
+	u32 tzqcs;
+	u32 tzqcsi;
+	u32 tdqs;
+	u32 tcksre;
+	u32 tcksrx;
+	u32 tcke;
+	u32 tmod;
+	u32 trstl;
+	u32 tzqcl;
+	u32 tmrr;
+	u32 tckesr;
+	u32 tdpd;
+	u32 trefi_mem_ddr3;
+};
+
+struct rk322x_phy_timing {
+	u32 mr[4];
+	u32 mr11;
+	u32 bl;
+	u32 cl_al;
+};
+
+struct rk322x_msch_timings {
+	u32 ddrtiming;
+	u32 ddrmode;
+	u32 readlatency;
+	u32 activate;
+	u32 devtodev;
+};
+
+struct rk322x_service_sys {
+	u32 id_coreid;
+	u32 id_revisionid;
+	u32 ddrconf;
+	u32 ddrtiming;
+	u32 ddrmode;
+	u32 readlatency;
+	u32 activate;
+	u32 devtodev;
+};
+
+struct rk322x_base_params {
+	struct rk322x_msch_timings noc_timing;
+	u32 ddrconfig;
+	u32 ddr_freq;
+	u32 dramtype;
+	/*
+	 * unused for rk322x
+	 */
+	u32 stride;
+	u32 odt;
+};
+
+/* PCT_DFISTCFG0 */
+#define DFI_INIT_START			BIT(0)
+#define DFI_DATA_BYTE_DISABLE_EN	BIT(2)
+
+/* PCT_DFISTCFG1 */
+#define DFI_DRAM_CLK_SR_EN		BIT(0)
+#define DFI_DRAM_CLK_DPD_EN		BIT(1)
+
+/* PCT_DFISTCFG2 */
+#define DFI_PARITY_INTR_EN		BIT(0)
+#define DFI_PARITY_EN			BIT(1)
+
+/* PCT_DFILPCFG0 */
+#define TLP_RESP_TIME_SHIFT		16
+#define LP_SR_EN			BIT(8)
+#define LP_PD_EN			BIT(0)
+
+/* PCT_DFITCTRLDELAY */
+#define TCTRL_DELAY_TIME_SHIFT		0
+
+/* PCT_DFITPHYWRDATA */
+#define TPHY_WRDATA_TIME_SHIFT		0
+
+/* PCT_DFITPHYRDLAT */
+#define TPHY_RDLAT_TIME_SHIFT		0
+
+/* PCT_DFITDRAMCLKDIS */
+#define TDRAM_CLK_DIS_TIME_SHIFT	0
+
+/* PCT_DFITDRAMCLKEN */
+#define TDRAM_CLK_EN_TIME_SHIFT		0
+
+/* PCTL_DFIODTCFG */
+#define RANK0_ODT_WRITE_SEL		BIT(3)
+#define RANK1_ODT_WRITE_SEL		BIT(11)
+
+/* PCTL_DFIODTCFG1 */
+#define ODT_LEN_BL8_W_SHIFT		16
+
+/* PUBL_ACDLLCR */
+#define ACDLLCR_DLLDIS			BIT(31)
+#define ACDLLCR_DLLSRST			BIT(30)
+
+/* PUBL_DXDLLCR */
+#define DXDLLCR_DLLDIS			BIT(31)
+#define DXDLLCR_DLLSRST			BIT(30)
+
+/* PUBL_DLLGCR */
+#define DLLGCR_SBIAS			BIT(30)
+
+/* PUBL_DXGCR */
+#define DQSRTT				BIT(9)
+#define DQRTT				BIT(10)
+
+/* PIR */
+#define PIR_INIT			BIT(0)
+#define PIR_DLLSRST			BIT(1)
+#define PIR_DLLLOCK			BIT(2)
+#define PIR_ZCAL			BIT(3)
+#define PIR_ITMSRST			BIT(4)
+#define PIR_DRAMRST			BIT(5)
+#define PIR_DRAMINIT			BIT(6)
+#define PIR_QSTRN			BIT(7)
+#define PIR_RVTRN			BIT(8)
+#define PIR_ICPC			BIT(16)
+#define PIR_DLLBYP			BIT(17)
+#define PIR_CTLDINIT			BIT(18)
+#define PIR_CLRSR			BIT(28)
+#define PIR_LOCKBYP			BIT(29)
+#define PIR_ZCALBYP			BIT(30)
+#define PIR_INITBYP			BIT(31)
+
+/* PGCR */
+#define PGCR_DFTLMT_SHIFT		3
+#define PGCR_DFTCMP_SHIFT		2
+#define PGCR_DQSCFG_SHIFT		1
+#define PGCR_ITMDMD_SHIFT		0
+
+/* PGSR */
+#define PGSR_IDONE			BIT(0)
+#define PGSR_DLDONE			BIT(1)
+#define PGSR_ZCDONE			BIT(2)
+#define PGSR_DIDONE			BIT(3)
+#define PGSR_DTDONE			BIT(4)
+#define PGSR_DTERR			BIT(5)
+#define PGSR_DTIERR			BIT(6)
+#define PGSR_DFTERR			BIT(7)
+#define PGSR_RVERR			BIT(8)
+#define PGSR_RVEIRR			BIT(9)
+
+/* PTR0 */
+#define PRT_ITMSRST_SHIFT		18
+#define PRT_DLLLOCK_SHIFT		6
+#define PRT_DLLSRST_SHIFT		0
+
+/* PTR1 */
+#define PRT_DINIT0_SHIFT		0
+#define PRT_DINIT1_SHIFT		19
+
+/* PTR2 */
+#define PRT_DINIT2_SHIFT		0
+#define PRT_DINIT3_SHIFT		17
+
+/* DCR */
+#define DDRMD_LPDDR			0
+#define DDRMD_DDR			1
+#define DDRMD_DDR2			2
+#define DDRMD_DDR3			3
+#define DDRMD_LPDDR2_LPDDR3		4
+#define DDRMD_MASK			7
+#define DDRMD_SHIFT			0
+#define PDQ_MASK			7
+#define PDQ_SHIFT			4
+
+/* DXCCR */
+#define DQSNRES_MASK			0xf
+#define DQSNRES_SHIFT			8
+#define DQSRES_MASK			0xf
+#define DQSRES_SHIFT			4
+
+/* DTPR */
+#define TDQSCKMAX_SHIFT			27
+#define TDQSCKMAX_MASK			7
+#define TDQSCK_SHIFT			24
+#define TDQSCK_MASK			7
+
+/* DSGCR */
+#define DQSGX_SHIFT			5
+#define DQSGX_MASK			7
+#define DQSGE_SHIFT			8
+#define DQSGE_MASK			7
+
+/* SCTL */
+#define INIT_STATE			0
+#define CFG_STATE			1
+#define GO_STATE			2
+#define SLEEP_STATE			3
+#define WAKEUP_STATE			4
+
+/* STAT */
+#define LP_TRIG_SHIFT			4
+#define LP_TRIG_MASK			7
+#define PCTL_STAT_MASK			7
+#define INIT_MEM			0
+#define CONFIG				1
+#define CONFIG_REQ			2
+#define ACCESS				3
+#define ACCESS_REQ			4
+#define LOW_POWER			5
+#define LOW_POWER_ENTRY_REQ		6
+#define LOW_POWER_EXIT_REQ		7
+
+/* ZQCR*/
+#define PD_OUTPUT_SHIFT			0
+#define PU_OUTPUT_SHIFT			5
+#define PD_ONDIE_SHIFT			10
+#define PU_ONDIE_SHIFT			15
+#define ZDEN_SHIFT			28
+
+/* DDLGCR */
+#define SBIAS_BYPASS			BIT(23)
+
+/* MCFG */
+#define MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT	24
+#define PD_IDLE_SHIFT			8
+#define MDDR_EN				(2 << 22)
+#define LPDDR2_EN			(3 << 22)
+#define LPDDR3_EN			(1 << 22)
+#define DDR2_EN				(0 << 5)
+#define DDR3_EN				(1 << 5)
+#define LPDDR2_S2			(0 << 6)
+#define LPDDR2_S4			(1 << 6)
+#define MDDR_LPDDR2_BL_2		(0 << 20)
+#define MDDR_LPDDR2_BL_4		(1 << 20)
+#define MDDR_LPDDR2_BL_8		(2 << 20)
+#define MDDR_LPDDR2_BL_16		(3 << 20)
+#define DDR2_DDR3_BL_4			0
+#define DDR2_DDR3_BL_8			1
+#define TFAW_SHIFT			18
+#define PD_EXIT_SLOW			(0 << 17)
+#define PD_EXIT_FAST			(1 << 17)
+#define PD_TYPE_SHIFT			16
+#define BURSTLENGTH_SHIFT		20
+
+/* POWCTL */
+#define POWER_UP_START			BIT(0)
+
+/* POWSTAT */
+#define POWER_UP_DONE			BIT(0)
+
+/* MCMD */
+enum {
+	DESELECT_CMD			= 0,
+	PREA_CMD,
+	REF_CMD,
+	MRS_CMD,
+	ZQCS_CMD,
+	ZQCL_CMD,
+	RSTL_CMD,
+	MRR_CMD				= 8,
+	DPDE_CMD,
+};
+
+#define BANK_ADDR_MASK			7
+#define BANK_ADDR_SHIFT			17
+#define CMD_ADDR_MASK			0x1fff
+#define CMD_ADDR_SHIFT			4
+
+#define LPDDR23_MA_SHIFT		4
+#define LPDDR23_MA_MASK			0xff
+#define LPDDR23_OP_SHIFT		12
+#define LPDDR23_OP_MASK			0xff
+
+#define START_CMD			(1u << 31)
+
+/* DDRPHY REG */
+enum {
+	/* DDRPHY_REG0 */
+	SOFT_RESET_MASK				= 3,
+	SOFT_DERESET_ANALOG			= 1 << 2,
+	SOFT_DERESET_DIGITAL			= 1 << 3,
+	SOFT_RESET_SHIFT			= 2,
+
+	/* DDRPHY REG1 */
+	PHY_DDR3				= 0,
+	PHY_DDR2				= 1,
+	PHY_LPDDR3				= 2,
+	PHY_LPDDR2				= 3,
+
+	PHT_BL_8				= 1 << 2,
+	PHY_BL_4				= 0 << 2,
+
+	/* DDRPHY_REG2 */
+	MEMORY_SELECT_DDR3			= 0 << 0,
+	MEMORY_SELECT_LPDDR3			= 2 << 0,
+	MEMORY_SELECT_LPDDR2			= 3 << 0,
+	DQS_SQU_CAL_SEL_CS0_CS1			= 0 << 4,
+	DQS_SQU_CAL_SEL_CS1			= 1 << 4,
+	DQS_SQU_CAL_SEL_CS0			= 2 << 4,
+	DQS_SQU_CAL_NORMAL_MODE			= 0 << 1,
+	DQS_SQU_CAL_BYPASS_MODE			= 1 << 1,
+	DQS_SQU_CAL_START			= 1 << 0,
+	DQS_SQU_NO_CAL				= 0 << 0,
+};
+
+/* CK pull up/down driver strength control */
+enum {
+	PHY_RON_RTT_DISABLE = 0,
+	PHY_RON_RTT_451OHM = 1,
+	PHY_RON_RTT_225OHM,
+	PHY_RON_RTT_150OHM,
+	PHY_RON_RTT_112OHM,
+	PHY_RON_RTT_90OHM,
+	PHY_RON_RTT_75OHM,
+	PHY_RON_RTT_64OHM = 7,
+
+	PHY_RON_RTT_56OHM = 16,
+	PHY_RON_RTT_50OHM,
+	PHY_RON_RTT_45OHM,
+	PHY_RON_RTT_41OHM,
+	PHY_RON_RTT_37OHM,
+	PHY_RON_RTT_34OHM,
+	PHY_RON_RTT_33OHM,
+	PHY_RON_RTT_30OHM = 23,
+
+	PHY_RON_RTT_28OHM = 24,
+	PHY_RON_RTT_26OHM,
+	PHY_RON_RTT_25OHM,
+	PHY_RON_RTT_23OHM,
+	PHY_RON_RTT_22OHM,
+	PHY_RON_RTT_21OHM,
+	PHY_RON_RTT_20OHM,
+	PHY_RON_RTT_19OHM = 31,
+};
+
+/* DQS squelch DLL delay */
+enum {
+	DQS_DLL_NO_DELAY	= 0,
+	DQS_DLL_22P5_DELAY,
+	DQS_DLL_45_DELAY,
+	DQS_DLL_67P5_DELAY,
+	DQS_DLL_90_DELAY,
+	DQS_DLL_112P5_DELAY,
+	DQS_DLL_135_DELAY,
+	DQS_DLL_157P5_DELAY,
+};
+
+/* GRF_SOC_CON0 */
+#define GRF_DDR_16BIT_EN		(((0x1 << 0) << 16) | (0x1 << 0))
+#define GRF_DDR_32BIT_EN		(((0x1 << 0) << 16) | (0x0 << 0))
+#define GRF_MSCH_NOC_16BIT_EN		(((0x1 << 7) << 16) | (0x1 << 7))
+#define GRF_MSCH_NOC_32BIT_EN		(((0x1 << 7) << 16) | (0x0 << 7))
+
+#define GRF_DDRPHY_BUFFEREN_CORE_EN	(((0x1 << 8) << 16) | (0x0 << 8))
+#define GRF_DDRPHY_BUFFEREN_CORE_DIS	(((0x1 << 8) << 16) | (0x1 << 8))
+
+#define GRF_DDR3_EN			(((0x1 << 6) << 16) | (0x1 << 6))
+#define GRF_LPDDR2_3_EN			(((0x1 << 6) << 16) | (0x0 << 6))
+
+#define PHY_DRV_ODT_SET(n)		(((n) << 4) | (n))
+#define DDR3_DLL_RESET			(1 << 8)
+
+#endif /* _ASM_ARCH_SDRAM_RK322X_H */
diff --git a/arch/arm/include/asm/arch-rockchip/sys_proto.h b/arch/arm/include/asm/arch-rockchip/sys_proto.h
index 35423e1..e428d59 100644
--- a/arch/arm/include/asm/arch-rockchip/sys_proto.h
+++ b/arch/arm/include/asm/arch-rockchip/sys_proto.h
@@ -7,4 +7,27 @@
 #ifndef _ASM_ARCH_SYS_PROTO_H
 #define _ASM_ARCH_SYS_PROTO_H
 
+#ifdef CONFIG_ROCKCHIP_RK3288
+#include <asm/armv7.h>
+
+static void configure_l2ctlr(void)
+{
+	uint32_t l2ctlr;
+
+	l2ctlr = read_l2ctlr();
+	l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */
+
+	/*
+	* Data RAM write latency: 2 cycles
+	* Data RAM read latency: 2 cycles
+	* Data RAM setup latency: 1 cycle
+	* Tag RAM write latency: 1 cycle
+	* Tag RAM read latency: 1 cycle
+	* Tag RAM setup latency: 1 cycle
+	*/
+	l2ctlr |= (1 << 3 | 1 << 0);
+	write_l2ctlr(l2ctlr);
+}
+#endif /* CONFIG_ROCKCHIP_RK3288 */
+
 #endif /* _ASM_ARCH_SYS_PROTO_H */
diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h
index 9358397..a70b179 100644
--- a/arch/arm/include/asm/arch-sunxi/spl.h
+++ b/arch/arm/include/asm/arch-sunxi/spl.h
@@ -78,4 +78,6 @@
 
 #define is_boot0_magic(addr)	(memcmp((void *)addr, BOOT0_MAGIC, 8) == 0)
 
+uint32_t sunxi_get_boot_device(void);
+
 #endif
diff --git a/arch/arm/include/asm/arch-sunxi/usb_phy.h b/arch/arm/include/asm/arch-sunxi/usb_phy.h
index cef6c98..5a9cacb 100644
--- a/arch/arm/include/asm/arch-sunxi/usb_phy.h
+++ b/arch/arm/include/asm/arch-sunxi/usb_phy.h
@@ -19,10 +19,3 @@
 int sunxi_usb_phy_vbus_detect(int index);
 int sunxi_usb_phy_id_detect(int index);
 void sunxi_usb_phy_enable_squelch_detect(int index, int enable);
-
-/* Not really phy related, but we have to declare this somewhere ... */
-#if defined(CONFIG_USB_MUSB_HOST) || defined(CONFIG_USB_MUSB_GADGET)
-void sunxi_musb_board_init(void);
-#else
-#define sunxi_musb_board_init()
-#endif
diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h
index a20702e..efc515e 100644
--- a/arch/arm/include/asm/armv7.h
+++ b/arch/arm/include/asm/armv7.h
@@ -61,6 +61,27 @@
 #include <asm/io.h>
 #include <asm/barriers.h>
 
+/* read L2 control register (L2CTLR) */
+static inline uint32_t read_l2ctlr(void)
+{
+	uint32_t val = 0;
+
+	asm volatile ("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
+
+	return val;
+}
+
+/* write L2 control register (L2CTLR) */
+static inline void write_l2ctlr(uint32_t val)
+{
+	/*
+	 * Note: L2CTLR can only be written when the L2 memory system
+	 * is idle, ie before the MMU is enabled.
+	 */
+	asm volatile("mcr p15, 1, %0, c9, c0, 2" : : "r" (val) : "memory");
+	isb();
+}
+
 /*
  * Workaround for ARM errata # 798870
  * Set L2ACTLR[7] to reissue any memory transaction in the L2 that has been
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 5834f5b..5df7472 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -35,35 +35,6 @@
 }
 
 /*
- * Given a physical address and a length, return a virtual address
- * that can be used to access the memory range with the caching
- * properties specified by "flags".
- */
-#define MAP_NOCACHE	(0)
-#define MAP_WRCOMBINE	(0)
-#define MAP_WRBACK	(0)
-#define MAP_WRTHROUGH	(0)
-
-static inline void *
-map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
-{
-	return (void *)((unsigned long)paddr);
-}
-
-/*
- * Take down a mapping set up by map_physmem().
- */
-static inline void unmap_physmem(void *vaddr, unsigned long flags)
-{
-
-}
-
-static inline phys_addr_t virt_to_phys(void * vaddr)
-{
-	return (phys_addr_t)((unsigned long)vaddr);
-}
-
-/*
  * Generic virtual read/write.  Note that we don't support half-word
  * read/writes.  We define __arch_*[bl] here, and leave __arch_*w
  * to the architecture specific code.
@@ -426,6 +397,7 @@
 #endif	/* __mem_isa */
 #endif	/* __KERNEL__ */
 
+#include <asm-generic/io.h>
 #include <iotrace.h>
 
 #endif	/* __ASM_ARM_IO_H */
diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h
index e1916f7..0c8652a 100644
--- a/arch/arm/include/asm/macro.h
+++ b/arch/arm/include/asm/macro.h
@@ -131,6 +131,7 @@
 	/* NOTE: MPIDR handling will be erroneous on multi-cluster machines */
 	mrs	\xreg1, mpidr_el1
 	lsr	\xreg2, \xreg1, #32
+	lsl	\xreg2, \xreg2, #32
 	lsl	\xreg1, \xreg1, #40
 	lsr	\xreg1, \xreg1, #40
 	orr	\xreg1, \xreg1, \xreg2
diff --git a/arch/arm/lib/crt0_64.S b/arch/arm/lib/crt0_64.S
index 62fad45..9c46c93 100644
--- a/arch/arm/lib/crt0_64.S
+++ b/arch/arm/lib/crt0_64.S
@@ -95,8 +95,7 @@
  */
 	ldr	x0, [x18, #GD_START_ADDR_SP]	/* x0 <- gd->start_addr_sp */
 	bic	sp, x0, #0xf	/* 16-byte alignment for ABI compliance */
-	ldr	x18, [x18, #GD_BD]		/* x18 <- gd->bd */
-	sub	x18, x18, #GD_SIZE		/* new GD is below bd */
+	ldr	x18, [x18, #GD_NEW_GD]		/* x18 <- gd->new_gd */
 
 	adr	lr, relocation_return
 	ldr	x9, [x18, #GD_RELOC_OFF]	/* x9 <- gd->reloc_off */
diff --git a/arch/arm/lib/relocate_64.S b/arch/arm/lib/relocate_64.S
index c760053..fdba004 100644
--- a/arch/arm/lib/relocate_64.S
+++ b/arch/arm/lib/relocate_64.S
@@ -73,6 +73,6 @@
 	isb	sy
 4:	ldp	x0, x1, [sp, #16]
 	bl	__asm_flush_dcache_range
-5:	ldp	x29, x30, [sp],#16
+5:	ldp	x29, x30, [sp],#32
 	ret
 ENDPROC(relocate_code)
diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c
index 5944f99..fb94c96 100644
--- a/arch/arm/mach-imx/spl.c
+++ b/arch/arm/mach-imx/spl.c
@@ -99,7 +99,7 @@
 #ifdef CONFIG_SPL_USB_GADGET_SUPPORT
 int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
 {
-	put_unaligned(CONFIG_G_DNL_PRODUCT_NUM + 0xfff, &dev->idProduct);
+	put_unaligned(CONFIG_USB_GADGET_PRODUCT_NUM + 0xfff, &dev->idProduct);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/am33xx/board.c b/arch/arm/mach-omap2/am33xx/board.c
index 913a44a..ae86b69 100644
--- a/arch/arm/mach-omap2/am33xx/board.c
+++ b/arch/arm/mach-omap2/am33xx/board.c
@@ -241,7 +241,7 @@
 #if defined(CONFIG_DM_ETH) && defined(CONFIG_USB_ETHER)
 	ret = usb_ether_init();
 	if (ret) {
-		error("USB ether init failed\n");
+		pr_err("USB ether init failed\n");
 		return ret;
 	}
 #endif
diff --git a/arch/arm/mach-omap2/hwinit-common.c b/arch/arm/mach-omap2/hwinit-common.c
index 7324d52..56890a0 100644
--- a/arch/arm/mach-omap2/hwinit-common.c
+++ b/arch/arm/mach-omap2/hwinit-common.c
@@ -165,9 +165,11 @@
 	 * to prevent overwrites.
 	 */
 	save_omap_boot_params();
-	spl_early_init();
 #endif
 	do_board_detect();
+#ifdef CONFIG_SPL_BUILD
+	spl_early_init();
+#endif
 	vcores_init();
 #ifdef CONFIG_DEBUG_UART_OMAP
 	debug_uart_init();
diff --git a/arch/arm/mach-omap2/omap3/Kconfig b/arch/arm/mach-omap2/omap3/Kconfig
index 11f5f05..4dbf9a2 100644
--- a/arch/arm/mach-omap2/omap3/Kconfig
+++ b/arch/arm/mach-omap2/omap3/Kconfig
@@ -22,6 +22,11 @@
 
 config TARGET_AM3517_EVM
 	bool "AM3517 EVM"
+	select DM
+	select DM_SERIAL
+	select DM_GPIO
+	select DM_I2C
+	select DM_MMC
 
 config TARGET_MT_VENTOUX
 	bool "TeeJet Mt.Ventoux"
diff --git a/arch/arm/mach-omap2/sec-common.c b/arch/arm/mach-omap2/sec-common.c
index 52e1785..2630e7d 100644
--- a/arch/arm/mach-omap2/sec-common.c
+++ b/arch/arm/mach-omap2/sec-common.c
@@ -41,6 +41,9 @@
 #define PPA_SERV_HAL_SETUP_EMIF_FW_REGION   (PPA_HAL_SERVICES_START_INDEX + 26)
 #define PPA_SERV_HAL_LOCK_EMIF_FW           (PPA_HAL_SERVICES_START_INDEX + 27)
 
+/* Offset of header size if image is signed as ISW */
+#define HEADER_SIZE_OFFSET	(0x6D)
+
 int tee_loaded = 0;
 
 /* Argument for PPA_SERV_HAL_TEE_LOAD_MASTER */
@@ -125,6 +128,9 @@
 	}
 
 	*size = sig_addr - cert_addr;	/* Subtract out the signature size */
+	/* Subtract header if present */
+	if (strncmp((char *)sig_addr, "CERT_ISW_", 9) == 0)
+		*size = ((u32 *)*image)[HEADER_SIZE_OFFSET];
 	cert_size = *size;
 
 	/* Check if image load address is 32-bit aligned */
diff --git a/arch/arm/mach-omap2/utils.c b/arch/arm/mach-omap2/utils.c
index 0b0bf18..d4f171b 100644
--- a/arch/arm/mach-omap2/utils.c
+++ b/arch/arm/mach-omap2/utils.c
@@ -87,15 +87,14 @@
 
 	dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
 	if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
-		error("invalid mmc device\n");
+		pr_err("invalid mmc device\n");
 		return 0;
 	}
 
-	res = part_get_info_by_name(dev_desc, part, &info);
-	if (res < 0) {
-		error("cannot find partition: '%s'\n", part);
+	/* Check only for EFI (GPT) partition table */
+	res = part_get_info_by_name_type(dev_desc, part, &info, PART_TYPE_EFI);
+	if (res < 0)
 		return 0;
-	}
 
 	/* Calculate size in bytes */
 	sz = (info.size * (u64)info.blksz);
@@ -111,13 +110,10 @@
 	u32 sz_kb;
 
 	sz_kb = omap_mmc_get_part_size("userdata");
-	if (sz_kb == 0) {
-		buf[0] = '\0';
-		printf("Warning: fastboot.userdata_size: unable to calc\n");
-	} else {
-		sprintf(buf, "%u", sz_kb);
-	}
+	if (sz_kb == 0)
+		return; /* probably it's not Android partition table */
 
+	sprintf(buf, "%u", sz_kb);
 	env_set("fastboot.userdata_size", buf);
 }
 #else
diff --git a/arch/arm/mach-qemu/Kconfig b/arch/arm/mach-qemu/Kconfig
new file mode 100644
index 0000000..3500b56
--- /dev/null
+++ b/arch/arm/mach-qemu/Kconfig
@@ -0,0 +1,12 @@
+if ARCH_QEMU
+
+config SYS_VENDOR
+	default "emulation"
+
+config SYS_BOARD
+	default "qemu-arm"
+
+config SYS_CONFIG_NAME
+	default "qemu-arm"
+
+endif
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 79e9704..daafc8d 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -12,6 +12,7 @@
 obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o
 
 obj-tpl-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-tpl.o
+obj-tpl-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-tpl.o
 obj-tpl-$(CONFIG_ROCKCHIP_RK3368) += rk3368-board-tpl.o
 
 obj-spl-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board-spl.o
diff --git a/arch/arm/mach-rockchip/rk3188-board-spl.c b/arch/arm/mach-rockchip/rk3188-board-spl.c
index d3866bf..406207e 100644
--- a/arch/arm/mach-rockchip/rk3188-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3188-board-spl.c
@@ -151,7 +151,7 @@
 	 */
 	pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
 	if (IS_ERR(pmu))
-		error("pmu syscon returned %ld\n", PTR_ERR(pmu));
+		pr_err("pmu syscon returned %ld\n", PTR_ERR(pmu));
 	SAVE_SP_ADDR = readl(&pmu->sys_reg[2]);
 
 	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
diff --git a/arch/arm/mach-rockchip/rk3188-board.c b/arch/arm/mach-rockchip/rk3188-board.c
index 622e046..96859a5 100644
--- a/arch/arm/mach-rockchip/rk3188-board.c
+++ b/arch/arm/mach-rockchip/rk3188-board.c
@@ -26,7 +26,7 @@
 
 	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
 	if (IS_ERR(grf)) {
-		error("grf syscon returned %ld\n", PTR_ERR(grf));
+		pr_err("grf syscon returned %ld\n", PTR_ERR(grf));
 	} else {
 		/* enable noc remap to mimic legacy loaders */
 		rk_clrsetreg(&grf->soc_con0,
diff --git a/arch/arm/mach-rockchip/rk3188/Makefile b/arch/arm/mach-rockchip/rk3188/Makefile
index 2dc9511..7fa0104 100644
--- a/arch/arm/mach-rockchip/rk3188/Makefile
+++ b/arch/arm/mach-rockchip/rk3188/Makefile
@@ -6,6 +6,5 @@
 
 ifndef CONFIG_TPL_BUILD
 obj-y += clk_rk3188.o
-obj-y += sdram_rk3188.o
 obj-y += syscon_rk3188.o
 endif
diff --git a/arch/arm/mach-rockchip/rk322x-board.c b/arch/arm/mach-rockchip/rk322x-board.c
index dcd8cf8..d443114 100644
--- a/arch/arm/mach-rockchip/rk322x-board.c
+++ b/arch/arm/mach-rockchip/rk322x-board.c
@@ -21,12 +21,12 @@
 static void setup_boot_mode(void)
 {
 	struct rk322x_grf *const grf = (void *)GRF_BASE;
-	int boot_mode = readl(&grf->os_reg[4]);
+	int boot_mode = readl(&grf->os_reg[0]);
 
 	debug("boot mode %x.\n", boot_mode);
 
 	/* Clear boot mode */
-	writel(BOOT_NORMAL, &grf->os_reg[4]);
+	writel(BOOT_NORMAL, &grf->os_reg[0]);
 
 	switch (boot_mode) {
 	case BOOT_FASTBOOT:
diff --git a/arch/arm/mach-rockchip/rk3288-board-spl.c b/arch/arm/mach-rockchip/rk3288-board-spl.c
index 6b7bf85..7b7fd5a 100644
--- a/arch/arm/mach-rockchip/rk3288-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3288-board-spl.c
@@ -19,7 +19,10 @@
 #include <asm/arch/clock.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/periph.h>
+#include <asm/arch/pmu_rk3288.h>
 #include <asm/arch/sdram.h>
+#include <asm/arch/sdram_common.h>
+#include <asm/arch/sys_proto.h>
 #include <asm/arch/timer.h>
 #include <dm/pinctrl.h>
 #include <dm/root.h>
@@ -80,46 +83,6 @@
 	return MMCSD_MODE_RAW;
 }
 
-/* read L2 control register (L2CTLR) */
-static inline uint32_t read_l2ctlr(void)
-{
-	uint32_t val = 0;
-
-	asm volatile ("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
-
-	return val;
-}
-
-/* write L2 control register (L2CTLR) */
-static inline void write_l2ctlr(uint32_t val)
-{
-	/*
-	 * Note: L2CTLR can only be written when the L2 memory system
-	 * is idle, ie before the MMU is enabled.
-	 */
-	asm volatile("mcr p15, 1, %0, c9, c0, 2" : : "r" (val) : "memory");
-	isb();
-}
-
-static void configure_l2ctlr(void)
-{
-	uint32_t l2ctlr;
-
-	l2ctlr = read_l2ctlr();
-	l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */
-
-	/*
-	* Data RAM write latency: 2 cycles
-	* Data RAM read latency: 2 cycles
-	* Data RAM setup latency: 1 cycle
-	* Tag RAM write latency: 1 cycle
-	* Tag RAM read latency: 1 cycle
-	* Tag RAM setup latency: 1 cycle
-	*/
-	l2ctlr |= (1 << 3 | 1 << 0);
-	write_l2ctlr(l2ctlr);
-}
-
 #ifdef CONFIG_SPL_MMC_SUPPORT
 static int configure_emmc(struct udevice *pinctrl)
 {
@@ -243,12 +206,15 @@
 	}
 #endif
 
+#if !defined(CONFIG_SUPPORT_TPL)
 	debug("\nspl:init dram\n");
 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
 	if (ret) {
 		debug("DRAM init failed: %d\n", ret);
 		return;
 	}
+#endif
+
 #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT)
 	back_to_bootrom();
 #endif
@@ -326,3 +292,18 @@
 	/* No way to report error here */
 	hang();
 }
+
+#ifdef CONFIG_SPL_OS_BOOT
+
+#define PMU_BASE		0xff730000
+int dram_init_banksize(void)
+{
+	struct rk3288_pmu *const pmu = (void *)PMU_BASE;
+	size_t size = rockchip_sdram_size((phys_addr_t)&pmu->sys_reg[2]);
+
+	gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+	gd->bd->bi_dram[0].size = size;
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/mach-rockchip/rk3288-board-tpl.c b/arch/arm/mach-rockchip/rk3288-board-tpl.c
new file mode 100644
index 0000000..3d08b5b
--- /dev/null
+++ b/arch/arm/mach-rockchip/rk3288-board-tpl.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 Amarula Solutions
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <ram.h>
+#include <spl.h>
+#include <version.h>
+#include <asm/io.h>
+#include <asm/arch/bootrom.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/grf_rk3288.h>
+#include <asm/arch/periph.h>
+#include <asm/arch/pmu_rk3288.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/timer.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define GRF_BASE		0xff770000
+void board_init_f(ulong dummy)
+{
+	struct udevice *dev;
+	int ret;
+
+	/* Example code showing how to enable the debug UART on RK3288 */
+	/* Enable early UART on the RK3288 */
+	struct rk3288_grf * const grf = (void *)GRF_BASE;
+
+	rk_clrsetreg(&grf->gpio7ch_iomux, GPIO7C7_MASK << GPIO7C7_SHIFT |
+		     GPIO7C6_MASK << GPIO7C6_SHIFT,
+		     GPIO7C7_UART2DBG_SOUT << GPIO7C7_SHIFT |
+		     GPIO7C6_UART2DBG_SIN << GPIO7C6_SHIFT);
+	/*
+	 * Debug UART can be used from here if required:
+	 *
+	 * debug_uart_init();
+	 * printch('a');
+	 * printhex8(0x1234);
+	 * printascii("string");
+	 */
+	debug_uart_init();
+
+	ret = spl_early_init();
+	if (ret) {
+		debug("spl_early_init() failed: %d\n", ret);
+		hang();
+	}
+
+	rockchip_timer_init();
+	configure_l2ctlr();
+
+	ret = rockchip_get_clk(&dev);
+	if (ret) {
+		debug("CLK init failed: %d\n", ret);
+		return;
+	}
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret) {
+		debug("DRAM init failed: %d\n", ret);
+		return;
+	}
+}
+
+void board_return_to_bootrom(void)
+{
+	back_to_bootrom();
+}
+
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_BOOTROM;
+}
+
+void spl_board_init(void)
+{
+	puts("\nU-Boot TPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \
+				U_BOOT_TIME ")\n");
+}
diff --git a/arch/arm/mach-rockchip/rk3288/Kconfig b/arch/arm/mach-rockchip/rk3288/Kconfig
index 4ad2940..6beb26f 100644
--- a/arch/arm/mach-rockchip/rk3288/Kconfig
+++ b/arch/arm/mach-rockchip/rk3288/Kconfig
@@ -87,6 +87,22 @@
 config TARGET_VYASA_RK3288
 	bool "Vyasa-RK3288"
 	select BOARD_LATE_INIT
+	select TPL
+	select SUPPORT_TPL
+	select TPL_DM
+	select TPL_REGMAP
+	select TPL_SYSCON
+	select TPL_CLK
+	select TPL_RAM
+	select TPL_OF_PLATDATA
+	select TPL_OF_CONTROL
+	select TPL_BOOTROM_SUPPORT
+	select TPL_NEEDS_SEPARATE_TEXT_BASE if SPL
+	select ROCKCHIP_BROM_HELPER
+	select TPL_DRIVERS_MISC_SUPPORT
+	select TPL_LIBCOMMON_SUPPORT
+	select TPL_LIBGENERIC_SUPPORT
+	select TPL_SERIAL_SUPPORT
 	help
 	  Vyasa is a RK3288-based development board with 2 USB ports,
 	  HDMI, VGA, micro-SD card, audio, WiFi  and Gigabit Ethernet, It
diff --git a/arch/arm/mach-rockchip/rk3288/Makefile b/arch/arm/mach-rockchip/rk3288/Makefile
index b5b28ef..a0033a0 100644
--- a/arch/arm/mach-rockchip/rk3288/Makefile
+++ b/arch/arm/mach-rockchip/rk3288/Makefile
@@ -6,5 +6,4 @@
 
 obj-y += clk_rk3288.o
 obj-y += rk3288.o
-obj-y += sdram_rk3288.o
 obj-y += syscon_rk3288.o
diff --git a/arch/arm/mach-rockchip/rk3328/Makefile b/arch/arm/mach-rockchip/rk3328/Makefile
index 72873e2..bbab036 100644
--- a/arch/arm/mach-rockchip/rk3328/Makefile
+++ b/arch/arm/mach-rockchip/rk3328/Makefile
@@ -6,5 +6,4 @@
 
 obj-y += clk_rk3328.o
 obj-y += rk3328.o
-obj-y += sdram_rk3328.o
 obj-y += syscon_rk3328.o
diff --git a/arch/arm/mach-rockchip/rk3368-board-spl.c b/arch/arm/mach-rockchip/rk3368-board-spl.c
index cabf344..72d2c97 100644
--- a/arch/arm/mach-rockchip/rk3368-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3368-board-spl.c
@@ -38,13 +38,13 @@
 	/* Set up our preloader console */
 	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
 	if (ret) {
-		error("%s: pinctrl init failed: %d\n", __func__, ret);
+		pr_err("%s: pinctrl init failed: %d\n", __func__, ret);
 		hang();
 	}
 
 	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART0);
 	if (ret) {
-		error("%s: failed to set up console UART\n", __func__);
+		pr_err("%s: failed to set up console UART\n", __func__);
 		hang();
 	}
 
diff --git a/arch/arm/mach-rockchip/rk3399-board-spl.c b/arch/arm/mach-rockchip/rk3399-board-spl.c
index 3406156..9c20f56 100644
--- a/arch/arm/mach-rockchip/rk3399-board-spl.c
+++ b/arch/arm/mach-rockchip/rk3399-board-spl.c
@@ -1,10 +1,12 @@
 /*
  * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
  *
  * SPDX-License-Identifier:     GPL-2.0+
  */
 
 #include <common.h>
+#include <asm/arch/bootrom.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/grf_rk3399.h>
 #include <asm/arch/hardware.h>
@@ -19,9 +21,43 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+void board_return_to_bootrom(void)
+{
+	back_to_bootrom();
+}
+
+static const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
+	[BROM_BOOTSOURCE_EMMC] = "/sdhci@fe330000",
+	[BROM_BOOTSOURCE_SPINOR] = "/spi@ff1d0000",
+	[BROM_BOOTSOURCE_SD] = "/dwmmc@fe320000",
+};
+
+const char *board_spl_was_booted_from(void)
+{
+	u32  bootdevice_brom_id = readl(RK3399_BROM_BOOTSOURCE_ID_ADDR);
+	const char *bootdevice_ofpath = NULL;
+
+	if (bootdevice_brom_id < ARRAY_SIZE(boot_devices))
+		bootdevice_ofpath = boot_devices[bootdevice_brom_id];
+
+	if (bootdevice_ofpath)
+		debug("%s: brom_bootdevice_id %x maps to '%s'\n",
+		      __func__, bootdevice_brom_id, bootdevice_ofpath);
+	else
+		debug("%s: failed to resolve brom_bootdevice_id %x\n",
+		      __func__, bootdevice_brom_id);
+
+	return bootdevice_ofpath;
+}
+
 u32 spl_boot_device(void)
 {
-	return BOOT_DEVICE_MMC1;
+	u32 boot_device = BOOT_DEVICE_MMC1;
+
+	if (CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM))
+		return BOOT_DEVICE_BOOTROM;
+
+	return boot_device;
 }
 
 u32 spl_boot_mode(const u32 boot_device)
@@ -137,37 +173,6 @@
 	}
 }
 
-void spl_board_init(void)
-{
-	struct udevice *pinctrl;
-	int ret;
-
-	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
-	if (ret) {
-		debug("%s: Cannot find pinctrl device\n", __func__);
-		goto err;
-	}
-
-	/* Enable debug UART */
-	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG);
-	if (ret) {
-		debug("%s: Failed to set up console UART\n", __func__);
-		goto err;
-	}
-
-	preloader_console_init();
-#if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)
-	back_to_bootrom();
-#endif
-
-	return;
-err:
-	printf("spl_board_init: Error %d\n", ret);
-
-	/* No way to report error here */
-	hang();
-}
-
 #ifdef CONFIG_SPL_LOAD_FIT
 int board_fit_config_name_match(const char *name)
 {
diff --git a/arch/arm/mach-rockchip/rk3399/Makefile b/arch/arm/mach-rockchip/rk3399/Makefile
index 793ce31..98ebeac 100644
--- a/arch/arm/mach-rockchip/rk3399/Makefile
+++ b/arch/arm/mach-rockchip/rk3399/Makefile
@@ -6,5 +6,4 @@
 
 obj-y += clk_rk3399.o
 obj-y += rk3399.o
-obj-y += sdram_rk3399.o
 obj-y += syscon_rk3399.o
diff --git a/arch/arm/mach-rockchip/spl-boot-order.c b/arch/arm/mach-rockchip/spl-boot-order.c
index 4f78c72..843998d 100644
--- a/arch/arm/mach-rockchip/spl-boot-order.c
+++ b/arch/arm/mach-rockchip/spl-boot-order.c
@@ -10,6 +10,25 @@
 #include <spl.h>
 
 #if CONFIG_IS_ENABLED(OF_CONTROL)
+/**
+ * spl_node_to_boot_device() - maps from a DT-node to a SPL boot device
+ * @node:	of_offset of the node
+ *
+ * The SPL framework uses BOOT_DEVICE_... constants to identify its boot
+ * sources.  These may take on a device-specific meaning, depending on
+ * what nodes are enabled in a DTS (e.g. BOOT_DEVICE_MMC1 may refer to
+ * different controllers/block-devices, depending on which SD/MMC controllers
+ * are enabled in any given DTS).  This function maps from a DT-node back
+ * onto a BOOT_DEVICE_... constant, considering the currently active devices.
+ *
+ * Returns
+ *   -ENOENT, if no device matching the node could be found
+ *   -ENOSYS, if the device matching the node can not be mapped onto a
+ *            SPL boot device (e.g. the third MMC device)
+ *   -1, for unspecified failures
+ *   a positive integer (from the BOOT_DEVICE_... family) on succes.
+ */
+
 static int spl_node_to_boot_device(int node)
 {
 	struct udevice *parent;
@@ -57,6 +76,24 @@
 	return -1;
 }
 
+/**
+ * board_spl_was_booted_from() - retrieves the of-path the SPL was loaded from
+ *
+ * To support a 'same-as-spl' specification in the search-order for the next
+ * stage, we need a SoC- or board-specific way to handshake with what 'came
+ * before us' (either a BROM or TPL stage) and map the info retrieved onto
+ * a OF path.
+ *
+ * Returns
+ *   NULL, on failure or if the device could not be identified
+ *   a of_path (a string), on success
+ */
+__weak const char *board_spl_was_booted_from(void)
+{
+	debug("%s: no support for 'same-as-spl' for this board\n", __func__);
+	return NULL;
+}
+
 void board_boot_order(u32 *spl_boot_list)
 {
 	const void *blob = gd->fdt_blob;
@@ -78,8 +115,17 @@
 	     (conf = fdt_stringlist_get(blob, chosen_node,
 					"u-boot,spl-boot-order", elem, NULL));
 	     elem++) {
+		const char *alias;
+
+		/* Handle the case of 'same device the SPL was loaded from' */
+		if (strncmp(conf, "same-as-spl", 11) == 0) {
+			conf = board_spl_was_booted_from();
+			if (!conf)
+				continue;
+		}
+
 		/* First check if the list element is an alias */
-		const char *alias = fdt_get_alias(blob, conf);
+		alias = fdt_get_alias(blob, conf);
 		if (alias)
 			conf = alias;
 
diff --git a/arch/arm/mach-socfpga/reset_manager_arria10.c b/arch/arm/mach-socfpga/reset_manager_arria10.c
index 66f1ec2..ae16897 100644
--- a/arch/arm/mach-socfpga/reset_manager_arria10.c
+++ b/arch/arm/mach-socfpga/reset_manager_arria10.c
@@ -174,7 +174,7 @@
 		emacmask = ALT_RSTMGR_PER0MODRST_EMAC2_SET_MSK;
 		break;
 	default:
-		error("emac base address unexpected! %lx", emacbase);
+		pr_err("emac base address unexpected! %lx", emacbase);
 		hang();
 		break;
 	}
diff --git a/arch/arm/mach-stm32/stm32f7/timer.c b/arch/arm/mach-stm32/stm32f7/timer.c
index c15f8bb..b04c101 100644
--- a/arch/arm/mach-stm32/stm32f7/timer.c
+++ b/arch/arm/mach-stm32/stm32f7/timer.c
@@ -26,7 +26,7 @@
 	/* Stop the timer */
 	writel(readl(&gpt1_regs_ptr->cr1) & ~GPT_CR1_CEN, &gpt1_regs_ptr->cr1);
 
-	writel((CONFIG_SYS_CLK_FREQ/CONFIG_SYS_HZ_CLOCK) - 1,
+	writel((CONFIG_SYS_CLK_FREQ / 2 / CONFIG_SYS_HZ_CLOCK) - 1,
 						&gpt1_regs_ptr->psc);
 
 	/* Configure timer for auto-reload */
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 65b1ebd..0c60ee0 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -14,9 +14,7 @@
 #include <mmc.h>
 #include <i2c.h>
 #include <serial.h>
-#ifdef CONFIG_SPL_BUILD
 #include <spl.h>
-#endif
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
@@ -212,11 +210,12 @@
 
 #ifdef CONFIG_SPL_BUILD
 DECLARE_GLOBAL_DATA_PTR;
+#endif
 
 /* The sunxi internal brom will try to loader external bootloader
  * from mmc0, nand flash, mmc2.
  */
-u32 spl_boot_device(void)
+uint32_t sunxi_get_boot_device(void)
 {
 	int boot_source;
 
@@ -255,6 +254,12 @@
 	return -1;		/* Never reached */
 }
 
+#ifdef CONFIG_SPL_BUILD
+u32 spl_boot_device(void)
+{
+	return sunxi_get_boot_device();
+}
+
 /* No confirmation data available in SPL yet. Hardcode bootmode */
 u32 spl_boot_mode(const u32 boot_device)
 {
diff --git a/arch/arm/mach-sunxi/usb_phy.c b/arch/arm/mach-sunxi/usb_phy.c
index 9bf0b56..2f1cad1 100644
--- a/arch/arm/mach-sunxi/usb_phy.c
+++ b/arch/arm/mach-sunxi/usb_phy.c
@@ -18,12 +18,18 @@
 #include <asm/io.h>
 #include <errno.h>
 
-#define SUNXI_USB_PMU_IRQ_ENABLE	0x800
-#ifdef CONFIG_MACH_SUN8I_A33
-#define SUNXI_USB_CSR			0x410
-#else
+#if defined(CONFIG_MACH_SUN4I) ||		   \
+	defined(CONFIG_MACH_SUN5I) ||		   \
+	defined(CONFIG_MACH_SUN6I) ||		   \
+	defined(CONFIG_MACH_SUN7I) ||		   \
+	defined(CONFIG_MACH_SUN8I_A23) ||	   \
+	defined(CONFIG_MACH_SUN9I)
 #define SUNXI_USB_CSR			0x404
+#else
+#define SUNXI_USB_CSR			0x410
 #endif
+
+#define SUNXI_USB_PMU_IRQ_ENABLE	0x800
 #define SUNXI_USB_PASSBY_EN		1
 
 #define SUNXI_EHCI_AHB_ICHR8_EN		(1 << 10)
diff --git a/arch/arm/mach-tegra/ivc.c b/arch/arm/mach-tegra/ivc.c
index cf6626f..dec7d90 100644
--- a/arch/arm/mach-tegra/ivc.c
+++ b/arch/arm/mach-tegra/ivc.c
@@ -493,7 +493,7 @@
 	       (TEGRA_IVC_ALIGN - 1));
 
 	if ((uint64_t)nframes * (uint64_t)frame_size >= 0x100000000) {
-		error("tegra_ivc: nframes * frame_size overflows\n");
+		pr_err("tegra_ivc: nframes * frame_size overflows\n");
 		return -EINVAL;
 	}
 
@@ -503,12 +503,12 @@
 	 */
 	if ((qbase1 & (TEGRA_IVC_ALIGN - 1)) ||
 	    (qbase2 & (TEGRA_IVC_ALIGN - 1))) {
-		error("tegra_ivc: channel start not aligned\n");
+		pr_err("tegra_ivc: channel start not aligned\n");
 		return -EINVAL;
 	}
 
 	if (frame_size & (TEGRA_IVC_ALIGN - 1)) {
-		error("tegra_ivc: frame size not adequately aligned\n");
+		pr_err("tegra_ivc: frame size not adequately aligned\n");
 		return -EINVAL;
 	}
 
@@ -521,7 +521,7 @@
 	}
 
 	if (ret) {
-		error("tegra_ivc: queue regions overlap\n");
+		pr_err("tegra_ivc: queue regions overlap\n");
 		return ret;
 	}
 
diff --git a/arch/arm/mach-tegra/tegra124/xusb-padctl.c b/arch/arm/mach-tegra/tegra124/xusb-padctl.c
index d326a6a..bfc0ab8 100644
--- a/arch/arm/mach-tegra/tegra124/xusb-padctl.c
+++ b/arch/arm/mach-tegra/tegra124/xusb-padctl.c
@@ -137,7 +137,7 @@
 	u32 value;
 
 	if (padctl->enable == 0) {
-		error("unbalanced enable/disable");
+		pr_err("unbalanced enable/disable");
 		return 0;
 	}
 
diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c
index 966cf9f..5224ef6 100644
--- a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c
+++ b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c
@@ -45,12 +45,12 @@
 
 	node = fdt_path_offset(nvtboot_blob, "/memory");
 	if (node < 0) {
-		error("Can't find /memory node in nvtboot DTB");
+		pr_err("Can't find /memory node in nvtboot DTB");
 		hang();
 	}
 	prop = fdt_getprop(nvtboot_blob, node, "reg", &len);
 	if (!prop) {
-		error("Can't find /memory/reg property in nvtboot DTB");
+		pr_err("Can't find /memory/reg property in nvtboot DTB");
 		hang();
 	}
 
diff --git a/arch/arm/mach-tegra/tegra20/clock.c b/arch/arm/mach-tegra/tegra20/clock.c
index ec04cf5..81fb1d8 100644
--- a/arch/arm/mach-tegra/tegra20/clock.c
+++ b/arch/arm/mach-tegra/tegra20/clock.c
@@ -667,7 +667,7 @@
 	} while (--timeout);
 
 	if (timeout == 0) {
-		error("timeout waiting for PLLE to become ready");
+		pr_err("timeout waiting for PLLE to become ready");
 		return -ETIMEDOUT;
 	}
 
@@ -697,7 +697,7 @@
 	if ((value & PLLE_MISC_PLL_READY) == 0) {
 		err = tegra_plle_train();
 		if (err < 0) {
-			error("failed to train PLLE: %d", err);
+			pr_err("failed to train PLLE: %d", err);
 			return err;
 		}
 	}
@@ -726,7 +726,7 @@
 	} while (--timeout);
 
 	if (timeout == 0) {
-		error("timeout waiting for PLLE to lock");
+		pr_err("timeout waiting for PLLE to lock");
 		return -ETIMEDOUT;
 	}
 
diff --git a/arch/arm/mach-tegra/tegra210/xusb-padctl.c b/arch/arm/mach-tegra/tegra210/xusb-padctl.c
index bf85e07..a3e3e37 100644
--- a/arch/arm/mach-tegra/tegra210/xusb-padctl.c
+++ b/arch/arm/mach-tegra/tegra210/xusb-padctl.c
@@ -125,7 +125,7 @@
 	u32 value;
 
 	if (padctl->enable == 0) {
-		error("unbalanced enable/disable");
+		pr_err("unbalanced enable/disable");
 		return 0;
 	}
 
diff --git a/arch/arm/mach-tegra/tegra30/clock.c b/arch/arm/mach-tegra/tegra30/clock.c
index 4fd8b8a..282f34f 100644
--- a/arch/arm/mach-tegra/tegra30/clock.c
+++ b/arch/arm/mach-tegra/tegra30/clock.c
@@ -696,7 +696,7 @@
 	} while (--timeout);
 
 	if (timeout == 0) {
-		error("timeout waiting for PLLE to become ready");
+		pr_err("timeout waiting for PLLE to become ready");
 		return -ETIMEDOUT;
 	}
 
@@ -726,7 +726,7 @@
 	if ((value & PLLE_MISC_PLL_READY) == 0) {
 		err = tegra_plle_train();
 		if (err < 0) {
-			error("failed to train PLLE: %d", err);
+			pr_err("failed to train PLLE: %d", err);
 			return err;
 		}
 	}
@@ -772,7 +772,7 @@
 	} while (--timeout);
 
 	if (timeout == 0) {
-		error("timeout waiting for PLLE to lock");
+		pr_err("timeout waiting for PLLE to lock");
 		return -ETIMEDOUT;
 	}
 
diff --git a/arch/arm/mach-tegra/xusb-padctl-common.c b/arch/arm/mach-tegra/xusb-padctl-common.c
index abc18c0..c8a468a 100644
--- a/arch/arm/mach-tegra/xusb-padctl-common.c
+++ b/arch/arm/mach-tegra/xusb-padctl-common.c
@@ -84,7 +84,7 @@
 
 	len = ofnode_read_string_count(node, "nvidia,lanes");
 	if (len < 0) {
-		error("failed to parse \"nvidia,lanes\" property");
+		pr_err("failed to parse \"nvidia,lanes\" property");
 		return -EINVAL;
 	}
 
@@ -94,7 +94,7 @@
 		ret = ofnode_read_string_index(node, "nvidia,lanes", i,
 					       &group->pins[i]);
 		if (ret) {
-			error("failed to read string from \"nvidia,lanes\" property");
+			pr_err("failed to read string from \"nvidia,lanes\" property");
 			return -EINVAL;
 		}
 	}
@@ -104,7 +104,7 @@
 	ret = ofnode_read_string_index(node, "nvidia,function", 0,
 				       &group->func);
 	if (ret) {
-		error("failed to parse \"nvidia,func\" property");
+		pr_err("failed to parse \"nvidia,func\" property");
 		return -EINVAL;
 	}
 
@@ -157,14 +157,14 @@
 
 		lane = tegra_xusb_padctl_find_lane(padctl, group->pins[i]);
 		if (!lane) {
-			error("no lane for pin %s", group->pins[i]);
+			pr_err("no lane for pin %s", group->pins[i]);
 			continue;
 		}
 
 		func = tegra_xusb_padctl_lane_find_function(padctl, lane,
 							    group->func);
 		if (func < 0) {
-			error("function %s invalid for lane %s: %d",
+			pr_err("function %s invalid for lane %s: %d",
 			      group->func, lane->name, func);
 			continue;
 		}
@@ -206,7 +206,7 @@
 
 		err = tegra_xusb_padctl_group_apply(padctl, group);
 		if (err < 0) {
-			error("failed to apply group %s: %d",
+			pr_err("failed to apply group %s: %d",
 			      group->name, err);
 			continue;
 		}
@@ -232,7 +232,7 @@
 
 		err = tegra_xusb_padctl_group_parse_dt(padctl, group, subnode);
 		if (err < 0) {
-			error("failed to parse group %s", group->name);
+			pr_err("failed to parse group %s", group->name);
 			return err;
 		}
 
@@ -250,7 +250,7 @@
 
 	err = ofnode_read_resource(node, 0, &padctl->regs);
 	if (err < 0) {
-		error("registers not found");
+		pr_err("registers not found");
 		return err;
 	}
 
@@ -261,7 +261,7 @@
 		err = tegra_xusb_padctl_config_parse_dt(padctl, config,
 							subnode);
 		if (err < 0) {
-			error("failed to parse entry %s: %d",
+			pr_err("failed to parse entry %s: %d",
 			      config->name, err);
 			continue;
 		}
@@ -289,7 +289,7 @@
 
 		err = tegra_xusb_padctl_parse_dt(&padctl, nodes[i]);
 		if (err < 0) {
-			error("failed to parse DT: %d", err);
+			pr_err("failed to parse DT: %d", err);
 			continue;
 		}
 
@@ -298,7 +298,7 @@
 
 		err = tegra_xusb_padctl_config_apply(&padctl, &padctl.config);
 		if (err < 0) {
-			error("failed to apply pinmux: %d", err);
+			pr_err("failed to apply pinmux: %d", err);
 			continue;
 		}
 
diff --git a/arch/arm/mach-uniphier/dram_init.c b/arch/arm/mach-uniphier/dram_init.c
index 32d3593..2213685 100644
--- a/arch/arm/mach-uniphier/dram_init.c
+++ b/arch/arm/mach-uniphier/dram_init.c
@@ -15,9 +15,6 @@
 #include "sg-regs.h"
 #include "soc-info.h"
 
-#define pr_warn(fmt, args...)	printf(fmt, ##args)
-#define pr_err(fmt, args...)	printf(fmt, ##args)
-
 DECLARE_GLOBAL_DATA_PTR;
 
 struct uniphier_memif_data {
diff --git a/arch/arm/mach-uniphier/init.h b/arch/arm/mach-uniphier/init.h
index 29f638d..da20935 100644
--- a/arch/arm/mach-uniphier/init.h
+++ b/arch/arm/mach-uniphier/init.h
@@ -104,9 +104,4 @@
 int uniphier_boot_from_backend(void);
 int uniphier_pin_init(const char *pinconfig_name);
 
-#undef pr_warn
-#define pr_warn(fmt, args...)	printf(fmt, ##args)
-#undef pr_err
-#define pr_err(fmt, args...)	printf(fmt, ##args)
-
 #endif /* __MACH_INIT_H */
diff --git a/arch/m68k/include/asm/io.h b/arch/m68k/include/asm/io.h
index 384308b..dfe77f0 100644
--- a/arch/m68k/include/asm/io.h
+++ b/arch/m68k/include/asm/io.h
@@ -253,33 +253,6 @@
 	 */
 }
 
-/*
- * Given a physical address and a length, return a virtual address
- * that can be used to access the memory range with the caching
- * properties specified by "flags".
- */
-#define MAP_NOCACHE	(0)
-#define MAP_WRCOMBINE	(0)
-#define MAP_WRBACK	(0)
-#define MAP_WRTHROUGH	(0)
-
-static inline void *map_physmem(phys_addr_t paddr, unsigned long len,
-				unsigned long flags)
-{
-	return (void *)paddr;
-}
-
-/*
- * Take down a mapping set up by map_physmem().
- */
-static inline void unmap_physmem(void *vaddr, unsigned long flags)
-{
-
-}
-
-static inline phys_addr_t virt_to_phys(void * vaddr)
-{
-	return (phys_addr_t)(vaddr);
-}
+#include <asm-generic/io.h>
 
 #endif				/* __ASM_M68K_IO_H__ */
diff --git a/arch/microblaze/include/asm/io.h b/arch/microblaze/include/asm/io.h
index 584cbce..c7516a4 100644
--- a/arch/microblaze/include/asm/io.h
+++ b/arch/microblaze/include/asm/io.h
@@ -131,33 +131,6 @@
 {
 }
 
-/*
- * Given a physical address and a length, return a virtual address
- * that can be used to access the memory range with the caching
- * properties specified by "flags".
- */
-#define MAP_NOCACHE	(0)
-#define MAP_WRCOMBINE	(0)
-#define MAP_WRBACK	(0)
-#define MAP_WRTHROUGH	(0)
-
-static inline void *
-map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
-{
-	return (void *)paddr;
-}
-
-/*
- * Take down a mapping set up by map_physmem().
- */
-static inline void unmap_physmem(void *vaddr, unsigned long flags)
-{
-
-}
-
-static inline phys_addr_t virt_to_phys(void * vaddr)
-{
-	return (phys_addr_t)(vaddr);
-}
+#include <asm-generic/io.h>
 
 #endif /* __MICROBLAZE_IO_H__ */
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index ee7a592..45d7ca0 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -95,6 +95,7 @@
 #endif
 	return CPHYSADDR(addr);
 }
+#define virt_to_phys virt_to_phys
 
 /*
  *     phys_to_virt    -       map physical address to virtual
@@ -112,6 +113,7 @@
 {
 	return (void *)(address + PAGE_OFFSET - PHYS_OFFSET);
 }
+#define phys_to_virt phys_to_virt
 
 /*
  * ISA I/O bus memory addresses are 1:1 with the physical address.
@@ -490,10 +492,7 @@
  */
 #define sync()		mmiowb()
 
-#define MAP_NOCACHE	(1)
-#define MAP_WRCOMBINE	(0)
-#define MAP_WRBACK	(0)
-#define MAP_WRTHROUGH	(0)
+#define MAP_NOCACHE	1
 
 static inline void *
 map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
@@ -503,13 +502,7 @@
 
 	return (void *)CKSEG0ADDR(paddr);
 }
-
-/*
- * Take down a mapping set up by map_physmem().
- */
-static inline void unmap_physmem(void *vaddr, unsigned long flags)
-{
-}
+#define map_physmem map_physmem
 
 #define __BUILD_CLRBITS(bwlq, sfx, end, type)				\
 									\
@@ -566,4 +559,6 @@
 BUILD_CLRSETBITS(q, be64, be64, u64)
 BUILD_CLRSETBITS(q, 64, _, u64)
 
+#include <asm-generic/io.h>
+
 #endif /* _ASM_IO_H */
diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h
index 25ef9a4..c6d8d9b 100644
--- a/arch/nds32/include/asm/io.h
+++ b/arch/nds32/include/asm/io.h
@@ -38,16 +38,6 @@
 {
 }
 
-/*
- * Given a physical address and a length, return a virtual address
- * that can be used to access the memory range with the caching
- * properties specified by "flags".
- */
-#define MAP_NOCACHE	(0)
-#define MAP_WRCOMBINE	(0)
-#define MAP_WRBACK	(0)
-#define MAP_WRTHROUGH	(0)
-
 #ifdef CONFIG_ARCH_MAP_SYSMEM
 static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
 {
@@ -69,25 +59,6 @@
 }
 #endif
 
-static inline void *
-map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
-{
-	return (void *)paddr;
-}
-
-/*
- * Take down a mapping set up by map_physmem().
- */
-static inline void unmap_physmem(void *vaddr, unsigned long flags)
-{
-
-}
-
-static inline phys_addr_t virt_to_phys(void *vaddr)
-{
-	return (phys_addr_t)(vaddr);
-}
-
 /*
  * Generic virtual read/write.  Note that we don't support half-word
  * read/writes.  We define __arch_*[bl] here, and leave __arch_*w
@@ -480,5 +451,8 @@
 #define isa_check_signature(io, sig, len)	(0)
 
 #endif	/* __mem_isa */
+
+#include <asm-generic/io.h>
+
 #endif	/* __KERNEL__ */
 #endif	/* __ASM_NDS_IO_H */
diff --git a/arch/nios2/include/asm/io.h b/arch/nios2/include/asm/io.h
index e951500..4e5b44a 100644
--- a/arch/nios2/include/asm/io.h
+++ b/arch/nios2/include/asm/io.h
@@ -19,9 +19,6 @@
  * properties specified by "flags".
  */
 #define MAP_NOCACHE	1
-#define MAP_WRCOMBINE	0
-#define MAP_WRBACK	0
-#define MAP_WRTHROUGH	0
 
 static inline void *
 map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
@@ -32,20 +29,22 @@
 	else
 		return (void *)(paddr | gd->arch.mem_region_base);
 }
+#define map_physmem map_physmem
 
-/*
- * Take down a mapping set up by map_physmem().
- */
-static inline void unmap_physmem(void *vaddr, unsigned long flags)
+static inline void *phys_to_virt(phys_addr_t paddr)
 {
+	DECLARE_GLOBAL_DATA_PTR;
 
+	return (void *)(paddr | gd->arch.mem_region_base);
 }
+#define phys_to_virt phys_to_virt
 
 static inline phys_addr_t virt_to_phys(void * vaddr)
 {
 	DECLARE_GLOBAL_DATA_PTR;
 	return (phys_addr_t)vaddr & gd->arch.physaddr_mask;
 }
+#define virt_to_phys virt_to_phys
 
 #define __raw_writeb(v,a)       (*(volatile unsigned char  *)(a) = (v))
 #define __raw_writew(v,a)       (*(volatile unsigned short *)(a) = (v))
@@ -171,4 +170,6 @@
 #define memcpy_fromio(a, b, c)		memcpy((a), (void *)(b), (c))
 #define memcpy_toio(a, b, c)		memcpy((void *)(a), (b), (c))
 
+#include <asm-generic/io.h>
+
 #endif /* __ASM_NIOS2_IO_H_ */
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index a54fc46..34fbfdf 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -282,18 +282,7 @@
 #define setbits_8(addr, set) setbits(8, addr, set)
 #define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
 
-/*
- * Given a physical address and a length, return a virtual address
- * that can be used to access the memory range with the caching
- * properties specified by "flags".
- */
-#define MAP_NOCACHE	(0)
-#define MAP_WRCOMBINE	(0)
-#define MAP_WRBACK	(0)
-#define MAP_WRTHROUGH	(0)
-
-static inline void *
-map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
+static inline void *phys_to_virt(phys_addr_t paddr)
 {
 #ifdef CONFIG_ADDR_MAP
 	return addrmap_phys_to_virt(paddr);
@@ -301,14 +290,7 @@
 	return (void *)((unsigned long)paddr);
 #endif
 }
-
-/*
- * Take down a mapping set up by map_physmem().
- */
-static inline void unmap_physmem(void *vaddr, unsigned long flags)
-{
-
-}
+#define phys_to_virt phys_to_virt
 
 static inline phys_addr_t virt_to_phys(void * vaddr)
 {
@@ -318,5 +300,8 @@
 	return (phys_addr_t)((unsigned long)vaddr);
 #endif
 }
+#define virt_to_phys virt_to_phys
+
+#include <asm-generic/io.h>
 
 #endif
diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index 0199104..66c3a6a 100644
--- a/arch/sandbox/cpu/cpu.c
+++ b/arch/sandbox/cpu/cpu.c
@@ -56,6 +56,16 @@
 	return 0;
 }
 
+void *phys_to_virt(phys_addr_t paddr)
+{
+	return (void *)(gd->arch.ram_buf + paddr);
+}
+
+phys_addr_t virt_to_phys(void *vaddr)
+{
+	return (phys_addr_t)((uint8_t *)vaddr - gd->arch.ram_buf);
+}
+
 void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
 {
 #if defined(CONFIG_PCI) && !defined(CONFIG_SPL_BUILD)
@@ -73,7 +83,7 @@
 	}
 #endif
 
-	return (void *)(gd->arch.ram_buf + paddr);
+	return phys_to_virt(paddr);
 }
 
 void unmap_physmem(const void *vaddr, unsigned long flags)
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index a685635..ae6883f 100644
--- a/arch/sandbox/include/asm/io.h
+++ b/arch/sandbox/include/asm/io.h
@@ -7,22 +7,22 @@
 #ifndef __SANDBOX_ASM_IO_H
 #define __SANDBOX_ASM_IO_H
 
-/*
- * Given a physical address and a length, return a virtual address
- * that can be used to access the memory range with the caching
- * properties specified by "flags".
- */
-#define MAP_NOCACHE	(0)
-#define MAP_WRCOMBINE	(0)
-#define MAP_WRBACK	(0)
-#define MAP_WRTHROUGH	(0)
+void *phys_to_virt(phys_addr_t paddr);
+#define phys_to_virt phys_to_virt
+
+phys_addr_t virt_to_phys(void *vaddr);
+#define virt_to_phys virt_to_phys
 
 void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags);
+#define map_physmem map_physmem
 
 /*
  * Take down a mapping set up by map_physmem().
  */
 void unmap_physmem(const void *vaddr, unsigned long flags);
+#define unmap_physmem unmap_physmem
+
+#include <asm-generic/io.h>
 
 /* For sandbox, we want addresses to point into our RAM buffer */
 static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
@@ -56,6 +56,53 @@
 void outw(unsigned int value, unsigned int addr);
 void outb(unsigned int value, unsigned int addr);
 
+#define out_arch(type,endian,a,v)	write##type(cpu_to_##endian(v),a)
+#define in_arch(type,endian,a)		endian##_to_cpu(read##type(a))
+
+#define out_le32(a,v)	out_arch(l,le32,a,v)
+#define out_le16(a,v)	out_arch(w,le16,a,v)
+
+#define in_le32(a)	in_arch(l,le32,a)
+#define in_le16(a)	in_arch(w,le16,a)
+
+#define out_be32(a,v)	out_arch(l,be32,a,v)
+#define out_be16(a,v)	out_arch(w,be16,a,v)
+
+#define in_be32(a)	in_arch(l,be32,a)
+#define in_be16(a)	in_arch(w,be16,a)
+
+#define out_8(a,v)	writeb(v,a)
+#define in_8(a)		readb(a)
+
+#define clrbits(type, addr, clear) \
+	out_##type((addr), in_##type(addr) & ~(clear))
+
+#define setbits(type, addr, set) \
+	out_##type((addr), in_##type(addr) | (set))
+
+#define clrsetbits(type, addr, clear, set) \
+	out_##type((addr), (in_##type(addr) & ~(clear)) | (set))
+
+#define clrbits_be32(addr, clear) clrbits(be32, addr, clear)
+#define setbits_be32(addr, set) setbits(be32, addr, set)
+#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set)
+
+#define clrbits_le32(addr, clear) clrbits(le32, addr, clear)
+#define setbits_le32(addr, set) setbits(le32, addr, set)
+#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set)
+
+#define clrbits_be16(addr, clear) clrbits(be16, addr, clear)
+#define setbits_be16(addr, set) setbits(be16, addr, set)
+#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set)
+
+#define clrbits_le16(addr, clear) clrbits(le16, addr, clear)
+#define setbits_le16(addr, set) setbits(le16, addr, set)
+#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set)
+
+#define clrbits_8(addr, clear) clrbits(8, addr, clear)
+#define setbits_8(addr, set) setbits(8, addr, set)
+#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
+
 static inline void _insw(volatile u16 *port, void *buf, int ns)
 {
 }
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 5cb000c..be1ff4a 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -231,34 +231,7 @@
 #define setbits_8(addr, set) setbits(8, addr, set)
 #define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
 
-/*
- * Given a physical address and a length, return a virtual address
- * that can be used to access the memory range with the caching
- * properties specified by "flags".
- */
-#define MAP_NOCACHE     (0)
-#define MAP_WRCOMBINE   (0)
-#define MAP_WRBACK      (0)
-#define MAP_WRTHROUGH   (0)
-
-static inline void *
-map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
-{
-	return (void *)paddr;
-}
-
-/*
- * Take down a mapping set up by map_physmem().
- */
-static inline void unmap_physmem(void *vaddr, unsigned long flags)
-{
-
-}
-
-static inline phys_addr_t virt_to_phys(void *vaddr)
-{
-	return (phys_addr_t)(vaddr);
-}
+#include <asm-generic/io.h>
 
 #endif	/* __KERNEL__ */
 #endif	/* __ASM_SH_IO_H */
diff --git a/arch/x86/cpu/tangier/Makefile b/arch/x86/cpu/tangier/Makefile
index d146b3f..92cfa55 100644
--- a/arch/x86/cpu/tangier/Makefile
+++ b/arch/x86/cpu/tangier/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-y += car.o tangier.o sdram.o
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o
diff --git a/arch/x86/cpu/tangier/acpi.c b/arch/x86/cpu/tangier/acpi.c
new file mode 100644
index 0000000..75e777d
--- /dev/null
+++ b/arch/x86/cpu/tangier/acpi.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Partially based on acpi.c for other x86 platforms
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <dm/uclass-internal.h>
+#include <asm/acpi_table.h>
+#include <asm/ioapic.h>
+#include <asm/mpspec.h>
+#include <asm/tables.h>
+#include <asm/arch/global_nvs.h>
+
+void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs,
+		      void *dsdt)
+{
+	struct acpi_table_header *header = &(fadt->header);
+
+	memset((void *)fadt, 0, sizeof(struct acpi_fadt));
+
+	acpi_fill_header(header, "FACP");
+	header->length = sizeof(struct acpi_fadt);
+	header->revision = 6;
+
+	fadt->firmware_ctrl = (u32)facs;
+	fadt->dsdt = (u32)dsdt;
+	fadt->preferred_pm_profile = ACPI_PM_UNSPECIFIED;
+
+	fadt->iapc_boot_arch = ACPI_FADT_VGA_NOT_PRESENT |
+			       ACPI_FADT_NO_PCIE_ASPM_CONTROL;
+	fadt->flags =
+		ACPI_FADT_WBINVD |
+		ACPI_FADT_POWER_BUTTON | ACPI_FADT_SLEEP_BUTTON |
+		ACPI_FADT_SEALED_CASE | ACPI_FADT_HEADLESS |
+		ACPI_FADT_HW_REDUCED_ACPI;
+
+	fadt->minor_revision = 2;
+
+	fadt->x_firmware_ctl_l = (u32)facs;
+	fadt->x_firmware_ctl_h = 0;
+	fadt->x_dsdt_l = (u32)dsdt;
+	fadt->x_dsdt_h = 0;
+
+	header->checksum = table_compute_checksum(fadt, header->length);
+}
+
+u32 acpi_fill_madt(u32 current)
+{
+	current += acpi_create_madt_lapics(current);
+
+	current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
+			io_apic_read(IO_APIC_ID) >> 24, IO_APIC_ADDR, 0);
+
+	return current;
+}
+
+u32 acpi_fill_mcfg(u32 current)
+{
+	/* TODO: Derive parameters from SFI MCFG table */
+	current += acpi_create_mcfg_mmconfig
+		((struct acpi_mcfg_mmconfig *)current,
+		0x3f500000, 0x0, 0x0, 0x0);
+
+	return current;
+}
+
+void acpi_create_gnvs(struct acpi_global_nvs *gnvs)
+{
+	struct udevice *dev;
+	int ret;
+
+	/* at least we have one processor */
+	gnvs->pcnt = 1;
+
+	/* override the processor count with actual number */
+	ret = uclass_find_first_device(UCLASS_CPU, &dev);
+	if (ret == 0 && dev != NULL) {
+		ret = cpu_get_count(dev);
+		if (ret > 0)
+			gnvs->pcnt = ret;
+	}
+}
diff --git a/arch/x86/cpu/tangier/sdram.c b/arch/x86/cpu/tangier/sdram.c
index 5743077..eae8d78 100644
--- a/arch/x86/cpu/tangier/sdram.c
+++ b/arch/x86/cpu/tangier/sdram.c
@@ -39,7 +39,7 @@
 		chksum += *pos++;
 
 	if (chksum)
-		error("sfi: Invalid checksum\n");
+		pr_err("sfi: Invalid checksum\n");
 
 	/* Checksum is OK if zero */
 	return chksum ? -EILSEQ : 0;
@@ -76,7 +76,7 @@
 	/* Find SYST table */
 	sb = sfi_get_table_by_sig(SFI_BASE_ADDR, SFI_SIG_SYST);
 	if (!sb) {
-		error("sfi: failed to locate SYST table\n");
+		pr_err("sfi: failed to locate SYST table\n");
 		return NULL;
 	}
 
@@ -90,7 +90,7 @@
 			return (struct sfi_table_simple *)sbh;
 	}
 
-	error("sfi: failed to locate SFI MMAP table\n");
+	pr_err("sfi: failed to locate SFI MMAP table\n");
 	return NULL;
 }
 
diff --git a/arch/x86/include/asm/arch-tangier/acpi/global_nvs.asl b/arch/x86/include/asm/arch-tangier/acpi/global_nvs.asl
new file mode 100644
index 0000000..b1f0f67
--- /dev/null
+++ b/arch/x86/include/asm/arch-tangier/acpi/global_nvs.asl
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Partially based on global_nvs.asl for other x86 platforms
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/acpi/global_nvs.h>
+
+OperationRegion(GNVS, SystemMemory, ACPI_GNVS_ADDR, ACPI_GNVS_SIZE)
+Field(GNVS, ByteAcc, NoLock, Preserve)
+{
+    Offset (0x00),
+    PCNT, 8,    /* processor count */
+}
diff --git a/arch/x86/include/asm/arch-tangier/acpi/platform.asl b/arch/x86/include/asm/arch-tangier/acpi/platform.asl
new file mode 100644
index 0000000..a57b7cb
--- /dev/null
+++ b/arch/x86/include/asm/arch-tangier/acpi/platform.asl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Partially based on platform.asl for other x86 platforms
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/acpi/statdef.asl>
+
+/*
+ * The _PTS method (Prepare To Sleep) is called before the OS is
+ * entering a sleep state. The sleep state number is passed in Arg0.
+ */
+Method(_PTS, 1)
+{
+}
+
+/* The _WAK method is called on system wakeup */
+Method(_WAK, 1)
+{
+    Return (Package() {0, 0})
+}
+
+/* ACPI global NVS */
+#include "global_nvs.asl"
+
+Scope (\_SB)
+{
+    #include "southcluster.asl"
+}
diff --git a/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl b/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl
new file mode 100644
index 0000000..e80ec0a
--- /dev/null
+++ b/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Partially based on southcluster.asl for other x86 platforms
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+Device (PCI0)
+{
+    Name (_HID, EISAID("PNP0A08"))    /* PCIe */
+    Name (_CID, EISAID("PNP0A03"))    /* PCI */
+
+    Name (_ADR, 0)
+    Name (_BBN, 0)
+
+    Name (MCRS, ResourceTemplate()
+    {
+        /* Bus Numbers */
+        WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode,
+                0x0000, 0x0000, 0x00ff, 0x0000, 0x0100, , , PB00)
+
+        /* IO Region 0 */
+        WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+                0x0000, 0x0000, 0x0cf7, 0x0000, 0x0cf8, , , PI00)
+
+        /* PCI Config Space */
+        IO(Decode16, 0x0cf8, 0x0cf8, 0x0001, 0x0008)
+
+        /* IO Region 1 */
+        WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+                0x0000, 0x0d00, 0xffff, 0x0000, 0xf300, , , PI01)
+
+        /* GPIO Low Memory Region */
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                Cacheable, ReadWrite,
+                0x00000000, 0x000ddcc0, 0x000ddccf, 0x00000000,
+                0x00000010, , , GP00)
+
+        /* PSH Memory Region 0 */
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                Cacheable, ReadWrite,
+                0x00000000, 0x04819000, 0x04898fff, 0x00000000,
+                0x00080000, , , PSH0)
+
+        /* PSH Memory Region 1 */
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                Cacheable, ReadWrite,
+                0x00000000, 0x04919000, 0x04920fff, 0x00000000,
+                0x00008000, , , PSH1)
+
+        /* SST Memory Region */
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                Cacheable, ReadWrite,
+                0x00000000, 0x05e00000, 0x05ffffff, 0x00000000,
+                0x00200000, , , SST0)
+
+        /* PCI Memory Region */
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                Cacheable, ReadWrite,
+                0x00000000, 0x80000000, 0xffffffff, 0x00000000,
+                0x80000000, , , PMEM)
+    })
+
+    Method (_CRS, 0, Serialized)
+    {
+        Return (MCRS)
+    }
+
+    Method (_OSC, 4)
+    {
+        /* Check for proper GUID */
+        If (LEqual(Arg0, ToUUID("33db4d5b-1ff7-401c-9657-7441c03dd766"))) {
+            /* Let OS control everything */
+            Return (Arg3)
+        } Else {
+            /* Unrecognized UUID */
+            CreateDWordField(Arg3, 0, CDW1)
+            Or(CDW1, 4, CDW1)
+            Return (Arg3)
+        }
+    }
+
+    Device (SDHC)
+    {
+        Name (_ADR, 0x00010003)
+        Name (_DEP, Package (0x01)
+        {
+            GPIO
+        })
+        Name (PSTS, Zero)
+
+        Method (_STA)
+        {
+            Return (STA_VISIBLE)
+        }
+
+        Method (_PS3, 0, NotSerialized)
+        {
+        }
+
+        Method (_PS0, 0, NotSerialized)
+        {
+            If (PSTS == Zero)
+            {
+                If (^^GPIO.AVBL == One)
+                {
+                    ^^GPIO.WFD3 = One
+                    PSTS = One
+                }
+            }
+        }
+
+        /* BCM43340 */
+        Device (BRC1)
+        {
+            Name (_ADR, 0x01)
+            Name (_DEP, Package (0x01)
+            {
+                GPIO
+            })
+
+            Method (_STA)
+            {
+                Return (STA_VISIBLE)
+            }
+
+            Method (_RMV, 0, NotSerialized)
+            {
+                Return (Zero)
+            }
+
+            Method (_PS3, 0, NotSerialized)
+            {
+                If (^^^GPIO.AVBL == One)
+                {
+                    ^^^GPIO.WFD3 = Zero
+                    PSTS = Zero
+                }
+            }
+
+            Method (_PS0, 0, NotSerialized)
+            {
+                If (PSTS == Zero)
+                {
+                    If (^^^GPIO.AVBL == One)
+                    {
+                        ^^^GPIO.WFD3 = One
+                        PSTS = One
+                    }
+                }
+            }
+        }
+
+        Device (BRC2)
+        {
+            Name (_ADR, 0x02)
+            Method (_STA, 0, NotSerialized)
+            {
+                Return (STA_VISIBLE)
+            }
+
+            Method (_RMV, 0, NotSerialized)
+            {
+                Return (Zero)
+            }
+        }
+    }
+
+    Device (SPI5)
+    {
+        Name (_ADR, 0x00070001)
+        Name (RBUF, ResourceTemplate()
+        {
+            GpioIo(Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
+                "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 91 }
+            GpioIo(Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
+                "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 92 }
+            GpioIo(Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
+                "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 93 }
+            GpioIo(Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
+                "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 94 }
+        })
+
+        Method (_CRS, 0, NotSerialized)
+        {
+            Return (RBUF)
+        }
+
+        /*
+         * See
+         * http://www.kernel.org/doc/Documentation/acpi/gpio-properties.txt
+         * for more information about GPIO bindings.
+         */
+        Name (_DSD, Package () {
+            ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+            Package () {
+                Package () {
+                    "cs-gpios", Package () {
+                        ^SPI5, 0, 0, 0,
+                        ^SPI5, 1, 0, 0,
+                        ^SPI5, 2, 0, 0,
+                        ^SPI5, 3, 0, 0,
+                    },
+                },
+            }
+        })
+
+        Method (_STA, 0, NotSerialized)
+        {
+            Return (STA_VISIBLE)
+        }
+    }
+
+    Device (I2C1)
+    {
+        Name (_ADR, 0x00080000)
+
+        Method (_STA, 0, NotSerialized)
+        {
+            Return (STA_VISIBLE)
+        }
+    }
+
+    Device (GPIO)
+    {
+        Name (_ADR, 0x000c0000)
+
+        Method (_STA)
+        {
+            Return (STA_VISIBLE)
+        }
+
+        Name (AVBL, Zero)
+        Method (_REG, 2, NotSerialized)
+        {
+            If (Arg0 == 0x08)
+            {
+                AVBL = Arg1
+            }
+        }
+
+        OperationRegion (GPOP, GeneralPurposeIo, 0, 1)
+        Field (GPOP, ByteAcc, NoLock, Preserve)
+        {
+            Connection (
+                GpioIo(Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly,
+                    "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 56 }
+            ),
+            WFD3, 1,
+        }
+    }
+
+    Device (PWM0)
+    {
+        Name (_ADR, 0x00170000)
+
+        Method (_STA, 0, NotSerialized)
+        {
+            Return (STA_VISIBLE)
+        }
+    }
+}
+
+Device (FLIS)
+{
+    Name (_HID, "PRP0001")
+    Name (_DDN, "Intel Merrifield Family-Level Interface Shim")
+    Name (RBUF, ResourceTemplate()
+    {
+        Memory32Fixed(ReadWrite, 0xFF0C0000, 0x00008000, )
+        PinGroup("spi5", ResourceProducer, ) { 90, 91, 92, 93, 94, 95, 96 }
+        PinGroup("uart0", ResourceProducer, ) { 115, 116, 117, 118 }
+        PinGroup("uart1", ResourceProducer, ) { 119, 120, 121, 122 }
+        PinGroup("uart2", ResourceProducer, ) { 123, 124, 125, 126 }
+        PinGroup("pwm0", ResourceProducer, ) { 144 }
+        PinGroup("pwm1", ResourceProducer, ) { 145 }
+        PinGroup("pwm2", ResourceProducer, ) { 132 }
+        PinGroup("pwm3", ResourceProducer, ) { 133 }
+    })
+
+    Method (_CRS, 0, NotSerialized)
+    {
+        Return (RBUF)
+    }
+
+    Name (_DSD, Package () {
+        ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+        Package () {
+            Package () {"compatible", "intel,merrifield-pinctrl"},
+        }
+    })
+
+    Method (_STA, 0, NotSerialized)
+    {
+        Return (STA_VISIBLE)
+    }
+}
diff --git a/arch/x86/include/asm/arch-tangier/global_nvs.h b/arch/x86/include/asm/arch-tangier/global_nvs.h
new file mode 100644
index 0000000..8ab5cf2
--- /dev/null
+++ b/arch/x86/include/asm/arch-tangier/global_nvs.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Partially based on global_nvs.h for other x86 platforms
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _GLOBAL_NVS_H_
+#define _GLOBAL_NVS_H_
+
+struct __packed acpi_global_nvs {
+	u8	pcnt;		/* processor count */
+
+	/*
+	 * Add padding so sizeof(struct acpi_global_nvs) == 0x100.
+	 * This must match the size defined in the global_nvs.asl.
+	 */
+	u8	rsvd[255];
+};
+
+#endif /* _GLOBAL_NVS_H_ */
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index a72daf2..263dd8f 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -231,35 +231,6 @@
 }
 
 /*
- * Given a physical address and a length, return a virtual address
- * that can be used to access the memory range with the caching
- * properties specified by "flags".
- */
-#define MAP_NOCACHE	(0)
-#define MAP_WRCOMBINE	(0)
-#define MAP_WRBACK	(0)
-#define MAP_WRTHROUGH	(0)
-
-static inline void *
-map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
-{
-	return (void *)(uintptr_t)paddr;
-}
-
-/*
- * Take down a mapping set up by map_physmem().
- */
-static inline void unmap_physmem(void *vaddr, unsigned long flags)
-{
-
-}
-
-static inline phys_addr_t virt_to_phys(void * vaddr)
-{
-	return (phys_addr_t)(uintptr_t)(vaddr);
-}
-
-/*
  * TODO: The kernel offers some more advanced versions of barriers, it might
  * have some advantages to use them instead of the simple one here.
  */
@@ -267,4 +238,6 @@
 #define __iormb()	dmb()
 #define __iowmb()	dmb()
 
+#include <asm-generic/io.h>
+
 #endif /* _ASM_IO_H */
diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h
index e34d6e1..c9e335f 100644
--- a/arch/xtensa/include/asm/io.h
+++ b/arch/xtensa/include/asm/io.h
@@ -115,29 +115,6 @@
  */
 #define xlate_dev_kmem_ptr(p)   p
 
-#define MAP_NOCACHE	(0)
-#define MAP_WRCOMBINE	(0)
-#define MAP_WRBACK	(0)
-#define MAP_WRTHROUGH	(0)
-
-static inline void *
-map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
-{
-	return (void *)paddr;
-}
-
-/*
- * Take down a mapping set up by map_physmem().
- */
-static inline void unmap_physmem(void *vaddr, unsigned long flags)
-{
-}
-
-static inline phys_addr_t virt_to_phys(void *vaddr)
-{
-	return (phys_addr_t)((unsigned long)vaddr);
-}
-
 /*
  * Dummy function to keep U-Boot's cfi_flash.c driver happy.
  */
@@ -145,4 +122,6 @@
 {
 }
 
+#include <asm-generic/io.h>
+
 #endif	/* _XTENSA_IO_H */
diff --git a/board/amarula/vyasa-rk3288/vyasa-rk3288.c b/board/amarula/vyasa-rk3288/vyasa-rk3288.c
index ceee42c..7985671 100644
--- a/board/amarula/vyasa-rk3288/vyasa-rk3288.c
+++ b/board/amarula/vyasa-rk3288/vyasa-rk3288.c
@@ -5,3 +5,16 @@
  */
 
 #include <common.h>
+
+#ifndef CONFIG_TPL_BUILD
+#include <spl.h>
+
+int spl_start_uboot(void)
+{
+        /* break into full u-boot on 'c' */
+        if (serial_tstc() && serial_getc() == 'c')
+                return 1;
+
+        return 0;
+}
+#endif
diff --git a/board/davinci/da8xxevm/Kconfig b/board/davinci/da8xxevm/Kconfig
index bb1188b..e0df97c 100644
--- a/board/davinci/da8xxevm/Kconfig
+++ b/board/davinci/da8xxevm/Kconfig
@@ -33,6 +33,8 @@
 
 endif
 
+source "board/ti/common/Kconfig"
+
 endif
 
 if TARGET_OMAPL138_LCDK
diff --git a/board/davinci/da8xxevm/da850evm.c b/board/davinci/da8xxevm/da850evm.c
index 516d86d..83c9f29 100644
--- a/board/davinci/da8xxevm/da850evm.c
+++ b/board/davinci/da8xxevm/da850evm.c
@@ -60,7 +60,7 @@
 		return -1;
 	}
 
-	ret = spi_flash_read(flash, CFG_MAC_ADDR_OFFSET, 6, addr);
+	ret = spi_flash_read(flash, (CFG_MAC_ADDR_OFFSET) + 1, 7, addr);
 	if (ret) {
 		printf("Error - unable to read MAC address from SPI flash.\n");
 		return -1;
@@ -140,6 +140,7 @@
 	uchar buff[6];
 
 	spi_mac_read = get_mac_addr(buff);
+	buff[0] = 0;
 
 	/*
 	 * MAC address not present in the environment
diff --git a/board/emulation/qemu-arm/MAINTAINERS b/board/emulation/qemu-arm/MAINTAINERS
new file mode 100644
index 0000000..a803061
--- /dev/null
+++ b/board/emulation/qemu-arm/MAINTAINERS
@@ -0,0 +1,6 @@
+QEMU ARM 'VIRT' BOARD
+M:	Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
+S:	Maintained
+F:	board/emulation/qemu-arm/
+F:	include/configs/qemu-arm.h
+F:	configs/qemu_arm_defconfig
diff --git a/board/emulation/qemu-arm/Makefile b/board/emulation/qemu-arm/Makefile
new file mode 100644
index 0000000..716a6e9
--- /dev/null
+++ b/board/emulation/qemu-arm/Makefile
@@ -0,0 +1,5 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	+= qemu-arm.o
diff --git a/board/emulation/qemu-arm/qemu-arm.c b/board/emulation/qemu-arm/qemu-arm.c
new file mode 100644
index 0000000..e29ba46
--- /dev/null
+++ b/board/emulation/qemu-arm/qemu-arm.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017 Tuomas Tynkkynen
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <fdtdec.h>
+
+int board_init(void)
+{
+	return 0;
+}
+
+int dram_init(void)
+{
+	if (fdtdec_setup_memory_size() != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+int dram_init_banksize(void)
+{
+	fdtdec_setup_memory_banksize();
+
+	return 0;
+}
+
+void *board_fdt_blob_setup(void)
+{
+	/* QEMU loads a generated DTB for us at the start of RAM. */
+	return (void *)CONFIG_SYS_SDRAM_BASE;
+}
diff --git a/board/intel/edison/.gitignore b/board/intel/edison/.gitignore
new file mode 100644
index 0000000..6eb8a54
--- /dev/null
+++ b/board/intel/edison/.gitignore
@@ -0,0 +1,3 @@
+dsdt.aml
+dsdt.asl.tmp
+dsdt.c
diff --git a/board/intel/edison/Kconfig b/board/intel/edison/Kconfig
index 4ff9d5a..ef9b14a 100644
--- a/board/intel/edison/Kconfig
+++ b/board/intel/edison/Kconfig
@@ -15,6 +15,12 @@
 config SYS_TEXT_BASE
 	default 0x01101000
 
+config ROM_TABLE_ADDR
+	default 0x0e4500
+
+config ROM_TABLE_SIZE
+	default 0x007b00
+
 config BOARD_SPECIFIC_OPTIONS # dummy
 	def_bool y
 	select X86_LOAD_FROM_32_BIT
diff --git a/board/intel/edison/Makefile b/board/intel/edison/Makefile
index dde1594..eed8d65 100644
--- a/board/intel/edison/Makefile
+++ b/board/intel/edison/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-y	+= start.o edison.o
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += dsdt.o
diff --git a/board/intel/edison/dsdt.asl b/board/intel/edison/dsdt.asl
new file mode 100644
index 0000000..d2e0473
--- /dev/null
+++ b/board/intel/edison/dsdt.asl
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Partially based on dsdt.asl for other x86 boards
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+DefinitionBlock("dsdt.aml", "DSDT", 2, "U-BOOT", "U-BOOTBL", 0x00010000)
+{
+	/* platform specific */
+	#include <asm/arch/acpi/platform.asl>
+}
diff --git a/board/logicpd/am3517evm/am3517evm.c b/board/logicpd/am3517evm/am3517evm.c
index c18a5a3..29f136a 100644
--- a/board/logicpd/am3517evm/am3517evm.c
+++ b/board/logicpd/am3517evm/am3517evm.c
@@ -12,6 +12,8 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <ns16550.h>
 #include <asm/io.h>
 #include <asm/omap_musb.h>
 #include <asm/arch/am35x_def.h>
@@ -34,6 +36,22 @@
 
 #define AM3517_IP_SW_RESET	0x48002598
 #define CPGMACSS_SW_RST		(1 << 1)
+#define PHY_GPIO		30
+
+/* This is only needed until SPL gets OF support */
+#ifdef CONFIG_SPL_BUILD
+static const struct ns16550_platdata am3517_serial = {
+	.base = OMAP34XX_UART3,
+	.reg_shift = 2,
+	.clock = V_NS16550_CLK,
+	.fcr = UART_FCR_DEFVAL,
+};
+
+U_BOOT_DEVICE(am3517_uart) = {
+	"ns16550_serial",
+	&am3517_serial
+};
+#endif
 
 /*
  * Routine: board_init
@@ -113,30 +131,35 @@
 
 	am3517_evm_musb_init();
 
-	/* activate PHY reset */
-	gpio_direction_output(30, 0);
-	gpio_set_value(30, 0);
+	if (gpio_request(PHY_GPIO, "gpio_30") == 0) {
+		/* activate PHY reset */
+		gpio_direction_output(PHY_GPIO, 0);
+		gpio_set_value(PHY_GPIO, 0);
 
-	ctr  = 0;
-	do {
-		udelay(1000);
-		ctr++;
-	} while (ctr < 300);
+		ctr  = 0;
+		do {
+			udelay(1000);
+			ctr++;
+		} while (ctr < 300);
 
-	/* deactivate PHY reset */
-	gpio_set_value(30, 1);
+		/* deactivate PHY reset */
+		gpio_set_value(PHY_GPIO, 1);
 
-	/* allow the PHY to stabilize and settle down */
-	ctr = 0;
-	do {
-		udelay(1000);
-		ctr++;
-	} while (ctr < 300);
+		/* allow the PHY to stabilize and settle down */
+		ctr = 0;
+		do {
+			udelay(1000);
+			ctr++;
+		} while (ctr < 300);
 
-	/* ensure that the module is out of reset */
-	reset = readl(AM3517_IP_SW_RESET);
-	reset &= (~CPGMACSS_SW_RST);
-	writel(reset,AM3517_IP_SW_RESET);
+		/* ensure that the module is out of reset */
+		reset = readl(AM3517_IP_SW_RESET);
+		reset &= (~CPGMACSS_SW_RST);
+		writel(reset, AM3517_IP_SW_RESET);
+
+		/* Free requested GPIO */
+		gpio_free(PHY_GPIO);
+	}
 
 	return 0;
 }
diff --git a/board/nvidia/jetson-tk1/jetson-tk1.c b/board/nvidia/jetson-tk1/jetson-tk1.c
index bd08a2e..c20da29 100644
--- a/board/nvidia/jetson-tk1/jetson-tk1.c
+++ b/board/nvidia/jetson-tk1/jetson-tk1.c
@@ -49,7 +49,7 @@
 
 	err = pmic_clrsetbits(pmic, AS3722_SD_CONTROL, 0, 1 << sd);
 	if (err) {
-		error("failed to update SD control register: %d", err);
+		pr_err("failed to update SD control register: %d", err);
 		return err;
 	}
 
@@ -70,13 +70,13 @@
 
 	ret = as3722_sd_enable(dev, 4);
 	if (ret < 0) {
-		error("failed to enable SD4: %d\n", ret);
+		pr_err("failed to enable SD4: %d\n", ret);
 		return ret;
 	}
 
 	ret = as3722_sd_set_voltage(dev, 4, 0x24);
 	if (ret < 0) {
-		error("failed to set SD4 voltage: %d\n", ret);
+		pr_err("failed to set SD4 voltage: %d\n", ret);
 		return ret;
 	}
 
diff --git a/board/rockchip/evb_rk3399/evb-rk3399.c b/board/rockchip/evb_rk3399/evb-rk3399.c
index d50c59d..502dec3 100644
--- a/board/rockchip/evb_rk3399/evb-rk3399.c
+++ b/board/rockchip/evb_rk3399/evb-rk3399.c
@@ -3,13 +3,14 @@
  *
  * SPDX-License-Identifier:     GPL-2.0+
  */
+
 #include <common.h>
 #include <dm.h>
-#include <ram.h>
 #include <dm/pinctrl.h>
 #include <dm/uclass-internal.h>
 #include <asm/arch/periph.h>
 #include <power/regulator.h>
+#include <spl.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -67,3 +68,30 @@
 out:
 	return 0;
 }
+
+void spl_board_init(void)
+{
+	struct udevice *pinctrl;
+	int ret;
+
+	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
+	if (ret) {
+		debug("%s: Cannot find pinctrl device\n", __func__);
+		goto err;
+	}
+
+	/* Enable debug UART */
+	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG);
+	if (ret) {
+		debug("%s: Failed to set up console UART\n", __func__);
+		goto err;
+	}
+
+	preloader_console_init();
+	return;
+err:
+	printf("%s: Error %d\n", __func__, ret);
+
+	/* No way to report error here */
+	hang();
+}
diff --git a/board/samsung/common/exynos5-dt.c b/board/samsung/common/exynos5-dt.c
index ae2a6e6..0d17f30 100644
--- a/board/samsung/common/exynos5-dt.c
+++ b/board/samsung/common/exynos5-dt.c
@@ -161,7 +161,7 @@
 		samsung_get_base_usb3_phy();
 
 	if (!phy) {
-		error("usb3 phy not supported");
+		pr_err("usb3 phy not supported");
 		return -ENODEV;
 	}
 
diff --git a/board/samsung/common/gadget.c b/board/samsung/common/gadget.c
index 6a1e57f..ef732be 100644
--- a/board/samsung/common/gadget.c
+++ b/board/samsung/common/gadget.c
@@ -17,8 +17,8 @@
 		put_unaligned(CONFIG_G_DNL_UMS_VENDOR_NUM, &dev->idVendor);
 		put_unaligned(CONFIG_G_DNL_UMS_PRODUCT_NUM, &dev->idProduct);
 	} else {
-		put_unaligned(CONFIG_G_DNL_VENDOR_NUM, &dev->idVendor);
-		put_unaligned(CONFIG_G_DNL_PRODUCT_NUM, &dev->idProduct);
+		put_unaligned(CONFIG_USB_GADGET_VENDOR_NUM, &dev->idVendor);
+		put_unaligned(CONFIG_USB_GADGET_PRODUCT_NUM, &dev->idProduct);
 	}
 	return 0;
 }
diff --git a/board/samsung/common/misc.c b/board/samsung/common/misc.c
index 4157349..eba25b7 100644
--- a/board/samsung/common/misc.c
+++ b/board/samsung/common/misc.c
@@ -457,7 +457,7 @@
 
 	addr = panel_info.logo_addr;
 	if (!addr) {
-		error("There is no logo data.");
+		pr_err("There is no logo data.");
 		return;
 	}
 
diff --git a/board/samsung/goni/goni.c b/board/samsung/goni/goni.c
index d0247ac..debc4c5 100644
--- a/board/samsung/goni/goni.c
+++ b/board/samsung/goni/goni.c
@@ -102,7 +102,7 @@
 
 	ret = s5p_mmc_init(0, 4);
 	if (ret)
-		error("MMC: Failed to init MMC:0.\n");
+		pr_err("MMC: Failed to init MMC:0.\n");
 
 	/*
 	 * SD card (T_FLASH) detect and init
@@ -127,7 +127,7 @@
 
 		ret_sd = s5p_mmc_init(2, 4);
 		if (ret_sd)
-			error("MMC: Failed to init SD card (MMC:2).\n");
+			pr_err("MMC: Failed to init SD card (MMC:2).\n");
 	}
 
 	return ret & ret_sd;
diff --git a/board/samsung/odroid/odroid.c b/board/samsung/odroid/odroid.c
index e40a2f6..0df96c1 100644
--- a/board/samsung/odroid/odroid.c
+++ b/board/samsung/odroid/odroid.c
@@ -429,7 +429,7 @@
 	};
 
 	if (regulator_list_autoset(mmc_regulators, NULL, true))
-		error("Unable to init all mmc regulators");
+		pr_err("Unable to init all mmc regulators");
 
 	return 0;
 }
@@ -442,7 +442,7 @@
 
 	ret = regulator_get_by_platname("VDD_UOTG_3.0V", &dev);
 	if (ret) {
-		error("Regulator get error: %d", ret);
+		pr_err("Regulator get error: %d", ret);
 		return ret;
 	}
 
@@ -487,25 +487,25 @@
 
 	ret = regulator_get_by_platname("VCC_P3V3_2.85V", &dev);
 	if (ret) {
-		error("Regulator get error: %d", ret);
+		pr_err("Regulator get error: %d", ret);
 		return ret;
 	}
 
 	ret = regulator_set_enable(dev, true);
 	if (ret) {
-		error("Regulator %s enable setting error: %d", dev->name, ret);
+		pr_err("Regulator %s enable setting error: %d", dev->name, ret);
 		return ret;
 	}
 
 	ret = regulator_set_value(dev, 750000);
 	if (ret) {
-		error("Regulator %s value setting error: %d", dev->name, ret);
+		pr_err("Regulator %s value setting error: %d", dev->name, ret);
 		return ret;
 	}
 
 	ret = regulator_set_value(dev, 3300000);
 	if (ret) {
-		error("Regulator %s value setting error: %d", dev->name, ret);
+		pr_err("Regulator %s value setting error: %d", dev->name, ret);
 		return ret;
 	}
 #endif
diff --git a/board/siemens/common/factoryset.c b/board/siemens/common/factoryset.c
index b4f027a..81bbb57 100644
--- a/board/siemens/common/factoryset.c
+++ b/board/siemens/common/factoryset.c
@@ -145,8 +145,8 @@
 	unsigned char *cp, *cp1;
 
 #if defined(CONFIG_USB_FUNCTION_DFU)
-	factory_dat.usb_vendor_id = CONFIG_G_DNL_VENDOR_NUM;
-	factory_dat.usb_product_id = CONFIG_G_DNL_PRODUCT_NUM;
+	factory_dat.usb_vendor_id = CONFIG_USB_GADGET_VENDOR_NUM;
+	factory_dat.usb_product_id = CONFIG_USB_GADGET_PRODUCT_NUM;
 #endif
 	if (i2c_probe(i2c_addr))
 		goto err;
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index ff6eea2..26c452e 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -118,6 +118,11 @@
 S:	Maintained
 F:	configs/Ampe_A76_defconfig
 
+BANANAPI M1 PLUS
+M:	Jagan Teki <jagan@amarulasolutions.com>
+S:	Maintained
+F:	configs/bananapi_m1_plus_defconfig
+
 BANANAPI M2 ULTRA BOARD
 M:	Chen-Yu Tsai <wens@csie.org>
 S:	Maintained
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 70e0143..6e13ee3 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -32,6 +32,7 @@
 #include <libfdt.h>
 #include <nand.h>
 #include <net.h>
+#include <spl.h>
 #include <sy8106a.h>
 #include <asm/setup.h>
 
@@ -491,20 +492,6 @@
 		return -1;
 #endif
 
-#if !defined(CONFIG_SPL_BUILD) && CONFIG_MMC_SUNXI_SLOT_EXTRA == 2
-	/*
-	 * On systems with an emmc (mmc2), figure out if we are booting from
-	 * the emmc and if we are make it "mmc dev 0" so that boot.scr, etc.
-	 * are searched there first. Note we only do this for u-boot proper,
-	 * not for the SPL, see spl_boot_device().
-	 */
-	if (readb(SPL_ADDR + 0x28) == SUNXI_BOOTED_FROM_MMC2) {
-		/* Booting from emmc / mmc2, swap */
-		mmc0->block_dev.devnum = 1;
-		mmc1->block_dev.devnum = 0;
-	}
-#endif
-
 	return 0;
 }
 #endif
@@ -720,13 +707,22 @@
 int misc_init_r(void)
 {
 	__maybe_unused int ret;
+	uint boot;
 
 	env_set("fel_booted", NULL);
 	env_set("fel_scriptaddr", NULL);
+	env_set("mmc_bootdev", NULL);
+
+	boot = sunxi_get_boot_device();
 	/* determine if we are running in FEL mode */
-	if (!is_boot0_magic(SPL_ADDR + 4)) { /* eGON.BT0 */
+	if (boot == BOOT_DEVICE_BOARD) {
 		env_set("fel_booted", "1");
 		parse_spl_header(SPL_ADDR);
+	/* or if we booted from MMC, and which one */
+	} else if (boot == BOOT_DEVICE_MMC1) {
+		env_set("mmc_bootdev", "0");
+	} else if (boot == BOOT_DEVICE_MMC2) {
+		env_set("mmc_bootdev", "1");
 	}
 
 	setup_environment(gd->fdt_blob);
@@ -736,7 +732,10 @@
 	if (ret)
 		return ret;
 #endif
-	sunxi_musb_board_init();
+
+#ifdef CONFIG_USB_ETHER
+	usb_ether_init();
+#endif
 
 	return 0;
 }
diff --git a/board/theobroma-systems/lion_rk3368/fit_spl_atf.its b/board/theobroma-systems/lion_rk3368/fit_spl_atf.its
index 405750f..60daddc 100644
--- a/board/theobroma-systems/lion_rk3368/fit_spl_atf.its
+++ b/board/theobroma-systems/lion_rk3368/fit_spl_atf.its
@@ -27,8 +27,8 @@
 			type = "firmware";
 			arch = "arm64";
 			compression = "none";
-			load = <0x00010000>;
-			entry = <0x00010000>;
+			load = <0x00100000>;
+			entry = <0x00100000>;
 		};
 
 		fdt {
diff --git a/board/theobroma-systems/puma_rk3399/puma-rk3399.c b/board/theobroma-systems/puma_rk3399/puma-rk3399.c
index 45d56cd..2b4988e 100644
--- a/board/theobroma-systems/puma_rk3399/puma-rk3399.c
+++ b/board/theobroma-systems/puma_rk3399/puma-rk3399.c
@@ -3,62 +3,50 @@
  *
  * SPDX-License-Identifier:     GPL-2.0+
  */
+
 #include <common.h>
 #include <dm.h>
 #include <misc.h>
-#include <ram.h>
 #include <dm/pinctrl.h>
 #include <dm/uclass-internal.h>
 #include <asm/setup.h>
 #include <asm/arch/periph.h>
 #include <power/regulator.h>
+#include <spl.h>
 #include <u-boot/sha256.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
 int board_init(void)
 {
-	struct udevice *pinctrl, *regulator;
 	int ret;
 
 	/*
-	 * The PWM does not have decicated interrupt number in dts and can
-	 * not get periph_id by pinctrl framework, so let's init them here.
-	 * The PWM2 and PWM3 are for pwm regulators.
+	 * We need to call into regulators_enable_boot_on() again, as the call
+	 * during SPL may have not included all regulators.
 	 */
-	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
-	if (ret) {
-		debug("%s: Cannot find pinctrl device\n", __func__);
-		goto out;
-	}
-
-	ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_PWM2);
-	if (ret) {
-		debug("%s PWM2 pinctrl init fail!\n", __func__);
-		goto out;
-	}
-
-	/* rk3399 need to init vdd_center to get the correct output voltage */
-	ret = regulator_get_by_platname("vdd_center", &regulator);
+	ret = regulators_enable_boot_on(false);
 	if (ret)
-		debug("%s: Cannot get vdd_center regulator\n", __func__);
+		debug("%s: Cannot enable boot on regulator\n", __func__);
 
-	ret = regulator_get_by_platname("vcc5v0_host", &regulator);
-	if (ret) {
-		debug("%s vcc5v0_host init fail! ret %d\n", __func__, ret);
-		goto out;
-	}
-
-	ret = regulator_set_enable(regulator, true);
-	if (ret) {
-		debug("%s vcc5v0-host-en set fail!\n", __func__);
-		goto out;
-	}
-
-out:
 	return 0;
 }
 
+void spl_board_init(void)
+{
+	int  ret;
+
+	/*
+	 * Turning the eMMC and SPI back on (if disabled via the Qseven
+	 * BIOS_ENABLE) signal is done through a always-on regulator).
+	 */
+	ret = regulators_enable_boot_on(false);
+	if (ret)
+		debug("%s: Cannot enable boot on regulator\n", __func__);
+
+	preloader_console_init();
+}
+
 static void setup_macaddr(void)
 {
 #if CONFIG_IS_ENABLED(CMD_NET)
@@ -91,8 +79,6 @@
 	mac_addr[0] |= 0x02;  /* set local assignment bit (IEEE802) */
 	eth_env_set_enetaddr("ethaddr", mac_addr);
 #endif
-
-	return;
 }
 
 static void setup_serial(void)
@@ -147,8 +133,6 @@
 	env_set("cpuid#", cpuid_str);
 	env_set("serial#", serialno_str);
 #endif
-
-	return;
 }
 
 int misc_init_r(void)
diff --git a/board/ti/ks2_evm/board_k2e.c b/board/ti/ks2_evm/board_k2e.c
index 266a66b..6c77d91 100644
--- a/board/ti/ks2_evm/board_k2e.c
+++ b/board/ti/ks2_evm/board_k2e.c
@@ -166,7 +166,7 @@
 }
 #endif
 
-#if defined(CONFIG_FIT_EMBED)
+#if defined(CONFIG_MULTI_DTB_FIT)
 int board_fit_config_name_match(const char *name)
 {
 	if (!strcmp(name, "keystone-k2e-evm"))
diff --git a/board/ti/ks2_evm/board_k2g.c b/board/ti/ks2_evm/board_k2g.c
index f1c4ddc..01328f1 100644
--- a/board/ti/ks2_evm/board_k2g.c
+++ b/board/ti/ks2_evm/board_k2g.c
@@ -217,7 +217,7 @@
 }
 #endif
 
-#if defined(CONFIG_FIT_EMBED)
+#if defined(CONFIG_MULTI_DTB_FIT)
 int board_fit_config_name_match(const char *name)
 {
 	bool eeprom_read = board_ti_was_eeprom_read();
diff --git a/board/ti/ks2_evm/board_k2hk.c b/board/ti/ks2_evm/board_k2hk.c
index c733099..e99e635 100644
--- a/board/ti/ks2_evm/board_k2hk.c
+++ b/board/ti/ks2_evm/board_k2hk.c
@@ -150,7 +150,7 @@
 }
 #endif
 
-#if defined(CONFIG_FIT_EMBED)
+#if defined(CONFIG_MULTI_DTB_FIT)
 int board_fit_config_name_match(const char *name)
 {
 	if (!strcmp(name, "keystone-k2hk-evm"))
diff --git a/board/ti/ks2_evm/board_k2l.c b/board/ti/ks2_evm/board_k2l.c
index 166367b..c65f331 100644
--- a/board/ti/ks2_evm/board_k2l.c
+++ b/board/ti/ks2_evm/board_k2l.c
@@ -138,7 +138,7 @@
 }
 #endif
 
-#if defined(CONFIG_FIT_EMBED)
+#if defined(CONFIG_MULTI_DTB_FIT)
 int board_fit_config_name_match(const char *name)
 {
 	if (!strcmp(name, "keystone-k2l-evm"))
diff --git a/cmd/Kconfig b/cmd/Kconfig
index d6d130e..681c81a 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -116,6 +116,9 @@
 
 source "cmd/fastboot/Kconfig"
 
+config BUILD_BIN2C
+	bool
+
 comment "Commands"
 
 menu "Info commands"
@@ -222,6 +225,8 @@
 	  for testing that EFI is working at a basic level, and for bringing
 	  up EFI support on a new architecture.
 
+source lib/efi_selftest/Kconfig
+
 config CMD_BOOTMENU
 	bool "bootmenu"
 	select MENU
@@ -526,6 +531,7 @@
 
 config CMD_LZMADEC
 	bool "lzmadec"
+	default y if CMD_BOOTI
 	select LZMA
 	help
 	  Support decompressing an LZMA (Lempel-Ziv-Markov chain algorithm)
@@ -533,6 +539,7 @@
 
 config CMD_UNZIP
 	bool "unzip"
+	default y if CMD_BOOTI
 	help
 	  Uncompress a zip-compressed memory region.
 
@@ -663,10 +670,17 @@
 	bool "GPT (GUID Partition Table) command"
 	select PARTITION_UUIDS
 	select EFI_PARTITION
+	imply RANDOM_UUID
 	help
 	  Enable the 'gpt' command to ready and write GPT style partition
 	  tables.
 
+config RANDOM_UUID
+	bool "GPT Random UUID generation"
+	help
+	  Enable the generation of partitions with random UUIDs if none
+	  are provided.
+
 config CMD_GPT_RENAME
 	bool "GPT partition renaming commands"
 	depends on CMD_GPT
@@ -1311,6 +1325,16 @@
 endmenu
 
 menu "Filesystem commands"
+config CMD_BTRFS
+	bool "Enable the 'btrsubvol' command"
+	select FS_BTRFS
+	help
+	  This enables the 'btrsubvol' command to list subvolumes
+	  of a BTRFS filesystem. There are no special commands for
+	  listing BTRFS directories or loading BTRFS files - this
+	  can be done by the generic 'fs' commands (see CMD_FS_GENERIC)
+	  when BTRFS is enabled (see FS_BTRFS).
+
 config CMD_CBFS
 	bool "Enable the 'cbfs' command"
 	depends on FS_CBFS
diff --git a/cmd/Makefile b/cmd/Makefile
index 2a5b8ce..2b0444d 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -27,6 +27,7 @@
 obj-$(CONFIG_CMD_BOOTSTAGE) += bootstage.o
 obj-$(CONFIG_CMD_BOOTZ) += bootz.o
 obj-$(CONFIG_CMD_BOOTI) += booti.o
+obj-$(CONFIG_CMD_BTRFS) += btrfs.o
 obj-$(CONFIG_CMD_CACHE) += cache.o
 obj-$(CONFIG_CMD_CBFS) += cbfs.o
 obj-$(CONFIG_CMD_CLK) += clk.o
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 3196d86..b7087e3 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -22,97 +22,14 @@
 
 static uint8_t efi_obj_list_initalized;
 
-/*
- * When booting using the "bootefi" command, we don't know which
- * physical device the file came from. So we create a pseudo-device
- * called "bootefi" with the device path /bootefi.
- *
- * In addition to the originating device we also declare the file path
- * of "bootefi" based loads to be /bootefi.
- */
-static struct efi_device_path_file_path bootefi_image_path[] = {
-	{
-		.dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
-		.dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
-		.dp.length = sizeof(bootefi_image_path[0]),
-		.str = { 'b','o','o','t','e','f','i' },
-	}, {
-		.dp.type = DEVICE_PATH_TYPE_END,
-		.dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
-		.dp.length = sizeof(bootefi_image_path[0]),
-	}
-};
-
-static struct efi_device_path_file_path bootefi_device_path[] = {
-	{
-		.dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
-		.dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
-		.dp.length = sizeof(bootefi_image_path[0]),
-		.str = { 'b','o','o','t','e','f','i' },
-	}, {
-		.dp.type = DEVICE_PATH_TYPE_END,
-		.dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
-		.dp.length = sizeof(bootefi_image_path[0]),
-	}
-};
-
-/* The EFI loaded_image interface for the image executed via "bootefi" */
-static struct efi_loaded_image loaded_image_info = {
-	.device_handle = bootefi_device_path,
-	.file_path = bootefi_image_path,
-};
-
-/* The EFI object struct for the image executed via "bootefi" */
-static struct efi_object loaded_image_info_obj = {
-	.handle = &loaded_image_info,
-	.protocols = {
-		{
-			/*
-			 * When asking for the loaded_image interface, just
-			 * return handle which points to loaded_image_info
-			 */
-			.guid = &efi_guid_loaded_image,
-			.protocol_interface = &loaded_image_info,
-		},
-		{
-			/*
-			 * When asking for the device path interface, return
-			 * bootefi_device_path
-			 */
-			.guid = &efi_guid_device_path,
-			.protocol_interface = bootefi_device_path,
-		},
-		{
-			.guid = &efi_guid_console_control,
-			.protocol_interface = (void *) &efi_console_control
-		},
-		{
-			.guid = &efi_guid_device_path_to_text_protocol,
-			.protocol_interface = (void *) &efi_device_path_to_text
-		},
-	},
-};
-
-/* The EFI object struct for the device the "bootefi" image was loaded from */
-static struct efi_object bootefi_device_obj = {
-	.handle = bootefi_device_path,
-	.protocols = {
-		{
-			/* When asking for the device path interface, return
-			 * bootefi_device_path */
-			.guid = &efi_guid_device_path,
-			.protocol_interface = bootefi_device_path
-		}
-	},
-};
+static struct efi_device_path *bootefi_image_path;
+static struct efi_device_path *bootefi_device_path;
 
 /* Initialize and populate EFI object list */
 static void efi_init_obj_list(void)
 {
 	efi_obj_list_initalized = 1;
 
-	list_add_tail(&loaded_image_info_obj.link, &efi_obj_list);
-	list_add_tail(&bootefi_device_obj.link, &efi_obj_list);
 	efi_console_register();
 #ifdef CONFIG_PARTITIONS
 	efi_disk_register();
@@ -121,13 +38,7 @@
 	efi_gop_register();
 #endif
 #ifdef CONFIG_NET
-	void *nethandle = loaded_image_info.device_handle;
-	efi_net_register(&nethandle);
-
-	if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6))
-		loaded_image_info.device_handle = nethandle;
-	else
-		loaded_image_info.device_handle = bootefi_device_path;
+	efi_net_register();
 #endif
 #ifdef CONFIG_GENERATE_SMBIOS_TABLE
 	efi_smbios_register();
@@ -210,14 +121,27 @@
  * Load an EFI payload into a newly allocated piece of memory, register all
  * EFI objects it would want to access and jump to it.
  */
-static unsigned long do_bootefi_exec(void *efi, void *fdt)
+static unsigned long do_bootefi_exec(void *efi, void *fdt,
+				     struct efi_device_path *device_path,
+				     struct efi_device_path *image_path)
 {
+	struct efi_loaded_image loaded_image_info = {};
+	struct efi_object loaded_image_info_obj = {};
+	ulong ret;
+
 	ulong (*entry)(void *image_handle, struct efi_system_table *st)
 		asmlinkage;
 	ulong fdt_pages, fdt_size, fdt_start, fdt_end;
 	const efi_guid_t fdt_guid = EFI_FDT_GUID;
 	bootm_headers_t img = { 0 };
 
+	/* Initialize and populate EFI object list */
+	if (!efi_obj_list_initalized)
+		efi_init_obj_list();
+
+	efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj,
+			       device_path, image_path);
+
 	/*
 	 * gd lives in a fixed register which may get clobbered while we execute
 	 * the payload. So save it here and restore it on every callback entry
@@ -252,18 +176,21 @@
 
 	/* Load the EFI payload */
 	entry = efi_load_pe(efi, &loaded_image_info);
-	if (!entry)
-		return -ENOENT;
+	if (!entry) {
+		ret = -ENOENT;
+		goto exit;
+	}
 
-	/* Initialize and populate EFI object list */
-	if (!efi_obj_list_initalized)
-		efi_init_obj_list();
+	/* we don't support much: */
+	env_set("efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported",
+		"{ro,boot}(blob)0000000000000000");
 
 	/* Call our payload! */
 	debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
 
 	if (setjmp(&loaded_image_info.exit_jmp)) {
-		return loaded_image_info.exit_status;
+		ret = loaded_image_info.exit_status;
+		goto exit;
 	}
 
 #ifdef CONFIG_ARM64
@@ -282,9 +209,45 @@
 	}
 #endif
 
-	return efi_do_enter(&loaded_image_info, &systab, entry);
+	ret = efi_do_enter(&loaded_image_info, &systab, entry);
+
+exit:
+	/* image has returned, loaded-image obj goes *poof*: */
+	list_del(&loaded_image_info_obj.link);
+
+	return ret;
 }
 
+static int do_bootefi_bootmgr_exec(unsigned long fdt_addr)
+{
+	struct efi_device_path *device_path, *file_path;
+	void *addr;
+	efi_status_t r;
+
+	/* Initialize and populate EFI object list */
+	if (!efi_obj_list_initalized)
+		efi_init_obj_list();
+
+	/*
+	 * gd lives in a fixed register which may get clobbered while we execute
+	 * the payload. So save it here and restore it on every callback entry
+	 */
+	efi_save_gd();
+
+	addr = efi_bootmgr_load(&device_path, &file_path);
+	if (!addr)
+		return 1;
+
+	printf("## Starting EFI application at %p ...\n", addr);
+	r = do_bootefi_exec(addr, (void *)fdt_addr, device_path, file_path);
+	printf("## Application terminated, r = %lu\n",
+	       r & ~EFI_ERROR_MASK);
+
+	if (r != EFI_SUCCESS)
+		return 1;
+
+	return 0;
+}
 
 /* Interpreter command to boot an arbitrary EFI image from memory */
 static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -297,13 +260,44 @@
 		return CMD_RET_USAGE;
 #ifdef CONFIG_CMD_BOOTEFI_HELLO
 	if (!strcmp(argv[1], "hello")) {
-		ulong size = __efi_hello_world_end - __efi_hello_world_begin;
+		ulong size = __efi_helloworld_end - __efi_helloworld_begin;
 
-		addr = CONFIG_SYS_LOAD_ADDR;
-		memcpy((char *)addr, __efi_hello_world_begin, size);
+		saddr = env_get("loadaddr");
+		if (saddr)
+			addr = simple_strtoul(saddr, NULL, 16);
+		else
+			addr = CONFIG_SYS_LOAD_ADDR;
+		memcpy((char *)addr, __efi_helloworld_begin, size);
 	} else
 #endif
-	{
+#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
+	if (!strcmp(argv[1], "selftest")) {
+		struct efi_loaded_image loaded_image_info = {};
+		struct efi_object loaded_image_info_obj = {};
+
+		efi_setup_loaded_image(&loaded_image_info,
+				       &loaded_image_info_obj,
+				       bootefi_device_path, bootefi_image_path);
+		/*
+		 * gd lives in a fixed register which may get clobbered while we
+		 * execute the payload. So save it here and restore it on every
+		 * callback entry
+		 */
+		efi_save_gd();
+		/* Initialize and populate EFI object list */
+		if (!efi_obj_list_initalized)
+			efi_init_obj_list();
+		return efi_selftest(&loaded_image_info, &systab);
+	} else
+#endif
+	if (!strcmp(argv[1], "bootmgr")) {
+		unsigned long fdt_addr = 0;
+
+		if (argc > 2)
+			fdt_addr = simple_strtoul(argv[2], NULL, 16);
+
+		return do_bootefi_bootmgr_exec(fdt_addr);
+	} else {
 		saddr = argv[1];
 
 		addr = simple_strtoul(saddr, NULL, 16);
@@ -315,7 +309,8 @@
 	}
 
 	printf("## Starting EFI application at %08lx ...\n", addr);
-	r = do_bootefi_exec((void *)addr, (void*)fdt_addr);
+	r = do_bootefi_exec((void *)addr, (void *)fdt_addr,
+			    bootefi_device_path, bootefi_image_path);
 	printf("## Application terminated, r = %lu\n",
 	       r & ~EFI_ERROR_MASK);
 
@@ -332,10 +327,18 @@
 	"    If specified, the device tree located at <fdt address> gets\n"
 	"    exposed as EFI configuration table.\n"
 #ifdef CONFIG_CMD_BOOTEFI_HELLO
-	"hello\n"
-	"  - boot a sample Hello World application stored within U-Boot"
+	"bootefi hello\n"
+	"  - boot a sample Hello World application stored within U-Boot\n"
 #endif
-	;
+#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
+	"bootefi selftest\n"
+	"  - boot an EFI selftest application stored within U-Boot\n"
+#endif
+	"bootmgr [fdt addr]\n"
+	"  - load and boot EFI payload based on BootOrder/BootXXXX variables.\n"
+	"\n"
+	"    If specified, the device tree located at <fdt address> gets\n"
+	"    exposed as EFI configuration table.\n";
 #endif
 
 U_BOOT_CMD(
@@ -344,58 +347,47 @@
 	bootefi_help_text
 );
 
+static int parse_partnum(const char *devnr)
+{
+	const char *str = strchr(devnr, ':');
+	if (str) {
+		str++;
+		return simple_strtoul(str, NULL, 16);
+	}
+	return 0;
+}
+
 void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
 {
-	__maybe_unused struct blk_desc *desc;
-	char devname[32] = { 0 }; /* dp->str is u16[32] long */
-	char *colon, *s;
+	char filename[32] = { 0 }; /* dp->str is u16[32] long */
+	char *s;
 
-#if defined(CONFIG_BLK) || CONFIG_IS_ENABLED(ISO_PARTITION)
-	desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10));
+	if (strcmp(dev, "Net")) {
+		struct blk_desc *desc;
+		int part;
+
+		desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10));
+		part = parse_partnum(devnr);
+
+		bootefi_device_path = efi_dp_from_part(desc, part);
+	} else {
+#ifdef CONFIG_NET
+		bootefi_device_path = efi_dp_from_eth();
 #endif
-
-#ifdef CONFIG_BLK
-	if (desc) {
-		snprintf(devname, sizeof(devname), "%s", desc->bdev->name);
-	} else
-#endif
-
-	{
-		/* Assemble the condensed device name we use in efi_disk.c */
-		snprintf(devname, sizeof(devname), "%s%s", dev, devnr);
 	}
 
-	colon = strchr(devname, ':');
+	if (!path)
+		return;
 
-#if CONFIG_IS_ENABLED(ISO_PARTITION)
-	/* For ISOs we create partition block devices */
-	if (desc && (desc->type != DEV_TYPE_UNKNOWN) &&
-	    (desc->part_type == PART_TYPE_ISO)) {
-		if (!colon)
-			snprintf(devname, sizeof(devname), "%s:1", devname);
-
-		colon = NULL;
-	}
-#endif
-
-	if (colon)
-		*colon = '\0';
-
-	/* Patch bootefi_device_path to the target device */
-	memset(bootefi_device_path[0].str, 0, sizeof(bootefi_device_path[0].str));
-	ascii2unicode(bootefi_device_path[0].str, devname);
-
-	/* Patch bootefi_image_path to the target file path */
-	memset(bootefi_image_path[0].str, 0, sizeof(bootefi_image_path[0].str));
 	if (strcmp(dev, "Net")) {
 		/* Add leading / to fs paths, because they're absolute */
-		snprintf(devname, sizeof(devname), "/%s", path);
+		snprintf(filename, sizeof(filename), "/%s", path);
 	} else {
-		snprintf(devname, sizeof(devname), "%s", path);
+		snprintf(filename, sizeof(filename), "%s", path);
 	}
 	/* DOS style file path: */
-	s = devname;
+	s = filename;
 	while ((s = strchr(s, '/')))
 		*s++ = '\\';
-	ascii2unicode(bootefi_image_path[0].str, devname);
+	bootefi_image_path = efi_dp_from_file(NULL, 0, filename);
 }
diff --git a/cmd/btrfs.c b/cmd/btrfs.c
new file mode 100644
index 0000000..3f4f1b7
--- /dev/null
+++ b/cmd/btrfs.c
@@ -0,0 +1,28 @@
+/*
+ * 2017 by Marek Behun <marek.behun@nic.cz>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <btrfs.h>
+#include <fs.h>
+
+int do_btrsubvol(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	if (argc != 3)
+		return CMD_RET_USAGE;
+
+	if (fs_set_blk_dev(argv[1], argv[2], FS_TYPE_BTRFS))
+		return 1;
+
+	btrfs_list_subvols();
+	return 0;
+}
+
+U_BOOT_CMD(btrsubvol, 3, 1, do_btrsubvol,
+	"list subvolumes of a BTRFS filesystem",
+	"<interface> <dev[:part]>\n"
+	"     - List subvolumes of a BTRFS filesystem."
+)
diff --git a/cmd/fastboot.c b/cmd/fastboot.c
index 488822a..8adcca5 100644
--- a/cmd/fastboot.c
+++ b/cmd/fastboot.c
@@ -27,7 +27,7 @@
 
 	ret = board_usb_init(controller_index, USB_INIT_DEVICE);
 	if (ret) {
-		error("USB init failed: %d", ret);
+		pr_err("USB init failed: %d", ret);
 		return CMD_RET_FAILURE;
 	}
 
diff --git a/cmd/fastboot/Kconfig b/cmd/fastboot/Kconfig
index fb0c5da..214bbc2 100644
--- a/cmd/fastboot/Kconfig
+++ b/cmd/fastboot/Kconfig
@@ -3,11 +3,16 @@
 menuconfig FASTBOOT
 	bool "Fastboot support"
 	depends on USB_GADGET
+	default y if ARCH_SUNXI && USB_MUSB_GADGET
 
 if FASTBOOT
 
 config USB_FUNCTION_FASTBOOT
 	bool "Enable USB fastboot gadget"
+	default y
+	select USB_GADGET_DOWNLOAD
+	imply ANDROID_BOOT_IMAGE
+	imply CMD_FASTBOOT
 	help
 	  This enables the USB part of the fastboot gadget.
 
@@ -69,6 +74,8 @@
 config FASTBOOT_FLASH_MMC_DEV
 	int "Define FASTBOOT MMC FLASH default device"
 	depends on FASTBOOT_FLASH && MMC
+	default 0 if ARCH_SUNXI && MMC_SUNXI_SLOT_EXTRA = -1
+	default 1 if ARCH_SUNXI && MMC_SUNXI_SLOT_EXTRA != -1
 	help
 	  The fastboot "flash" command requires additional information
 	  regarding the non-volatile storage device. Define this to
diff --git a/cmd/gpt.c b/cmd/gpt.c
index d4406e3..27dd987 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -402,7 +402,7 @@
 	if (!val) {
 #ifdef CONFIG_RANDOM_UUID
 		*str_disk_guid = malloc(UUID_STR_LEN + 1);
-		if (str_disk_guid == NULL)
+		if (*str_disk_guid == NULL)
 			return -ENOMEM;
 		gen_rand_uuid_str(*str_disk_guid, UUID_STR_FORMAT_STD);
 #else
@@ -633,6 +633,21 @@
 }
 
 #ifdef CONFIG_CMD_GPT_RENAME
+/*
+ * There are 3 malloc() calls in set_gpt_info() and there is no info about which
+ * failed.
+ */
+static void set_gpt_cleanup(char **str_disk_guid,
+			    disk_partition_t **partitions)
+{
+#ifdef CONFIG_RANDOM_UUID
+	if (str_disk_guid)
+		free(str_disk_guid);
+#endif
+	if (partitions)
+		free(partitions);
+}
+
 static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
 			       char *name1, char *name2)
 {
@@ -651,19 +666,27 @@
 	ret = get_disk_guid(dev_desc, disk_guid);
 	if (ret < 0)
 		return ret;
+	/*
+	 * Allocates disk_partitions, requiring matching call to del_gpt_info()
+	 * if successful.
+	 */
 	numparts = get_gpt_info(dev_desc);
 	if (numparts <=  0)
 		return numparts ? numparts : -ENODEV;
 
 	partlistlen = calc_parts_list_len(numparts);
 	partitions_list = malloc(partlistlen);
-	if (partitions_list == NULL)
+	if (!partitions_list) {
+		del_gpt_info();
 		return -ENOMEM;
+	}
 	memset(partitions_list, '\0', partlistlen);
 
 	ret = create_gpt_partitions_list(numparts, disk_guid, partitions_list);
-	if (ret < 0)
+	if (ret < 0) {
+		free(partitions_list);
 		return ret;
+	}
 	/*
 	 * Uncomment the following line to print a string that 'gpt write'
 	 * or 'gpt verify' will accept as input.
@@ -671,15 +694,23 @@
 	debug("OLD partitions_list is %s with %u chars\n", partitions_list,
 	      (unsigned)strlen(partitions_list));
 
+	/* set_gpt_info allocates new_partitions and str_disk_guid */
 	ret = set_gpt_info(dev_desc, partitions_list, &str_disk_guid,
 			   &new_partitions, &part_count);
-	if (ret < 0)
-		return ret;
+	if (ret < 0) {
+		del_gpt_info();
+		free(partitions_list);
+		if (ret == -ENOMEM)
+			set_gpt_cleanup(&str_disk_guid, &new_partitions);
+		else
+			goto out;
+	}
 
 	if (!strcmp(subcomm, "swap")) {
 		if ((strlen(name1) > PART_NAME_LEN) || (strlen(name2) > PART_NAME_LEN)) {
 			printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out;
 		}
 		list_for_each(pos, &disk_partitions) {
 			curr = list_entry(pos, struct disk_part, list);
@@ -693,21 +724,24 @@
 		}
 		if ((ctr1 + ctr2 < 2) || (ctr1 != ctr2)) {
 			printf("Cannot swap partition names except in pairs.\n");
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out;
 		}
 	} else { /* rename */
 		if (strlen(name2) > PART_NAME_LEN) {
 			printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out;
 		}
 		partnum = (int)simple_strtol(name1, NULL, 10);
 		if ((partnum < 0) || (partnum > numparts)) {
 			printf("Illegal partition number %s\n", name1);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out;
 		}
 		ret = part_get_info(dev_desc, partnum, new_partitions);
 		if (ret < 0)
-			return ret;
+			goto out;
 
 		/* U-Boot partition numbering starts at 1 */
 		list_for_each(pos, &disk_partitions) {
@@ -722,33 +756,50 @@
 
 	ret = create_gpt_partitions_list(numparts, disk_guid, partitions_list);
 	if (ret < 0)
-		return ret;
+		goto out;
 	debug("NEW partitions_list is %s with %u chars\n", partitions_list,
 	      (unsigned)strlen(partitions_list));
 
 	ret = set_gpt_info(dev_desc, partitions_list, &str_disk_guid,
 			   &new_partitions, &part_count);
-	if (ret < 0)
-		return ret;
+	/*
+	 * Even though valid pointers are here passed into set_gpt_info(),
+	 * it mallocs again, and there's no way to tell which failed.
+	 */
+	if (ret < 0) {
+		del_gpt_info();
+		free(partitions_list);
+		if (ret == -ENOMEM)
+			set_gpt_cleanup(&str_disk_guid, &new_partitions);
+		else
+			goto out;
+	}
 
 	debug("Writing new partition table\n");
 	ret = gpt_restore(dev_desc, disk_guid, new_partitions, numparts);
 	if (ret < 0) {
 		printf("Writing new partition table failed\n");
-		return ret;
+		goto out;
 	}
 
 	debug("Reading back new partition table\n");
+	/*
+	 * Empty the existing disk_partitions list, as otherwise the memory in
+	 * the original list is unreachable.
+	 */
+	del_gpt_info();
 	numparts = get_gpt_info(dev_desc);
-	if (numparts <=  0)
-		return numparts ? numparts : -ENODEV;
+	if (numparts <=  0) {
+		ret = numparts ? numparts : -ENODEV;
+		goto out;
+	}
 	printf("new partition table with %d partitions is:\n", numparts);
 	print_gpt_info();
-
 	del_gpt_info();
-	free(partitions_list);
-	free(str_disk_guid);
+ out:
 	free(new_partitions);
+	free(str_disk_guid);
+	free(partitions_list);
 	return ret;
 }
 #endif
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index 4033d90..90f76bb 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -393,15 +393,18 @@
 		sprintf(message, "Please enter '%s': ", argv[1]);
 	} else {
 		/* env_ask envname message1 ... messagen [size] */
-		for (i = 2, pos = 0; i < argc; i++) {
+		for (i = 2, pos = 0; i < argc && pos+1 < sizeof(message); i++) {
 			if (pos)
 				message[pos++] = ' ';
 
-			strcpy(message + pos, argv[i]);
+			strncpy(message + pos, argv[i], sizeof(message) - pos);
 			pos += strlen(argv[i]);
 		}
-		message[pos++] = ' ';
-		message[pos] = '\0';
+		if (pos < sizeof(message) - 1) {
+			message[pos++] = ' ';
+			message[pos] = '\0';
+		} else
+			message[CONFIG_SYS_CBSIZE - 1] = '\0';
 	}
 
 	if (size >= CONFIG_SYS_CBSIZE)
@@ -927,7 +930,7 @@
 				H_MATCH_KEY | H_MATCH_IDENT,
 				&ptr, size, argc, argv);
 		if (len < 0) {
-			error("Cannot export environment: errno = %d\n", errno);
+			pr_err("Cannot export environment: errno = %d\n", errno);
 			return 1;
 		}
 		sprintf(buf, "%zX", (size_t)len);
@@ -947,7 +950,7 @@
 			H_MATCH_KEY | H_MATCH_IDENT,
 			&res, ENV_SIZE, argc, argv);
 	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
+		pr_err("Cannot export environment: errno = %d\n", errno);
 		return 1;
 	}
 
@@ -1082,7 +1085,7 @@
 
 	if (himport_r(&env_htab, ptr, size, sep, del ? 0 : H_NOCLEAR,
 			crlf_is_lf, 0, NULL) == 0) {
-		error("Environment import failed: errno = %d\n", errno);
+		pr_err("Environment import failed: errno = %d\n", errno);
 		return 1;
 	}
 	gd->flags |= GD_FLG_ENV_READY;
diff --git a/cmd/pxe.c b/cmd/pxe.c
index c5a770a..a62cbe1 100644
--- a/cmd/pxe.c
+++ b/cmd/pxe.c
@@ -616,7 +616,7 @@
 static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
 {
 	char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL };
-	char initrd_str[22];
+	char initrd_str[28];
 	char mac_str[29] = "";
 	char ip_str[68] = "";
 	int bootm_argc = 2;
@@ -648,9 +648,9 @@
 		}
 
 		bootm_argv[2] = initrd_str;
-		strcpy(bootm_argv[2], env_get("ramdisk_addr_r"));
+		strncpy(bootm_argv[2], env_get("ramdisk_addr_r"), 18);
 		strcat(bootm_argv[2], ":");
-		strcat(bootm_argv[2], env_get("filesize"));
+		strncat(bootm_argv[2], env_get("filesize"), 9);
 	}
 
 	if (get_relfile_envaddr(cmdtp, label->kernel, "kernel_addr_r") < 0) {
@@ -689,9 +689,9 @@
 		}
 
 		if (label->append)
-			strcpy(bootargs, label->append);
-		strcat(bootargs, ip_str);
-		strcat(bootargs, mac_str);
+			strncpy(bootargs, label->append, sizeof(bootargs));
+		strncat(bootargs, ip_str, sizeof(bootargs) - strlen(bootargs));
+		strncat(bootargs, mac_str, sizeof(bootargs) - strlen(bootargs));
 
 		cli_simple_process_macros(bootargs, finalbootargs);
 		env_set("bootargs", finalbootargs);
diff --git a/cmd/regulator.c b/cmd/regulator.c
index 2ef5bc9..b605255 100644
--- a/cmd/regulator.c
+++ b/cmd/regulator.c
@@ -71,7 +71,7 @@
 
 	*uc_pdata = dev_get_uclass_platdata(*devp);
 	if (!*uc_pdata) {
-		error("Regulator: %s - missing platform data!", currdev->name);
+		pr_err("Regulator: %s - missing platform data!", currdev->name);
 		return CMD_RET_FAILURE;
 	}
 
diff --git a/cmd/thordown.c b/cmd/thordown.c
index 436b7f5..1bb5fc2 100644
--- a/cmd/thordown.c
+++ b/cmd/thordown.c
@@ -33,7 +33,7 @@
 	int controller_index = simple_strtoul(usb_controller, NULL, 0);
 	ret = board_usb_init(controller_index, USB_INIT_DEVICE);
 	if (ret) {
-		error("USB init failed: %d", ret);
+		pr_err("USB init failed: %d", ret);
 		ret = CMD_RET_FAILURE;
 		goto exit;
 	}
@@ -42,14 +42,14 @@
 
 	ret = thor_init();
 	if (ret) {
-		error("THOR DOWNLOAD failed: %d", ret);
+		pr_err("THOR DOWNLOAD failed: %d", ret);
 		ret = CMD_RET_FAILURE;
 		goto exit;
 	}
 
 	ret = thor_handle();
 	if (ret) {
-		error("THOR failed: %d", ret);
+		pr_err("THOR failed: %d", ret);
 		ret = CMD_RET_FAILURE;
 		goto exit;
 	}
diff --git a/cmd/time.c b/cmd/time.c
index de57e3b..2cd8b1a 100644
--- a/cmd/time.c
+++ b/cmd/time.c
@@ -28,7 +28,7 @@
 {
 	ulong cycles = 0;
 	int retval = 0;
-	int repeatable;
+	int repeatable = 0;
 
 	if (argc == 1)
 		return CMD_RET_USAGE;
diff --git a/cmd/tpm_test.c b/cmd/tpm_test.c
index 3306405..37ad2ff 100644
--- a/cmd/tpm_test.c
+++ b/cmd/tpm_test.c
@@ -303,12 +303,12 @@
 	index_0 += 1;
 	if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0) !=
 		TPM_SUCCESS)) {
-		error("\tcould not write index 0\n");
+		pr_err("\tcould not write index 0\n");
 	}
 	tpm_nv_write_value_lock(INDEX0);
 	if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)) ==
 			TPM_SUCCESS)
-		error("\tindex 0 is not locked\n");
+		pr_err("\tindex 0 is not locked\n");
 
 	printf("\tdone\n");
 	return 0;
@@ -471,7 +471,7 @@
 		case TPM_MAXNVWRITES:
 			assert(i >= TPM_MAX_NV_WRITES_NOOWNER);
 		default:
-			error("\tunexpected error code %d (0x%x)\n",
+			pr_err("\tunexpected error code %d (0x%x)\n",
 			      result, result);
 		}
 	}
diff --git a/cmd/usb_gadget_sdp.c b/cmd/usb_gadget_sdp.c
index b1d8b28..ae4d73c 100644
--- a/cmd/usb_gadget_sdp.c
+++ b/cmd/usb_gadget_sdp.c
@@ -28,13 +28,13 @@
 
 	ret = sdp_init(controller_index);
 	if (ret) {
-		error("SDP init failed: %d", ret);
+		pr_err("SDP init failed: %d", ret);
 		goto exit;
 	}
 
 	/* This command typically does not return but jumps to an image */
 	sdp_handle(controller_index);
-	error("SDP ended");
+	pr_err("SDP ended");
 
 exit:
 	g_dnl_unregister();
diff --git a/cmd/usb_mass_storage.c b/cmd/usb_mass_storage.c
index 3353f95..cfeecb7 100644
--- a/cmd/usb_mass_storage.c
+++ b/cmd/usb_mass_storage.c
@@ -162,21 +162,21 @@
 	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.");
+		pr_err("Couldn't init USB controller.");
 		rc = CMD_RET_FAILURE;
 		goto cleanup_ums_init;
 	}
 
 	rc = fsg_init(ums, ums_count);
 	if (rc) {
-		error("fsg_init failed");
+		pr_err("fsg_init failed");
 		rc = CMD_RET_FAILURE;
 		goto cleanup_board;
 	}
 
 	rc = g_dnl_register("usb_dnl_ums");
 	if (rc) {
-		error("g_dnl_register failed");
+		pr_err("g_dnl_register failed");
 		rc = CMD_RET_FAILURE;
 		goto cleanup_board;
 	}
diff --git a/common/Kconfig b/common/Kconfig
index 540cc99..f96a25f 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -241,6 +241,27 @@
 	help
 	  This options adds the board specific name to u-boot version.
 
+config LOGLEVEL
+	int "loglevel"
+	default 4
+	range 0 8
+	help
+	  All Messages with a loglevel smaller than the console loglevel will
+	  be compiled in. The loglevels are defined as follows:
+
+	  0 (KERN_EMERG)          system is unusable
+	  1 (KERN_ALERT)          action must be taken immediately
+	  2 (KERN_CRIT)           critical conditions
+	  3 (KERN_ERR)            error conditions
+	  4 (KERN_WARNING)        warning conditions
+	  5 (KERN_NOTICE)         normal but significant condition
+	  6 (KERN_INFO)           informational
+	  7 (KERN_DEBUG)          debug-level messages
+
+config SPL_LOGLEVEL
+	int
+	default LOGLEVEL
+
 config SILENT_CONSOLE
 	bool "Support a silent console"
 	help
@@ -382,22 +403,6 @@
 
 endmenu
 
-config DTB_RESELECT
-	bool "Support swapping dtbs at a later point in boot"
-	depends on FIT_EMBED
-	help
-	  It is possible during initial boot you may need to use a generic
-	  dtb until you can fully determine the board your running on. This
-	  config allows boards to implement a function at a later point
-	  during boot to switch to the "correct" dtb.
-
-config FIT_EMBED
-	bool "Support a FIT image embedded in the U-boot image"
-	help
-	  This option provides hooks to allow U-boot to parse an
-	  appended FIT image and enable board specific code to then select
-	  the correct DTB to be used.
-
 config DEFAULT_FDT_FILE
 	string "Default fdt file"
 	help
diff --git a/common/Makefile b/common/Makefile
index 801ea31..cec506f 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -103,7 +103,7 @@
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
 obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o
-obj-$(CONFIG_FIT_EMBED) += boot_fit.o common_fit.o
+obj-$(CONFIG_$(SPL_)MULTI_DTB_FIT) += boot_fit.o common_fit.o
 obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += image-sig.o
 obj-$(CONFIG_IO_TRACE) += iotrace.o
 obj-y += memsize.o
diff --git a/common/boot_fit.c b/common/boot_fit.c
index 0a72315..add65c4 100644
--- a/common/boot_fit.c
+++ b/common/boot_fit.c
@@ -13,7 +13,7 @@
 #include <image.h>
 #include <libfdt.h>
 
-int fdt_offset(void *fit)
+static int fdt_offset(const void *fit)
 {
 	int images, node, fdt_len, fdt_node, fdt_offset;
 	const char *fdt_name;
@@ -55,7 +55,7 @@
 	return fdt_offset;
 }
 
-void *locate_dtb_in_fit(void *fit)
+void *locate_dtb_in_fit(const void *fit)
 {
 	struct image_header *header;
 	int size;
@@ -73,7 +73,7 @@
 
 	ret = fdt_offset(fit);
 
-	if (ret <= 0)
+	if (ret < 0)
 		return NULL;
 	else
 		return (void *)fit+size+ret;
diff --git a/common/common_fit.c b/common/common_fit.c
index 5f5f3f9..85b33d8 100644
--- a/common/common_fit.c
+++ b/common/common_fit.c
@@ -32,6 +32,9 @@
 {
 	const char *name;
 	int conf, node, len;
+	const char *dflt_conf_name;
+	const char *dflt_conf_desc = NULL;
+	int dflt_conf_node = -ENOENT;
 
 	conf = fdt_path_offset(fdt, FIT_CONFS_PATH);
 	if (conf < 0) {
@@ -39,6 +42,9 @@
 		      conf);
 		return -EINVAL;
 	}
+
+	dflt_conf_name = fdt_getprop(fdt, conf, "default", &len);
+
 	for (node = fdt_first_subnode(fdt, conf);
 	     node >= 0;
 	     node = fdt_next_subnode(fdt, node)) {
@@ -50,6 +56,15 @@
 #endif
 			return -EINVAL;
 		}
+
+		if (dflt_conf_name) {
+			const char *node_name = fdt_get_name(fdt, node, NULL);
+			if (strcmp(dflt_conf_name, node_name) == 0) {
+				dflt_conf_node = node;
+				dflt_conf_desc = name;
+			}
+		}
+
 		if (board_fit_config_name_match(name))
 			continue;
 
@@ -58,5 +73,10 @@
 		return node;
 	}
 
+	if (dflt_conf_node != -ENOENT) {
+		debug("Selecting default config '%s'", dflt_conf_desc);
+		return dflt_conf_node;
+	}
+
 	return -ENOENT;
 }
diff --git a/common/dfu.c b/common/dfu.c
index 546a1ab..07dff31 100644
--- a/common/dfu.c
+++ b/common/dfu.c
@@ -26,13 +26,13 @@
 
 	ret = board_usb_init(usbctrl_index, USB_INIT_DEVICE);
 	if (ret) {
-		error("board usb init failed\n");
+		pr_err("board usb init failed\n");
 		return CMD_RET_FAILURE;
 	}
 	g_dnl_clear_detach();
 	ret = g_dnl_register(usb_dnl_gadget);
 	if (ret) {
-		error("g_dnl_register failed");
+		pr_err("g_dnl_register failed");
 		return CMD_RET_FAILURE;
 	}
 
@@ -75,7 +75,7 @@
 			ret = dfu_flush(dfu_get_defer_flush(), NULL, 0, 0);
 			dfu_set_defer_flush(NULL);
 			if (ret) {
-				error("Deferred dfu_flush() failed!");
+				pr_err("Deferred dfu_flush() failed!");
 				goto exit;
 			}
 		}
diff --git a/common/fb_mmc.c b/common/fb_mmc.c
index 26d60b8..cf5b77c 100644
--- a/common/fb_mmc.c
+++ b/common/fb_mmc.c
@@ -84,7 +84,7 @@
 	blkcnt = lldiv(blkcnt, info->blksz);
 
 	if (blkcnt > info->size) {
-		error("too large for partition: '%s'\n", part_name);
+		pr_err("too large for partition: '%s'\n", part_name);
 		fastboot_fail("too large for partition");
 		return;
 	}
@@ -93,7 +93,7 @@
 
 	blks = blk_dwrite(dev_desc, info->start, blkcnt, buffer);
 	if (blks != blkcnt) {
-		error("failed writing to device %d\n", dev_desc->devnum);
+		pr_err("failed writing to device %d\n", dev_desc->devnum);
 		fastboot_fail("failed writing to device");
 		return;
 	}
@@ -125,7 +125,7 @@
 	sector_size = info->blksz;
 	hdr_sectors = DIV_ROUND_UP(sizeof(struct andr_img_hdr), sector_size);
 	if (hdr_sectors == 0) {
-		error("invalid number of boot sectors: 0");
+		pr_err("invalid number of boot sectors: 0");
 		fastboot_fail("invalid number of boot sectors: 0");
 		return 0;
 	}
@@ -133,7 +133,7 @@
 	/* Read the boot image header */
 	res = blk_dread(dev_desc, info->start, hdr_sectors, (void *)hdr);
 	if (res != hdr_sectors) {
-		error("cannot read header from boot partition");
+		pr_err("cannot read header from boot partition");
 		fastboot_fail("cannot read header from boot partition");
 		return 0;
 	}
@@ -141,7 +141,7 @@
 	/* Check boot header magic string */
 	res = android_image_check_header(hdr);
 	if (res != 0) {
-		error("bad boot image magic");
+		pr_err("bad boot image magic");
 		fastboot_fail("boot partition not initialized");
 		return 0;
 	}
@@ -179,7 +179,7 @@
 	/* Get boot partition info */
 	res = part_get_info_by_name(dev_desc, BOOT_PARTITION_NAME, &info);
 	if (res < 0) {
-		error("cannot find boot partition");
+		pr_err("cannot find boot partition");
 		fastboot_fail("cannot find boot partition");
 		return -1;
 	}
@@ -191,14 +191,14 @@
 	/* Read boot image header */
 	hdr_sectors = fb_mmc_get_boot_header(dev_desc, &info, hdr);
 	if (hdr_sectors == 0) {
-		error("unable to read boot image header");
+		pr_err("unable to read boot image header");
 		fastboot_fail("unable to read boot image header");
 		return -1;
 	}
 
 	/* Check if boot image has second stage in it (we don't support it) */
 	if (hdr->second_size > 0) {
-		error("moving second stage is not supported yet");
+		pr_err("moving second stage is not supported yet");
 		fastboot_fail("moving second stage is not supported yet");
 		return -1;
 	}
@@ -216,7 +216,7 @@
 	res = blk_dread(dev_desc, ramdisk_sector_start, ramdisk_sectors,
 			ramdisk_buffer);
 	if (res != ramdisk_sectors) {
-		error("cannot read ramdisk from boot partition");
+		pr_err("cannot read ramdisk from boot partition");
 		fastboot_fail("cannot read ramdisk from boot partition");
 		return -1;
 	}
@@ -225,7 +225,7 @@
 	hdr->kernel_size = download_bytes;
 	res = blk_dwrite(dev_desc, info.start, hdr_sectors, (void *)hdr);
 	if (res == 0) {
-		error("cannot writeback boot image header");
+		pr_err("cannot writeback boot image header");
 		fastboot_fail("cannot write back boot image header");
 		return -1;
 	}
@@ -237,7 +237,7 @@
 	res = blk_dwrite(dev_desc, kernel_sector_start, kernel_sectors,
 			 download_buffer);
 	if (res == 0) {
-		error("cannot write new kernel");
+		pr_err("cannot write new kernel");
 		fastboot_fail("cannot write new kernel");
 		return -1;
 	}
@@ -249,7 +249,7 @@
 	res = blk_dwrite(dev_desc, ramdisk_sector_start, ramdisk_sectors,
 			 ramdisk_buffer);
 	if (res == 0) {
-		error("cannot write back original ramdisk");
+		pr_err("cannot write back original ramdisk");
 		fastboot_fail("cannot write back original ramdisk");
 		return -1;
 	}
@@ -268,7 +268,7 @@
 
 	dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
 	if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
-		error("invalid mmc device\n");
+		pr_err("invalid mmc device\n");
 		fastboot_fail("invalid mmc device");
 		return;
 	}
@@ -322,7 +322,7 @@
 #endif
 
 	if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) {
-		error("cannot find partition: '%s'\n", cmd);
+		pr_err("cannot find partition: '%s'\n", cmd);
 		fastboot_fail("cannot find partition");
 		return;
 	}
@@ -360,21 +360,21 @@
 	struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
 
 	if (mmc == NULL) {
-		error("invalid mmc device");
+		pr_err("invalid mmc device");
 		fastboot_fail("invalid mmc device");
 		return;
 	}
 
 	dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
 	if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
-		error("invalid mmc device");
+		pr_err("invalid mmc device");
 		fastboot_fail("invalid mmc device");
 		return;
 	}
 
 	ret = part_get_info_by_name_or_alias(dev_desc, cmd, &info);
 	if (ret < 0) {
-		error("cannot find partition: '%s'", cmd);
+		pr_err("cannot find partition: '%s'", cmd);
 		fastboot_fail("cannot find partition");
 		return;
 	}
@@ -393,7 +393,7 @@
 
 	blks = blk_derase(dev_desc, blks_start, blks_size);
 	if (blks != blks_size) {
-		error("failed erasing from device %d", dev_desc->devnum);
+		pr_err("failed erasing from device %d", dev_desc->devnum);
 		fastboot_fail("failed erasing from device");
 		return;
 	}
diff --git a/common/fb_nand.c b/common/fb_nand.c
index 3d027d4..aa28046 100644
--- a/common/fb_nand.c
+++ b/common/fb_nand.c
@@ -40,20 +40,20 @@
 
 	ret = mtdparts_init();
 	if (ret) {
-		error("Cannot initialize MTD partitions\n");
+		pr_err("Cannot initialize MTD partitions\n");
 		fastboot_fail("cannot init mtdparts");
 		return ret;
 	}
 
 	ret = find_dev_and_part(partname, &dev, &pnum, part);
 	if (ret) {
-		error("cannot find partition: '%s'", partname);
+		pr_err("cannot find partition: '%s'", partname);
 		fastboot_fail("cannot find partition");
 		return ret;
 	}
 
 	if (dev->id->type != MTD_DEV_TYPE_NAND) {
-		error("partition '%s' is not stored on a NAND device",
+		pr_err("partition '%s' is not stored on a NAND device",
 		      partname);
 		fastboot_fail("not a NAND device");
 		return -EINVAL;
@@ -154,7 +154,7 @@
 
 	ret = fb_nand_lookup(cmd, &mtd, &part);
 	if (ret) {
-		error("invalid NAND device");
+		pr_err("invalid NAND device");
 		fastboot_fail("invalid NAND device");
 		return;
 	}
@@ -209,7 +209,7 @@
 
 	ret = fb_nand_lookup(cmd, &mtd, &part);
 	if (ret) {
-		error("invalid NAND device");
+		pr_err("invalid NAND device");
 		fastboot_fail("invalid NAND device");
 		return;
 	}
@@ -220,7 +220,7 @@
 
 	ret = _fb_nand_erase(mtd, part);
 	if (ret) {
-		error("failed erasing from device %s", mtd->name);
+		pr_err("failed erasing from device %s", mtd->name);
 		fastboot_fail("failed erasing from device");
 		return;
 	}
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index b05ec21..0bd8370 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -94,6 +94,7 @@
 config SPL_STACK_R_ADDR
 	depends on SPL_STACK_R
 	hex "SDRAM location for SPL stack"
+	default 0x82000000 if ARCH_OMAP2PLUS
 	help
 	  Specify the address in SDRAM for the SPL stack. This will be set up
 	  before board_init_r() is called.
diff --git a/common/spl/spl_dfu.c b/common/spl/spl_dfu.c
index 2c97473..05bb210 100644
--- a/common/spl/spl_dfu.c
+++ b/common/spl/spl_dfu.c
@@ -42,13 +42,13 @@
 	set_default_env(0);
 	str_env = env_get(dfu_alt_info);
 	if (!str_env) {
-		error("\"dfu_alt_info\" env variable not defined!\n");
+		pr_err("\"dfu_alt_info\" env variable not defined!\n");
 		return -EINVAL;
 	}
 
 	ret = env_set("dfu_alt_info", str_env);
 	if (ret) {
-		error("unable to set env variable \"dfu_alt_info\"!\n");
+		pr_err("unable to set env variable \"dfu_alt_info\"!\n");
 		return -EINVAL;
 	}
 
diff --git a/common/spl/spl_sdp.c b/common/spl/spl_sdp.c
index 350bcdb..333d518 100644
--- a/common/spl/spl_sdp.c
+++ b/common/spl/spl_sdp.c
@@ -24,13 +24,13 @@
 
 	ret = sdp_init(controller_index);
 	if (ret) {
-		error("SDP init failed: %d", ret);
+		pr_err("SDP init failed: %d", ret);
 		return -ENODEV;
 	}
 
 	/* This command typically does not return but jumps to an image */
 	sdp_handle(controller_index);
-	error("SDP ended");
+	pr_err("SDP ended");
 
 	return -EINVAL;
 }
diff --git a/common/update.c b/common/update.c
index 974f465..33bffaa 100644
--- a/common/update.c
+++ b/common/update.c
@@ -242,7 +242,7 @@
 	} else if (interface && devstring) {
 		update_tftp_dfu = true;
 	} else {
-		error("Interface: %s and devstring: %s not supported!\n",
+		pr_err("Interface: %s and devstring: %s not supported!\n",
 		      interface, devstring);
 		return -EINVAL;
 	}
diff --git a/common/usb.c b/common/usb.c
index 0904259..8d27bc7 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -437,12 +437,13 @@
 			}
 			break;
 		case USB_DT_ENDPOINT:
-			if (head->bLength != USB_DT_ENDPOINT_SIZE) {
+			if (head->bLength != USB_DT_ENDPOINT_SIZE &&
+			    head->bLength != USB_DT_ENDPOINT_AUDIO_SIZE) {
 				printf("ERROR: Invalid USB EP length (%d)\n",
 					head->bLength);
 				break;
 			}
-			if (index + USB_DT_ENDPOINT_SIZE >
+			if (index + head->bLength >
 			    dev->config.desc.wTotalLength) {
 				puts("USB EP descriptor overflowed buffer!\n");
 				break;
@@ -969,23 +970,24 @@
 	dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0;
 	dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
 
-	if (do_read) {
+	if (do_read && dev->speed == USB_SPEED_FULL) {
 		int err;
 
 		/*
-		 * Validate we've received only at least 8 bytes, not that we've
-		 * received the entire descriptor. The reasoning is:
-		 * - The code only uses fields in the first 8 bytes, so that's all we
-		 *   need to have fetched at this stage.
-		 * - The smallest maxpacket size is 8 bytes. Before we know the actual
-		 *   maxpacket the device uses, the USB controller may only accept a
-		 *   single packet. Consequently we are only guaranteed to receive 1
-		 *   packet (at least 8 bytes) even in a non-error case.
+		 * Validate we've received only at least 8 bytes, not that
+		 * we've received the entire descriptor. The reasoning is:
+		 * - The code only uses fields in the first 8 bytes, so
+		 *   that's all we need to have fetched at this stage.
+		 * - The smallest maxpacket size is 8 bytes. Before we know
+		 *   the actual maxpacket the device uses, the USB controller
+		 *   may only accept a single packet. Consequently we are only
+		 *   guaranteed to receive 1 packet (at least 8 bytes) even in
+		 *   a non-error case.
 		 *
-		 * At least the DWC2 controller needs to be programmed with the number
-		 * of packets in addition to the number of bytes. A request for 64
-		 * bytes of data with the maxpacket guessed as 64 (above) yields a
-		 * request for 1 packet.
+		 * At least the DWC2 controller needs to be programmed with
+		 * the number of packets in addition to the number of bytes.
+		 * A request for 64 bytes of data with the maxpacket guessed
+		 * as 64 (above) yields a request for 1 packet.
 		 */
 		err = get_descriptor_len(dev, 64, 8);
 		if (err)
@@ -1008,7 +1010,7 @@
 		dev->maxpacketsize = PACKET_SIZE_64;
 		break;
 	default:
-		printf("usb_new_device: invalid max packet size\n");
+		printf("%s: invalid max packet size\n", __func__);
 		return -EIO;
 	}
 
@@ -1050,6 +1052,17 @@
 
 	mdelay(10);	/* Let the SET_ADDRESS settle */
 
+	/*
+	 * If we haven't read device descriptor before, read it here
+	 * after device is assigned an address. This is only applicable
+	 * to xHCI so far.
+	 */
+	if (!do_read) {
+		err = usb_setup_descriptor(dev, true);
+		if (err)
+			return err;
+	}
+
 	return 0;
 }
 
diff --git a/common/usb_hub.c b/common/usb_hub.c
index 86a3477..325d16d 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -489,6 +489,17 @@
 		return 0;
 	}
 
+	if (portchange & USB_PORT_STAT_C_RESET) {
+		debug("port %d reset change\n", i + 1);
+		usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
+	}
+
+	if ((portchange & USB_SS_PORT_STAT_C_BH_RESET) &&
+	    usb_hub_is_superspeed(dev)) {
+		debug("port %d BH reset change\n", i + 1);
+		usb_clear_port_feature(dev, i + 1, USB_SS_PORT_FEAT_C_BH_RESET);
+	}
+
 	/* A new USB device is ready at this point */
 	debug("devnum=%d port=%d: USB dev found\n", dev->devnum, i + 1);
 
@@ -543,11 +554,6 @@
 		       hub->overcurrent_count[i]);
 	}
 
-	if (portchange & USB_PORT_STAT_C_RESET) {
-		debug("port %d reset change\n", i + 1);
-		usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
-	}
-
 	/*
 	 * We're done with this device, so let's remove this device from
 	 * scanning list
diff --git a/common/usb_storage.c b/common/usb_storage.c
index a57570b..a91b1c0 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -964,7 +964,7 @@
 		blk = 20;
 	} else {
 		if (size > USHRT_MAX * 512)
-			blk = USHRT_MAX;
+			size = USHRT_MAX * 512;
 		blk = size / 512;
 	}
 #endif
diff --git a/configs/A13-OLinuXino_defconfig b/configs/A13-OLinuXino_defconfig
index fbacce0..ed83490 100644
--- a/configs/A13-OLinuXino_defconfig
+++ b/configs/A13-OLinuXino_defconfig
@@ -31,8 +31,3 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Allwinner Technology"
-CONFIG_G_DNL_VENDOR_NUM=0x1f3a
-CONFIG_G_DNL_PRODUCT_NUM=0x1010
diff --git a/configs/A20-OLinuXino-Lime2-eMMC_defconfig b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
index 58aa988..b89c505 100644
--- a/configs/A20-OLinuXino-Lime2-eMMC_defconfig
+++ b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
@@ -14,7 +14,6 @@
 CONFIG_SPL=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_FASTBOOT_FLASH=y
-CONFIG_FASTBOOT_FLASH_MMC_DEV=0
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_DFU=y
 # CONFIG_CMD_FLASH is not set
@@ -33,8 +32,3 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Allwinner Technology"
-CONFIG_G_DNL_VENDOR_NUM=0x1f3a
-CONFIG_G_DNL_PRODUCT_NUM=0x1010
diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig
index 6d7c588..f9388a0 100644
--- a/configs/A20-OLinuXino-Lime2_defconfig
+++ b/configs/A20-OLinuXino-Lime2_defconfig
@@ -32,8 +32,3 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Allwinner Technology"
-CONFIG_G_DNL_VENDOR_NUM=0x1f3a
-CONFIG_G_DNL_PRODUCT_NUM=0x1010
diff --git a/configs/A20-OLinuXino_MICRO-eMMC_defconfig b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
new file mode 100644
index 0000000..3e07d00
--- /dev/null
+++ b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
@@ -0,0 +1,27 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_MACH_SUN7I=y
+CONFIG_DRAM_CLK=384
+CONFIG_MMC0_CD_PIN="PH1"
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+CONFIG_I2C1_ENABLE=y
+CONFIG_VIDEO_VGA=y
+CONFIG_SATAPWR="PB8"
+CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-olinuxino-micro"
+CONFIG_AHCI=y
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL=y
+CONFIG_SPL_I2C_SUPPORT=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_ISO_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_SUN7I_GMAC=y
+CONFIG_AXP_ALDO3_VOLT=2800
+CONFIG_AXP_ALDO4_VOLT=2800
+CONFIG_SCSI=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/CHIP_defconfig b/configs/CHIP_defconfig
index 83228bd..5acce42 100644
--- a/configs/CHIP_defconfig
+++ b/configs/CHIP_defconfig
@@ -22,9 +22,4 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Allwinner Technology"
-CONFIG_G_DNL_VENDOR_NUM=0x1f3a
-CONFIG_G_DNL_PRODUCT_NUM=0x1010
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/CHIP_pro_defconfig b/configs/CHIP_pro_defconfig
index 3a748fc..2303135 100644
--- a/configs/CHIP_pro_defconfig
+++ b/configs/CHIP_pro_defconfig
@@ -27,9 +27,4 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Allwinner Technology"
-CONFIG_G_DNL_VENDOR_NUM=0x1f3a
-CONFIG_G_DNL_PRODUCT_NUM=0x1010
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/Cubietruck_defconfig b/configs/Cubietruck_defconfig
index f93ff0d..3dff02f 100644
--- a/configs/Cubietruck_defconfig
+++ b/configs/Cubietruck_defconfig
@@ -32,8 +32,3 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Allwinner Technology"
-CONFIG_G_DNL_VENDOR_NUM=0x1f3a
-CONFIG_G_DNL_PRODUCT_NUM=0x1010
diff --git a/configs/Cubietruck_plus_defconfig b/configs/Cubietruck_plus_defconfig
index 34444ec..3d99919 100644
--- a/configs/Cubietruck_plus_defconfig
+++ b/configs/Cubietruck_plus_defconfig
@@ -4,6 +4,7 @@
 CONFIG_DRAM_CLK=672
 CONFIG_DRAM_ZQ=15355
 CONFIG_DRAM_ODT_EN=y
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
 CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
 CONFIG_USB0_ID_DET="PH11"
diff --git a/configs/LicheePi_Zero_defconfig b/configs/LicheePi_Zero_defconfig
index bd754cb..6cda4ea 100644
--- a/configs/LicheePi_Zero_defconfig
+++ b/configs/LicheePi_Zero_defconfig
@@ -4,8 +4,12 @@
 CONFIG_DRAM_CLK=360
 CONFIG_DRAM_ZQ=14779
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-v3s-licheepi-zero"
+CONFIG_SPL=y
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_FPGA is not set
 # CONFIG_NETDEVICES is not set
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_ISO_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/Nintendo_NES_Classic_Edition_defconfig b/configs/Nintendo_NES_Classic_Edition_defconfig
index d05375d..26fcffa 100644
--- a/configs/Nintendo_NES_Classic_Edition_defconfig
+++ b/configs/Nintendo_NES_Classic_Edition_defconfig
@@ -22,8 +22,3 @@
 CONFIG_AXP_ELDO2_VOLT=1800
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Allwinner Technology"
-CONFIG_G_DNL_VENDOR_NUM=0x1f3a
-CONFIG_G_DNL_PRODUCT_NUM=0x1010
diff --git a/configs/Sinlinx_SinA33_defconfig b/configs/Sinlinx_SinA33_defconfig
index af00e54..32c8872 100644
--- a/configs/Sinlinx_SinA33_defconfig
+++ b/configs/Sinlinx_SinA33_defconfig
@@ -15,7 +15,6 @@
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL=y
 CONFIG_FASTBOOT_FLASH=y
-CONFIG_FASTBOOT_FLASH_MMC_DEV=0
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_DFU=y
 # CONFIG_CMD_FLASH is not set
@@ -27,8 +26,3 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Allwinner Technology"
-CONFIG_G_DNL_VENDOR_NUM=0x1f3a
-CONFIG_G_DNL_PRODUCT_NUM=0x1010
diff --git a/configs/Sinovoip_BPI_M3_defconfig b/configs/Sinovoip_BPI_M3_defconfig
index 04d8169..f321d94 100644
--- a/configs/Sinovoip_BPI_M3_defconfig
+++ b/configs/Sinovoip_BPI_M3_defconfig
@@ -13,7 +13,7 @@
 CONFIG_USB1_VBUS_PIN="PD24"
 CONFIG_AXP_GPIO=y
 CONFIG_SATAPWR="PD25"
-CONFIG_DEFAULT_DEVICE_TREE="sun8i-a83t-sinovoip-bpi-m3"
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-a83t-bananapi-m3"
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_CONSOLE_MUX=y
 CONFIG_SPL=y
diff --git a/configs/am335x_baltos_defconfig b/configs/am335x_baltos_defconfig
index eb8338f..3794b86 100644
--- a/configs/am335x_baltos_defconfig
+++ b/configs/am335x_baltos_defconfig
@@ -10,7 +10,6 @@
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_OF_BOARD_SETUP=y
@@ -18,7 +17,6 @@
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_MTD_SUPPORT=y
@@ -59,9 +57,11 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0403
+CONFIG_USB_GADGET_PRODUCT_NUM=0xbd00
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0403
-CONFIG_G_DNL_PRODUCT_NUM=0xbd00
+CONFIG_USB_ETHER=y
+CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00"
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/am335x_boneblack_defconfig b/configs/am335x_boneblack_defconfig
index b8526fc..0d6018a 100644
--- a/configs/am335x_boneblack_defconfig
+++ b/configs/am335x_boneblack_defconfig
@@ -3,14 +3,12 @@
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_AM33XX=y
 # CONFIG_SPL_NAND_SUPPORT is not set
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_AUTOBOOT_KEYED=y
@@ -18,7 +16,6 @@
 CONFIG_AUTOBOOT_DELAY_STR="d"
 CONFIG_AUTOBOOT_STOP_STR=" "
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_SPL=y
 # CONFIG_CMD_FLASH is not set
@@ -38,10 +35,11 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
+CONFIG_USB_ETHER=y
+CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00"
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/am335x_boneblack_vboot_defconfig b/configs/am335x_boneblack_vboot_defconfig
index 0a239bb..84887b3 100644
--- a/configs/am335x_boneblack_vboot_defconfig
+++ b/configs/am335x_boneblack_vboot_defconfig
@@ -3,7 +3,6 @@
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_AM33XX=y
 # CONFIG_SPL_NAND_SUPPORT is not set
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="am335x-boneblack"
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_FIT_SIGNATURE=y
@@ -13,7 +12,6 @@
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_AUTOBOOT_KEYED=y
@@ -21,7 +19,6 @@
 CONFIG_AUTOBOOT_DELAY_STR="d"
 CONFIG_AUTOBOOT_STOP_STR=" "
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_SPL=y
 # CONFIG_CMD_FLASH is not set
@@ -48,8 +45,8 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
+CONFIG_USB_ETHER=y
 CONFIG_LZO=y
diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig
index 00c1af4..50999af 100644
--- a/configs/am335x_evm_defconfig
+++ b/configs/am335x_evm_defconfig
@@ -2,7 +2,6 @@
 CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_AM33XX=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="am335x-evm"
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SPL_LOAD_FIT=y
@@ -10,12 +9,10 @@
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_SPL=y
 CONFIG_CMD_SPL_NAND_OFS=0x00080000
@@ -50,10 +47,10 @@
 CONFIG_USB_MUSB_TI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
+CONFIG_USB_ETHER=y
 CONFIG_RSA=y
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/am335x_evm_nor_defconfig b/configs/am335x_evm_nor_defconfig
index 9f08edf..c9b1eae 100644
--- a/configs/am335x_evm_nor_defconfig
+++ b/configs/am335x_evm_nor_defconfig
@@ -3,18 +3,15 @@
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_AM33XX=y
 CONFIG_NOR=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_SPL=y
 CONFIG_CMD_SPL_NAND_OFS=0x00080000
@@ -37,10 +34,10 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
+CONFIG_USB_ETHER=y
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/am335x_evm_norboot_defconfig b/configs/am335x_evm_norboot_defconfig
index c5e7425..e786565 100644
--- a/configs/am335x_evm_norboot_defconfig
+++ b/configs/am335x_evm_norboot_defconfig
@@ -12,7 +12,6 @@
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_MTDPARTS=y
@@ -31,10 +30,11 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
+CONFIG_USB_ETHER=y
+CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00"
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/am335x_evm_spiboot_defconfig b/configs/am335x_evm_spiboot_defconfig
index 501fb2b..9fa2708 100644
--- a/configs/am335x_evm_spiboot_defconfig
+++ b/configs/am335x_evm_spiboot_defconfig
@@ -5,7 +5,6 @@
 # CONFIG_SPL_NAND_SUPPORT is not set
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SYS_EXTRA_OPTIONS="SPI_BOOT"
 CONFIG_SPI_BOOT=y
@@ -13,10 +12,8 @@
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
@@ -35,10 +32,10 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
+CONFIG_USB_ETHER=y
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/am335x_evm_usbspl_defconfig b/configs/am335x_evm_usbspl_defconfig
index 7c35138..4c28bb4 100644
--- a/configs/am335x_evm_usbspl_defconfig
+++ b/configs/am335x_evm_usbspl_defconfig
@@ -3,14 +3,12 @@
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_AM33XX=y
 # CONFIG_SPL_NAND_SUPPORT is not set
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DISTRO_DEFAULTS=y
 # CONFIG_ANDROID_BOOT_IMAGE is not set
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_SPL_NET_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
@@ -18,7 +16,6 @@
 CONFIG_SPL_USBETH_SUPPORT=y
 # CONFIG_SPL_YMODEM_SUPPORT is not set
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_SPL=y
 CONFIG_CMD_SPL_NAND_OFS=0x00080000
@@ -41,10 +38,10 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
+CONFIG_USB_ETHER=y
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/am335x_hs_evm_defconfig b/configs/am335x_hs_evm_defconfig
index acdd56b..60919f8 100644
--- a/configs/am335x_hs_evm_defconfig
+++ b/configs/am335x_hs_evm_defconfig
@@ -5,7 +5,6 @@
 CONFIG_TI_SECURE_DEVICE=y
 CONFIG_ISW_ENTRY_ADDR=0x40300350
 # CONFIG_SPL_NAND_SUPPORT is not set
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="am335x-evm"
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_ANDROID_BOOT_IMAGE=y
@@ -16,7 +15,6 @@
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 # CONFIG_SPL_ENV_SUPPORT is not set
 # CONFIG_SPL_EXT_SUPPORT is not set
 CONFIG_SPL_MTD_SUPPORT=y
@@ -54,9 +52,10 @@
 CONFIG_USB_MUSB_TI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_ETHER=y
 CONFIG_RSA=y
 CONFIG_LZO=y
diff --git a/configs/am335x_hs_evm_uart_defconfig b/configs/am335x_hs_evm_uart_defconfig
new file mode 100644
index 0000000..1c453fb
--- /dev/null
+++ b/configs/am335x_hs_evm_uart_defconfig
@@ -0,0 +1,67 @@
+CONFIG_ARM=y
+CONFIG_ARCH_OMAP2PLUS=y
+CONFIG_TI_COMMON_CMD_OPTIONS=y
+CONFIG_AM33XX=y
+# CONFIG_SPL_FAT_SUPPORT is not set
+# CONFIG_SPL_LIBDISK_SUPPORT is not set
+# CONFIG_SPL_MMC_SUPPORT is not set
+# CONFIG_SPL_NAND_SUPPORT is not set
+CONFIG_TI_SECURE_DEVICE=y
+CONFIG_ISW_ENTRY_ADDR=0x40301950
+CONFIG_SPL_STACK_R_ADDR=0x82000000
+CONFIG_DEFAULT_DEVICE_TREE="am335x-evm"
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT_IMAGE_POST_PROCESS=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_VERSION_VARIABLE=y
+CONFIG_ARCH_MISC_INIT=y
+CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_STACK_R=y
+# CONFIG_SPL_ENV_SUPPORT is not set
+# CONFIG_SPL_EXT_SUPPORT is not set
+CONFIG_SPL_MTD_SUPPORT=y
+# CONFIG_SPL_YMODEM_SUPPORT is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_NAND=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_MTDPARTS=y
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIST="am335x-evm am335x-bone am335x-boneblack am335x-evmsk am335x-bonegreen am335x-icev2"
+# CONFIG_BLK is not set
+CONFIG_DFU_MMC=y
+CONFIG_DFU_NAND=y
+CONFIG_DFU_RAM=y
+CONFIG_DM_I2C=y
+CONFIG_MISC=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_OMAP_HS=y
+CONFIG_NAND=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_PHYLIB=y
+CONFIG_DM_ETH=y
+CONFIG_PHY_GIGE=y
+CONFIG_SYS_NS16550=y
+CONFIG_OMAP3_SPI=y
+CONFIG_TIMER=y
+CONFIG_OMAP_TIMER=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_MUSB_HOST=y
+CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_TI=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
+CONFIG_G_DNL_VENDOR_NUM=0x0451
+CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_RSA=y
+CONFIG_LZO=y
+CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/am335x_igep003x_defconfig b/configs/am335x_igep003x_defconfig
index 1b03c33..f344a73 100644
--- a/configs/am335x_igep003x_defconfig
+++ b/configs/am335x_igep003x_defconfig
@@ -11,14 +11,12 @@
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_SYS_EXTRA_OPTIONS="MACH_TYPE=MACH_TYPE_IGEP0033"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_MTD_SUPPORT=y
diff --git a/configs/am335x_shc_defconfig b/configs/am335x_shc_defconfig
index c63e388..0b29290 100644
--- a/configs/am335x_shc_defconfig
+++ b/configs/am335x_shc_defconfig
@@ -9,13 +9,11 @@
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_SERIES=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
diff --git a/configs/am335x_shc_ict_defconfig b/configs/am335x_shc_ict_defconfig
index 1bcf683..73e0d28 100644
--- a/configs/am335x_shc_ict_defconfig
+++ b/configs/am335x_shc_ict_defconfig
@@ -9,14 +9,12 @@
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_SHC_ICT=y
 CONFIG_SERIES=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
diff --git a/configs/am335x_shc_netboot_defconfig b/configs/am335x_shc_netboot_defconfig
index 9528a8c..c4f2f55 100644
--- a/configs/am335x_shc_netboot_defconfig
+++ b/configs/am335x_shc_netboot_defconfig
@@ -9,14 +9,12 @@
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_SHC_NETBOOT=y
 CONFIG_SERIES=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
diff --git a/configs/am335x_shc_prompt_defconfig b/configs/am335x_shc_prompt_defconfig
index 8519282..4eac21b 100644
--- a/configs/am335x_shc_prompt_defconfig
+++ b/configs/am335x_shc_prompt_defconfig
@@ -9,13 +9,11 @@
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_SERIES=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
diff --git a/configs/am335x_shc_sdboot_defconfig b/configs/am335x_shc_sdboot_defconfig
index b00d6f6..e3a37db 100644
--- a/configs/am335x_shc_sdboot_defconfig
+++ b/configs/am335x_shc_sdboot_defconfig
@@ -9,14 +9,12 @@
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_SHC_SDBOOT=y
 CONFIG_SERIES=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
diff --git a/configs/am335x_shc_sdboot_prompt_defconfig b/configs/am335x_shc_sdboot_prompt_defconfig
index b00d6f6..e3a37db 100644
--- a/configs/am335x_shc_sdboot_prompt_defconfig
+++ b/configs/am335x_shc_sdboot_prompt_defconfig
@@ -9,14 +9,12 @@
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_SHC_SDBOOT=y
 CONFIG_SERIES=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
diff --git a/configs/am335x_sl50_defconfig b/configs/am335x_sl50_defconfig
index 3fa5d5e..e9ca0d6 100644
--- a/configs/am335x_sl50_defconfig
+++ b/configs/am335x_sl50_defconfig
@@ -9,14 +9,12 @@
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
diff --git a/configs/am3517_evm_defconfig b/configs/am3517_evm_defconfig
index 920c61c..8ab0186 100644
--- a/configs/am3517_evm_defconfig
+++ b/configs/am3517_evm_defconfig
@@ -4,11 +4,14 @@
 CONFIG_SYS_TEXT_BASE=0x80100000
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 # CONFIG_SPL_GPIO_SUPPORT is not set
+CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_TARGET_AM3517_EVM=y
 CONFIG_EMIF4=y
+CONFIG_DEFAULT_DEVICE_TREE="am3517-evm"
 CONFIG_BOOTDELAY=10
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 # CONFIG_SPL_EXT_SUPPORT is not set
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_HUSH_PARSER=y
@@ -27,13 +30,12 @@
 # CONFIG_CMD_TIME is not set
 CONFIG_CMD_UBI=y
 CONFIG_SPL_PARTITION_UUIDS=y
+CONFIG_OF_CONTROL=y
 CONFIG_ENV_IS_IN_NAND=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NAND=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
-CONFIG_USB_STORAGE=y
 # CONFIG_FAT_WRITE is not set
 CONFIG_BCH=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/am43xx_evm_defconfig b/configs/am43xx_evm_defconfig
index 15c25d3..c694020 100644
--- a/configs/am43xx_evm_defconfig
+++ b/configs/am43xx_evm_defconfig
@@ -3,14 +3,12 @@
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_AM43XX=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="am437x-gp-evm"
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=1"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_HUSH_PARSER=y
@@ -52,7 +50,7 @@
 CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0403
+CONFIG_USB_GADGET_PRODUCT_NUM=0xbd00
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0403
-CONFIG_G_DNL_PRODUCT_NUM=0xbd00
diff --git a/configs/am43xx_evm_ethboot_defconfig b/configs/am43xx_evm_ethboot_defconfig
index 6c17088..7bcec25 100644
--- a/configs/am43xx_evm_ethboot_defconfig
+++ b/configs/am43xx_evm_ethboot_defconfig
@@ -61,8 +61,8 @@
 CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0403
+CONFIG_USB_GADGET_PRODUCT_NUM=0xbd00
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0403
-CONFIG_G_DNL_PRODUCT_NUM=0xbd00
 CONFIG_OF_LIBFDT=y
diff --git a/configs/am43xx_evm_qspiboot_defconfig b/configs/am43xx_evm_qspiboot_defconfig
index fde41c5..e72d435 100644
--- a/configs/am43xx_evm_qspiboot_defconfig
+++ b/configs/am43xx_evm_qspiboot_defconfig
@@ -52,9 +52,9 @@
 CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0403
+CONFIG_USB_GADGET_PRODUCT_NUM=0xbd00
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0403
-CONFIG_G_DNL_PRODUCT_NUM=0xbd00
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/am43xx_evm_usbhost_boot_defconfig b/configs/am43xx_evm_usbhost_boot_defconfig
index 0bed335..02e5a01 100644
--- a/configs/am43xx_evm_usbhost_boot_defconfig
+++ b/configs/am43xx_evm_usbhost_boot_defconfig
@@ -3,14 +3,12 @@
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_AM43XX=y
 CONFIG_ISW_ENTRY_ADDR=0x40300350
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="am437x-gp-evm"
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SYS_EXTRA_OPTIONS="SERIAL1,CONS_INDEX=1"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_SPL_USB_HOST_SUPPORT=y
@@ -75,7 +73,7 @@
 CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0403
+CONFIG_USB_GADGET_PRODUCT_NUM=0xbd00
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0403
-CONFIG_G_DNL_PRODUCT_NUM=0xbd00
diff --git a/configs/am43xx_hs_evm_defconfig b/configs/am43xx_hs_evm_defconfig
index a4d23e1..ab0761b 100644
--- a/configs/am43xx_hs_evm_defconfig
+++ b/configs/am43xx_hs_evm_defconfig
@@ -8,7 +8,6 @@
 CONFIG_TI_SECURE_EMIF_TOTAL_REGION_SIZE=0x02000000
 CONFIG_TI_SECURE_EMIF_PROTECTED_REGION_SIZE=0x01c00000
 CONFIG_ISW_ENTRY_ADDR=0x403018e0
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="am437x-gp-evm"
 CONFIG_FIT_IMAGE_POST_PROCESS=y
 CONFIG_SPL_LOAD_FIT=y
@@ -18,7 +17,6 @@
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_ETH_SUPPORT=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_NET_SUPPORT=y
@@ -63,7 +61,7 @@
 CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0403
+CONFIG_USB_GADGET_PRODUCT_NUM=0xbd00
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0403
-CONFIG_G_DNL_PRODUCT_NUM=0xbd00
diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig
index 0e4679a..da9e61c 100644
--- a/configs/am57xx_evm_defconfig
+++ b/configs/am57xx_evm_defconfig
@@ -7,7 +7,6 @@
 # CONFIG_SPL_NAND_SUPPORT is not set
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_ARMV7_LPAE=y
 CONFIG_DEFAULT_DEVICE_TREE="am572x-idk"
 CONFIG_SPL_LOAD_FIT=y
@@ -19,13 +18,11 @@
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DMA_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x82000000
 CONFIG_FASTBOOT_BUF_SIZE=0x2F000000
 CONFIG_FASTBOOT_USB_DEV=1
@@ -72,7 +69,6 @@
 CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
diff --git a/configs/am57xx_evm_nodt_defconfig b/configs/am57xx_evm_nodt_defconfig
index f963486..88b8bc1 100644
--- a/configs/am57xx_evm_nodt_defconfig
+++ b/configs/am57xx_evm_nodt_defconfig
@@ -15,8 +15,6 @@
 CONFIG_SPL_OS_BOOT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x82000000
 CONFIG_FASTBOOT_BUF_SIZE=0x2F000000
 CONFIG_FASTBOOT_USB_DEV=1
@@ -62,9 +60,8 @@
 CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/am57xx_hs_evm_defconfig b/configs/am57xx_hs_evm_defconfig
index e7638b8..97cc43c 100644
--- a/configs/am57xx_hs_evm_defconfig
+++ b/configs/am57xx_hs_evm_defconfig
@@ -11,7 +11,6 @@
 # CONFIG_SPL_NAND_SUPPORT is not set
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_ARMV7_LPAE=y
 CONFIG_DEFAULT_DEVICE_TREE="am57xx-beagle-x15"
 CONFIG_FIT_IMAGE_POST_PROCESS=y
@@ -25,12 +24,10 @@
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DMA_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x82000000
 CONFIG_FASTBOOT_BUF_SIZE=0x2F000000
 CONFIG_FASTBOOT_USB_DEV=1
@@ -75,7 +72,6 @@
 CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
diff --git a/configs/apalis-tk1_defconfig b/configs/apalis-tk1_defconfig
index e6e3a9b..84e0106 100644
--- a/configs/apalis-tk1_defconfig
+++ b/configs/apalis-tk1_defconfig
@@ -47,9 +47,9 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Toradex"
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
+CONFIG_USB_GADGET_PRODUCT_NUM=0xffff
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Toradex"
-CONFIG_G_DNL_VENDOR_NUM=0x1b67
-CONFIG_G_DNL_PRODUCT_NUM=0xffff
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/apalis_imx6_defconfig b/configs/apalis_imx6_defconfig
index 13f2a3b..57332f5 100644
--- a/configs/apalis_imx6_defconfig
+++ b/configs/apalis_imx6_defconfig
@@ -55,11 +55,11 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Toradex"
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
+CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Toradex"
-CONFIG_G_DNL_VENDOR_NUM=0x1b67
-CONFIG_G_DNL_PRODUCT_NUM=0x4000
 CONFIG_USB_HOST_ETHER=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/apalis_imx6_nospl_com_defconfig b/configs/apalis_imx6_nospl_com_defconfig
index 7165749..60ece90 100644
--- a/configs/apalis_imx6_nospl_com_defconfig
+++ b/configs/apalis_imx6_nospl_com_defconfig
@@ -44,11 +44,11 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Toradex"
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
+CONFIG_USB_GADGET_PRODUCT_NUM=0x4020
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Toradex"
-CONFIG_G_DNL_VENDOR_NUM=0x1b67
-CONFIG_G_DNL_PRODUCT_NUM=0x4020
 CONFIG_USB_HOST_ETHER=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/apalis_imx6_nospl_it_defconfig b/configs/apalis_imx6_nospl_it_defconfig
index 0ad7674..4fd356f 100644
--- a/configs/apalis_imx6_nospl_it_defconfig
+++ b/configs/apalis_imx6_nospl_it_defconfig
@@ -44,11 +44,11 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Toradex"
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
+CONFIG_USB_GADGET_PRODUCT_NUM=0x4020
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Toradex"
-CONFIG_G_DNL_VENDOR_NUM=0x1b67
-CONFIG_G_DNL_PRODUCT_NUM=0x4020
 CONFIG_USB_HOST_ETHER=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/apalis_t30_defconfig b/configs/apalis_t30_defconfig
index e15e11a..588c184 100644
--- a/configs/apalis_t30_defconfig
+++ b/configs/apalis_t30_defconfig
@@ -40,9 +40,9 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Toradex"
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
+CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Toradex"
-CONFIG_G_DNL_VENDOR_NUM=0x1b67
-CONFIG_G_DNL_PRODUCT_NUM=0x4000
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/bananapi_m1_plus_defconfig b/configs/bananapi_m1_plus_defconfig
new file mode 100644
index 0000000..dc4c82f
--- /dev/null
+++ b/configs/bananapi_m1_plus_defconfig
@@ -0,0 +1,24 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_MACH_SUN7I=y
+CONFIG_DRAM_CLK=432
+CONFIG_MACPWR="PH23"
+CONFIG_VIDEO_COMPOSITE=y
+CONFIG_GMAC_TX_DELAY=3
+CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapi-m1-plus"
+CONFIG_AHCI=y
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL=y
+CONFIG_SPL_I2C_SUPPORT=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_ISO_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_NETCONSOLE=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_RGMII=y
+CONFIG_SUN7I_GMAC=y
+CONFIG_SCSI=y
+CONFIG_USB_EHCI_HCD=y
diff --git a/configs/bcm11130_defconfig b/configs/bcm11130_defconfig
index cf3a7cd..4d93975 100644
--- a/configs/bcm11130_defconfig
+++ b/configs/bcm11130_defconfig
@@ -27,9 +27,9 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Broadcom Corporation"
+CONFIG_USB_GADGET_VENDOR_NUM=0x18d1
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0d02
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DWC2_OTG_PHY_BUS_WIDTH_8=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Broadcom Corporation"
-CONFIG_G_DNL_VENDOR_NUM=0x18d1
-CONFIG_G_DNL_PRODUCT_NUM=0x0d02
diff --git a/configs/bcm11130_nand_defconfig b/configs/bcm11130_nand_defconfig
index 2ce9179..555ff05 100644
--- a/configs/bcm11130_nand_defconfig
+++ b/configs/bcm11130_nand_defconfig
@@ -27,9 +27,9 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Broadcom Corporation"
+CONFIG_USB_GADGET_VENDOR_NUM=0x18d1
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0d02
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DWC2_OTG_PHY_BUS_WIDTH_8=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Broadcom Corporation"
-CONFIG_G_DNL_VENDOR_NUM=0x18d1
-CONFIG_G_DNL_PRODUCT_NUM=0x0d02
diff --git a/configs/bcm23550_w1d_defconfig b/configs/bcm23550_w1d_defconfig
index 7091865..f7af02f 100644
--- a/configs/bcm23550_w1d_defconfig
+++ b/configs/bcm23550_w1d_defconfig
@@ -7,8 +7,6 @@
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x80000000
 CONFIG_FASTBOOT_BUF_SIZE=0x1D000000
 CONFIG_FASTBOOT_FLASH=y
@@ -34,11 +32,10 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Broadcom Corporation"
+CONFIG_USB_GADGET_VENDOR_NUM=0x18d1
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0d02
 CONFIG_USB_GADGET_BCM_UDC_OTG_PHY=y
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DWC2_OTG_PHY_BUS_WIDTH_8=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Broadcom Corporation"
-CONFIG_G_DNL_VENDOR_NUM=0x18d1
-CONFIG_G_DNL_PRODUCT_NUM=0x0d02
 CONFIG_OF_LIBFDT=y
diff --git a/configs/bcm28155_ap_defconfig b/configs/bcm28155_ap_defconfig
index db1ad40..2d24200 100644
--- a/configs/bcm28155_ap_defconfig
+++ b/configs/bcm28155_ap_defconfig
@@ -8,8 +8,6 @@
 CONFIG_HUSH_PARSER=y
 # CONFIG_AUTOBOOT is not set
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x80000000
 CONFIG_FASTBOOT_BUF_SIZE=0x7FF00000
 CONFIG_FASTBOOT_FLASH=y
@@ -35,11 +33,10 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Broadcom Corporation"
+CONFIG_USB_GADGET_VENDOR_NUM=0x18d1
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0d02
 CONFIG_USB_GADGET_BCM_UDC_OTG_PHY=y
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DWC2_OTG_PHY_BUS_WIDTH_8=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Broadcom Corporation"
-CONFIG_G_DNL_VENDOR_NUM=0x18d1
-CONFIG_G_DNL_PRODUCT_NUM=0x0d02
 CONFIG_OF_LIBFDT=y
diff --git a/configs/bcm28155_w1d_defconfig b/configs/bcm28155_w1d_defconfig
index 3684fae..8f8668b 100644
--- a/configs/bcm28155_w1d_defconfig
+++ b/configs/bcm28155_w1d_defconfig
@@ -29,9 +29,9 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Broadcom Corporation"
+CONFIG_USB_GADGET_VENDOR_NUM=0x18d1
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0d02
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DWC2_OTG_PHY_BUS_WIDTH_8=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Broadcom Corporation"
-CONFIG_G_DNL_VENDOR_NUM=0x18d1
-CONFIG_G_DNL_PRODUCT_NUM=0x0d02
diff --git a/configs/beaver_defconfig b/configs/beaver_defconfig
index 7fb88e4..ad26354 100644
--- a/configs/beaver_defconfig
+++ b/configs/beaver_defconfig
@@ -45,10 +45,10 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="NVIDIA"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0955
+CONFIG_USB_GADGET_PRODUCT_NUM=0x701a
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="NVIDIA"
-CONFIG_G_DNL_VENDOR_NUM=0x0955
-CONFIG_G_DNL_PRODUCT_NUM=0x701a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
diff --git a/configs/birdland_bav335a_defconfig b/configs/birdland_bav335a_defconfig
index 44f4eac..828bbd1 100644
--- a/configs/birdland_bav335a_defconfig
+++ b/configs/birdland_bav335a_defconfig
@@ -24,8 +24,6 @@
 CONFIG_SPL_YMODEM_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x82000000
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -66,10 +64,9 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
 CONFIG_FAT_WRITE=y
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/birdland_bav335b_defconfig b/configs/birdland_bav335b_defconfig
index 1dffd1a..d851575 100644
--- a/configs/birdland_bav335b_defconfig
+++ b/configs/birdland_bav335b_defconfig
@@ -24,8 +24,6 @@
 CONFIG_SPL_YMODEM_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x82000000
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -66,10 +64,9 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
 CONFIG_FAT_WRITE=y
 CONFIG_LZO=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/cei-tk1-som_defconfig b/configs/cei-tk1-som_defconfig
index 91b5647..a4cd270 100644
--- a/configs/cei-tk1-som_defconfig
+++ b/configs/cei-tk1-som_defconfig
@@ -48,10 +48,10 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="NVIDIA"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0955
+CONFIG_USB_GADGET_PRODUCT_NUM=0x701a
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="NVIDIA"
-CONFIG_G_DNL_VENDOR_NUM=0x0955
-CONFIG_G_DNL_PRODUCT_NUM=0x701a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
diff --git a/configs/cgtqmx6eval_defconfig b/configs/cgtqmx6eval_defconfig
index fc33610..201a331 100644
--- a/configs/cgtqmx6eval_defconfig
+++ b/configs/cgtqmx6eval_defconfig
@@ -24,8 +24,6 @@
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="CGT-QMX6-Quad U-Boot > "
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x12000000
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -57,11 +55,10 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Congatec"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Congatec"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 # CONFIG_VIDEO_SW_CURSOR is not set
diff --git a/configs/chiliboard_defconfig b/configs/chiliboard_defconfig
index ea729b0..d0f6f5f 100644
--- a/configs/chiliboard_defconfig
+++ b/configs/chiliboard_defconfig
@@ -9,12 +9,10 @@
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_BOOTDELAY=1
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_POWER_SUPPORT=y
 CONFIG_HUSH_PARSER=y
diff --git a/configs/chromebit_mickey_defconfig b/configs/chromebit_mickey_defconfig
index f40c0b9..e061b26 100644
--- a/configs/chromebit_mickey_defconfig
+++ b/configs/chromebit_mickey_defconfig
@@ -75,11 +75,10 @@
 CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x320a
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
diff --git a/configs/chromebook_jerry_defconfig b/configs/chromebook_jerry_defconfig
index cdeabaa..2f6b4e5 100644
--- a/configs/chromebook_jerry_defconfig
+++ b/configs/chromebook_jerry_defconfig
@@ -76,11 +76,10 @@
 CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x320a
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
diff --git a/configs/chromebook_minnie_defconfig b/configs/chromebook_minnie_defconfig
index c1e36fa..3b76cb4 100644
--- a/configs/chromebook_minnie_defconfig
+++ b/configs/chromebook_minnie_defconfig
@@ -75,11 +75,10 @@
 CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x320a
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
diff --git a/configs/colibri_imx6_defconfig b/configs/colibri_imx6_defconfig
index 7e10086..9b45811 100644
--- a/configs/colibri_imx6_defconfig
+++ b/configs/colibri_imx6_defconfig
@@ -53,11 +53,11 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Toradex"
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
+CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Toradex"
-CONFIG_G_DNL_VENDOR_NUM=0x1b67
-CONFIG_G_DNL_PRODUCT_NUM=0x4000
 CONFIG_USB_HOST_ETHER=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/colibri_imx6_nospl_defconfig b/configs/colibri_imx6_nospl_defconfig
index ba4b2dd..3204003 100644
--- a/configs/colibri_imx6_nospl_defconfig
+++ b/configs/colibri_imx6_nospl_defconfig
@@ -42,11 +42,11 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Toradex"
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
+CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Toradex"
-CONFIG_G_DNL_VENDOR_NUM=0x1b67
-CONFIG_G_DNL_PRODUCT_NUM=0x4000
 CONFIG_USB_HOST_ETHER=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/colibri_imx7_defconfig b/configs/colibri_imx7_defconfig
index d0b6c68..56ae867 100644
--- a/configs/colibri_imx7_defconfig
+++ b/configs/colibri_imx7_defconfig
@@ -56,10 +56,10 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Toradex"
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
+CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Toradex"
-CONFIG_G_DNL_VENDOR_NUM=0x1b67
-CONFIG_G_DNL_PRODUCT_NUM=0x4000
 CONFIG_OF_LIBFDT_OVERLAY=y
 CONFIG_FDT_FIXUP_PARTITIONS=y
diff --git a/configs/colibri_t20_defconfig b/configs/colibri_t20_defconfig
index 0b5604c..786d50b 100644
--- a/configs/colibri_t20_defconfig
+++ b/configs/colibri_t20_defconfig
@@ -47,11 +47,11 @@
 CONFIG_USB_ULPI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Toradex"
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
+CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Toradex"
-CONFIG_G_DNL_VENDOR_NUM=0x1b67
-CONFIG_G_DNL_PRODUCT_NUM=0x4000
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_DM_VIDEO=y
diff --git a/configs/colibri_t30_defconfig b/configs/colibri_t30_defconfig
index 65fa90f..1601aa6 100644
--- a/configs/colibri_t30_defconfig
+++ b/configs/colibri_t30_defconfig
@@ -34,11 +34,11 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Toradex"
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
+CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Toradex"
-CONFIG_G_DNL_VENDOR_NUM=0x1b67
-CONFIG_G_DNL_PRODUCT_NUM=0x4000
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/colibri_vf_defconfig b/configs/colibri_vf_defconfig
index 1ffe861..d3547db 100644
--- a/configs/colibri_vf_defconfig
+++ b/configs/colibri_vf_defconfig
@@ -6,6 +6,7 @@
 CONFIG_DEFAULT_DEVICE_TREE="vf610-colibri"
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/toradex/colibri_vf/imximage.cfg,IMX_NAND"
 CONFIG_BOOTDELAY=1
+CONFIG_LOGLEVEL=3
 CONFIG_VERSION_VARIABLE=y
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_ARCH_MISC_INIT=y
@@ -53,11 +54,11 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Toradex"
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
+CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Toradex"
-CONFIG_G_DNL_VENDOR_NUM=0x1b67
-CONFIG_G_DNL_PRODUCT_NUM=0x4000
 CONFIG_VIDEO_FSL_DCU_FB=y
 CONFIG_SYS_CONSOLE_FG_COL=0x00
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/corvus_defconfig b/configs/corvus_defconfig
index 705e001..066dc38 100644
--- a/configs/corvus_defconfig
+++ b/configs/corvus_defconfig
@@ -49,9 +49,9 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0908
+CONFIG_USB_GADGET_PRODUCT_NUM=0x02d2
 CONFIG_USB_GADGET_ATMEL_USBA=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Siemens AG"
-CONFIG_G_DNL_VENDOR_NUM=0x0908
-CONFIG_G_DNL_PRODUCT_NUM=0x02d2
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/da850_am18xxevm_defconfig b/configs/da850_am18xxevm_defconfig
index 27370e7..0c60fef 100644
--- a/configs/da850_am18xxevm_defconfig
+++ b/configs/da850_am18xxevm_defconfig
@@ -1,17 +1,16 @@
 CONFIG_ARM=y
 CONFIG_ARCH_DAVINCI=y
 CONFIG_TARGET_DA850EVM=y
-CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_MAC_ADDR_IN_EEPROM=y
+CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_DEFAULT_DEVICE_TREE="da850-evm"
 CONFIG_SYS_EXTRA_OPTIONS="DA850_AM18X_EVM,SYS_I2C_EEPROM_ADDR_LEN=2,SYS_I2C_EEPROM_ADDR=0x50"
 CONFIG_BOOTDELAY=3
-CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="mem=32M console=ttyS2,115200n8 root=/dev/mtdblock2 rw noinitrd ip=dhcp"
 CONFIG_VERSION_VARIABLE=y
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
@@ -19,24 +18,29 @@
 CONFIG_SPL=y
 CONFIG_SPL_BOARD_INIT=y
 CONFIG_HUSH_PARSER=y
-# CONFIG_CMD_BOOTZ is not set
+CONFIG_SYS_PROMPT="U-Boot > "
 # CONFIG_CMD_IMLS is not set
 CONFIG_CRC32_VERIFY=y
 # CONFIG_CMD_EEPROM is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_GPIO is not set
 # CONFIG_CMD_GPT is not set
-# CONFIG_CMD_I2C is not set
 # CONFIG_CMD_PART is not set
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_TIME is not set
 # CONFIG_CMD_EXT4 is not set
 # CONFIG_CMD_FS_GENERIC is not set
 CONFIG_CMD_DIAG=y
+CONFIG_OF_CONTROL=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_DM=y
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
+CONFIG_DM_SPI=y
 # CONFIG_FAT_WRITE is not set
-CONFIG_OF_LIBFDT=y
diff --git a/configs/da850evm_defconfig b/configs/da850evm_defconfig
index bfa5ea1..d6eb4a5 100644
--- a/configs/da850evm_defconfig
+++ b/configs/da850evm_defconfig
@@ -7,9 +7,9 @@
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_DEFAULT_DEVICE_TREE="da850-evm"
+CONFIG_SYS_EXTRA_OPTIONS="MAC_ADDR_IN_SPIFLASH"
 CONFIG_BOOTDELAY=3
-CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="mem=32M console=ttyS2,115200n8 root=/dev/mtdblock2 rw noinitrd ip=dhcp"
 CONFIG_VERSION_VARIABLE=y
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
@@ -24,17 +24,24 @@
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_GPIO is not set
 # CONFIG_CMD_GPT is not set
-# CONFIG_CMD_I2C is not set
 # CONFIG_CMD_PART is not set
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_TIME is not set
 # CONFIG_CMD_EXT4 is not set
 # CONFIG_CMD_FS_GENERIC is not set
+CONFIG_CMD_MTDPARTS=y
 CONFIG_CMD_DIAG=y
+CONFIG_OF_CONTROL=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_DM=y
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
+CONFIG_DM_SPI=y
 # CONFIG_FAT_WRITE is not set
-CONFIG_OF_LIBFDT=y
diff --git a/configs/da850evm_direct_nor_defconfig b/configs/da850evm_direct_nor_defconfig
index 24ab892..3c8e7ad 100644
--- a/configs/da850evm_direct_nor_defconfig
+++ b/configs/da850evm_direct_nor_defconfig
@@ -2,6 +2,8 @@
 CONFIG_ARCH_DAVINCI=y
 CONFIG_TARGET_DA850EVM=y
 CONFIG_TI_COMMON_CMD_OPTIONS=y
+CONFIG_DEFAULT_DEVICE_TREE="da850-evm"
+# CONFIG_SYS_MALLOC_F is not set
 CONFIG_SYS_EXTRA_OPTIONS="USE_NOR,DIRECT_NOR_BOOT"
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTARGS=y
@@ -17,7 +19,6 @@
 # CONFIG_CMD_EEPROM is not set
 # CONFIG_CMD_GPIO is not set
 # CONFIG_CMD_GPT is not set
-# CONFIG_CMD_I2C is not set
 # CONFIG_CMD_MMC is not set
 # CONFIG_CMD_PART is not set
 # CONFIG_CMD_SPI is not set
@@ -28,11 +29,16 @@
 # CONFIG_CMD_FAT is not set
 # CONFIG_CMD_FS_GENERIC is not set
 CONFIG_CMD_DIAG=y
+CONFIG_OF_CONTROL=y
 CONFIG_ENV_IS_IN_FLASH=y
+CONFIG_DM=y
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_COMPAT=y
 # CONFIG_MMC is not set
 CONFIG_MTD_NOR_FLASH=y
+CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SYS_NS16550=y
-CONFIG_OF_LIBFDT=y
+CONFIG_DM_SPI=y
diff --git a/configs/dalmore_defconfig b/configs/dalmore_defconfig
index ba3d478..caf998b 100644
--- a/configs/dalmore_defconfig
+++ b/configs/dalmore_defconfig
@@ -39,10 +39,10 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="NVIDIA"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0955
+CONFIG_USB_GADGET_PRODUCT_NUM=0x701a
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="NVIDIA"
-CONFIG_G_DNL_VENDOR_NUM=0x0955
-CONFIG_G_DNL_PRODUCT_NUM=0x701a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
diff --git a/configs/dms-ba16-1g_defconfig b/configs/dms-ba16-1g_defconfig
index 2342f34..352ab04 100644
--- a/configs/dms-ba16-1g_defconfig
+++ b/configs/dms-ba16-1g_defconfig
@@ -38,10 +38,10 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Advantech"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Advantech"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 # CONFIG_VIDEO_SW_CURSOR is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/dms-ba16_defconfig b/configs/dms-ba16_defconfig
index 08d96ad..8a38c8d 100644
--- a/configs/dms-ba16_defconfig
+++ b/configs/dms-ba16_defconfig
@@ -37,10 +37,10 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Advantech"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Advantech"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 # CONFIG_VIDEO_SW_CURSOR is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig
index 53903bf..468c288 100644
--- a/configs/dra7xx_evm_defconfig
+++ b/configs/dra7xx_evm_defconfig
@@ -7,7 +7,6 @@
 # CONFIG_SPL_NAND_SUPPORT is not set
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_ARMV7_LPAE=y
 CONFIG_DEFAULT_DEVICE_TREE="dra7-evm"
 CONFIG_SPL_LOAD_FIT=y
@@ -19,13 +18,11 @@
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DMA_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x82000000
 CONFIG_FASTBOOT_BUF_SIZE=0x2F000000
 CONFIG_FASTBOOT_FLASH=y
@@ -90,7 +87,6 @@
 CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig
index 06d8834..66d347d 100644
--- a/configs/dra7xx_hs_evm_defconfig
+++ b/configs/dra7xx_hs_evm_defconfig
@@ -11,7 +11,6 @@
 # CONFIG_SPL_NAND_SUPPORT is not set
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_ARMV7_LPAE=y
 CONFIG_DEFAULT_DEVICE_TREE="dra7-evm"
 CONFIG_FIT_IMAGE_POST_PROCESS=y
@@ -25,12 +24,10 @@
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DMA_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x82000000
 CONFIG_FASTBOOT_BUF_SIZE=0x2F000000
 CONFIG_FASTBOOT_FLASH=y
@@ -92,7 +89,6 @@
 CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
diff --git a/configs/draco_defconfig b/configs/draco_defconfig
index f5a2c1b..de2961b 100644
--- a/configs/draco_defconfig
+++ b/configs/draco_defconfig
@@ -66,7 +66,8 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0908
+CONFIG_USB_GADGET_PRODUCT_NUM=0x02d2
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Siemens AG"
-CONFIG_G_DNL_VENDOR_NUM=0x0908
-CONFIG_G_DNL_PRODUCT_NUM=0x02d2
+CONFIG_USB_ETHER=y
diff --git a/configs/e2220-1170_defconfig b/configs/e2220-1170_defconfig
index 4124818..2670512 100644
--- a/configs/e2220-1170_defconfig
+++ b/configs/e2220-1170_defconfig
@@ -35,8 +35,8 @@
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="NVIDIA"
-CONFIG_G_DNL_VENDOR_NUM=0x0955
-CONFIG_G_DNL_PRODUCT_NUM=0x701a
+CONFIG_USB_GADGET_MANUFACTURER="NVIDIA"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0955
+CONFIG_USB_GADGET_PRODUCT_NUM=0x701a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
diff --git a/configs/edison_defconfig b/configs/edison_defconfig
index d58700c..d3b67c3 100644
--- a/configs/edison_defconfig
+++ b/configs/edison_defconfig
@@ -33,9 +33,9 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Intel"
-CONFIG_G_DNL_VENDOR_NUM=0x8087
-CONFIG_G_DNL_PRODUCT_NUM=0x0a99
+CONFIG_USB_GADGET_MANUFACTURER="Intel"
+CONFIG_USB_GADGET_VENDOR_NUM=0x8087
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0a99
 # CONFIG_USB_HOST_ETHER is not set
 CONFIG_FAT_WRITE=y
 CONFIG_SHA1=y
diff --git a/configs/etamin_defconfig b/configs/etamin_defconfig
index 148d421..7055989 100644
--- a/configs/etamin_defconfig
+++ b/configs/etamin_defconfig
@@ -66,7 +66,8 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0908
+CONFIG_USB_GADGET_PRODUCT_NUM=0x02d2
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Siemens AG"
-CONFIG_G_DNL_VENDOR_NUM=0x0908
-CONFIG_G_DNL_PRODUCT_NUM=0x02d2
+CONFIG_USB_ETHER=y
diff --git a/configs/evb-rk3036_defconfig b/configs/evb-rk3036_defconfig
index 5a53951..f2c4d8c 100644
--- a/configs/evb-rk3036_defconfig
+++ b/configs/evb-rk3036_defconfig
@@ -44,11 +44,10 @@
 CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x310a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x310a
 CONFIG_SPL_TINY_MEMSET=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/evb-rk3229_defconfig b/configs/evb-rk3229_defconfig
index 5a658a1..2bc9f4a 100644
--- a/configs/evb-rk3229_defconfig
+++ b/configs/evb-rk3229_defconfig
@@ -44,9 +44,8 @@
 CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x320a
 CONFIG_ERRNO_STR=y
diff --git a/configs/evb-rk3288_defconfig b/configs/evb-rk3288_defconfig
index 5294ba9..d8dadd7 100644
--- a/configs/evb-rk3288_defconfig
+++ b/configs/evb-rk3288_defconfig
@@ -66,11 +66,10 @@
 CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x320a
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig
index 7bec001..d73c931 100644
--- a/configs/evb-rk3328_defconfig
+++ b/configs/evb-rk3328_defconfig
@@ -22,12 +22,18 @@
 CONFIG_SYSCON=y
 CONFIG_CLK=y
 CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_ROCKCHIP_RK3328=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_DM_REGULATOR=y
 CONFIG_REGULATOR_PWM=y
 CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
 CONFIG_BAUDRATE=1500000
 CONFIG_DEBUG_UART_BASE=0xFF130000
@@ -47,8 +53,8 @@
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x330a
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x330a
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/evb-rv1108_defconfig b/configs/evb-rv1108_defconfig
index 7036f43..f035066 100644
--- a/configs/evb-rv1108_defconfig
+++ b/configs/evb-rv1108_defconfig
@@ -13,6 +13,7 @@
 CONFIG_FASTBOOT_FLASH=y
 CONFIG_FASTBOOT_FLASH_MMC_DEV=1
 # CONFIG_CMD_IMLS is not set
+CONFIG_RANDOM_UUID=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
@@ -51,7 +52,7 @@
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x110a
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x110a
 CONFIG_ERRNO_STR=y
diff --git a/configs/fennec-rk3288_defconfig b/configs/fennec-rk3288_defconfig
index 96a07de..adc3f7a 100644
--- a/configs/fennec-rk3288_defconfig
+++ b/configs/fennec-rk3288_defconfig
@@ -69,11 +69,10 @@
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x320a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/firefly-rk3288_defconfig b/configs/firefly-rk3288_defconfig
index 178c879..d092d60 100644
--- a/configs/firefly-rk3288_defconfig
+++ b/configs/firefly-rk3288_defconfig
@@ -74,11 +74,10 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x320a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/gwventana_emmc_defconfig b/configs/gwventana_emmc_defconfig
index 74aa2ef..eeb7958 100644
--- a/configs/gwventana_emmc_defconfig
+++ b/configs/gwventana_emmc_defconfig
@@ -63,11 +63,13 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Gateworks"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Gateworks"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/gwventana_gw5904_defconfig b/configs/gwventana_gw5904_defconfig
index 7bbdd50..75a07c5 100644
--- a/configs/gwventana_gw5904_defconfig
+++ b/configs/gwventana_gw5904_defconfig
@@ -67,11 +67,13 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Gateworks"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Gateworks"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/gwventana_nand_defconfig b/configs/gwventana_nand_defconfig
index aaedf93..1819b9f 100644
--- a/configs/gwventana_nand_defconfig
+++ b/configs/gwventana_nand_defconfig
@@ -66,11 +66,13 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Gateworks"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Gateworks"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/h2200_defconfig b/configs/h2200_defconfig
index 5d2189e..8b4deae 100644
--- a/configs/h2200_defconfig
+++ b/configs/h2200_defconfig
@@ -29,3 +29,6 @@
 # CONFIG_CMD_MISC is not set
 # CONFIG_MMC is not set
 CONFIG_PXA_SERIAL=y
+CONFIG_USB=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETHER=y
diff --git a/configs/jetson-tk1_defconfig b/configs/jetson-tk1_defconfig
index 1e3e4be..f40f6ae 100644
--- a/configs/jetson-tk1_defconfig
+++ b/configs/jetson-tk1_defconfig
@@ -49,10 +49,10 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="NVIDIA"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0955
+CONFIG_USB_GADGET_PRODUCT_NUM=0x701a
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="NVIDIA"
-CONFIG_G_DNL_VENDOR_NUM=0x0955
-CONFIG_G_DNL_PRODUCT_NUM=0x701a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
diff --git a/configs/k2e_evm_defconfig b/configs/k2e_evm_defconfig
index fed6add..b6a5282 100644
--- a/configs/k2e_evm_defconfig
+++ b/configs/k2e_evm_defconfig
@@ -12,7 +12,7 @@
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_DTB_RESELECT=y
-CONFIG_FIT_EMBED=y
+CONFIG_MULTI_DTB_FIT=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
diff --git a/configs/k2g_evm_defconfig b/configs/k2g_evm_defconfig
index 2b29bf4..9c8b66d 100644
--- a/configs/k2g_evm_defconfig
+++ b/configs/k2g_evm_defconfig
@@ -12,7 +12,7 @@
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_DTB_RESELECT=y
-CONFIG_FIT_EMBED=y
+CONFIG_MULTI_DTB_FIT=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
diff --git a/configs/k2hk_evm_defconfig b/configs/k2hk_evm_defconfig
index 80546ec..bfb95ab 100644
--- a/configs/k2hk_evm_defconfig
+++ b/configs/k2hk_evm_defconfig
@@ -12,7 +12,7 @@
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_DTB_RESELECT=y
-CONFIG_FIT_EMBED=y
+CONFIG_MULTI_DTB_FIT=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
diff --git a/configs/k2l_evm_defconfig b/configs/k2l_evm_defconfig
index 732c9d2..7ab0d47 100644
--- a/configs/k2l_evm_defconfig
+++ b/configs/k2l_evm_defconfig
@@ -12,7 +12,7 @@
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_DTB_RESELECT=y
-CONFIG_FIT_EMBED=y
+CONFIG_MULTI_DTB_FIT=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
diff --git a/configs/kc1_defconfig b/configs/kc1_defconfig
index d9c2efc..87b3eec 100644
--- a/configs/kc1_defconfig
+++ b/configs/kc1_defconfig
@@ -12,8 +12,6 @@
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="kc1 # "
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x82000000
 CONFIG_FASTBOOT_BUF_SIZE=0x2000000
 CONFIG_FASTBOOT_FLASH=y
@@ -42,8 +40,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
 CONFIG_OF_LIBFDT=y
diff --git a/configs/kylin-rk3036_defconfig b/configs/kylin-rk3036_defconfig
index a42f5e0..5adf577 100644
--- a/configs/kylin-rk3036_defconfig
+++ b/configs/kylin-rk3036_defconfig
@@ -44,11 +44,10 @@
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x310a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x310a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/lion-rk3368_defconfig b/configs/lion-rk3368_defconfig
index c7ee7b3..985fb1c 100644
--- a/configs/lion-rk3368_defconfig
+++ b/configs/lion-rk3368_defconfig
@@ -23,7 +23,6 @@
 CONFIG_SPL_BOOTSTAGE=y
 CONFIG_BOOTSTAGE_REPORT=y
 CONFIG_BOOTSTAGE_FDT=y
-CONFIG_ENV_IS_IN_MMC=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_ARCH_EARLY_INIT_R=y
 CONFIG_SPL=y
diff --git a/configs/ma5d4evk_defconfig b/configs/ma5d4evk_defconfig
index cbe76b6..9e03b7c 100644
--- a/configs/ma5d4evk_defconfig
+++ b/configs/ma5d4evk_defconfig
@@ -47,11 +47,12 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="AriesEmbedded"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_USB_GADGET_ATMEL_USBA=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="AriesEmbedded"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_ETHER=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/miqi-rk3288_defconfig b/configs/miqi-rk3288_defconfig
index b0437e1..e5d1b75 100644
--- a/configs/miqi-rk3288_defconfig
+++ b/configs/miqi-rk3288_defconfig
@@ -69,11 +69,10 @@
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x320a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/mx6qsabrelite_defconfig b/configs/mx6qsabrelite_defconfig
index 57aba7e..3dfe25e 100644
--- a/configs/mx6qsabrelite_defconfig
+++ b/configs/mx6qsabrelite_defconfig
@@ -10,8 +10,6 @@
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x12000000
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -49,10 +47,11 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Boundary"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Boundary"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
 # CONFIG_VIDEO_SW_CURSOR is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/mx6sabreauto_defconfig b/configs/mx6sabreauto_defconfig
index 8283189..2e375c3 100644
--- a/configs/mx6sabreauto_defconfig
+++ b/configs/mx6sabreauto_defconfig
@@ -48,11 +48,11 @@
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="FSL"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="FSL"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 # CONFIG_VIDEO_SW_CURSOR is not set
diff --git a/configs/mx6sabresd_defconfig b/configs/mx6sabresd_defconfig
index ad5d448..29f21be 100644
--- a/configs/mx6sabresd_defconfig
+++ b/configs/mx6sabresd_defconfig
@@ -52,11 +52,11 @@
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="FSL"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="FSL"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 # CONFIG_VIDEO_SW_CURSOR is not set
diff --git a/configs/mx7dsabresd_defconfig b/configs/mx7dsabresd_defconfig
index 795c4f2..26250fd 100644
--- a/configs/mx7dsabresd_defconfig
+++ b/configs/mx7dsabresd_defconfig
@@ -64,11 +64,11 @@
 CONFIG_MXC_USB_OTG_HACTIVE=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="FSL"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="FSL"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/mx7dsabresd_secure_defconfig b/configs/mx7dsabresd_secure_defconfig
index bd68831..970f821 100644
--- a/configs/mx7dsabresd_secure_defconfig
+++ b/configs/mx7dsabresd_secure_defconfig
@@ -66,11 +66,11 @@
 CONFIG_MXC_USB_OTG_HACTIVE=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="FSL"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="FSL"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/nitrogen6dl2g_defconfig b/configs/nitrogen6dl2g_defconfig
index 50e6b70..32c6eea 100644
--- a/configs/nitrogen6dl2g_defconfig
+++ b/configs/nitrogen6dl2g_defconfig
@@ -10,8 +10,6 @@
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x12000000
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -46,10 +44,11 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Boundary"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Boundary"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
 # CONFIG_VIDEO_SW_CURSOR is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/nitrogen6dl_defconfig b/configs/nitrogen6dl_defconfig
index 61e5ea4..8ce2515 100644
--- a/configs/nitrogen6dl_defconfig
+++ b/configs/nitrogen6dl_defconfig
@@ -10,8 +10,6 @@
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x12000000
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -46,10 +44,11 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Boundary"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Boundary"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
 # CONFIG_VIDEO_SW_CURSOR is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/nitrogen6q2g_defconfig b/configs/nitrogen6q2g_defconfig
index 9dbb718..1c149b5 100644
--- a/configs/nitrogen6q2g_defconfig
+++ b/configs/nitrogen6q2g_defconfig
@@ -10,8 +10,6 @@
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x12000000
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -47,10 +45,11 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Boundary"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Boundary"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
 # CONFIG_VIDEO_SW_CURSOR is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/nitrogen6q_defconfig b/configs/nitrogen6q_defconfig
index 5478390..29e59fd 100644
--- a/configs/nitrogen6q_defconfig
+++ b/configs/nitrogen6q_defconfig
@@ -10,8 +10,6 @@
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x12000000
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -47,10 +45,11 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Boundary"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Boundary"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
 # CONFIG_VIDEO_SW_CURSOR is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/nitrogen6s1g_defconfig b/configs/nitrogen6s1g_defconfig
index 0188168..a06d6e1 100644
--- a/configs/nitrogen6s1g_defconfig
+++ b/configs/nitrogen6s1g_defconfig
@@ -10,8 +10,6 @@
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x12000000
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -46,10 +44,11 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Boundary"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Boundary"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
 # CONFIG_VIDEO_SW_CURSOR is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/nitrogen6s_defconfig b/configs/nitrogen6s_defconfig
index 51f1f91..a7a54bb 100644
--- a/configs/nitrogen6s_defconfig
+++ b/configs/nitrogen6s_defconfig
@@ -10,8 +10,6 @@
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_HUSH_PARSER=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x12000000
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -46,10 +44,11 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Boundary"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Boundary"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
 # CONFIG_VIDEO_SW_CURSOR is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/novena_defconfig b/configs/novena_defconfig
index 2921525..a7056ff 100644
--- a/configs/novena_defconfig
+++ b/configs/novena_defconfig
@@ -48,6 +48,8 @@
 CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig
index 29d918d..ba9d8f5 100644
--- a/configs/nyan-big_defconfig
+++ b/configs/nyan-big_defconfig
@@ -65,11 +65,11 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="NVIDIA"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0955
+CONFIG_USB_GADGET_PRODUCT_NUM=0x701a
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="NVIDIA"
-CONFIG_G_DNL_VENDOR_NUM=0x0955
-CONFIG_G_DNL_PRODUCT_NUM=0x701a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_DM_VIDEO=y
diff --git a/configs/odroid-xu3_defconfig b/configs/odroid-xu3_defconfig
index a5e47c8..ab7f8bd 100644
--- a/configs/odroid-xu3_defconfig
+++ b/configs/odroid-xu3_defconfig
@@ -43,10 +43,10 @@
 CONFIG_USB_DWC3_PHY_SAMSUNG=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Samsung"
+CONFIG_USB_GADGET_VENDOR_NUM=0x04e8
+CONFIG_USB_GADGET_PRODUCT_NUM=0x6601
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Samsung"
-CONFIG_G_DNL_VENDOR_NUM=0x04e8
-CONFIG_G_DNL_PRODUCT_NUM=0x6601
 CONFIG_USB_HOST_ETHER=y
 CONFIG_VIDEO_BRIDGE=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/odroid_defconfig b/configs/odroid_defconfig
index 0dc1a25..ddac08c 100644
--- a/configs/odroid_defconfig
+++ b/configs/odroid_defconfig
@@ -56,11 +56,11 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Samsung"
+CONFIG_USB_GADGET_VENDOR_NUM=0x04e8
+CONFIG_USB_GADGET_PRODUCT_NUM=0x6601
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Samsung"
-CONFIG_G_DNL_VENDOR_NUM=0x04e8
-CONFIG_G_DNL_PRODUCT_NUM=0x6601
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_SMSC95XX=y
 CONFIG_ERRNO_STR=y
diff --git a/configs/omap3_beagle_defconfig b/configs/omap3_beagle_defconfig
index cf888f3..024e356 100644
--- a/configs/omap3_beagle_defconfig
+++ b/configs/omap3_beagle_defconfig
@@ -9,8 +9,6 @@
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x82000000
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_SPL=y
@@ -48,10 +46,10 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="TI"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="TI"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
+CONFIG_USB_ETHER=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_MCS7830=y
diff --git a/configs/omap3_evm_defconfig b/configs/omap3_evm_defconfig
index 962ffa0..0c5e5ca 100644
--- a/configs/omap3_evm_defconfig
+++ b/configs/omap3_evm_defconfig
@@ -5,7 +5,6 @@
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_SYS_MPUCLK=720
 CONFIG_TARGET_OMAP3_EVM=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BOOTDELAY=3
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
@@ -13,7 +12,6 @@
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 # CONFIG_SPL_EXT_SUPPORT is not set
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SYS_PROMPT="OMAP3_EVM # "
@@ -52,10 +50,11 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0x5678
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0x5678
+CONFIG_USB_ETHER=y
 CONFIG_FAT_WRITE=y
 CONFIG_BCH=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/omap3_logic_defconfig b/configs/omap3_logic_defconfig
index b8f2588..bd5caff 100644
--- a/configs/omap3_logic_defconfig
+++ b/configs/omap3_logic_defconfig
@@ -3,19 +3,16 @@
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_TARGET_OMAP3_LOGIC=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_DEFAULT_DEVICE_TREE="logicpd-torpedo-37xx-devkit"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="OMAP Logic # "
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x82000000
 # CONFIG_CMD_IMI is not set
 # CONFIG_CMD_IMLS is not set
@@ -46,8 +43,8 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="TI"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="TI"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
+CONFIG_USB_ETHER=y
 CONFIG_BCH=y
diff --git a/configs/omap3_overo_defconfig b/configs/omap3_overo_defconfig
index 5d1cbe9..4043c42 100644
--- a/configs/omap3_overo_defconfig
+++ b/configs/omap3_overo_defconfig
@@ -2,12 +2,10 @@
 CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_TARGET_OMAP3_OVERO=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_SPL=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
 CONFIG_HUSH_PARSER=y
diff --git a/configs/omap5_uevm_defconfig b/configs/omap5_uevm_defconfig
index 6e860ef..e229575 100644
--- a/configs/omap5_uevm_defconfig
+++ b/configs/omap5_uevm_defconfig
@@ -49,10 +49,10 @@
 CONFIG_USB_DWC3_PHY_OMAP=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0403
+CONFIG_USB_GADGET_PRODUCT_NUM=0xbd00
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0403
-CONFIG_G_DNL_PRODUCT_NUM=0xbd00
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_SMSC95XX=y
 CONFIG_FAT_WRITE=y
diff --git a/configs/openrd_base_defconfig b/configs/openrd_base_defconfig
index b2a0e04..f31af1c 100644
--- a/configs/openrd_base_defconfig
+++ b/configs/openrd_base_defconfig
@@ -5,6 +5,7 @@
 CONFIG_IDENT_STRING="\nOpenRD-Base"
 CONFIG_SYS_EXTRA_OPTIONS="BOARD_IS_OPENRD_BASE"
 CONFIG_BOOTDELAY=3
+CONFIG_LOGLEVEL=3
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/openrd_client_defconfig b/configs/openrd_client_defconfig
index 8b1d35e..bee818b 100644
--- a/configs/openrd_client_defconfig
+++ b/configs/openrd_client_defconfig
@@ -5,6 +5,7 @@
 CONFIG_IDENT_STRING="\nOpenRD-Client"
 CONFIG_SYS_EXTRA_OPTIONS="BOARD_IS_OPENRD_CLIENT"
 CONFIG_BOOTDELAY=3
+CONFIG_LOGLEVEL=3
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/openrd_ultimate_defconfig b/configs/openrd_ultimate_defconfig
index 4cc0205..e9462e5 100644
--- a/configs/openrd_ultimate_defconfig
+++ b/configs/openrd_ultimate_defconfig
@@ -5,6 +5,7 @@
 CONFIG_IDENT_STRING="\nOpenRD-Ultimate"
 CONFIG_SYS_EXTRA_OPTIONS="BOARD_IS_OPENRD_ULTIMATE"
 CONFIG_BOOTDELAY=3
+CONFIG_LOGLEVEL=3
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/opos6uldev_defconfig b/configs/opos6uldev_defconfig
index a880c62..0c23192 100644
--- a/configs/opos6uldev_defconfig
+++ b/configs/opos6uldev_defconfig
@@ -79,10 +79,10 @@
 CONFIG_DM_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Armadeus Systems"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Armadeus Systems"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_OF_LIBFDT_OVERLAY=y
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/origen_defconfig b/configs/origen_defconfig
index 298e7a4..013eec1 100644
--- a/configs/origen_defconfig
+++ b/configs/origen_defconfig
@@ -41,8 +41,8 @@
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Samsung"
+CONFIG_USB_GADGET_VENDOR_NUM=0x04e8
+CONFIG_USB_GADGET_PRODUCT_NUM=0x6601
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Samsung"
-CONFIG_G_DNL_VENDOR_NUM=0x04e8
-CONFIG_G_DNL_PRODUCT_NUM=0x6601
diff --git a/configs/p2371-0000_defconfig b/configs/p2371-0000_defconfig
index e499b82..e186526 100644
--- a/configs/p2371-0000_defconfig
+++ b/configs/p2371-0000_defconfig
@@ -36,8 +36,8 @@
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="NVIDIA"
-CONFIG_G_DNL_VENDOR_NUM=0x0955
-CONFIG_G_DNL_PRODUCT_NUM=0x701a
+CONFIG_USB_GADGET_MANUFACTURER="NVIDIA"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0955
+CONFIG_USB_GADGET_PRODUCT_NUM=0x701a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
diff --git a/configs/p2371-2180_defconfig b/configs/p2371-2180_defconfig
index 3330d23..6713564 100644
--- a/configs/p2371-2180_defconfig
+++ b/configs/p2371-2180_defconfig
@@ -43,8 +43,8 @@
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="NVIDIA"
-CONFIG_G_DNL_VENDOR_NUM=0x0955
-CONFIG_G_DNL_PRODUCT_NUM=0x701a
+CONFIG_USB_GADGET_MANUFACTURER="NVIDIA"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0955
+CONFIG_USB_GADGET_PRODUCT_NUM=0x701a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
diff --git a/configs/p2571_defconfig b/configs/p2571_defconfig
index 9259c13..ae896bd 100644
--- a/configs/p2571_defconfig
+++ b/configs/p2571_defconfig
@@ -36,8 +36,8 @@
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="NVIDIA"
-CONFIG_G_DNL_VENDOR_NUM=0x0955
-CONFIG_G_DNL_PRODUCT_NUM=0x701a
+CONFIG_USB_GADGET_MANUFACTURER="NVIDIA"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0955
+CONFIG_USB_GADGET_PRODUCT_NUM=0x701a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
diff --git a/configs/parrot_r16_defconfig b/configs/parrot_r16_defconfig
index 53825eb..d6bc89c 100644
--- a/configs/parrot_r16_defconfig
+++ b/configs/parrot_r16_defconfig
@@ -13,7 +13,6 @@
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL=y
 CONFIG_FASTBOOT_FLASH=y
-CONFIG_FASTBOOT_FLASH_MMC_DEV=0
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_FPGA is not set
@@ -23,8 +22,3 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Allwinner Technology"
-CONFIG_G_DNL_VENDOR_NUM=0x1f3a
-CONFIG_G_DNL_PRODUCT_NUM=0x1010
diff --git a/configs/pcm051_rev1_defconfig b/configs/pcm051_rev1_defconfig
index 1683f88..9b325d4 100644
--- a/configs/pcm051_rev1_defconfig
+++ b/configs/pcm051_rev1_defconfig
@@ -60,5 +60,6 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_ETHER=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/pcm051_rev3_defconfig b/configs/pcm051_rev3_defconfig
index d082bb4..14211ec 100644
--- a/configs/pcm051_rev3_defconfig
+++ b/configs/pcm051_rev3_defconfig
@@ -60,5 +60,6 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_ETHER=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/phycore-rk3288_defconfig b/configs/phycore-rk3288_defconfig
index 93ee353..f9a53fc 100644
--- a/configs/phycore-rk3288_defconfig
+++ b/configs/phycore-rk3288_defconfig
@@ -72,11 +72,10 @@
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x320a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/pico-imx6ul_defconfig b/configs/pico-imx6ul_defconfig
index abafc65..c213493 100644
--- a/configs/pico-imx6ul_defconfig
+++ b/configs/pico-imx6ul_defconfig
@@ -32,9 +32,9 @@
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="FSL"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="FSL"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_OF_LIBFDT=y
diff --git a/configs/pico-imx7d_defconfig b/configs/pico-imx7d_defconfig
index 114c397..d34e6ce 100644
--- a/configs/pico-imx7d_defconfig
+++ b/configs/pico-imx7d_defconfig
@@ -28,9 +28,9 @@
 CONFIG_MXC_USB_OTG_HACTIVE=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="FSL"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="FSL"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_OF_LIBFDT=y
diff --git a/configs/popmetal-rk3288_defconfig b/configs/popmetal-rk3288_defconfig
index 5e99f9c..5e592e6 100644
--- a/configs/popmetal-rk3288_defconfig
+++ b/configs/popmetal-rk3288_defconfig
@@ -69,11 +69,10 @@
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x320a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/puma-rk3399_defconfig b/configs/puma-rk3399_defconfig
index 2ab2516..62a8d7c 100644
--- a/configs/puma-rk3399_defconfig
+++ b/configs/puma-rk3399_defconfig
@@ -1,5 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_SYS_MALLOC_F_LEN=0x4000
@@ -20,6 +21,8 @@
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x4000
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200
+CONFIG_SPL_I2C_SUPPORT=y
+CONFIG_SPL_POWER_SUPPORT=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_GPT=y
@@ -63,8 +66,10 @@
 CONFIG_PINCTRL_ROCKCHIP_RK3399=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_RK8XX=y
-CONFIG_REGULATOR_PWM=y
+CONFIG_SPL_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_SPL_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
 CONFIG_REGULATOR_RK8XX=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_RAM=y
diff --git a/configs/pxm2_defconfig b/configs/pxm2_defconfig
index 38370ee..384ad35 100644
--- a/configs/pxm2_defconfig
+++ b/configs/pxm2_defconfig
@@ -70,10 +70,12 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0908
+CONFIG_USB_GADGET_PRODUCT_NUM=0x02d2
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Siemens AG"
-CONFIG_G_DNL_VENDOR_NUM=0x0908
-CONFIG_G_DNL_PRODUCT_NUM=0x02d2
+CONFIG_USB_ETHER=y
+CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00"
 # CONFIG_VIDEO_SW_CURSOR is not set
 CONFIG_SYS_CONSOLE_BG_COL=0xff
 CONFIG_SYS_CONSOLE_FG_COL=0x00
diff --git a/configs/qemu_arm_defconfig b/configs/qemu_arm_defconfig
new file mode 100644
index 0000000..2a8594d
--- /dev/null
+++ b/configs/qemu_arm_defconfig
@@ -0,0 +1,28 @@
+CONFIG_ARM=y
+CONFIG_ARM_SMCCC=y
+CONFIG_ARCH_QEMU=y
+CONFIG_AHCI=y
+CONFIG_DISTRO_DEFAULTS=y
+# CONFIG_DISPLAY_CPUINFO is not set
+# CONFIG_DISPLAY_BOARDINFO is not set
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_PCI=y
+CONFIG_CMD_USB=y
+CONFIG_OF_BOARD=y
+CONFIG_AHCI_PCI=y
+CONFIG_BLK=y
+# CONFIG_MMC is not set
+CONFIG_DM_ETH=y
+CONFIG_E1000=y
+CONFIG_NVME=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_PCIE_ECAM_GENERIC=y
+CONFIG_SCSI=y
+CONFIG_DM_SCSI=y
+CONFIG_SYSRESET=y
+CONFIG_SYSRESET_PSCI=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_PCI=y
diff --git a/configs/rastaban_defconfig b/configs/rastaban_defconfig
index 5acfe22..3c9c2b3 100644
--- a/configs/rastaban_defconfig
+++ b/configs/rastaban_defconfig
@@ -66,7 +66,9 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0908
+CONFIG_USB_GADGET_PRODUCT_NUM=0x02d2
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Siemens AG"
-CONFIG_G_DNL_VENDOR_NUM=0x0908
-CONFIG_G_DNL_PRODUCT_NUM=0x02d2
+CONFIG_USB_ETHER=y
+CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00"
diff --git a/configs/rock2_defconfig b/configs/rock2_defconfig
index b41644e..be28c66 100644
--- a/configs/rock2_defconfig
+++ b/configs/rock2_defconfig
@@ -67,11 +67,10 @@
 CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x320a
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
diff --git a/configs/rock_defconfig b/configs/rock_defconfig
index aaf2775..599760d 100644
--- a/configs/rock_defconfig
+++ b/configs/rock_defconfig
@@ -14,6 +14,7 @@
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000
 # CONFIG_CMD_IMLS is not set
+CONFIG_RANDOM_UUID=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/rut_defconfig b/configs/rut_defconfig
index 6ec8ff3..1f47200 100644
--- a/configs/rut_defconfig
+++ b/configs/rut_defconfig
@@ -71,10 +71,11 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0908
+CONFIG_USB_GADGET_PRODUCT_NUM=0x02d2
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Siemens AG"
-CONFIG_G_DNL_VENDOR_NUM=0x0908
-CONFIG_G_DNL_PRODUCT_NUM=0x02d2
+CONFIG_USB_ETHER=y
 # CONFIG_VIDEO_SW_CURSOR is not set
 CONFIG_SYS_CONSOLE_BG_COL=0xff
 CONFIG_SYS_CONSOLE_FG_COL=0x00
diff --git a/configs/s5p_goni_defconfig b/configs/s5p_goni_defconfig
index 7d8792c..eb6c2d7 100644
--- a/configs/s5p_goni_defconfig
+++ b/configs/s5p_goni_defconfig
@@ -35,9 +35,9 @@
 CONFIG_DM_PMIC_MAX8998=y
 CONFIG_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Samsung"
+CONFIG_USB_GADGET_VENDOR_NUM=0x04e8
+CONFIG_USB_GADGET_PRODUCT_NUM=0x6601
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Samsung"
-CONFIG_G_DNL_VENDOR_NUM=0x04e8
-CONFIG_G_DNL_PRODUCT_NUM=0x6601
 CONFIG_FAT_WRITE=y
diff --git a/configs/s5pc210_universal_defconfig b/configs/s5pc210_universal_defconfig
index 16352ad..e48e4b5 100644
--- a/configs/s5pc210_universal_defconfig
+++ b/configs/s5pc210_universal_defconfig
@@ -46,8 +46,8 @@
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Samsung"
+CONFIG_USB_GADGET_VENDOR_NUM=0x04e8
+CONFIG_USB_GADGET_PRODUCT_NUM=0x6601
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Samsung"
-CONFIG_G_DNL_VENDOR_NUM=0x04e8
-CONFIG_G_DNL_PRODUCT_NUM=0x6601
diff --git a/configs/sama5d2_ptc_nandflash_defconfig b/configs/sama5d2_ptc_nandflash_defconfig
index 3f1eb90..06b6ec7 100644
--- a/configs/sama5d2_ptc_nandflash_defconfig
+++ b/configs/sama5d2_ptc_nandflash_defconfig
@@ -29,4 +29,6 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Atmel SAMA5D2_PTC"
 CONFIG_USB_GADGET_ATMEL_USBA=y
+CONFIG_USB_ETHER=y
diff --git a/configs/sama5d2_ptc_spiflash_defconfig b/configs/sama5d2_ptc_spiflash_defconfig
index ad62f47..6574448 100644
--- a/configs/sama5d2_ptc_spiflash_defconfig
+++ b/configs/sama5d2_ptc_spiflash_defconfig
@@ -30,4 +30,6 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Atmel SAMA5D2_PTC"
 CONFIG_USB_GADGET_ATMEL_USBA=y
+CONFIG_USB_ETHER=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 632e0aa..891322b 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -60,6 +60,7 @@
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_TPM=y
 CONFIG_CMD_TPM_TEST=y
+CONFIG_CMD_BTRFS=y
 CONFIG_CMD_CBFS=y
 CONFIG_CMD_CRAMFS=y
 CONFIG_CMD_EXT4_WRITE=y
diff --git a/configs/sansa_fuze_plus_defconfig b/configs/sansa_fuze_plus_defconfig
index f6ce09c..b5443dd 100644
--- a/configs/sansa_fuze_plus_defconfig
+++ b/configs/sansa_fuze_plus_defconfig
@@ -32,4 +32,6 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/smartweb_defconfig b/configs/smartweb_defconfig
index accdd5d..583000e 100644
--- a/configs/smartweb_defconfig
+++ b/configs/smartweb_defconfig
@@ -46,10 +46,10 @@
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0908
+CONFIG_USB_GADGET_PRODUCT_NUM=0x02d2
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Siemens AG"
-CONFIG_G_DNL_VENDOR_NUM=0x0908
-CONFIG_G_DNL_PRODUCT_NUM=0x02d2
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_MCS7830=y
diff --git a/configs/sniper_defconfig b/configs/sniper_defconfig
index f24153b..21254a5 100644
--- a/configs/sniper_defconfig
+++ b/configs/sniper_defconfig
@@ -13,8 +13,6 @@
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="sniper # "
 CONFIG_FASTBOOT=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_CMD_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x82000000
 CONFIG_FASTBOOT_BUF_SIZE=0x2000000
 CONFIG_FASTBOOT_FLASH=y
@@ -43,8 +41,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
-CONFIG_G_DNL_VENDOR_NUM=0x0451
-CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0451
+CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
 CONFIG_OF_LIBFDT=y
diff --git a/configs/socfpga_arria5_defconfig b/configs/socfpga_arria5_defconfig
index cf4fa20..dc21821 100644
--- a/configs/socfpga_arria5_defconfig
+++ b/configs/socfpga_arria5_defconfig
@@ -64,9 +64,9 @@
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="altera"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="altera"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_USE_TINY_PRINTF=y
diff --git a/configs/socfpga_cyclone5_defconfig b/configs/socfpga_cyclone5_defconfig
index 1cc6e16..9d46576 100644
--- a/configs/socfpga_cyclone5_defconfig
+++ b/configs/socfpga_cyclone5_defconfig
@@ -64,9 +64,9 @@
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="altera"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="altera"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_USE_TINY_PRINTF=y
diff --git a/configs/socfpga_de0_nano_soc_defconfig b/configs/socfpga_de0_nano_soc_defconfig
index b4fd29d..50c53ac 100644
--- a/configs/socfpga_de0_nano_soc_defconfig
+++ b/configs/socfpga_de0_nano_soc_defconfig
@@ -61,9 +61,9 @@
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="terasic"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="terasic"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_USE_TINY_PRINTF=y
diff --git a/configs/socfpga_de10_nano_defconfig b/configs/socfpga_de10_nano_defconfig
index 16cff90..c9f9e50 100644
--- a/configs/socfpga_de10_nano_defconfig
+++ b/configs/socfpga_de10_nano_defconfig
@@ -56,9 +56,9 @@
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="terasic"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="terasic"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_USE_TINY_PRINTF=y
diff --git a/configs/socfpga_mcvevk_defconfig b/configs/socfpga_mcvevk_defconfig
index 0b4ad41..d06db25 100644
--- a/configs/socfpga_mcvevk_defconfig
+++ b/configs/socfpga_mcvevk_defconfig
@@ -58,9 +58,9 @@
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="denx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="denx"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_USE_TINY_PRINTF=y
diff --git a/configs/socfpga_sockit_defconfig b/configs/socfpga_sockit_defconfig
index b22bf6f..1d50140 100644
--- a/configs/socfpga_sockit_defconfig
+++ b/configs/socfpga_sockit_defconfig
@@ -64,9 +64,9 @@
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="terasic"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="terasic"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_USE_TINY_PRINTF=y
diff --git a/configs/socfpga_socrates_defconfig b/configs/socfpga_socrates_defconfig
index 335c9e8..c088c3e 100644
--- a/configs/socfpga_socrates_defconfig
+++ b/configs/socfpga_socrates_defconfig
@@ -64,9 +64,9 @@
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="ebv"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="ebv"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_USE_TINY_PRINTF=y
diff --git a/configs/socfpga_vining_fpga_defconfig b/configs/socfpga_vining_fpga_defconfig
index 3bcedb6..1911735 100644
--- a/configs/socfpga_vining_fpga_defconfig
+++ b/configs/socfpga_vining_fpga_defconfig
@@ -81,9 +81,9 @@
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="samtec"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="samtec"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_USE_TINY_PRINTF=y
diff --git a/configs/stih410-b2260_defconfig b/configs/stih410-b2260_defconfig
index 8fd1ff2..d4aa4f3 100644
--- a/configs/stih410-b2260_defconfig
+++ b/configs/stih410-b2260_defconfig
@@ -6,7 +6,7 @@
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_USE_BOOTARGS=y
-CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel"
+CONFIG_BOOTARGS="console=ttyAS1,115200 CONSOLE=/dev/ttyAS1 consoleblank=0 root=/dev/mmcblk0p2 rootfstype=ext4 rw rootwait mem=992M@0x40000000 vmalloc=256m"
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SYS_PROMPT="stih410-b2260 => "
 CONFIG_FASTBOOT=y
@@ -52,8 +52,8 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="STMicroelectronics"
-CONFIG_G_DNL_VENDOR_NUM=0x483
-CONFIG_G_DNL_PRODUCT_NUM=0x7270
+CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
+CONFIG_USB_GADGET_VENDOR_NUM=0x483
+CONFIG_USB_GADGET_PRODUCT_NUM=0x7270
 CONFIG_OF_LIBFDT_OVERLAY=y
 CONFIG_SPL_OF_LIBFDT=y
diff --git a/configs/stm32h743-disco_defconfig b/configs/stm32h743-disco_defconfig
index eed921d2..1716333 100644
--- a/configs/stm32h743-disco_defconfig
+++ b/configs/stm32h743-disco_defconfig
@@ -16,12 +16,21 @@
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_TIMER=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_CONTROL=y
 CONFIG_OF_EMBED=y
+CONFIG_DM_MMC=y
+CONFIG_STM32_SDMMC2=y
 # CONFIG_PINCTRL_FULL is not set
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_REGEX=y
diff --git a/configs/stm32h743-eval_defconfig b/configs/stm32h743-eval_defconfig
index 61e702e..4714ff2 100644
--- a/configs/stm32h743-eval_defconfig
+++ b/configs/stm32h743-eval_defconfig
@@ -16,12 +16,21 @@
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPT=y
+CONFIG_CMD_MMC=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_TIMER=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_CONTROL=y
 CONFIG_OF_EMBED=y
+CONFIG_DM_MMC=y
+CONFIG_STM32_SDMMC2=y
 # CONFIG_PINCTRL_FULL is not set
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_REGEX=y
diff --git a/configs/taurus_defconfig b/configs/taurus_defconfig
index 71a382a..bde93e9 100644
--- a/configs/taurus_defconfig
+++ b/configs/taurus_defconfig
@@ -53,8 +53,8 @@
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0908
+CONFIG_USB_GADGET_PRODUCT_NUM=0x02d2
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Siemens AG"
-CONFIG_G_DNL_VENDOR_NUM=0x0908
-CONFIG_G_DNL_PRODUCT_NUM=0x02d2
 CONFIG_USE_TINY_PRINTF=y
diff --git a/configs/tbs2910_defconfig b/configs/tbs2910_defconfig
index 20814cc..81225e8 100644
--- a/configs/tbs2910_defconfig
+++ b/configs/tbs2910_defconfig
@@ -45,10 +45,10 @@
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="TBS"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="TBS"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_CFB_CONSOLE_ANSI=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/theadorable-x86-conga-qa3-e3845-pcie-x4_defconfig b/configs/theadorable-x86-conga-qa3-e3845-pcie-x4_defconfig
index 1888f08..344a8f2 100644
--- a/configs/theadorable-x86-conga-qa3-e3845-pcie-x4_defconfig
+++ b/configs/theadorable-x86-conga-qa3-e3845-pcie-x4_defconfig
@@ -27,7 +27,6 @@
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
-# CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_PING=y
diff --git a/configs/theadorable-x86-conga-qa3-e3845_defconfig b/configs/theadorable-x86-conga-qa3-e3845_defconfig
index 4c9492c..84a92c5 100644
--- a/configs/theadorable-x86-conga-qa3-e3845_defconfig
+++ b/configs/theadorable-x86-conga-qa3-e3845_defconfig
@@ -26,7 +26,6 @@
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
-# CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_PING=y
diff --git a/configs/theadorable-x86-dfi-bt700_defconfig b/configs/theadorable-x86-dfi-bt700_defconfig
index 348d917..d42798e 100644
--- a/configs/theadorable-x86-dfi-bt700_defconfig
+++ b/configs/theadorable-x86-dfi-bt700_defconfig
@@ -25,7 +25,6 @@
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
-# CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_PING=y
diff --git a/configs/thuban_defconfig b/configs/thuban_defconfig
index c30e924..d9030ec 100644
--- a/configs/thuban_defconfig
+++ b/configs/thuban_defconfig
@@ -66,7 +66,8 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0908
+CONFIG_USB_GADGET_PRODUCT_NUM=0x02d2
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Siemens AG"
-CONFIG_G_DNL_VENDOR_NUM=0x0908
-CONFIG_G_DNL_PRODUCT_NUM=0x02d2
+CONFIG_USB_ETHER=y
diff --git a/configs/ti816x_evm_defconfig b/configs/ti816x_evm_defconfig
index 4341d8d..d269e36 100644
--- a/configs/ti816x_evm_defconfig
+++ b/configs/ti816x_evm_defconfig
@@ -9,7 +9,6 @@
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_SPL_NAND_SUPPORT=y
-CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_SPL_FAT_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="dm8168-evm"
 CONFIG_DISTRO_DEFAULTS=y
@@ -20,7 +19,6 @@
 CONFIG_VERSION_VARIABLE=y
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL=y
-CONFIG_SPL_STACK_R=y
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x300
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/tinker-rk3288_defconfig b/configs/tinker-rk3288_defconfig
index 00e2d81..816fc01 100644
--- a/configs/tinker-rk3288_defconfig
+++ b/configs/tinker-rk3288_defconfig
@@ -72,11 +72,10 @@
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Rockchip"
-CONFIG_G_DNL_VENDOR_NUM=0x2207
-CONFIG_G_DNL_PRODUCT_NUM=0x320a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/topic_miami_defconfig b/configs/topic_miami_defconfig
index 1080554..a8028b6 100644
--- a/configs/topic_miami_defconfig
+++ b/configs/topic_miami_defconfig
@@ -46,8 +46,8 @@
 CONFIG_USB_ULPI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03fd
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03fd
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
diff --git a/configs/topic_miamilite_defconfig b/configs/topic_miamilite_defconfig
index 1450fbc..568eb66 100644
--- a/configs/topic_miamilite_defconfig
+++ b/configs/topic_miamilite_defconfig
@@ -47,8 +47,8 @@
 CONFIG_USB_ULPI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03fd
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03fd
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
diff --git a/configs/topic_miamiplus_defconfig b/configs/topic_miamiplus_defconfig
index d3fc7ad..94fa962 100644
--- a/configs/topic_miamiplus_defconfig
+++ b/configs/topic_miamiplus_defconfig
@@ -46,8 +46,8 @@
 CONFIG_USB_ULPI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03fd
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03fd
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
diff --git a/configs/trats2_defconfig b/configs/trats2_defconfig
index bcc73d4..a4cd8c8 100644
--- a/configs/trats2_defconfig
+++ b/configs/trats2_defconfig
@@ -50,8 +50,8 @@
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Samsung"
+CONFIG_USB_GADGET_VENDOR_NUM=0x04e8
+CONFIG_USB_GADGET_PRODUCT_NUM=0x6601
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Samsung"
-CONFIG_G_DNL_VENDOR_NUM=0x04e8
-CONFIG_G_DNL_PRODUCT_NUM=0x6601
diff --git a/configs/trats_defconfig b/configs/trats_defconfig
index 3f0c59b..5c567f6 100644
--- a/configs/trats_defconfig
+++ b/configs/trats_defconfig
@@ -49,8 +49,8 @@
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Samsung"
+CONFIG_USB_GADGET_VENDOR_NUM=0x04e8
+CONFIG_USB_GADGET_PRODUCT_NUM=0x6601
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Samsung"
-CONFIG_G_DNL_VENDOR_NUM=0x04e8
-CONFIG_G_DNL_PRODUCT_NUM=0x6601
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index 870cfd51..b3f542d 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -26,6 +26,7 @@
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
+CONFIG_CMD_BTRFS=y
 # CONFIG_SPL_PARTITION_UUIDS is not set
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SPL_OF_TRANSLATE=y
diff --git a/configs/venice2_defconfig b/configs/venice2_defconfig
index f90936e..5820897 100644
--- a/configs/venice2_defconfig
+++ b/configs/venice2_defconfig
@@ -38,10 +38,10 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="NVIDIA"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0955
+CONFIG_USB_GADGET_PRODUCT_NUM=0x701a
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="NVIDIA"
-CONFIG_G_DNL_VENDOR_NUM=0x0955
-CONFIG_G_DNL_PRODUCT_NUM=0x701a
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
diff --git a/configs/vf610twr_defconfig b/configs/vf610twr_defconfig
index 948ea73..3c277be 100644
--- a/configs/vf610twr_defconfig
+++ b/configs/vf610twr_defconfig
@@ -3,6 +3,7 @@
 CONFIG_DEFAULT_DEVICE_TREE="vf610-twr"
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/vf610twr/imximage.cfg"
 CONFIG_BOOTDELAY=3
+CONFIG_LOGLEVEL=3
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
diff --git a/configs/vf610twr_nand_defconfig b/configs/vf610twr_nand_defconfig
index 10cdf06..1cd22b1 100644
--- a/configs/vf610twr_nand_defconfig
+++ b/configs/vf610twr_nand_defconfig
@@ -3,6 +3,7 @@
 CONFIG_DEFAULT_DEVICE_TREE="vf610-twr"
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/vf610twr/imximage.cfg"
 CONFIG_BOOTDELAY=3
+CONFIG_LOGLEVEL=3
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
diff --git a/configs/vinco_defconfig b/configs/vinco_defconfig
index 18eb173..704c36a 100644
--- a/configs/vinco_defconfig
+++ b/configs/vinco_defconfig
@@ -31,6 +31,8 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="L+G VInCo"
 CONFIG_USB_GADGET_ATMEL_USBA=y
+CONFIG_USB_ETHER=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/vyasa-rk3288_defconfig b/configs/vyasa-rk3288_defconfig
index 7db7b0b..7bd6068 100644
--- a/configs/vyasa-rk3288_defconfig
+++ b/configs/vyasa-rk3288_defconfig
@@ -1,8 +1,11 @@
 CONFIG_ARM=y
+# CONFIG_SPL_USE_ARCH_MEMCPY is not set
+# CONFIG_SPL_USE_ARCH_MEMSET is not set
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_ROCKCHIP_RK3288=y
 CONFIG_TARGET_VYASA_RK3288=y
+CONFIG_TPL_TEXT_BASE=0xff704004
 CONFIG_SPL_STACK_R_ADDR=0x80000
 CONFIG_DEFAULT_DEVICE_TREE="rk3288-vyasa"
 CONFIG_DEBUG_UART=y
diff --git a/configs/warp7_defconfig b/configs/warp7_defconfig
index 99fe800..c91090c 100644
--- a/configs/warp7_defconfig
+++ b/configs/warp7_defconfig
@@ -33,9 +33,12 @@
 CONFIG_MXC_USB_OTG_HACTIVE=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="FSL"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="FSL"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
+CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00"
 CONFIG_OF_LIBFDT=y
diff --git a/configs/warp7_secure_defconfig b/configs/warp7_secure_defconfig
index 8beda72..5a2b394 100644
--- a/configs/warp7_secure_defconfig
+++ b/configs/warp7_secure_defconfig
@@ -31,9 +31,12 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_MXC_USB_OTG_HACTIVE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="FSL"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="FSL"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
+CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00"
 CONFIG_OF_LIBFDT=y
diff --git a/configs/warp_defconfig b/configs/warp_defconfig
index 8e58790..3432a78 100644
--- a/configs/warp_defconfig
+++ b/configs/warp_defconfig
@@ -30,9 +30,9 @@
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="FSL"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="FSL"
-CONFIG_G_DNL_VENDOR_NUM=0x0525
-CONFIG_G_DNL_PRODUCT_NUM=0xa4a5
 CONFIG_OF_LIBFDT=y
diff --git a/configs/xfi3_defconfig b/configs/xfi3_defconfig
index de80da6..91768a4 100644
--- a/configs/xfi3_defconfig
+++ b/configs/xfi3_defconfig
@@ -31,4 +31,6 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
+CONFIG_USB_ETHER=y
+CONFIG_USB_ETH_CDC=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig
index c3ba5bf..03f529e 100644
--- a/configs/xilinx_zynqmp_ep_defconfig
+++ b/configs/xilinx_zynqmp_ep_defconfig
@@ -85,8 +85,8 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03fd
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03fd
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 # CONFIG_REGEX is not set
 CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
index 588b154..92ac41a 100644
--- a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
@@ -77,7 +77,7 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03FD
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03FD
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
index 0a3ac9d..7a40b05 100644
--- a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
@@ -75,7 +75,7 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03FD
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03FD
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
diff --git a/configs/xilinx_zynqmp_zcu102_revA_defconfig b/configs/xilinx_zynqmp_zcu102_revA_defconfig
index ee0beda..6702068 100644
--- a/configs/xilinx_zynqmp_zcu102_revA_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_revA_defconfig
@@ -80,7 +80,7 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03FD
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03FD
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig
index e47e4bf..d878c18 100644
--- a/configs/xilinx_zynqmp_zcu102_revB_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig
@@ -80,7 +80,7 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03FD
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03FD
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
diff --git a/configs/zynq_microzed_defconfig b/configs/zynq_microzed_defconfig
index ae248f5..cb86701 100644
--- a/configs/zynq_microzed_defconfig
+++ b/configs/zynq_microzed_defconfig
@@ -53,8 +53,8 @@
 CONFIG_USB_ULPI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03FD
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03FD
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
diff --git a/configs/zynq_picozed_defconfig b/configs/zynq_picozed_defconfig
index 0afdd11..39d76ba 100644
--- a/configs/zynq_picozed_defconfig
+++ b/configs/zynq_picozed_defconfig
@@ -42,8 +42,8 @@
 CONFIG_USB_ULPI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03fd
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03fd
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
diff --git a/configs/zynq_z_turn_defconfig b/configs/zynq_z_turn_defconfig
index 3684b85..d21a8fa 100644
--- a/configs/zynq_z_turn_defconfig
+++ b/configs/zynq_z_turn_defconfig
@@ -52,8 +52,8 @@
 CONFIG_USB_ULPI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03FD
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03FD
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
diff --git a/configs/zynq_zc702_defconfig b/configs/zynq_zc702_defconfig
index 21852e5..a574a89 100644
--- a/configs/zynq_zc702_defconfig
+++ b/configs/zynq_zc702_defconfig
@@ -60,8 +60,8 @@
 CONFIG_USB_ULPI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03fd
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03fd
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
diff --git a/configs/zynq_zc706_defconfig b/configs/zynq_zc706_defconfig
index dfafc9a..d9718b0 100644
--- a/configs/zynq_zc706_defconfig
+++ b/configs/zynq_zc706_defconfig
@@ -56,8 +56,8 @@
 CONFIG_USB_ULPI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03fd
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03fd
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
diff --git a/configs/zynq_zed_defconfig b/configs/zynq_zed_defconfig
index bb512af..3a18c4a 100644
--- a/configs/zynq_zed_defconfig
+++ b/configs/zynq_zed_defconfig
@@ -53,8 +53,8 @@
 CONFIG_USB_ULPI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03fd
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03fd
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
diff --git a/configs/zynq_zybo_defconfig b/configs/zynq_zybo_defconfig
index fd31b4d..9edde2a 100644
--- a/configs/zynq_zybo_defconfig
+++ b/configs/zynq_zybo_defconfig
@@ -58,8 +58,8 @@
 CONFIG_USB_ULPI=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
+CONFIG_USB_GADGET_VENDOR_NUM=0x03fd
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_G_DNL_MANUFACTURER="Xilinx"
-CONFIG_G_DNL_VENDOR_NUM=0x03fd
-CONFIG_G_DNL_PRODUCT_NUM=0x0300
diff --git a/disk/part.c b/disk/part.c
index aa9183d..66b8101 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -21,6 +21,9 @@
 #define PRINTF(fmt,args...)
 #endif
 
+/* Check all partition types */
+#define PART_TYPE_ALL		-1
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #ifdef HAVE_BLOCK_DEVICE
@@ -626,8 +629,8 @@
 	return ret;
 }
 
-int part_get_info_by_name(struct blk_desc *dev_desc, const char *name,
-	disk_partition_t *info)
+int part_get_info_by_name_type(struct blk_desc *dev_desc, const char *name,
+			       disk_partition_t *info, int part_type)
 {
 	struct part_driver *first_drv =
 		ll_entry_start(struct part_driver, part_driver);
@@ -638,6 +641,8 @@
 		int ret;
 		int i;
 		for (i = 1; i < part_drv->max_entries; i++) {
+			if (part_type >= 0 && part_type != part_drv->part_type)
+				break;
 			ret = part_drv->get_info(dev_desc, i, info);
 			if (ret != 0) {
 				/* no more entries in table */
@@ -652,6 +657,12 @@
 	return -1;
 }
 
+int part_get_info_by_name(struct blk_desc *dev_desc, const char *name,
+			  disk_partition_t *info)
+{
+	return part_get_info_by_name_type(dev_desc, name, info, PART_TYPE_ALL);
+}
+
 void part_set_generic_name(const struct blk_desc *dev_desc,
 	int part_num, char *name)
 {
diff --git a/disk/part_dos.c b/disk/part_dos.c
index 7ede15e..6dd2c2d 100644
--- a/disk/part_dos.c
+++ b/disk/part_dos.c
@@ -44,7 +44,7 @@
 
 static inline int is_bootable(dos_partition_t *p)
 {
-	return p->boot_ind == 0x80;
+	return (p->sys_ind == 0xef) || (p->boot_ind == 0x80);
 }
 
 static void print_one_part(dos_partition_t *p, lbaint_t ext_part_sector,
@@ -89,6 +89,21 @@
 
 static int part_test_dos(struct blk_desc *dev_desc)
 {
+#ifndef CONFIG_SPL_BUILD
+	ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, mbr, dev_desc->blksz);
+
+	if (blk_dread(dev_desc, 0, 1, (ulong *)mbr) != 1)
+		return -1;
+
+	if (test_block_type((unsigned char *)mbr) != DOS_MBR)
+		return -1;
+
+	if (dev_desc->sig_type == SIG_TYPE_NONE &&
+	    mbr->unique_mbr_signature != 0) {
+		dev_desc->sig_type = SIG_TYPE_MBR;
+		dev_desc->mbr_sig = mbr->unique_mbr_signature;
+	}
+#else
 	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
 
 	if (blk_dread(dev_desc, 0, 1, (ulong *)buffer) != 1)
@@ -96,6 +111,7 @@
 
 	if (test_block_type(buffer) != DOS_MBR)
 		return -1;
+#endif
 
 	return 0;
 }
diff --git a/disk/part_efi.c b/disk/part_efi.c
index 2973d52..0abf487 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -360,7 +360,7 @@
 
 	/* Read MBR to backup boot code if it exists */
 	if (blk_dread(dev_desc, 0, 1, p_mbr) != 1) {
-		error("** Can't read from device %d **\n", dev_desc->devnum);
+		pr_err("** Can't read from device %d **\n", dev_desc->devnum);
 		return -1;
 	}
 
@@ -716,7 +716,7 @@
 
 	for (i = 0; i < parts; i++) {
 		if (i == gpt_head->num_partition_entries) {
-			error("More partitions than allowed!\n");
+			pr_err("More partitions than allowed!\n");
 			return -1;
 		}
 
@@ -729,7 +729,7 @@
 
 		if (strncmp(efi_str, (char *)partitions[i].name,
 			    sizeof(partitions->name))) {
-			error("Partition name: %s does not match %s!\n",
+			pr_err("Partition name: %s does not match %s!\n",
 			      efi_str, (char *)partitions[i].name);
 			return -1;
 		}
@@ -746,7 +746,7 @@
 			if ((i == parts - 1) && (partitions[i].size == 0))
 				continue;
 
-			error("Partition %s size: %llu does not match %llu!\n",
+			pr_err("Partition %s size: %llu does not match %llu!\n",
 			      efi_str, (unsigned long long)gpt_part_size,
 			      (unsigned long long)partitions[i].size);
 			return -1;
@@ -767,7 +767,7 @@
 		      (unsigned long long)partitions[i].start);
 
 		if (le64_to_cpu(gpt_e[i].starting_lba) != partitions[i].start) {
-			error("Partition %s start: %llu does not match %llu!\n",
+			pr_err("Partition %s start: %llu does not match %llu!\n",
 			      efi_str, le64_to_cpu(gpt_e[i].starting_lba),
 			      (unsigned long long)partitions[i].start);
 			return -1;
@@ -923,11 +923,19 @@
 static int is_gpt_valid(struct blk_desc *dev_desc, u64 lba,
 			gpt_header *pgpt_head, gpt_entry **pgpt_pte)
 {
+	ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, mbr, dev_desc->blksz);
+
 	if (!dev_desc || !pgpt_head) {
 		printf("%s: Invalid Argument(s)\n", __func__);
 		return 0;
 	}
 
+	/* Read MBR Header from device */
+	if (blk_dread(dev_desc, 0, 1, (ulong *)mbr) != 1) {
+		printf("*** ERROR: Can't read MBR header ***\n");
+		return 0;
+	}
+
 	/* Read GPT Header from device */
 	if (blk_dread(dev_desc, (lbaint_t)lba, 1, pgpt_head) != 1) {
 		printf("*** ERROR: Can't read GPT header ***\n");
@@ -937,6 +945,18 @@
 	if (validate_gpt_header(pgpt_head, (lbaint_t)lba, dev_desc->lba))
 		return 0;
 
+	if (dev_desc->sig_type == SIG_TYPE_NONE) {
+		efi_guid_t empty = {};
+		if (memcmp(&pgpt_head->disk_guid, &empty, sizeof(empty))) {
+			dev_desc->sig_type = SIG_TYPE_GUID;
+			memcpy(&dev_desc->guid_sig, &pgpt_head->disk_guid,
+			      sizeof(empty));
+		} else if (mbr->unique_mbr_signature != 0) {
+			dev_desc->sig_type = SIG_TYPE_MBR;
+			dev_desc->mbr_sig = mbr->unique_mbr_signature;
+		}
+	}
+
 	/* Read and allocate Partition Table Entries */
 	*pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head);
 	if (*pgpt_pte == NULL) {
diff --git a/doc/README.android-fastboot b/doc/README.android-fastboot
index b8afa15..2c3ee78 100644
--- a/doc/README.android-fastboot
+++ b/doc/README.android-fastboot
@@ -34,11 +34,11 @@
 options must be configured:
 
 CONFIG_USB_GADGET_DOWNLOAD
-CONFIG_G_DNL_VENDOR_NUM
-CONFIG_G_DNL_PRODUCT_NUM
-CONFIG_G_DNL_MANUFACTURER
+CONFIG_USB_GADGET_VENDOR_NUM
+CONFIG_USB_GADGET_PRODUCT_NUM
+CONFIG_USB_GADGET_MANUFACTURER
 
-NOTE: The CONFIG_G_DNL_VENDOR_NUM must be one of the numbers supported by
+NOTE: The CONFIG_USB_GADGET_VENDOR_NUM must be one of the numbers supported by
 the fastboot client. The list of vendor IDs supported can be found in the
 fastboot client source code (fastboot.c) mentioned above.
 
diff --git a/doc/README.multi-dtb-fit b/doc/README.multi-dtb-fit
new file mode 100644
index 0000000..6cc4965
--- /dev/null
+++ b/doc/README.multi-dtb-fit
@@ -0,0 +1,65 @@
+MULTI DTB FIT and SPL_MULTI_DTB_FIT
+
+The purpose of this feature is to enable U-Boot or the SPL to select its DTB
+from a FIT appended at the end of the binary.
+It comes in two flavors: U-Boot (CONFIG_MULTI_DTB_FIT) and SPL
+(CONFIG_SPL_MULTI_DTB_FIT).
+
+U-Boot flavor:
+Usually the DTB is selected by the SPL and passed down to U-Boot. But some
+platforms don't use the SPL. In this case MULTI_DTB_FIT can used to provide
+U-Boot with a choice of DTBs.
+The relevant DTBs are packed into a FIT (list provided by CONFIG__OF_LIST). The
+FIT is automatically generated at the end of the compilation and appended to
+u-boot.bin so that U-Boot can locate it and select the correct DTB from inside
+the FIT.
+The selection is done using board_fit_config_name_match() (same as what the SPL
+uses to select the DTB for U-Boot). The selection happens during fdtdec_setup()
+which is called during before relocation by board_init_f().
+
+SPL flavor:
+the SPL uses only a small subset of the DTB and it usually depends more
+on the SOC than on the board. So it's usually fine to include a DTB in the
+SPL that doesn't exactly match the board. There are howerver some cases
+where it's not possible. In the later case, in order to support multiple
+boards (or board revisions) with the same SPL binary, SPL_MULTI_DTB_FIT
+can be used.
+The relevant DTBs are packed into a FIT. This FIT is automatically generated
+at the end of the compilation, compressed and appended to u-boot-spl.bin, so
+that SPL can locate it and select the correct DTB from inside the FIT.
+CONFIG_SPL__OF_LIST is used to list the relevant DTBs.
+The compression stage is optional but reduces the impact on the size of the
+SPL. LZO and GZIP compressions are supported. By default, the area where the
+FIT is uncompressed is dynamicaly allocated but this behaviour can be changed
+for platforms that don't provide a HEAP big enough to contain the uncompressed
+FIT.
+The SPL uses board_fit_config_name_match() to find the correct DTB within the
+FIT (same as what the SPL uses to select the DTB for U-Boot).
+Uncompression and selection stages happen in fdtdec_setup() which is called
+during the early initialization stage of the SPL (spl_early_init() or
+spl_init())
+
+Impacts and performances (SPL flavor):
+The impact of this option is relatively small. Here are some numbers measured
+for a TI DRA72 platform:
+
+                            +----------+------------+-----------+------------+
+                            |  size    | size delta | SPL boot  | boot time  |
+                            |  (bytes) | (bytes)    | time (s)  | delta (s)  |
++---------------------------+----------+------------+-----------+------------+
+| 1 DTB                     |          |            |           |            |
++---------------------------+----------+------------+-----------+------------+
+| reference                 |   125305 |          0 |     1.389 |          0 |
+| LZO (dynamic allocation)  |   125391 |         86 |     1.381 |     -0.008 |
++---------------------------+----------+------------+-----------+------------+
+| 4 DTBs (DRA7, DRA71,      |          |            |           |            |
+| DRA72, DRA72 revC)        |          |            |           |            |
++---------------------------+----------+------------+-----------+------------+
+| LZO (dynamic allocation)  |   125991 |        686 |      1.39 |      0.001 |
+| LZO (user defined area)   |   125927 |        622 |     1.403 |      0.014 |
+| GZIP (user defined area)  |   133880 |       8575 |     1.421 |      0.032 |
+| No compression (in place) |   137472 |      12167 |     1.412 |      0.023 |
++---------------------------+----------+------------+-----------+------------+
+
+Note: SPL boot time is the time elapsed between the 'reset' command is entered
+and the time when the first U-Boot (not SPL) version string is displayed.
diff --git a/doc/README.rockchip b/doc/README.rockchip
index 12fec38..4b7be0b 100644
--- a/doc/README.rockchip
+++ b/doc/README.rockchip
@@ -150,6 +150,24 @@
       debug uart must be disabled
 
 
+Booting from an SD card on RK3288 with TPL
+==========================================
+
+Since the size of SPL can't be exceeded 0x8000 bytes in RK3288, it is not possible add
+new SPL features like Falcon mode or etc.
+
+So introduce TPL so-that adding new features to SPL is possible because now TPL should
+run minimal with code like DDR, clock etc and rest of new features in SPL.
+
+As of now TPL is added on Vyasa-RK3288 board.
+
+To write an image that boots from an SD card (assumed to be /dev/mmcblk0):
+
+   ./tools/mkimage -n rk3288 -T rksd -d ./tpl/u-boot-tpl.bin out &&
+    cat ./spl/u-boot-spl-dtb.bin >> out &&
+    sudo dd if=out of=/dev/mmcblk0 seek=64 &&
+    sudo dd if=u-boot-dtb.img of=/dev/mmcblk0 seek=256
+
 Booting from an SD card on RK3188
 =================================
 
diff --git a/doc/device-tree-bindings/chosen.txt b/doc/device-tree-bindings/chosen.txt
index 5625d21..c96b8f7 100644
--- a/doc/device-tree-bindings/chosen.txt
+++ b/doc/device-tree-bindings/chosen.txt
@@ -56,10 +56,20 @@
 in the order they are listed: references (i.e. implicit paths), a full
 path or an alias is expected for each entry.
 
+A special specifier "same-as-spl" can be used at any position in the
+boot-order to direct U-Boot to insert the device the SPL was booted
+from there.  Whether this is indeed inserted or silently ignored (if
+it is not supported on any given SoC/board or if the boot-device is
+not available to continue booting from) is implementation-defined.
+Note that if "same-as-spl" expands to an actual node for a given
+board, the corresponding node may appear multiple times in the
+boot-order (as there currently exists no mechanism to suppress
+duplicates from the list).
+
 Example
 -------
 / {
 	chosen {
-		u-boot,spl-boot-order = &sdmmc, "/sdhci@fe330000";
+		u-boot,spl-boot-order = "same-as-spl", &sdmmc, "/sdhci@fe330000";
 	};
 };
diff --git a/doc/device-tree-bindings/regulator/regulator.txt b/doc/device-tree-bindings/regulator/regulator.txt
index 2cf4b9d..918711e 100644
--- a/doc/device-tree-bindings/regulator/regulator.txt
+++ b/doc/device-tree-bindings/regulator/regulator.txt
@@ -10,10 +10,10 @@
 regulator: drivers/power/regulator/max77686.c
 
 For the node name e.g.: "prefix[:alpha:]num { ... }":
-- the driver prefix should be: "prefix" or "PREFIX" - case insensitive
+- the driver prefix should be: "prefix" - case sensitive
 - the node name's "num" is set as "dev->driver_data" on bind
 
-Example the prefix "ldo" will pass for: "ldo1", "ldo@1", "LDO1", "LDOREG@1"...
+Example the prefix "ldo" will pass for: "ldo1", "ldo@1", "ldoreg@1, ...
 
 Optional properties:
 - regulator-name: a string, required by the regulator uclass
diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig
index e5335f7..8094420 100644
--- a/drivers/adc/Kconfig
+++ b/drivers/adc/Kconfig
@@ -28,3 +28,12 @@
 	  - 4 analog input channels
 	  - 16-bit resolution
 	  - single and multi-channel conversion mode
+
+config SARADC_ROCKCHIP
+	bool "Enable Rockchip SARADC driver"
+	help
+	  This enables driver for Rockchip SARADC.
+	  It provides:
+	  - 2~6 analog input channels
+	  - 1O or 12 bits resolution
+	  - Up to 1MSPS of sample rate
diff --git a/drivers/adc/Makefile b/drivers/adc/Makefile
index cebf26d..4b5aa69 100644
--- a/drivers/adc/Makefile
+++ b/drivers/adc/Makefile
@@ -8,3 +8,4 @@
 obj-$(CONFIG_ADC) += adc-uclass.o
 obj-$(CONFIG_ADC_EXYNOS) += exynos-adc.o
 obj-$(CONFIG_ADC_SANDBOX) += sandbox.o
+obj-$(CONFIG_SARADC_ROCKCHIP) += rockchip-saradc.o
diff --git a/drivers/adc/adc-uclass.c b/drivers/adc/adc-uclass.c
index a5ef722..a4c20f4 100644
--- a/drivers/adc/adc-uclass.c
+++ b/drivers/adc/adc-uclass.c
@@ -64,7 +64,7 @@
 	}
 
 	if (ret)
-		error("%s: can't enable %s-supply!", dev->name, supply_type);
+		pr_err("%s: can't enable %s-supply!", dev->name, supply_type);
 
 	return ret;
 }
@@ -389,12 +389,12 @@
 	/* Set ADC VDD platdata: polarity, uV, regulator (phandle). */
 	ret = adc_vdd_platdata_set(dev);
 	if (ret)
-		error("%s: Can't update Vdd. Error: %d", dev->name, ret);
+		pr_err("%s: Can't update Vdd. Error: %d", dev->name, ret);
 
 	/* Set ADC VSS platdata: polarity, uV, regulator (phandle). */
 	ret = adc_vss_platdata_set(dev);
 	if (ret)
-		error("%s: Can't update Vss. Error: %d", dev->name, ret);
+		pr_err("%s: Can't update Vss. Error: %d", dev->name, ret);
 
 	return 0;
 }
diff --git a/drivers/adc/exynos-adc.c b/drivers/adc/exynos-adc.c
index 324d72f..3bb065d 100644
--- a/drivers/adc/exynos-adc.c
+++ b/drivers/adc/exynos-adc.c
@@ -22,7 +22,7 @@
 	struct exynos_adc_v2 *regs = priv->regs;
 
 	if (channel != priv->active_channel) {
-		error("Requested channel is not active!");
+		pr_err("Requested channel is not active!");
 		return -EINVAL;
 	}
 
@@ -80,7 +80,7 @@
 
 	/* Check HW version */
 	if (readl(&regs->version) != ADC_V2_VERSION) {
-		error("This driver supports only ADC v2!");
+		pr_err("This driver supports only ADC v2!");
 		return -ENXIO;
 	}
 
@@ -109,7 +109,7 @@
 
 	priv->regs = (struct exynos_adc_v2 *)devfdt_get_addr(dev);
 	if (priv->regs == (struct exynos_adc_v2 *)FDT_ADDR_T_NONE) {
-		error("Dev: %s - can't get address!", dev->name);
+		pr_err("Dev: %s - can't get address!", dev->name);
 		return -ENODATA;
 	}
 
diff --git a/drivers/adc/rockchip-saradc.c b/drivers/adc/rockchip-saradc.c
new file mode 100644
index 0000000..a2856db
--- /dev/null
+++ b/drivers/adc/rockchip-saradc.c
@@ -0,0 +1,183 @@
+/*
+ * (C) Copyright 2017, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Rockchip SARADC driver for U-Boot
+ */
+
+#include <common.h>
+#include <adc.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+
+#define SARADC_CTRL_CHN_MASK		GENMASK(2, 0)
+#define SARADC_CTRL_POWER_CTRL		BIT(3)
+#define SARADC_CTRL_IRQ_ENABLE		BIT(5)
+#define SARADC_CTRL_IRQ_STATUS		BIT(6)
+
+#define SARADC_TIMEOUT			(100 * 1000)
+
+struct rockchip_saradc_regs {
+	unsigned int data;
+	unsigned int stas;
+	unsigned int ctrl;
+	unsigned int dly_pu_soc;
+};
+
+struct rockchip_saradc_data {
+	int				num_bits;
+	int				num_channels;
+	unsigned long			clk_rate;
+};
+
+struct rockchip_saradc_priv {
+	struct rockchip_saradc_regs		*regs;
+	int					active_channel;
+	const struct rockchip_saradc_data	*data;
+};
+
+int rockchip_saradc_channel_data(struct udevice *dev, int channel,
+				 unsigned int *data)
+{
+	struct rockchip_saradc_priv *priv = dev_get_priv(dev);
+	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+
+	if (channel != priv->active_channel) {
+		pr_err("Requested channel is not active!");
+		return -EINVAL;
+	}
+
+	if ((readl(&priv->regs->ctrl) & SARADC_CTRL_IRQ_STATUS) !=
+	    SARADC_CTRL_IRQ_STATUS)
+		return -EBUSY;
+
+	/* Read value */
+	*data = readl(&priv->regs->data);
+	*data &= uc_pdata->data_mask;
+
+	/* Power down adc */
+	writel(0, &priv->regs->ctrl);
+
+	return 0;
+}
+
+int rockchip_saradc_start_channel(struct udevice *dev, int channel)
+{
+	struct rockchip_saradc_priv *priv = dev_get_priv(dev);
+
+	if (channel < 0 || channel >= priv->data->num_channels) {
+		pr_err("Requested channel is invalid!");
+		return -EINVAL;
+	}
+
+	/* 8 clock periods as delay between power up and start cmd */
+	writel(8, &priv->regs->dly_pu_soc);
+
+	/* Select the channel to be used and trigger conversion */
+	writel(SARADC_CTRL_POWER_CTRL | (channel & SARADC_CTRL_CHN_MASK) |
+	       SARADC_CTRL_IRQ_ENABLE, &priv->regs->ctrl);
+
+	priv->active_channel = channel;
+
+	return 0;
+}
+
+int rockchip_saradc_stop(struct udevice *dev)
+{
+	struct rockchip_saradc_priv *priv = dev_get_priv(dev);
+
+	/* Power down adc */
+	writel(0, &priv->regs->ctrl);
+
+	priv->active_channel = -1;
+
+	return 0;
+}
+
+int rockchip_saradc_probe(struct udevice *dev)
+{
+	struct rockchip_saradc_priv *priv = dev_get_priv(dev);
+	struct clk clk;
+	int ret;
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_set_rate(&clk, priv->data->clk_rate);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	priv->active_channel = -1;
+
+	return 0;
+}
+
+int rockchip_saradc_ofdata_to_platdata(struct udevice *dev)
+{
+	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+	struct rockchip_saradc_priv *priv = dev_get_priv(dev);
+	struct rockchip_saradc_data *data;
+
+	data = (struct rockchip_saradc_data *)dev_get_driver_data(dev);
+	priv->regs = (struct rockchip_saradc_regs *)dev_read_addr(dev);
+	if (priv->regs == (struct rockchip_saradc_regs *)FDT_ADDR_T_NONE) {
+		pr_err("Dev: %s - can't get address!", dev->name);
+		return -ENODATA;
+	}
+
+	priv->data = data;
+	uc_pdata->data_mask = (1 << priv->data->num_bits) - 1;;
+	uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
+	uc_pdata->data_timeout_us = SARADC_TIMEOUT / 5;
+	uc_pdata->channel_mask = (1 << priv->data->num_channels) - 1;
+
+	return 0;
+}
+
+static const struct adc_ops rockchip_saradc_ops = {
+	.start_channel = rockchip_saradc_start_channel,
+	.channel_data = rockchip_saradc_channel_data,
+	.stop = rockchip_saradc_stop,
+};
+
+static const struct rockchip_saradc_data saradc_data = {
+	.num_bits = 10,
+	.num_channels = 3,
+	.clk_rate = 1000000,
+};
+
+static const struct rockchip_saradc_data rk3066_tsadc_data = {
+	.num_bits = 12,
+	.num_channels = 2,
+	.clk_rate = 50000,
+};
+
+static const struct rockchip_saradc_data rk3399_saradc_data = {
+	.num_bits = 10,
+	.num_channels = 6,
+	.clk_rate = 1000000,
+};
+
+static const struct udevice_id rockchip_saradc_ids[] = {
+	{ .compatible = "rockchip,saradc",
+	  .data = (ulong)&saradc_data },
+	{ .compatible = "rockchip,rk3066-tsadc",
+	  .data = (ulong)&rk3066_tsadc_data },
+	{ .compatible = "rockchip,rk3399-saradc",
+	  .data = (ulong)&rk3399_saradc_data },
+	{ }
+};
+
+U_BOOT_DRIVER(rockchip_saradc) = {
+	.name		= "rockchip_saradc",
+	.id		= UCLASS_ADC,
+	.of_match	= rockchip_saradc_ids,
+	.ops		= &rockchip_saradc_ops,
+	.probe		= rockchip_saradc_probe,
+	.ofdata_to_platdata = rockchip_saradc_ofdata_to_platdata,
+	.priv_auto_alloc_size = sizeof(struct rockchip_saradc_priv),
+};
diff --git a/drivers/adc/sandbox.c b/drivers/adc/sandbox.c
index 3718922..80e8e37 100644
--- a/drivers/adc/sandbox.c
+++ b/drivers/adc/sandbox.c
@@ -61,7 +61,7 @@
 	/* For single-channel conversion mode, check if channel was selected */
 	if ((priv->conversion_mode == SANDBOX_ADC_MODE_SINGLE_CHANNEL) &&
 	    !(priv->active_channel_mask & (1 << channel))) {
-		error("Request for an inactive channel!");
+		pr_err("Request for an inactive channel!");
 		return -EINVAL;
 	}
 
@@ -82,12 +82,12 @@
 
 	/* Return error for single-channel conversion mode */
 	if (priv->conversion_mode == SANDBOX_ADC_MODE_SINGLE_CHANNEL) {
-		error("ADC in single-channel mode!");
+		pr_err("ADC in single-channel mode!");
 		return -EPERM;
 	}
 	/* Check channel selection */
 	if (!(priv->active_channel_mask & channel_mask)) {
-		error("Request for an inactive channel!");
+		pr_err("Request for an inactive channel!");
 		return -EINVAL;
 	}
 	/* The conversion must be started before reading the data */
diff --git a/drivers/ata/dwc_ahci.c b/drivers/ata/dwc_ahci.c
index f614798..b16304b 100644
--- a/drivers/ata/dwc_ahci.c
+++ b/drivers/ata/dwc_ahci.c
@@ -58,19 +58,19 @@
 
 	ret = generic_phy_get_by_name(dev, "sata-phy", &phy);
 	if (ret) {
-		error("can't get the phy from DT\n");
+		pr_err("can't get the phy from DT\n");
 		return ret;
 	}
 
 	ret = generic_phy_init(&phy);
 	if (ret) {
-		error("unable to initialize the sata phy\n");
+		pr_err("unable to initialize the sata phy\n");
 		return ret;
 	}
 
 	ret = generic_phy_power_on(&phy);
 	if (ret) {
-		error("unable to power on the sata phy\n");
+		pr_err("unable to power on the sata phy\n");
 		return ret;
 	}
 
diff --git a/drivers/bios_emulator/include/x86emu/x86emui.h b/drivers/bios_emulator/include/x86emu/x86emui.h
index a74957d..3537255 100644
--- a/drivers/bios_emulator/include/x86emu/x86emui.h
+++ b/drivers/bios_emulator/include/x86emu/x86emui.h
@@ -72,9 +72,6 @@
 #include <string.h>
 #endif
 
-#define printk printf
-
-
 /*--------------------------- Inline Functions ----------------------------*/
 
 #ifdef  __cplusplus
diff --git a/drivers/clk/clk_boston.c b/drivers/clk/clk_boston.c
index 78f1b75..5c05e3d 100644
--- a/drivers/clk/clk_boston.c
+++ b/drivers/clk/clk_boston.c
@@ -67,13 +67,13 @@
 	err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
 					   "regmap", &syscon);
 	if (err) {
-		error("unable to find syscon device\n");
+		pr_err("unable to find syscon device\n");
 		return err;
 	}
 
 	state->regmap = syscon_get_regmap(syscon);
 	if (!state->regmap) {
-		error("unable to find regmap\n");
+		pr_err("unable to find regmap\n");
 		return -ENODEV;
 	}
 
diff --git a/drivers/clk/clk_stm32f7.c b/drivers/clk/clk_stm32f7.c
index 255a583..96a06b8 100644
--- a/drivers/clk/clk_stm32f7.c
+++ b/drivers/clk/clk_stm32f7.c
@@ -224,7 +224,7 @@
 		return sysclk >>= shift;
 		break;
 	default:
-		error("clock index %ld out of range\n", clk->id);
+		pr_err("clock index %ld out of range\n", clk->id);
 		return -EINVAL;
 		break;
 	}
@@ -310,10 +310,11 @@
 };
 
 U_BOOT_DRIVER(stm32f7_clk) = {
-	.name		= "stm32f7_clk",
-	.id		= UCLASS_CLK,
-	.of_match	= stm32_clk_ids,
-	.ops		= &stm32_clk_ops,
-	.probe		= stm32_clk_probe,
-	.flags		= DM_FLAG_PRE_RELOC,
+	.name			= "stm32f7_clk",
+	.id			= UCLASS_CLK,
+	.of_match		= stm32_clk_ids,
+	.ops			= &stm32_clk_ops,
+	.probe			= stm32_clk_probe,
+	.priv_auto_alloc_size	= sizeof(struct stm32_clk),
+	.flags			= DM_FLAG_PRE_RELOC,
 };
diff --git a/drivers/clk/clk_stm32h7.c b/drivers/clk/clk_stm32h7.c
index fd0e3ab..931e5ef 100644
--- a/drivers/clk/clk_stm32h7.c
+++ b/drivers/clk/clk_stm32h7.c
@@ -472,13 +472,13 @@
 	clk.id = 0;
 	ret = uclass_get_device_by_name(UCLASS_CLK, name, &fixed_clock_dev);
 	if (ret) {
-		error("Can't find clk %s (%d)", name, ret);
+		pr_err("Can't find clk %s (%d)", name, ret);
 		return 0;
 	}
 
 	ret = clk_request(fixed_clock_dev, &clk);
 	if (ret) {
-		error("Can't request %s clk (%d)", name, ret);
+		pr_err("Can't request %s clk (%d)", name, ret);
 		return 0;
 	}
 
@@ -518,7 +518,7 @@
 		break;
 	case RCC_PLLCKSELR_PLLSRC_NO_CLK:
 		/* shouldn't happen */
-		error("wrong value for RCC_PLLCKSELR register\n");
+		pr_err("wrong value for RCC_PLLCKSELR register\n");
 		pllsrc = 0;
 		break;
 	}
@@ -695,7 +695,7 @@
 		break;
 
 	default:
-		error("unexpected gate_offset value (0x%x)\n", gate_offset);
+		pr_err("unexpected gate_offset value (0x%x)\n", gate_offset);
 		return -EINVAL;
 		break;
 	}
@@ -739,13 +739,13 @@
 					   "st,syscfg", &syscon);
 
 	if (err) {
-		error("unable to find syscon device\n");
+		pr_err("unable to find syscon device\n");
 		return err;
 	}
 
 	priv->pwr_regmap = syscon_get_regmap(syscon);
 	if (!priv->pwr_regmap) {
-		error("unable to find regmap\n");
+		pr_err("unable to find regmap\n");
 		return -ENODEV;
 	}
 
diff --git a/drivers/clk/rockchip/clk_rk322x.c b/drivers/clk/rockchip/clk_rk322x.c
index d7f6a3c..e87267d 100644
--- a/drivers/clk/rockchip/clk_rk322x.c
+++ b/drivers/clk/rockchip/clk_rk322x.c
@@ -117,16 +117,16 @@
 		     pclk_div << CORE_PERI_DIV_SHIFT);
 
 	/*
-	 * select apll as pd_bus bus clock source and
+	 * select gpll as pd_bus bus clock source and
 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
 	 */
 	aclk_div = GPLL_HZ / BUS_ACLK_HZ - 1;
 	assert((aclk_div + 1) * BUS_ACLK_HZ == GPLL_HZ && aclk_div <= 0x1f);
 
-	pclk_div = GPLL_HZ / BUS_PCLK_HZ - 1;
+	pclk_div = BUS_ACLK_HZ / BUS_PCLK_HZ - 1;
 	assert((pclk_div + 1) * BUS_PCLK_HZ == GPLL_HZ && pclk_div <= 0x7);
 
-	hclk_div = GPLL_HZ / BUS_HCLK_HZ - 1;
+	hclk_div = BUS_ACLK_HZ / BUS_HCLK_HZ - 1;
 	assert((hclk_div + 1) * BUS_HCLK_HZ == GPLL_HZ && hclk_div <= 0x3);
 
 	rk_clrsetreg(&cru->cru_clksel_con[0],
@@ -389,7 +389,7 @@
 	/* The reset driver does not have a device node, so bind it here */
 	ret = device_bind_driver(gd->dm_root, "rk322x_sysreset", "reset", &dev);
 	if (ret)
-		debug("Warning: No RK3036 reset driver: ret=%d\n", ret);
+		debug("Warning: No RK322x reset driver: ret=%d\n", ret);
 
 	return 0;
 }
diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c
index 478195b..a133810 100644
--- a/drivers/clk/rockchip/clk_rk3288.c
+++ b/drivers/clk/rockchip/clk_rk3288.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <bitfield.h>
 #include <clk-uclass.h>
 #include <dm.h>
 #include <dt-structs.h>
@@ -111,6 +112,15 @@
 	PERI_ACLK_DIV_SHIFT	= 0,
 	PERI_ACLK_DIV_MASK	= 0x1f << PERI_ACLK_DIV_SHIFT,
 
+	/*
+	 * CLKSEL24
+	 * saradc_div_con:
+	 * clk_saradc=24MHz/(saradc_div_con+1)
+	 */
+	CLK_SARADC_DIV_CON_SHIFT	= 8,
+	CLK_SARADC_DIV_CON_MASK		= GENMASK(15, 8),
+	CLK_SARADC_DIV_CON_WIDTH	= 8,
+
 	SOCSTS_DPLL_LOCK	= 1 << 5,
 	SOCSTS_APLL_LOCK	= 1 << 6,
 	SOCSTS_CPLL_LOCK	= 1 << 7,
@@ -634,6 +644,31 @@
 	return rockchip_spi_get_clk(cru, gclk_rate, periph);
 }
 
+static ulong rockchip_saradc_get_clk(struct rk3288_cru *cru)
+{
+	u32 div, val;
+
+	val = readl(&cru->cru_clksel_con[24]);
+	div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
+			       CLK_SARADC_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rockchip_saradc_set_clk(struct rk3288_cru *cru, uint hz)
+{
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
+	assert(src_clk_div < 128);
+
+	rk_clrsetreg(&cru->cru_clksel_con[24],
+		     CLK_SARADC_DIV_CON_MASK,
+		     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
+
+	return rockchip_saradc_get_clk(cru);
+}
+
 static ulong rk3288_clk_get_rate(struct clk *clk)
 {
 	struct rk3288_clk_priv *priv = dev_get_priv(clk->dev);
@@ -666,6 +701,9 @@
 		return gclk_rate;
 	case PCLK_PWM:
 		return PD_BUS_PCLK_HZ;
+	case SCLK_SARADC:
+		new_rate = rockchip_saradc_get_clk(priv->cru);
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -756,6 +794,9 @@
 		new_rate = rate;
 		break;
 #endif
+	case SCLK_SARADC:
+		new_rate = rockchip_saradc_set_clk(priv->cru, rate);
+		break;
 	default:
 		return -ENOENT;
 	}
diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c
index c3a6650..540d910 100644
--- a/drivers/clk/rockchip/clk_rk3328.c
+++ b/drivers/clk/rockchip/clk_rk3328.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <bitfield.h>
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
@@ -114,7 +115,8 @@
 
 	/* CLKSEL_CON23 */
 	CLK_SARADC_DIV_CON_SHIFT	= 0,
-	CLK_SARADC_DIV_CON_MASK		= 0x3ff << CLK_SARADC_DIV_CON_SHIFT,
+	CLK_SARADC_DIV_CON_MASK		= GENMASK(9, 0),
+	CLK_SARADC_DIV_CON_WIDTH	= 10,
 
 	/* CLKSEL_CON24 */
 	CLK_PWM_PLL_SEL_CPLL		= 0,
@@ -478,6 +480,31 @@
 	return DIV_TO_RATE(GPLL_HZ, div);
 }
 
+static ulong rk3328_saradc_get_clk(struct rk3328_cru *cru)
+{
+	u32 div, val;
+
+	val = readl(&cru->clksel_con[23]);
+	div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
+			       CLK_SARADC_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rk3328_saradc_set_clk(struct rk3328_cru *cru, uint hz)
+{
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
+	assert(src_clk_div < 128);
+
+	rk_clrsetreg(&cru->clksel_con[23],
+		     CLK_SARADC_DIV_CON_MASK,
+		     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
+
+	return rk3328_saradc_get_clk(cru);
+}
+
 static ulong rk3328_clk_get_rate(struct clk *clk)
 {
 	struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
@@ -501,6 +528,9 @@
 	case SCLK_PWM:
 		rate = rk3328_pwm_get_clk(priv->cru);
 		break;
+	case SCLK_SARADC:
+		rate = rk3328_saradc_get_clk(priv->cru);
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -531,6 +561,9 @@
 	case SCLK_PWM:
 		ret = rk3328_pwm_set_clk(priv->cru, rate);
 		break;
+	case SCLK_SARADC:
+		ret = rk3328_saradc_set_clk(priv->cru, rate);
+		break;
 	default:
 		return -ENOENT;
 	}
diff --git a/drivers/clk/rockchip/clk_rk3368.c b/drivers/clk/rockchip/clk_rk3368.c
index e274781..3661769 100644
--- a/drivers/clk/rockchip/clk_rk3368.c
+++ b/drivers/clk/rockchip/clk_rk3368.c
@@ -12,6 +12,7 @@
 #include <errno.h>
 #include <mapmem.h>
 #include <syscon.h>
+#include <bitfield.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/cru_rk3368.h>
 #include <asm/arch/hardware.h>
@@ -301,7 +302,7 @@
 		dpll_cfg = &dpll_1600;
 		break;
 	default:
-		error("Unsupported SDRAM frequency!,%ld\n", set_rate);
+		pr_err("Unsupported SDRAM frequency!,%ld\n", set_rate);
 	}
 	rkclk_set_pll(cru, DPLL, dpll_cfg);
 
@@ -359,7 +360,7 @@
 		break;
 
 	default:
-		error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
+		pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
 		return -EINVAL;
 	}
 
@@ -384,7 +385,7 @@
 		break;
 
 	default:
-		error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
+		pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
 		return -EINVAL;
 	}
 
@@ -397,6 +398,31 @@
 	return rk3368_spi_get_clk(cru, clk_id);
 }
 
+static ulong rk3368_saradc_get_clk(struct rk3368_cru *cru)
+{
+	u32 div, val;
+
+	val = readl(&cru->clksel_con[25]);
+	div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
+			       CLK_SARADC_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rk3368_saradc_set_clk(struct rk3368_cru *cru, uint hz)
+{
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
+	assert(src_clk_div < 128);
+
+	rk_clrsetreg(&cru->clksel_con[25],
+		     CLK_SARADC_DIV_CON_MASK,
+		     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
+
+	return rk3368_saradc_get_clk(cru);
+}
+
 static ulong rk3368_clk_get_rate(struct clk *clk)
 {
 	struct rk3368_clk_priv *priv = dev_get_priv(clk->dev);
@@ -419,6 +445,9 @@
 		rate = rk3368_mmc_get_clk(priv->cru, clk->id);
 		break;
 #endif
+	case SCLK_SARADC:
+		rate = rk3368_saradc_get_clk(priv->cru);
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -453,6 +482,9 @@
 		ret = rk3368_gmac_set_clk(priv->cru, clk->id, rate);
 		break;
 #endif
+	case SCLK_SARADC:
+		ret =  rk3368_saradc_set_clk(priv->cru, rate);
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -498,7 +530,7 @@
 	/* The reset driver does not have a device node, so bind it here */
 	ret = device_bind_driver(gd->dm_root, "rk3368_sysreset", "reset", &dev);
 	if (ret)
-		error("bind RK3368 reset driver failed: ret=%d\n", ret);
+		pr_err("bind RK3368 reset driver failed: ret=%d\n", ret);
 
 	return ret;
 }
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index 9d963be..f45bba4 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -12,6 +12,7 @@
 #include <errno.h>
 #include <mapmem.h>
 #include <syscon.h>
+#include <bitfield.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/cru_rk3399.h>
@@ -181,7 +182,8 @@
 
 	/* CLKSEL_CON26 */
 	CLK_SARADC_DIV_CON_SHIFT	= 8,
-	CLK_SARADC_DIV_CON_MASK		= 0xff << CLK_SARADC_DIV_CON_SHIFT,
+	CLK_SARADC_DIV_CON_MASK		= GENMASK(15, 8),
+	CLK_SARADC_DIV_CON_WIDTH	= 8,
 
 	/* CLKSEL_CON27 */
 	CLK_TSADC_SEL_X24M		= 0x0,
@@ -661,7 +663,7 @@
 		break;
 
 	default:
-		error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
+		pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
 		return -EINVAL;
 	}
 
@@ -685,7 +687,7 @@
 		break;
 
 	default:
-		error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
+		pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
 		return -EINVAL;
 	}
 
@@ -854,12 +856,38 @@
 		{.refdiv = 1, .fbdiv = 116, .postdiv1 = 3, .postdiv2 = 1};
 		break;
 	default:
-		error("Unsupported SDRAM frequency!,%ld\n", set_rate);
+		pr_err("Unsupported SDRAM frequency!,%ld\n", set_rate);
 	}
 	rkclk_set_pll(&cru->dpll_con[0], &dpll_cfg);
 
 	return set_rate;
 }
+
+static ulong rk3399_saradc_get_clk(struct rk3399_cru *cru)
+{
+	u32 div, val;
+
+	val = readl(&cru->clksel_con[26]);
+	div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
+			       CLK_SARADC_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rk3399_saradc_set_clk(struct rk3399_cru *cru, uint hz)
+{
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
+	assert(src_clk_div < 128);
+
+	rk_clrsetreg(&cru->clksel_con[26],
+		     CLK_SARADC_DIV_CON_MASK,
+		     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
+
+	return rk3399_saradc_get_clk(cru);
+}
+
 static ulong rk3399_clk_get_rate(struct clk *clk)
 {
 	struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
@@ -895,6 +923,9 @@
 		break;
 	case PCLK_EFUSE1024NS:
 		break;
+	case SCLK_SARADC:
+		rate = rk3399_saradc_get_clk(priv->cru);
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -943,6 +974,9 @@
 		break;
 	case PCLK_EFUSE1024NS:
 		break;
+	case SCLK_SARADC:
+		ret = rk3399_saradc_set_clk(priv->cru, rate);
+		break;
 	default:
 		return -ENOENT;
 	}
diff --git a/drivers/clk/rockchip/clk_rv1108.c b/drivers/clk/rockchip/clk_rv1108.c
index cf966bb..55741c3 100644
--- a/drivers/clk/rockchip/clk_rv1108.c
+++ b/drivers/clk/rockchip/clk_rv1108.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <bitfield.h>
 #include <clk-uclass.h>
 #include <dm.h>
 #include <errno.h>
@@ -36,7 +37,7 @@
 			 #hz "Hz cannot be hit with PLL "\
 			 "divisors on line " __stringify(__LINE__));
 
-/* use interge mode*/
+/* use integer mode */
 static inline int rv1108_pll_id(enum rk_clk_id clk_id)
 {
 	int id = 0;
@@ -130,6 +131,31 @@
 	return DIV_TO_RATE(pll_rate, div);
 }
 
+static ulong rv1108_saradc_get_clk(struct rv1108_cru *cru)
+{
+	u32 div, val;
+
+	val = readl(&cru->clksel_con[22]);
+	div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
+			       CLK_SARADC_DIV_CON_WIDTH);
+
+	return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rv1108_saradc_set_clk(struct rv1108_cru *cru, uint hz)
+{
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
+	assert(src_clk_div < 128);
+
+	rk_clrsetreg(&cru->clksel_con[22],
+		     CLK_SARADC_DIV_CON_MASK,
+		     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
+
+	return rv1108_saradc_get_clk(cru);
+}
+
 static ulong rv1108_clk_get_rate(struct clk *clk)
 {
 	struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
@@ -137,6 +163,8 @@
 	switch (clk->id) {
 	case 0 ... 63:
 		return rkclk_pll_get_rate(priv->cru, clk->id);
+	case SCLK_SARADC:
+		return rv1108_saradc_get_clk(priv->cru);
 	default:
 		return -ENOENT;
 	}
@@ -154,6 +182,9 @@
 	case SCLK_SFC:
 		new_rate = rv1108_sfc_set_clk(priv->cru, rate);
 		break;
+	case SCLK_SARADC:
+		new_rate = rv1108_saradc_set_clk(priv->cru, rate);
+		break;
 	default:
 		return -ENOENT;
 	}
@@ -196,7 +227,7 @@
 	/* The reset driver does not have a device node, so bind it here */
 	ret = device_bind_driver(gd->dm_root, "rv1108_sysreset", "reset", &dev);
 	if (ret)
-		error("No Rv1108 reset driver: ret=%d\n", ret);
+		pr_err("No Rv1108 reset driver: ret=%d\n", ret);
 
 	return 0;
 }
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 7afef1f..e8ba20c 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -45,6 +45,12 @@
 	  This will cause dm_warn() to be compiled out - it will do nothing
 	  when called.
 
+config DM_DEBUG
+	bool "Enable debug messages in driver model core"
+	depends on DM
+	help
+	  Say Y here if you want to compile in debug messages in DM core.
+
 config DM_DEVICE_REMOVE
 	bool "Support device removal"
 	depends on DM
diff --git a/drivers/core/Makefile b/drivers/core/Makefile
index 3d68c70..a5039c5 100644
--- a/drivers/core/Makefile
+++ b/drivers/core/Makefile
@@ -16,3 +16,5 @@
 obj-$(CONFIG_OF_CONTROL) += read.o
 endif
 obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o
+
+ccflags-$(CONFIG_DM_DEBUG) += -DDEBUG
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 5463d1f..de63e53 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -161,7 +161,7 @@
 	}
 
 	if (parent)
-		dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
+		pr_debug("Bound device %s to %s\n", dev->name, parent->name);
 	if (devp)
 		*devp = dev;
 
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index 6067914..6fa5d10 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -139,12 +139,13 @@
 	if (devp)
 		*devp = NULL;
 	name = ofnode_get_name(node);
-	dm_dbg("bind node %s\n", name);
+	pr_debug("bind node %s\n", name);
 
 	compat_list = ofnode_get_property(node, "compatible", &compat_length);
 	if (!compat_list) {
 		if (compat_length == -FDT_ERR_NOTFOUND) {
-			dm_dbg("Device '%s' has no compatible string\n", name);
+			pr_debug("Device '%s' has no compatible string\n",
+				 name);
 			return 0;
 		}
 
@@ -159,8 +160,8 @@
 	 */
 	for (i = 0; i < compat_length; i += strlen(compat) + 1) {
 		compat = compat_list + i;
-		dm_dbg("   - attempt to match compatible string '%s'\n",
-		       compat);
+		pr_debug("   - attempt to match compatible string '%s'\n",
+			 compat);
 
 		for (entry = driver; entry != driver + n_ents; entry++) {
 			ret = driver_check_compatible(entry->of_match, &id,
@@ -171,11 +172,11 @@
 		if (entry == driver + n_ents)
 			continue;
 
-		dm_dbg("   - found match at '%s'\n", entry->name);
+		pr_debug("   - found match at '%s'\n", entry->name);
 		ret = device_bind_with_driver_data(parent, entry, name,
 						   id->data, node, &dev);
 		if (ret == -ENODEV) {
-			dm_dbg("Driver '%s' refuses to bind\n", entry->name);
+			pr_debug("Driver '%s' refuses to bind\n", entry->name);
 			continue;
 		}
 		if (ret) {
@@ -191,7 +192,7 @@
 	}
 
 	if (!found && !result && ret != -ENODEV)
-		dm_dbg("No match for node '%s'\n", name);
+		pr_debug("No match for node '%s'\n", name);
 
 	return result;
 }
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 757d109..976e2c4 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -227,7 +227,7 @@
 		    !of_find_property(np, "u-boot,dm-pre-reloc", NULL))
 			continue;
 		if (!of_device_is_available(np)) {
-			dm_dbg("   - ignoring disabled device\n");
+			pr_debug("   - ignoring disabled device\n");
 			continue;
 		}
 		err = lists_bind_fdt(parent, np_to_ofnode(np), NULL);
@@ -270,7 +270,7 @@
 		    !dm_fdt_pre_reloc(blob, offset))
 			continue;
 		if (!fdtdec_get_is_enabled(blob, offset)) {
-			dm_dbg("   - ignoring disabled device\n");
+			pr_debug("   - ignoring disabled device\n");
 			continue;
 		}
 		err = lists_bind_fdt(parent, offset_to_ofnode(offset), NULL);
diff --git a/drivers/core/util.c b/drivers/core/util.c
index 2e232d5..aaaed4e 100644
--- a/drivers/core/util.c
+++ b/drivers/core/util.c
@@ -20,17 +20,6 @@
 }
 #endif
 
-#ifdef DEBUG
-void dm_dbg(const char *fmt, ...)
-{
-	va_list args;
-
-	va_start(args, fmt);
-	vprintf(fmt, args);
-	va_end(args);
-}
-#endif
-
 int list_count_items(struct list_head *head)
 {
 	struct list_head *node;
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index ff732ac..2c22b62 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -64,14 +64,14 @@
 #endif
 	str_env = env_get("dfu_alt_info");
 	if (!str_env) {
-		error("\"dfu_alt_info\" env variable not defined!\n");
+		pr_err("\"dfu_alt_info\" env variable not defined!\n");
 		return -EINVAL;
 	}
 
 	env_bkp = strdup(str_env);
 	ret = dfu_config_entities(env_bkp, interface, devstr);
 	if (ret) {
-		error("DFU entities configuration failed!\n");
+		pr_err("DFU entities configuration failed!\n");
 		return ret;
 	}
 
@@ -132,7 +132,7 @@
 		return s;
 	}
 
-	error("DFU hash method: %s not supported!\n", s);
+	pr_err("DFU hash method: %s not supported!\n", s);
 	return NULL;
 }
 
@@ -273,7 +273,7 @@
 
 	/* we should be in buffer now (if not then size too large) */
 	if ((dfu->i_buf + size) > dfu->i_buf_end) {
-		error("Buffer overflow! (0x%p + 0x%x > 0x%p)\n", dfu->i_buf,
+		pr_err("Buffer overflow! (0x%p + 0x%x > 0x%p)\n", dfu->i_buf,
 		      size, dfu->i_buf_end);
 		dfu_transaction_cleanup(dfu);
 		return -1;
@@ -451,7 +451,7 @@
 	if (s) {
 		ret = hash_lookup_algo(s, &dfu_hash_algo);
 		if (ret)
-			error("Hash algorithm %s not supported\n", s);
+			pr_err("Hash algorithm %s not supported\n", s);
 	}
 
 	dfu = calloc(sizeof(*dfu), dfu_alt_num);
@@ -576,7 +576,7 @@
 		      dp, left, write);
 		ret = dfu_write(dfu, dp, write, i);
 		if (ret) {
-			error("DFU write failed\n");
+			pr_err("DFU write failed\n");
 			return ret;
 		}
 
@@ -586,7 +586,7 @@
 
 	ret = dfu_flush(dfu, NULL, 0, i);
 	if (ret)
-		error("DFU flush failed!");
+		pr_err("DFU flush failed!");
 
 	return ret;
 }
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index 39e10b1..47948d3 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -29,7 +29,7 @@
 
 	mmc = find_mmc_device(dfu->data.mmc.dev_num);
 	if (!mmc) {
-		error("Device MMC %d - not found!", dfu->data.mmc.dev_num);
+		pr_err("Device MMC %d - not found!", dfu->data.mmc.dev_num);
 		return -ENODEV;
 	}
 
@@ -69,11 +69,11 @@
 			       buf);
 		break;
 	default:
-		error("Operation not supported\n");
+		pr_err("Operation not supported\n");
 	}
 
 	if (n != blk_count) {
-		error("MMC operation failed");
+		pr_err("MMC operation failed");
 		if (dfu->data.mmc.hw_partition >= 0)
 			blk_select_hwpart_devnum(IF_TYPE_MMC,
 						 dfu->data.mmc.dev_num,
@@ -312,7 +312,7 @@
 	for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) {
 		*parg = strsep(&s, " ");
 		if (*parg == NULL) {
-			error("Invalid number of arguments.\n");
+			pr_err("Invalid number of arguments.\n");
 			return -ENODEV;
 		}
 	}
@@ -327,13 +327,13 @@
 
 	mmc = find_mmc_device(dfu->data.mmc.dev_num);
 	if (mmc == NULL) {
-		error("Couldn't find MMC device no. %d.\n",
+		pr_err("Couldn't find MMC device no. %d.\n",
 		      dfu->data.mmc.dev_num);
 		return -ENODEV;
 	}
 
 	if (mmc_init(mmc)) {
-		error("Couldn't init MMC device.\n");
+		pr_err("Couldn't init MMC device.\n");
 		return -ENODEV;
 	}
 
@@ -360,7 +360,7 @@
 		int mmcpart = third_arg;
 
 		if (part_get_info(blk_dev, mmcpart, &partinfo) != 0) {
-			error("Couldn't find part #%d on mmc device #%d\n",
+			pr_err("Couldn't find part #%d on mmc device #%d\n",
 			      mmcpart, mmcdev);
 			return -ENODEV;
 		}
@@ -374,7 +374,7 @@
 	} else if (!strcmp(entity_type, "ext4")) {
 		dfu->layout = DFU_FS_EXT4;
 	} else {
-		error("Memory layout (%s) not supported!\n", entity_type);
+		pr_err("Memory layout (%s) not supported!\n", entity_type);
 		return -ENODEV;
 	}
 
@@ -397,7 +397,7 @@
 		dfu_file_buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
 					CONFIG_SYS_DFU_MAX_FILE_SIZE);
 		if (!dfu_file_buf) {
-			error("Could not memalign 0x%x bytes",
+			pr_err("Could not memalign 0x%x bytes",
 			      CONFIG_SYS_DFU_MAX_FILE_SIZE);
 			return -ENOMEM;
 		}
diff --git a/drivers/dfu/dfu_ram.c b/drivers/dfu/dfu_ram.c
index 6e3f531..2b5e05a 100644
--- a/drivers/dfu/dfu_ram.c
+++ b/drivers/dfu/dfu_ram.c
@@ -18,12 +18,12 @@
 				   u64 offset, void *buf, long *len)
 {
 	if (dfu->layout != DFU_RAM_ADDR) {
-		error("unsupported layout: %s\n", dfu_get_layout(dfu->layout));
+		pr_err("unsupported layout: %s\n", dfu_get_layout(dfu->layout));
 		return  -EINVAL;
 	}
 
 	if (offset > dfu->data.ram.size) {
-		error("request exceeds allowed area\n");
+		pr_err("request exceeds allowed area\n");
 		return -EINVAL;
 	}
 
@@ -62,14 +62,14 @@
 	for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) {
 		*parg = strsep(&s, " ");
 		if (*parg == NULL) {
-			error("Invalid number of arguments.\n");
+			pr_err("Invalid number of arguments.\n");
 			return -ENODEV;
 		}
 	}
 
 	dfu->dev_type = DFU_DEV_RAM;
 	if (strcmp(argv[0], "ram")) {
-		error("unsupported device: %s\n", argv[0]);
+		pr_err("unsupported device: %s\n", argv[0]);
 		return -ENODEV;
 	}
 
diff --git a/drivers/dfu/dfu_tftp.c b/drivers/dfu/dfu_tftp.c
index cd71708..62bf797 100644
--- a/drivers/dfu/dfu_tftp.c
+++ b/drivers/dfu/dfu_tftp.c
@@ -43,7 +43,7 @@
 	alt_setting_num = dfu_get_alt(sb);
 	free(sb);
 	if (alt_setting_num < 0) {
-		error("Alt setting [%d] to write not found!",
+		pr_err("Alt setting [%d] to write not found!",
 		      alt_setting_num);
 		ret = -ENODEV;
 		goto done;
@@ -51,7 +51,7 @@
 
 	dfu = dfu_get_entity(alt_setting_num);
 	if (!dfu) {
-		error("DFU entity for alt: %d not found!", alt_setting_num);
+		pr_err("DFU entity for alt: %d not found!", alt_setting_num);
 		ret = -ENODEV;
 		goto done;
 	}
diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c
index ea21fd9..3d0ce22 100644
--- a/drivers/dma/dma-uclass.c
+++ b/drivers/dma/dma-uclass.c
@@ -33,7 +33,7 @@
 	}
 
 	if (!dev) {
-		error("No DMA device found that supports %x type\n",
+		pr_err("No DMA device found that supports %x type\n",
 		      transfer_type);
 		return -EPROTONOSUPPORT;
 	}
diff --git a/drivers/dma/lpc32xx_dma.c b/drivers/dma/lpc32xx_dma.c
index 955adfe..63a8a2f 100644
--- a/drivers/dma/lpc32xx_dma.c
+++ b/drivers/dma/lpc32xx_dma.c
@@ -96,7 +96,7 @@
 {
 	if (unlikely(((BIT_MASK(channel) & alloc_ch) == 0) ||
 		     (channel >= DMA_NO_OF_CHANNELS))) {
-		error("Request for xfer on unallocated channel %d", channel);
+		pr_err("Request for xfer on unallocated channel %d", channel);
 		return -1;
 	}
 	writel(BIT_MASK(channel), &dma->int_tc_clear);
@@ -117,7 +117,7 @@
 
 	/* Check if given channel is valid */
 	if (unlikely(channel >= DMA_NO_OF_CHANNELS)) {
-		error("Request for status on unallocated channel %d", channel);
+		pr_err("Request for status on unallocated channel %d", channel);
 		return -1;
 	}
 
@@ -129,7 +129,7 @@
 			break;
 
 		if (get_timer(start) > CONFIG_SYS_HZ) {
-			error("DMA status timeout channel %d\n", channel);
+			pr_err("DMA status timeout channel %d\n", channel);
 			return -ETIMEDOUT;
 		}
 		udelay(1);
@@ -138,7 +138,7 @@
 	if (unlikely(readl(&dma->raw_err_stat) & BIT_MASK(channel))) {
 		setbits_le32(&dma->int_err_clear, BIT_MASK(channel));
 		setbits_le32(&dma->raw_err_stat, BIT_MASK(channel));
-		error("DMA error on channel %d\n", channel);
+		pr_err("DMA error on channel %d\n", channel);
 		return -1;
 	}
 	setbits_le32(&dma->int_tc_clear, BIT_MASK(channel));
diff --git a/drivers/dma/ti-edma3.c b/drivers/dma/ti-edma3.c
index 39e9793..635eb78 100644
--- a/drivers/dma/ti-edma3.c
+++ b/drivers/dma/ti-edma3.c
@@ -491,7 +491,7 @@
 		__edma3_transfer(priv->base, 1, dst, src, len);
 		break;
 	default:
-		error("Transfer type not implemented in DMA driver\n");
+		pr_err("Transfer type not implemented in DMA driver\n");
 		break;
 	}
 
diff --git a/drivers/i2c/i2c-gpio.c b/drivers/i2c/i2c-gpio.c
index aeeb304..4e8fa21 100644
--- a/drivers/i2c/i2c-gpio.c
+++ b/drivers/i2c/i2c-gpio.c
@@ -322,7 +322,7 @@
 
 	return 0;
 error:
-	error("Can't get %s gpios! Error: %d", dev->name, ret);
+	pr_err("Can't get %s gpios! Error: %d", dev->name, ret);
 	return ret;
 }
 
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index c98c627..5d33815 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -755,7 +755,7 @@
 
 	ret = __omap24_i2c_setspeed(i2c_base, speed, &adap->waitdelay);
 	if (ret) {
-		error("%s: set i2c speed failed\n", __func__);
+		pr_err("%s: set i2c speed failed\n", __func__);
 		return ret;
 	}
 
diff --git a/drivers/i2c/rk_i2c.c b/drivers/i2c/rk_i2c.c
index 840b3f6..332280c 100644
--- a/drivers/i2c/rk_i2c.c
+++ b/drivers/i2c/rk_i2c.c
@@ -396,6 +396,7 @@
 	{ .compatible = "rockchip,rk3066-i2c" },
 	{ .compatible = "rockchip,rk3188-i2c" },
 	{ .compatible = "rockchip,rk3288-i2c" },
+	{ .compatible = "rockchip,rk3328-i2c" },
 	{ .compatible = "rockchip,rk3399-i2c" },
 	{ }
 };
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c
index bf5fefa..196f236 100644
--- a/drivers/i2c/stm32f7_i2c.c
+++ b/drivers/i2c/stm32f7_i2c.c
@@ -549,7 +549,7 @@
 	}
 
 	if (list_empty(solutions)) {
-		error("%s: no Prescaler solution\n", __func__);
+		pr_err("%s: no Prescaler solution\n", __func__);
 		ret = -EPERM;
 	}
 
@@ -627,7 +627,7 @@
 	}
 
 	if (!s) {
-		error("%s: no solution at all\n", __func__);
+		pr_err("%s: no solution at all\n", __func__);
 		ret = -EPERM;
 	}
 
@@ -643,14 +643,14 @@
 	int ret;
 
 	if (setup->speed >= STM32_I2C_SPEED_END) {
-		error("%s: speed out of bound {%d/%d}\n", __func__,
+		pr_err("%s: speed out of bound {%d/%d}\n", __func__,
 		      setup->speed, STM32_I2C_SPEED_END - 1);
 		return -EINVAL;
 	}
 
 	if ((setup->rise_time > i2c_specs[setup->speed].rise_max) ||
 	    (setup->fall_time > i2c_specs[setup->speed].fall_max)) {
-		error("%s :timings out of bound Rise{%d>%d}/Fall{%d>%d}\n",
+		pr_err("%s :timings out of bound Rise{%d>%d}/Fall{%d>%d}\n",
 		      __func__,
 		      setup->rise_time, i2c_specs[setup->speed].rise_max,
 		      setup->fall_time, i2c_specs[setup->speed].fall_max);
@@ -658,13 +658,13 @@
 	}
 
 	if (setup->dnf > STM32_I2C_DNF_MAX) {
-		error("%s: DNF out of bound %d/%d\n", __func__,
+		pr_err("%s: DNF out of bound %d/%d\n", __func__,
 		      setup->dnf, STM32_I2C_DNF_MAX);
 		return -EINVAL;
 	}
 
 	if (setup->speed_freq > i2c_specs[setup->speed].rate) {
-		error("%s: Freq {%d/%d}\n", __func__,
+		pr_err("%s: Freq {%d/%d}\n", __func__,
 		      setup->speed_freq, i2c_specs[setup->speed].rate);
 		return -EINVAL;
 	}
@@ -711,7 +711,7 @@
 	setup->clock_src = clk_get_rate(&i2c_priv->clk);
 
 	if (!setup->clock_src) {
-		error("%s: clock rate is 0\n", __func__);
+		pr_err("%s: clock rate is 0\n", __func__);
 		return -EINVAL;
 	}
 
@@ -734,7 +734,7 @@
 	} while (ret);
 
 	if (ret) {
-		error("%s: impossible to compute I2C timings.\n", __func__);
+		pr_err("%s: impossible to compute I2C timings.\n", __func__);
 		return ret;
 	}
 
diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c
index 3255e8e..7d23e51 100644
--- a/drivers/i2c/tegra_i2c.c
+++ b/drivers/i2c/tegra_i2c.c
@@ -372,12 +372,12 @@
 
 	ret = reset_get_by_name(dev, "i2c", &i2c_bus->reset_ctl);
 	if (ret) {
-		error("reset_get_by_name() failed: %d\n", ret);
+		pr_err("reset_get_by_name() failed: %d\n", ret);
 		return ret;
 	}
 	ret = clk_get_by_name(dev, "div-clk", &i2c_bus->clk);
 	if (ret) {
-		error("clk_get_by_name() failed: %d\n", ret);
+		pr_err("clk_get_by_name() failed: %d\n", ret);
 		return ret;
 	}
 
diff --git a/drivers/misc/tegra186_bpmp.c b/drivers/misc/tegra186_bpmp.c
index d61bacf..1fdf8ef 100644
--- a/drivers/misc/tegra186_bpmp.c
+++ b/drivers/misc/tegra186_bpmp.c
@@ -44,7 +44,7 @@
 
 	ret = tegra_ivc_write_get_next_frame(&priv->ivc, &ivc_frame);
 	if (ret) {
-		error("tegra_ivc_write_get_next_frame() failed: %d\n", ret);
+		pr_err("tegra_ivc_write_get_next_frame() failed: %d\n", ret);
 		return ret;
 	}
 
@@ -55,7 +55,7 @@
 
 	ret = tegra_ivc_write_advance(&priv->ivc);
 	if (ret) {
-		error("tegra_ivc_write_advance() failed: %d\n", ret);
+		pr_err("tegra_ivc_write_advance() failed: %d\n", ret);
 		return ret;
 	}
 
@@ -63,7 +63,7 @@
 	for (;;) {
 		ret = tegra_ivc_channel_notified(&priv->ivc);
 		if (ret) {
-			error("tegra_ivc_channel_notified() failed: %d\n", ret);
+			pr_err("tegra_ivc_channel_notified() failed: %d\n", ret);
 			return ret;
 		}
 
@@ -73,7 +73,7 @@
 
 		/* Timeout 20ms; roughly 10x current max observed duration */
 		if ((timer_get_us() - start_time) > 20 * 1000) {
-			error("tegra_ivc_read_get_next_frame() timed out (%d)\n",
+			pr_err("tegra_ivc_read_get_next_frame() timed out (%d)\n",
 			      ret);
 			return -ETIMEDOUT;
 		}
@@ -86,12 +86,12 @@
 
 	ret = tegra_ivc_read_advance(&priv->ivc);
 	if (ret) {
-		error("tegra_ivc_write_advance() failed: %d\n", ret);
+		pr_err("tegra_ivc_write_advance() failed: %d\n", ret);
 		return ret;
 	}
 
 	if (err) {
-		error("BPMP responded with error %d\n", err);
+		pr_err("BPMP responded with error %d\n", err);
 		/* err isn't a U-Boot error code, so don't that */
 		return -EIO;
 	}
@@ -144,14 +144,14 @@
 	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
 					      "shmem", NULL, 0, index, &args);
 	if (ret < 0) {
-		error("fdtdec_parse_phandle_with_args() failed: %d\n", ret);
+		pr_err("fdtdec_parse_phandle_with_args() failed: %d\n", ret);
 		return ret;
 	}
 
 	reg = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, args.node,
 						 "reg", 0, NULL, true);
 	if (reg == FDT_ADDR_T_NONE) {
-		error("fdtdec_get_addr_size_auto_noparent() failed\n");
+		pr_err("fdtdec_get_addr_size_auto_noparent() failed\n");
 		return -ENODEV;
 	}
 
@@ -166,7 +166,7 @@
 
 	ret = mbox_send(&priv->mbox, NULL);
 	if (ret)
-		error("mbox_send() failed: %d\n", ret);
+		pr_err("mbox_send() failed: %d\n", ret);
 }
 
 static int tegra186_bpmp_probe(struct udevice *dev)
@@ -179,18 +179,18 @@
 
 	ret = mbox_get_by_index(dev, 0, &priv->mbox);
 	if (ret) {
-		error("mbox_get_by_index() failed: %d\n", ret);
+		pr_err("mbox_get_by_index() failed: %d\n", ret);
 		return ret;
 	}
 
 	tx_base = tegra186_bpmp_get_shmem(dev, 0);
 	if (IS_ERR_VALUE(tx_base)) {
-		error("tegra186_bpmp_get_shmem failed for tx_base\n");
+		pr_err("tegra186_bpmp_get_shmem failed for tx_base\n");
 		return tx_base;
 	}
 	rx_base = tegra186_bpmp_get_shmem(dev, 1);
 	if (IS_ERR_VALUE(rx_base)) {
-		error("tegra186_bpmp_get_shmem failed for rx_base\n");
+		pr_err("tegra186_bpmp_get_shmem failed for rx_base\n");
 		return rx_base;
 	}
 	debug("shmem: rx=%lx, tx=%lx\n", rx_base, tx_base);
@@ -198,7 +198,7 @@
 	ret = tegra_ivc_init(&priv->ivc, rx_base, tx_base, BPMP_IVC_FRAME_COUNT,
 			     BPMP_IVC_FRAME_SIZE, tegra186_bpmp_ivc_notify);
 	if (ret) {
-		error("tegra_ivc_init() failed: %d\n", ret);
+		pr_err("tegra_ivc_init() failed: %d\n", ret);
 		return ret;
 	}
 
@@ -211,7 +211,7 @@
 
 		/* Timeout 100ms */
 		if ((timer_get_us() - start_time) > 100 * 1000) {
-			error("Initial IVC reset timed out (%d)\n", ret);
+			pr_err("Initial IVC reset timed out (%d)\n", ret);
 			ret = -ETIMEDOUT;
 			goto err_free_mbox;
 		}
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 24b4ead..94050836 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -386,7 +386,7 @@
 
 config STM32_SDMMC2
 	bool "STMicroelectronics STM32H7 SD/MMC Host Controller support"
-	depends on DM_MMC && BLK && OF_CONTROL && DM_MMC_OPS
+	depends on DM_MMC && BLK && OF_CONTROL
 	help
 	  This selects support for the SD/MMC controller on STM32H7 SoCs.
 	  If you have a board based on such a SoC and with a SD/MMC slot,
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
index 40f7892..5edd383 100644
--- a/drivers/mmc/exynos_dw_mmc.c
+++ b/drivers/mmc/exynos_dw_mmc.c
@@ -155,7 +155,7 @@
 
 	priv = malloc(sizeof(struct dwmci_exynos_priv_data));
 	if (!priv) {
-		error("dwmci_exynos_priv_data malloc fail!\n");
+		pr_err("dwmci_exynos_priv_data malloc fail!\n");
 		return -ENOMEM;
 	}
 
diff --git a/drivers/mmc/hi6220_dw_mmc.c b/drivers/mmc/hi6220_dw_mmc.c
index d795198..44a8ef8 100644
--- a/drivers/mmc/hi6220_dw_mmc.c
+++ b/drivers/mmc/hi6220_dw_mmc.c
@@ -44,7 +44,7 @@
 
 	host = calloc(1, sizeof(struct dwmci_host));
 	if (!host) {
-		error("dwmci_host calloc failed!\n");
+		pr_err("dwmci_host calloc failed!\n");
 		return -ENOMEM;
 	}
 
diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c
index d8b5888..a98c1eb 100644
--- a/drivers/mmc/sti_sdhci.c
+++ b/drivers/mmc/sti_sdhci.c
@@ -43,7 +43,7 @@
 	if (plat->instance) {
 		ret = reset_deassert(&plat->reset);
 		if (ret < 0) {
-			error("MMC1 deassert failed: %d", ret);
+			pr_err("MMC1 deassert failed: %d", ret);
 			return ret;
 		}
 	}
diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c
index 0e1f40b..0bf7135 100644
--- a/drivers/mmc/stm32_sdmmc2.c
+++ b/drivers/mmc/stm32_sdmmc2.c
@@ -569,7 +569,7 @@
 	case 1:
 		break;
 	default:
-		error("invalid \"bus-width\" property, force to 1\n");
+		pr_err("invalid \"bus-width\" property, force to 1\n");
 	}
 
 	upriv->mmc = &plat->mmc;
diff --git a/drivers/mmc/xenon_sdhci.c b/drivers/mmc/xenon_sdhci.c
index 2b7cb7f..490a01f 100644
--- a/drivers/mmc/xenon_sdhci.c
+++ b/drivers/mmc/xenon_sdhci.c
@@ -159,7 +159,7 @@
 	}
 
 	if (time <= 0) {
-		error("Failed to enable MMC internal clock in time\n");
+		pr_err("Failed to enable MMC internal clock in time\n");
 		return -ETIMEDOUT;
 	}
 
@@ -187,7 +187,7 @@
 	}
 
 	if (time <= 0) {
-		error("Failed to init MMC PHY in time\n");
+		pr_err("Failed to init MMC PHY in time\n");
 		return -ETIMEDOUT;
 	}
 
diff --git a/drivers/mtd/nand/lpc32xx_nand_mlc.c b/drivers/mtd/nand/lpc32xx_nand_mlc.c
index 3af7e6d..e1b3670 100644
--- a/drivers/mtd/nand/lpc32xx_nand_mlc.c
+++ b/drivers/mtd/nand/lpc32xx_nand_mlc.c
@@ -583,21 +583,21 @@
 	/* identify chip */
 	ret = nand_scan_ident(mtd, CONFIG_SYS_MAX_NAND_CHIPS, NULL);
 	if (ret) {
-		error("nand_scan_ident returned %i", ret);
+		pr_err("nand_scan_ident returned %i", ret);
 		return;
 	}
 
 	/* finish scanning the chip */
 	ret = nand_scan_tail(mtd);
 	if (ret) {
-		error("nand_scan_tail returned %i", ret);
+		pr_err("nand_scan_tail returned %i", ret);
 		return;
 	}
 
 	/* chip is good, register it */
 	ret = nand_register(0, mtd);
 	if (ret)
-		error("nand_register returned %i", ret);
+		pr_err("nand_register returned %i", ret);
 }
 
 #else /* defined(CONFIG_SPL_BUILD) */
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 0042a7b..6ab3c8a 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1559,7 +1559,7 @@
 
 		pdata->num_cs = fdtdec_get_int(blob, node, "num-cs", 1);
 		if (pdata->num_cs != 1) {
-			error("pxa3xx driver supports single CS only\n");
+			pr_err("pxa3xx driver supports single CS only\n");
 			break;
 		}
 
diff --git a/drivers/net/bcm-sf2-eth-gmac.c b/drivers/net/bcm-sf2-eth-gmac.c
index 9ff72fa..a2b594e 100644
--- a/drivers/net/bcm-sf2-eth-gmac.c
+++ b/drivers/net/bcm-sf2-eth-gmac.c
@@ -610,7 +610,7 @@
 
 	/* Busy wait timeout is 1ms */
 	if (gmac_mii_busywait(1000)) {
-		error("%s: Prepare MII read: MII/MDIO busy\n", __func__);
+		pr_err("%s: Prepare MII read: MII/MDIO busy\n", __func__);
 		return -1;
 	}
 
@@ -622,7 +622,7 @@
 	writel(tmp, GMAC_MII_DATA_ADDR);
 
 	if (gmac_mii_busywait(1000)) {
-		error("%s: MII read failure: MII/MDIO busy\n", __func__);
+		pr_err("%s: MII read failure: MII/MDIO busy\n", __func__);
 		return -1;
 	}
 
@@ -638,7 +638,7 @@
 
 	/* Busy wait timeout is 1ms */
 	if (gmac_mii_busywait(1000)) {
-		error("%s: Prepare MII write: MII/MDIO busy\n", __func__);
+		pr_err("%s: Prepare MII write: MII/MDIO busy\n", __func__);
 		return -1;
 	}
 
@@ -651,7 +651,7 @@
 	writel(tmp, GMAC_MII_DATA_ADDR);
 
 	if (gmac_mii_busywait(1000)) {
-		error("%s: MII write failure: MII/MDIO busy\n", __func__);
+		pr_err("%s: MII write failure: MII/MDIO busy\n", __func__);
 		return -1;
 	}
 
@@ -742,7 +742,7 @@
 	} else if (speed == 10) {
 		speed_cfg = 0;
 	} else {
-		error("%s: Invalid GMAC speed(%d)!\n", __func__, speed);
+		pr_err("%s: Invalid GMAC speed(%d)!\n", __func__, speed);
 		return -1;
 	}
 
@@ -820,7 +820,7 @@
 	writel(0, GMAC0_INT_STATUS_ADDR);
 
 	if (dma_init(dma) < 0) {
-		error("%s: GMAC dma_init failed\n", __func__);
+		pr_err("%s: GMAC dma_init failed\n", __func__);
 		goto err_exit;
 	}
 
@@ -855,7 +855,7 @@
 	writel(tmp, GMAC_MII_CTRL_ADDR);
 
 	if (gmac_mii_busywait(1000)) {
-		error("%s: Configure MDIO: MII/MDIO busy\n", __func__);
+		pr_err("%s: Configure MDIO: MII/MDIO busy\n", __func__);
 		goto err_exit;
 	}
 
diff --git a/drivers/net/bcm-sf2-eth.c b/drivers/net/bcm-sf2-eth.c
index e274736..9056f71 100644
--- a/drivers/net/bcm-sf2-eth.c
+++ b/drivers/net/bcm-sf2-eth.c
@@ -40,7 +40,7 @@
 
 	rc = eth->mac_init(dev);
 	if (rc) {
-		error("%s: Couldn't cofigure MAC!\n", __func__);
+		pr_err("%s: Couldn't cofigure MAC!\n", __func__);
 		return rc;
 	}
 
@@ -90,7 +90,7 @@
 		debug(".");
 		i++;
 		if (i > 20) {
-			error("%s: Tx timeout: retried 20 times\n", __func__);
+			pr_err("%s: Tx timeout: retried 20 times\n", __func__);
 			rc = -1;
 			break;
 		}
@@ -117,7 +117,7 @@
 			debug("\nNO More Rx\n");
 			break;
 		} else if ((rcvlen == 0) || (rcvlen > RX_BUF_SIZE)) {
-			error("%s: Wrong Ethernet packet size (%d B), skip!\n",
+			pr_err("%s: Wrong Ethernet packet size (%d B), skip!\n",
 			      __func__, rcvlen);
 			break;
 		} else {
@@ -166,9 +166,9 @@
 	 */
 	for (i = 0; i < eth->port_num; i++) {
 		if (phy_startup(eth->port[i])) {
-			error("%s: PHY %d startup failed!\n", __func__, i);
+			pr_err("%s: PHY %d startup failed!\n", __func__, i);
 			if (i == CONFIG_BCM_SF2_ETH_DEFAULT_PORT) {
-				error("%s: No default port %d!\n", __func__, i);
+				pr_err("%s: No default port %d!\n", __func__, i);
 				return -1;
 			}
 		}
@@ -205,13 +205,13 @@
 
 	dev = (struct eth_device *)malloc(sizeof(struct eth_device));
 	if (dev == NULL) {
-		error("%s: Not enough memory!\n", __func__);
+		pr_err("%s: Not enough memory!\n", __func__);
 		return -1;
 	}
 
 	eth = (struct eth_info *)malloc(sizeof(struct eth_info));
 	if (eth == NULL) {
-		error("%s: Not enough memory!\n", __func__);
+		pr_err("%s: Not enough memory!\n", __func__);
 		return -1;
 	}
 
@@ -234,7 +234,7 @@
 	if (gmac_add(dev)) {
 		free(eth);
 		free(dev);
-		error("%s: Adding GMAC failed!\n", __func__);
+		pr_err("%s: Adding GMAC failed!\n", __func__);
 		return -1;
 	}
 #else
@@ -263,7 +263,7 @@
 
 	rc = bcm_sf2_eth_init(dev);
 	if (rc != 0) {
-		error("%s: configuration failed!\n", __func__);
+		pr_err("%s: configuration failed!\n", __func__);
 		return -1;
 	}
 
diff --git a/drivers/net/cpsw-common.c b/drivers/net/cpsw-common.c
index 8970ee0..0dc83ab 100644
--- a/drivers/net/cpsw-common.c
+++ b/drivers/net/cpsw-common.c
@@ -29,14 +29,14 @@
 
 	syscon = fdtdec_lookup_phandle(fdt, node, "syscon");
 	if (syscon < 0) {
-		error("Syscon offset not found\n");
+		pr_err("Syscon offset not found\n");
 		return -ENOENT;
 	}
 
 	addr = (u32)map_physmem(fdt_translate_address(fdt, syscon, &gmii),
 				sizeof(u32), MAP_NOCACHE);
 	if (addr == FDT_ADDR_T_NONE) {
-		error("Not able to get syscon address to get mac efuse address\n");
+		pr_err("Not able to get syscon address to get mac efuse address\n");
 		return -ENOENT;
 	}
 
@@ -69,14 +69,14 @@
 
 	syscon = fdtdec_lookup_phandle(fdt, node, "syscon");
 	if (syscon < 0) {
-		error("Syscon offset not found\n");
+		pr_err("Syscon offset not found\n");
 		return -ENOENT;
 	}
 
 	addr = (u32)map_physmem(fdt_translate_address(fdt, syscon, &gmii),
 				sizeof(u32), MAP_NOCACHE);
 	if (addr == FDT_ADDR_T_NONE) {
-		error("Not able to get syscon address to get mac efuse address\n");
+		pr_err("Not able to get syscon address to get mac efuse address\n");
 		return -ENOENT;
 	}
 
diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index d7db0fc..b72258f 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/cpsw.c
@@ -1368,7 +1368,7 @@
 
 			mdio_base = cpsw_get_addr_by_node(fdt, subnode);
 			if (mdio_base == FDT_ADDR_T_NONE) {
-				error("Not able to get MDIO address space\n");
+				pr_err("Not able to get MDIO address space\n");
 				return -ENOENT;
 			}
 			priv->data.mdio_base = mdio_base;
@@ -1407,7 +1407,7 @@
 								    subnode);
 
 			if (priv->data.gmii_sel == FDT_ADDR_T_NONE) {
-				error("Not able to get gmii_sel reg address\n");
+				pr_err("Not able to get gmii_sel reg address\n");
 				return -ENOENT;
 			}
 
@@ -1418,7 +1418,7 @@
 			phy_sel_compat = fdt_getprop(fdt, subnode, "compatible",
 						     NULL);
 			if (!phy_sel_compat) {
-				error("Not able to get gmii_sel compatible\n");
+				pr_err("Not able to get gmii_sel compatible\n");
 				return -ENOENT;
 			}
 		}
@@ -1434,7 +1434,7 @@
 
 	ret = ti_cm_get_macid(dev, active_slave, pdata->enetaddr);
 	if (ret < 0) {
-		error("cpsw read efuse mac failed\n");
+		pr_err("cpsw read efuse mac failed\n");
 		return ret;
 	}
 
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 5c4315f..00076cf 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -377,7 +377,7 @@
 
 	ret = eqos_mdio_wait_idle(eqos);
 	if (ret) {
-		error("MDIO not idle at entry");
+		pr_err("MDIO not idle at entry");
 		return ret;
 	}
 
@@ -397,7 +397,7 @@
 
 	ret = eqos_mdio_wait_idle(eqos);
 	if (ret) {
-		error("MDIO read didn't complete");
+		pr_err("MDIO read didn't complete");
 		return ret;
 	}
 
@@ -421,7 +421,7 @@
 
 	ret = eqos_mdio_wait_idle(eqos);
 	if (ret) {
-		error("MDIO not idle at entry");
+		pr_err("MDIO not idle at entry");
 		return ret;
 	}
 
@@ -443,7 +443,7 @@
 
 	ret = eqos_mdio_wait_idle(eqos);
 	if (ret) {
-		error("MDIO read didn't complete");
+		pr_err("MDIO read didn't complete");
 		return ret;
 	}
 
@@ -459,37 +459,37 @@
 
 	ret = clk_enable(&eqos->clk_slave_bus);
 	if (ret < 0) {
-		error("clk_enable(clk_slave_bus) failed: %d", ret);
+		pr_err("clk_enable(clk_slave_bus) failed: %d", ret);
 		goto err;
 	}
 
 	ret = clk_enable(&eqos->clk_master_bus);
 	if (ret < 0) {
-		error("clk_enable(clk_master_bus) failed: %d", ret);
+		pr_err("clk_enable(clk_master_bus) failed: %d", ret);
 		goto err_disable_clk_slave_bus;
 	}
 
 	ret = clk_enable(&eqos->clk_rx);
 	if (ret < 0) {
-		error("clk_enable(clk_rx) failed: %d", ret);
+		pr_err("clk_enable(clk_rx) failed: %d", ret);
 		goto err_disable_clk_master_bus;
 	}
 
 	ret = clk_enable(&eqos->clk_ptp_ref);
 	if (ret < 0) {
-		error("clk_enable(clk_ptp_ref) failed: %d", ret);
+		pr_err("clk_enable(clk_ptp_ref) failed: %d", ret);
 		goto err_disable_clk_rx;
 	}
 
 	ret = clk_set_rate(&eqos->clk_ptp_ref, 125 * 1000 * 1000);
 	if (ret < 0) {
-		error("clk_set_rate(clk_ptp_ref) failed: %d", ret);
+		pr_err("clk_set_rate(clk_ptp_ref) failed: %d", ret);
 		goto err_disable_clk_ptp_ref;
 	}
 
 	ret = clk_enable(&eqos->clk_tx);
 	if (ret < 0) {
-		error("clk_enable(clk_tx) failed: %d", ret);
+		pr_err("clk_enable(clk_tx) failed: %d", ret);
 		goto err_disable_clk_ptp_ref;
 	}
 
@@ -533,7 +533,7 @@
 
 	ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1);
 	if (ret < 0) {
-		error("dm_gpio_set_value(phy_reset, assert) failed: %d", ret);
+		pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", ret);
 		return ret;
 	}
 
@@ -541,13 +541,13 @@
 
 	ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
 	if (ret < 0) {
-		error("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret);
+		pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret);
 		return ret;
 	}
 
 	ret = reset_assert(&eqos->reset_ctl);
 	if (ret < 0) {
-		error("reset_assert() failed: %d", ret);
+		pr_err("reset_assert() failed: %d", ret);
 		return ret;
 	}
 
@@ -555,7 +555,7 @@
 
 	ret = reset_deassert(&eqos->reset_ctl);
 	if (ret < 0) {
-		error("reset_deassert() failed: %d", ret);
+		pr_err("reset_deassert() failed: %d", ret);
 		return ret;
 	}
 
@@ -591,14 +591,14 @@
 	ret = wait_for_bit(__func__, &eqos->tegra186_regs->auto_cal_status,
 			   EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false);
 	if (ret) {
-		error("calibrate didn't start");
+		pr_err("calibrate didn't start");
 		goto failed;
 	}
 
 	ret = wait_for_bit(__func__, &eqos->tegra186_regs->auto_cal_status,
 			   EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false);
 	if (ret) {
-		error("calibrate didn't finish");
+		pr_err("calibrate didn't finish");
 		goto failed;
 	}
 
@@ -713,13 +713,13 @@
 		rate = 2.5 * 1000 * 1000;
 		break;
 	default:
-		error("invalid speed %d", eqos->phy->speed);
+		pr_err("invalid speed %d", eqos->phy->speed);
 		return -EINVAL;
 	}
 
 	ret = clk_set_rate(&eqos->clk_tx, rate);
 	if (ret < 0) {
-		error("clk_set_rate(tx_clk, %lu) failed: %d", rate, ret);
+		pr_err("clk_set_rate(tx_clk, %lu) failed: %d", rate, ret);
 		return ret;
 	}
 
@@ -739,7 +739,7 @@
 	else
 		ret = eqos_set_half_duplex(dev);
 	if (ret < 0) {
-		error("eqos_set_*_duplex() failed: %d", ret);
+		pr_err("eqos_set_*_duplex() failed: %d", ret);
 		return ret;
 	}
 
@@ -757,24 +757,24 @@
 		ret = eqos_set_mii_speed_10(dev);
 		break;
 	default:
-		error("invalid speed %d", eqos->phy->speed);
+		pr_err("invalid speed %d", eqos->phy->speed);
 		return -EINVAL;
 	}
 	if (ret < 0) {
-		error("eqos_set_*mii_speed*() failed: %d", ret);
+		pr_err("eqos_set_*mii_speed*() failed: %d", ret);
 		return ret;
 	}
 
 	if (en_calibration) {
 		ret = eqos_calibrate_pads_tegra186(dev);
 		if (ret < 0) {
-			error("eqos_calibrate_pads_tegra186() failed: %d", ret);
+			pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
 			return ret;
 		}
 	} else {
 		ret = eqos_disable_calibration_tegra186(dev);
 		if (ret < 0) {
-			error("eqos_disable_calibration_tegra186() failed: %d",
+			pr_err("eqos_disable_calibration_tegra186() failed: %d",
 			      ret);
 			return ret;
 		}
@@ -782,7 +782,7 @@
 
 	ret = eqos_set_tx_clk_speed_tegra186(dev);
 	if (ret < 0) {
-		error("eqos_set_tx_clk_speed_tegra186() failed: %d", ret);
+		pr_err("eqos_set_tx_clk_speed_tegra186() failed: %d", ret);
 		return ret;
 	}
 
@@ -848,13 +848,13 @@
 
 	ret = eqos_start_clks_tegra186(dev);
 	if (ret < 0) {
-		error("eqos_start_clks_tegra186() failed: %d", ret);
+		pr_err("eqos_start_clks_tegra186() failed: %d", ret);
 		goto err;
 	}
 
 	ret = eqos_start_resets_tegra186(dev);
 	if (ret < 0) {
-		error("eqos_start_resets_tegra186() failed: %d", ret);
+		pr_err("eqos_start_resets_tegra186() failed: %d", ret);
 		goto err_stop_clks;
 	}
 
@@ -865,13 +865,13 @@
 	ret = wait_for_bit(__func__, &eqos->dma_regs->mode,
 			   EQOS_DMA_MODE_SWR, false, 10, false);
 	if (ret) {
-		error("EQOS_DMA_MODE_SWR stuck");
+		pr_err("EQOS_DMA_MODE_SWR stuck");
 		goto err_stop_resets;
 	}
 
 	ret = eqos_calibrate_pads_tegra186(dev);
 	if (ret < 0) {
-		error("eqos_calibrate_pads_tegra186() failed: %d", ret);
+		pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
 		goto err_stop_resets;
 	}
 
@@ -881,28 +881,28 @@
 
 	eqos->phy = phy_connect(eqos->mii, 0, dev, 0);
 	if (!eqos->phy) {
-		error("phy_connect() failed");
+		pr_err("phy_connect() failed");
 		goto err_stop_resets;
 	}
 	ret = phy_config(eqos->phy);
 	if (ret < 0) {
-		error("phy_config() failed: %d", ret);
+		pr_err("phy_config() failed: %d", ret);
 		goto err_shutdown_phy;
 	}
 	ret = phy_startup(eqos->phy);
 	if (ret < 0) {
-		error("phy_startup() failed: %d", ret);
+		pr_err("phy_startup() failed: %d", ret);
 		goto err_shutdown_phy;
 	}
 
 	if (!eqos->phy->link) {
-		error("No link");
+		pr_err("No link");
 		goto err_shutdown_phy;
 	}
 
 	ret = eqos_adjust_link(dev);
 	if (ret < 0) {
-		error("eqos_adjust_link() failed: %d", ret);
+		pr_err("eqos_adjust_link() failed: %d", ret);
 		goto err_shutdown_phy;
 	}
 
@@ -1119,7 +1119,7 @@
 err_stop_clks:
 	eqos_stop_clks_tegra186(dev);
 err:
-	error("FAILED: %d", ret);
+	pr_err("FAILED: %d", ret);
 	return ret;
 }
 
@@ -1361,7 +1361,7 @@
 
 	ret = reset_get_by_name(dev, "eqos", &eqos->reset_ctl);
 	if (ret) {
-		error("reset_get_by_name(rst) failed: %d", ret);
+		pr_err("reset_get_by_name(rst) failed: %d", ret);
 		return ret;
 	}
 
@@ -1369,38 +1369,38 @@
 				   &eqos->phy_reset_gpio,
 				   GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
 	if (ret) {
-		error("gpio_request_by_name(phy reset) failed: %d", ret);
+		pr_err("gpio_request_by_name(phy reset) failed: %d", ret);
 		goto err_free_reset_eqos;
 	}
 
 	ret = clk_get_by_name(dev, "slave_bus", &eqos->clk_slave_bus);
 	if (ret) {
-		error("clk_get_by_name(slave_bus) failed: %d", ret);
+		pr_err("clk_get_by_name(slave_bus) failed: %d", ret);
 		goto err_free_gpio_phy_reset;
 	}
 
 	ret = clk_get_by_name(dev, "master_bus", &eqos->clk_master_bus);
 	if (ret) {
-		error("clk_get_by_name(master_bus) failed: %d", ret);
+		pr_err("clk_get_by_name(master_bus) failed: %d", ret);
 		goto err_free_clk_slave_bus;
 	}
 
 	ret = clk_get_by_name(dev, "rx", &eqos->clk_rx);
 	if (ret) {
-		error("clk_get_by_name(rx) failed: %d", ret);
+		pr_err("clk_get_by_name(rx) failed: %d", ret);
 		goto err_free_clk_master_bus;
 	}
 
 	ret = clk_get_by_name(dev, "ptp_ref", &eqos->clk_ptp_ref);
 	if (ret) {
-		error("clk_get_by_name(ptp_ref) failed: %d", ret);
+		pr_err("clk_get_by_name(ptp_ref) failed: %d", ret);
 		goto err_free_clk_rx;
 		return ret;
 	}
 
 	ret = clk_get_by_name(dev, "tx", &eqos->clk_tx);
 	if (ret) {
-		error("clk_get_by_name(tx) failed: %d", ret);
+		pr_err("clk_get_by_name(tx) failed: %d", ret);
 		goto err_free_clk_ptp_ref;
 	}
 
@@ -1454,7 +1454,7 @@
 
 	eqos->regs = devfdt_get_addr(dev);
 	if (eqos->regs == FDT_ADDR_T_NONE) {
-		error("devfdt_get_addr() failed");
+		pr_err("devfdt_get_addr() failed");
 		return -ENODEV;
 	}
 	eqos->mac_regs = (void *)(eqos->regs + EQOS_MAC_REGS_BASE);
@@ -1464,19 +1464,19 @@
 
 	ret = eqos_probe_resources_core(dev);
 	if (ret < 0) {
-		error("eqos_probe_resources_core() failed: %d", ret);
+		pr_err("eqos_probe_resources_core() failed: %d", ret);
 		return ret;
 	}
 
 	ret = eqos_probe_resources_tegra186(dev);
 	if (ret < 0) {
-		error("eqos_probe_resources_tegra186() failed: %d", ret);
+		pr_err("eqos_probe_resources_tegra186() failed: %d", ret);
 		goto err_remove_resources_core;
 	}
 
 	eqos->mii = mdio_alloc();
 	if (!eqos->mii) {
-		error("mdio_alloc() failed");
+		pr_err("mdio_alloc() failed");
 		goto err_remove_resources_tegra;
 	}
 	eqos->mii->read = eqos_mdio_read;
@@ -1486,7 +1486,7 @@
 
 	ret = mdio_register(eqos->mii);
 	if (ret < 0) {
-		error("mdio_register() failed: %d", ret);
+		pr_err("mdio_register() failed: %d", ret);
 		goto err_free_mdio;
 	}
 
diff --git a/drivers/net/ep93xx_eth.c b/drivers/net/ep93xx_eth.c
index a94191b..bc45706 100644
--- a/drivers/net/ep93xx_eth.c
+++ b/drivers/net/ep93xx_eth.c
@@ -324,7 +324,7 @@
 			debug("reporting %d bytes...\n", len);
 		} else {
 			/* Do we have an erroneous packet? */
-			error("packet rx error, status %08X %08X",
+			pr_err("packet rx error, status %08X %08X",
 				priv->rx_sq.current->word1,
 				priv->rx_sq.current->word2);
 			dump_rx_descriptor_queue(dev);
@@ -401,7 +401,7 @@
 		; /* noop */
 
 	if (!TX_STATUS_TXWE(priv->tx_sq.current)) {
-		error("packet tx error, status %08X",
+		pr_err("packet tx error, status %08X",
 			priv->tx_sq.current->word1);
 		dump_tx_descriptor_queue(dev);
 		dump_tx_status_queue(dev);
@@ -452,7 +452,7 @@
 
 	priv = malloc(sizeof(*priv));
 	if (!priv) {
-		error("malloc() failed");
+		pr_err("malloc() failed");
 		goto eth_init_failed_0;
 	}
 	memset(priv, 0, sizeof(*priv));
@@ -462,34 +462,34 @@
 	priv->tx_dq.base = calloc(NUMTXDESC,
 				sizeof(struct tx_descriptor));
 	if (priv->tx_dq.base == NULL) {
-		error("calloc() failed");
+		pr_err("calloc() failed");
 		goto eth_init_failed_1;
 	}
 
 	priv->tx_sq.base = calloc(NUMTXDESC,
 				sizeof(struct tx_status));
 	if (priv->tx_sq.base == NULL) {
-		error("calloc() failed");
+		pr_err("calloc() failed");
 		goto eth_init_failed_2;
 	}
 
 	priv->rx_dq.base = calloc(NUMRXDESC,
 				sizeof(struct rx_descriptor));
 	if (priv->rx_dq.base == NULL) {
-		error("calloc() failed");
+		pr_err("calloc() failed");
 		goto eth_init_failed_3;
 	}
 
 	priv->rx_sq.base = calloc(NUMRXDESC,
 				sizeof(struct rx_status));
 	if (priv->rx_sq.base == NULL) {
-		error("calloc() failed");
+		pr_err("calloc() failed");
 		goto eth_init_failed_4;
 	}
 
 	dev = malloc(sizeof *dev);
 	if (dev == NULL) {
-		error("malloc() failed");
+		pr_err("malloc() failed");
 		goto eth_init_failed_5;
 	}
 	memset(dev, 0, sizeof *dev);
diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c
index 72ef42c..21ccab4 100644
--- a/drivers/net/keystone_net.c
+++ b/drivers/net/keystone_net.c
@@ -757,7 +757,7 @@
 	qm_init();
 
 	if (ksnav_init(priv->netcp_pktdma, &priv->net_rx_buffs)) {
-		error("ksnav_init failed\n");
+		pr_err("ksnav_init failed\n");
 		goto err_knav_init;
 	}
 
@@ -773,7 +773,7 @@
 
 		phy_startup(priv->phydev);
 		if (priv->phydev->link == 0) {
-			error("phy startup failed\n");
+			pr_err("phy startup failed\n");
 			goto err_phy_start;
 		}
 	}
@@ -923,7 +923,7 @@
 		 */
 		mdio_bus = mdio_alloc();
 		if (!mdio_bus) {
-			error("MDIO alloc failed\n");
+			pr_err("MDIO alloc failed\n");
 			return -ENOMEM;
 		}
 		priv->mdio_bus = mdio_bus;
@@ -935,7 +935,7 @@
 
 		ret = mdio_register(mdio_bus);
 		if (ret) {
-			error("MDIO bus register failed\n");
+			pr_err("MDIO bus register failed\n");
 			return ret;
 		}
 	} else {
@@ -1011,7 +1011,7 @@
 					slave_name, offset_to_ofnode(slave),
 					&sl_dev);
 			if (ret) {
-				error("ks2_net - not able to bind slave interfaces\n");
+				pr_err("ks2_net - not able to bind slave interfaces\n");
 				return ret;
 			}
 		}
@@ -1031,7 +1031,7 @@
 		ret = device_bind_driver_to_node(dev, "eth_ks2_sl", slave_name,
 					offset_to_ofnode(slave), &sl_dev);
 		if (ret) {
-			error("ks2_net - not able to bind slave interfaces\n");
+			pr_err("ks2_net - not able to bind slave interfaces\n");
 			return ret;
 		}
 	}
@@ -1074,7 +1074,7 @@
 
 		mdio = fdt_parent_offset(fdt, phy);
 		if (mdio < 0) {
-			error("mdio dt not found\n");
+			pr_err("mdio dt not found\n");
 			return -ENODEV;
 		}
 		priv->mdio_base = (void *)fdtdec_get_addr(fdt, mdio, "reg");
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 8af2470..58f128d 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -33,6 +33,14 @@
 	help
 	  Enable PCI memory and I/O space resource allocation and assignment.
 
+config PCIE_ECAM_GENERIC
+	bool "Generic ECAM-based PCI host controller support"
+	default n
+	depends on DM_PCI
+	help
+	  Say Y here if you want to enable support for generic ECAM-based
+	  PCIe host controllers, such as the one emulated by QEMU.
+
 config PCIE_DW_MVEBU
 	bool "Enable Armada-8K PCIe driver (DesignWare core)"
 	depends on DM_PCI
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index ad44e83..5eb12ef 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -17,6 +17,7 @@
 endif
 obj-$(CONFIG_PCI) += pci_auto_common.o pci_common.o
 
+obj-$(CONFIG_PCIE_ECAM_GENERIC) += pcie_ecam_generic.o
 obj-$(CONFIG_FSL_PCI_INIT) += fsl_pci_init.o
 obj-$(CONFIG_PCI_INDIRECT_BRIDGE) += pci_indirect.o
 obj-$(CONFIG_PCI_GT64120) += pci_gt64120.o
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 86df141..5a24eb6 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -518,6 +518,64 @@
 	return sub_bus;
 }
 
+int pci_generic_mmap_write_config(
+	struct udevice *bus,
+	int (*addr_f)(struct udevice *bus, pci_dev_t bdf, uint offset, void **addrp),
+	pci_dev_t bdf,
+	uint offset,
+	ulong value,
+	enum pci_size_t size)
+{
+	void *address;
+
+	if (addr_f(bus, bdf, offset, &address) < 0)
+		return 0;
+
+	switch (size) {
+	case PCI_SIZE_8:
+		writeb(value, address);
+		return 0;
+	case PCI_SIZE_16:
+		writew(value, address);
+		return 0;
+	case PCI_SIZE_32:
+		writel(value, address);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+int pci_generic_mmap_read_config(
+	struct udevice *bus,
+	int (*addr_f)(struct udevice *bus, pci_dev_t bdf, uint offset, void **addrp),
+	pci_dev_t bdf,
+	uint offset,
+	ulong *valuep,
+	enum pci_size_t size)
+{
+	void *address;
+
+	if (addr_f(bus, bdf, offset, &address) < 0) {
+		*valuep = pci_get_ff(size);
+		return 0;
+	}
+
+	switch (size) {
+	case PCI_SIZE_8:
+		*valuep = readb(address);
+		return 0;
+	case PCI_SIZE_16:
+		*valuep = readw(address);
+		return 0;
+	case PCI_SIZE_32:
+		*valuep = readl(address);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
 int dm_pci_hose_probe_bus(struct udevice *bus)
 {
 	int sub_bus;
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c
index 7d920d4..b5bd25e 100644
--- a/drivers/pci/pci_tegra.c
+++ b/drivers/pci/pci_tegra.c
@@ -369,7 +369,7 @@
 
 	addr = ofnode_get_property(node, "assigned-addresses", &len);
 	if (!addr) {
-		error("property \"assigned-addresses\" not found");
+		pr_err("property \"assigned-addresses\" not found");
 		return -FDT_ERR_NOTFOUND;
 	}
 
@@ -460,7 +460,7 @@
 
 	err = ofnode_read_u32_default(node, "nvidia,num-lanes", -1);
 	if (err < 0) {
-		error("failed to parse \"nvidia,num-lanes\" property");
+		pr_err("failed to parse \"nvidia,num-lanes\" property");
 		return err;
 	}
 
@@ -468,7 +468,7 @@
 
 	err = ofnode_read_pci_addr(node, 0, "reg", &addr);
 	if (err < 0) {
-		error("failed to parse \"reg\" property");
+		pr_err("failed to parse \"reg\" property");
 		return err;
 	}
 
@@ -491,25 +491,25 @@
 
 	err = dev_read_resource(dev, 0, &pcie->pads);
 	if (err < 0) {
-		error("resource \"pads\" not found");
+		pr_err("resource \"pads\" not found");
 		return err;
 	}
 
 	err = dev_read_resource(dev, 1, &pcie->afi);
 	if (err < 0) {
-		error("resource \"afi\" not found");
+		pr_err("resource \"afi\" not found");
 		return err;
 	}
 
 	err = dev_read_resource(dev, 2, &pcie->cs);
 	if (err < 0) {
-		error("resource \"cs\" not found");
+		pr_err("resource \"cs\" not found");
 		return err;
 	}
 
 	err = tegra_pcie_board_init();
 	if (err < 0) {
-		error("tegra_pcie_board_init() failed: err=%d", err);
+		pr_err("tegra_pcie_board_init() failed: err=%d", err);
 		return err;
 	}
 
@@ -518,7 +518,7 @@
 	if (pcie->phy) {
 		err = tegra_xusb_phy_prepare(pcie->phy);
 		if (err < 0) {
-			error("failed to prepare PHY: %d", err);
+			pr_err("failed to prepare PHY: %d", err);
 			return err;
 		}
 	}
@@ -530,7 +530,7 @@
 
 		err = tegra_pcie_parse_port_info(subnode, &index, &num_lanes);
 		if (err < 0) {
-			error("failed to obtain root port info");
+			pr_err("failed to obtain root port info");
 			continue;
 		}
 
@@ -560,7 +560,7 @@
 	err = tegra_pcie_get_xbar_config(dev_ofnode(dev), lanes, id,
 					 &pcie->xbar);
 	if (err < 0) {
-		error("invalid lane configuration");
+		pr_err("invalid lane configuration");
 		return err;
 	}
 
@@ -574,31 +574,31 @@
 
 	ret = power_domain_on(&pcie->pwrdom);
 	if (ret) {
-		error("power_domain_on() failed: %d\n", ret);
+		pr_err("power_domain_on() failed: %d\n", ret);
 		return ret;
 	}
 
 	ret = clk_enable(&pcie->clk_afi);
 	if (ret) {
-		error("clk_enable(afi) failed: %d\n", ret);
+		pr_err("clk_enable(afi) failed: %d\n", ret);
 		return ret;
 	}
 
 	ret = clk_enable(&pcie->clk_pex);
 	if (ret) {
-		error("clk_enable(pex) failed: %d\n", ret);
+		pr_err("clk_enable(pex) failed: %d\n", ret);
 		return ret;
 	}
 
 	ret = reset_deassert(&pcie->reset_afi);
 	if (ret) {
-		error("reset_deassert(afi) failed: %d\n", ret);
+		pr_err("reset_deassert(afi) failed: %d\n", ret);
 		return ret;
 	}
 
 	ret = reset_deassert(&pcie->reset_pex);
 	if (ret) {
-		error("reset_deassert(pex) failed: %d\n", ret);
+		pr_err("reset_deassert(pex) failed: %d\n", ret);
 		return ret;
 	}
 
@@ -618,14 +618,14 @@
 
 	err = tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
 	if (err < 0) {
-		error("failed to power off PCIe partition: %d", err);
+		pr_err("failed to power off PCIe partition: %d", err);
 		return err;
 	}
 
 	err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
 						PERIPH_ID_PCIE);
 	if (err < 0) {
-		error("failed to power up PCIe partition: %d", err);
+		pr_err("failed to power up PCIe partition: %d", err);
 		return err;
 	}
 
@@ -645,7 +645,7 @@
 
 	err = tegra_plle_enable();
 	if (err < 0) {
-		error("failed to enable PLLE: %d\n", err);
+		pr_err("failed to enable PLLE: %d\n", err);
 		return err;
 	}
 
@@ -705,7 +705,7 @@
 	/* wait for the PLL to lock */
 	err = tegra_pcie_pll_wait(pcie, 500);
 	if (err < 0) {
-		error("PLL failed to lock: %d", err);
+		pr_err("PLL failed to lock: %d", err);
 		return err;
 	}
 
@@ -769,7 +769,7 @@
 		err = tegra_pcie_phy_enable(pcie);
 
 	if (err < 0) {
-		error("failed to power on PHY: %d\n", err);
+		pr_err("failed to power on PHY: %d\n", err);
 		return err;
 	}
 #endif
@@ -778,7 +778,7 @@
 #ifdef CONFIG_TEGRA186
 	err = reset_deassert(&pcie->reset_pcie_x);
 	if (err) {
-		error("reset_deassert(pcie_x) failed: %d\n", err);
+		pr_err("reset_deassert(pcie_x) failed: %d\n", err);
 		return err;
 	}
 #else
@@ -1143,25 +1143,25 @@
 
 	err = tegra_pcie_power_on(pcie);
 	if (err < 0) {
-		error("failed to power on");
+		pr_err("failed to power on");
 		return err;
 	}
 
 	err = tegra_pcie_enable_controller(pcie);
 	if (err < 0) {
-		error("failed to enable controller");
+		pr_err("failed to enable controller");
 		return err;
 	}
 
 	err = tegra_pcie_setup_translations(dev);
 	if (err < 0) {
-		error("failed to decode ranges");
+		pr_err("failed to decode ranges");
 		return err;
 	}
 
 	err = tegra_pcie_enable(pcie);
 	if (err < 0) {
-		error("failed to enable PCIe");
+		pr_err("failed to enable PCIe");
 		return err;
 	}
 
diff --git a/drivers/pci/pcie_ecam_generic.c b/drivers/pci/pcie_ecam_generic.c
new file mode 100644
index 0000000..c7540ff
--- /dev/null
+++ b/drivers/pci/pcie_ecam_generic.c
@@ -0,0 +1,143 @@
+/*
+ * Generic PCIE host provided by e.g. QEMU
+ *
+ * Heavily based on drivers/pci/pcie_xilinx.c
+ *
+ * Copyright (C) 2016 Imagination Technologies
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pci.h>
+
+#include <asm/io.h>
+
+/**
+ * struct generic_ecam_pcie - generic_ecam PCIe controller state
+ * @cfg_base: The base address of memory mapped configuration space
+ */
+struct generic_ecam_pcie {
+	void *cfg_base;
+};
+
+/**
+ * pci_generic_ecam_conf_address() - Calculate the address of a config access
+ * @bus: Pointer to the PCI bus
+ * @bdf: Identifies the PCIe device to access
+ * @offset: The offset into the device's configuration space
+ * @paddress: Pointer to the pointer to write the calculates address to
+ *
+ * Calculates the address that should be accessed to perform a PCIe
+ * configuration space access for a given device identified by the PCIe
+ * controller device @pcie and the bus, device & function numbers in @bdf. If
+ * access to the device is not valid then the function will return an error
+ * code. Otherwise the address to access will be written to the pointer pointed
+ * to by @paddress.
+ */
+static int pci_generic_ecam_conf_address(struct udevice *bus, pci_dev_t bdf,
+					    uint offset, void **paddress)
+{
+	struct generic_ecam_pcie *pcie = dev_get_priv(bus);
+	void *addr;
+
+	addr = pcie->cfg_base;
+	addr += PCI_BUS(bdf) << 20;
+	addr += PCI_DEV(bdf) << 15;
+	addr += PCI_FUNC(bdf) << 12;
+	addr += offset;
+	*paddress = addr;
+
+	return 0;
+}
+
+/**
+ * pci_generic_ecam_read_config() - Read from configuration space
+ * @bus: Pointer to the PCI bus
+ * @bdf: Identifies the PCIe device to access
+ * @offset: The offset into the device's configuration space
+ * @valuep: A pointer at which to store the read value
+ * @size: Indicates the size of access to perform
+ *
+ * Read a value of size @size from offset @offset within the configuration
+ * space of the device identified by the bus, device & function numbers in @bdf
+ * on the PCI bus @bus.
+ */
+static int pci_generic_ecam_read_config(struct udevice *bus, pci_dev_t bdf,
+				   uint offset, ulong *valuep,
+				   enum pci_size_t size)
+{
+	return pci_generic_mmap_read_config(bus, pci_generic_ecam_conf_address,
+					    bdf, offset, valuep, size);
+}
+
+/**
+ * pci_generic_ecam_write_config() - Write to configuration space
+ * @bus: Pointer to the PCI bus
+ * @bdf: Identifies the PCIe device to access
+ * @offset: The offset into the device's configuration space
+ * @value: The value to write
+ * @size: Indicates the size of access to perform
+ *
+ * Write the value @value of size @size from offset @offset within the
+ * configuration space of the device identified by the bus, device & function
+ * numbers in @bdf on the PCI bus @bus.
+ */
+static int pci_generic_ecam_write_config(struct udevice *bus, pci_dev_t bdf,
+				    uint offset, ulong value,
+				    enum pci_size_t size)
+{
+	return pci_generic_mmap_write_config(bus, pci_generic_ecam_conf_address,
+					     bdf, offset, value, size);
+}
+
+/**
+ * pci_generic_ecam_ofdata_to_platdata() - Translate from DT to device state
+ * @dev: A pointer to the device being operated on
+ *
+ * Translate relevant data from the device tree pertaining to device @dev into
+ * state that the driver will later make use of. This state is stored in the
+ * device's private data structure.
+ *
+ * Return: 0 on success, else -EINVAL
+ */
+static int pci_generic_ecam_ofdata_to_platdata(struct udevice *dev)
+{
+	struct generic_ecam_pcie *pcie = dev_get_priv(dev);
+	struct fdt_resource reg_res;
+	DECLARE_GLOBAL_DATA_PTR;
+	int err;
+
+	err = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev), "reg",
+			       0, &reg_res);
+	if (err < 0) {
+		pr_err("\"reg\" resource not found\n");
+		return err;
+	}
+
+	pcie->cfg_base = map_physmem(reg_res.start,
+				     fdt_resource_size(&reg_res),
+				     MAP_NOCACHE);
+
+	return 0;
+}
+
+static const struct dm_pci_ops pci_generic_ecam_ops = {
+	.read_config	= pci_generic_ecam_read_config,
+	.write_config	= pci_generic_ecam_write_config,
+};
+
+static const struct udevice_id pci_generic_ecam_ids[] = {
+	{ .compatible = "pci-host-ecam-generic" },
+	{ }
+};
+
+U_BOOT_DRIVER(pci_generic_ecam) = {
+	.name			= "pci_generic_ecam",
+	.id			= UCLASS_PCI,
+	.of_match		= pci_generic_ecam_ids,
+	.ops			= &pci_generic_ecam_ops,
+	.ofdata_to_platdata	= pci_generic_ecam_ofdata_to_platdata,
+	.priv_auto_alloc_size	= sizeof(struct generic_ecam_pcie),
+};
diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c
index 610f85c..0cb7f6d 100644
--- a/drivers/pci/pcie_layerscape.c
+++ b/drivers/pci/pcie_layerscape.c
@@ -241,14 +241,19 @@
 	return 0;
 }
 
-void *ls_pcie_conf_address(struct ls_pcie *pcie, pci_dev_t bdf,
-				   int offset)
+int ls_pcie_conf_address(struct udevice *bus, pci_dev_t bdf,
+			 uint offset, void **paddress)
 {
-	struct udevice *bus = pcie->bus;
+	struct ls_pcie *pcie = dev_get_priv(bus);
 	u32 busdev;
 
-	if (PCI_BUS(bdf) == bus->seq)
-		return pcie->dbi + offset;
+	if (ls_pcie_addr_valid(pcie, bdf))
+		return -EINVAL;
+
+	if (PCI_BUS(bdf) == bus->seq) {
+		*paddress = pcie->dbi + offset;
+		return 0;
+	}
 
 	busdev = PCIE_ATU_BUS(PCI_BUS(bdf)) |
 		 PCIE_ATU_DEV(PCI_DEV(bdf)) |
@@ -256,67 +261,28 @@
 
 	if (PCI_BUS(bdf) == bus->seq + 1) {
 		ls_pcie_cfg0_set_busdev(pcie, busdev);
-		return pcie->cfg0 + offset;
+		*paddress = pcie->cfg0 + offset;
 	} else {
 		ls_pcie_cfg1_set_busdev(pcie, busdev);
-		return pcie->cfg1 + offset;
+		*paddress = pcie->cfg1 + offset;
 	}
+	return 0;
 }
 
 static int ls_pcie_read_config(struct udevice *bus, pci_dev_t bdf,
 			       uint offset, ulong *valuep,
 			       enum pci_size_t size)
 {
-	struct ls_pcie *pcie = dev_get_priv(bus);
-	void *address;
-
-	if (ls_pcie_addr_valid(pcie, bdf)) {
-		*valuep = pci_get_ff(size);
-		return 0;
-	}
-
-	address = ls_pcie_conf_address(pcie, bdf, offset);
-
-	switch (size) {
-	case PCI_SIZE_8:
-		*valuep = readb(address);
-		return 0;
-	case PCI_SIZE_16:
-		*valuep = readw(address);
-		return 0;
-	case PCI_SIZE_32:
-		*valuep = readl(address);
-		return 0;
-	default:
-		return -EINVAL;
-	}
+	return pci_generic_mmap_read_config(bus, ls_pcie_conf_address,
+					    bdf, offset, valuep, size);
 }
 
 static int ls_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
 				uint offset, ulong value,
 				enum pci_size_t size)
 {
-	struct ls_pcie *pcie = dev_get_priv(bus);
-	void *address;
-
-	if (ls_pcie_addr_valid(pcie, bdf))
-		return 0;
-
-	address = ls_pcie_conf_address(pcie, bdf, offset);
-
-	switch (size) {
-	case PCI_SIZE_8:
-		writeb(value, address);
-		return 0;
-	case PCI_SIZE_16:
-		writew(value, address);
-		return 0;
-	case PCI_SIZE_32:
-		writel(value, address);
-		return 0;
-	default:
-		return -EINVAL;
-	}
+	return pci_generic_mmap_write_config(bus, ls_pcie_conf_address,
+					     bdf, offset, value, size);
 }
 
 /* Clear multi-function bit */
diff --git a/drivers/pci/pcie_xilinx.c b/drivers/pci/pcie_xilinx.c
index 4ba32df..57112f5 100644
--- a/drivers/pci/pcie_xilinx.c
+++ b/drivers/pci/pcie_xilinx.c
@@ -41,7 +41,7 @@
 
 /**
  * pcie_xilinx_config_address() - Calculate the address of a config access
- * @pcie: Pointer to the PCI controller state
+ * @udev: Pointer to the PCI bus
  * @bdf: Identifies the PCIe device to access
  * @offset: The offset into the device's configuration space
  * @paddress: Pointer to the pointer to write the calculates address to
@@ -55,9 +55,10 @@
  *
  * Return: 0 on success, else -ENODEV
  */
-static int pcie_xilinx_config_address(struct xilinx_pcie *pcie, pci_dev_t bdf,
+static int pcie_xilinx_config_address(struct udevice *udev, pci_dev_t bdf,
 				      uint offset, void **paddress)
 {
+	struct xilinx_pcie *pcie = dev_get_priv(udev);
 	unsigned int bus = PCI_BUS(bdf);
 	unsigned int dev = PCI_DEV(bdf);
 	unsigned int func = PCI_FUNC(bdf);
@@ -101,29 +102,8 @@
 				   uint offset, ulong *valuep,
 				   enum pci_size_t size)
 {
-	struct xilinx_pcie *pcie = dev_get_priv(bus);
-	void *address;
-	int err;
-
-	err = pcie_xilinx_config_address(pcie, bdf, offset, &address);
-	if (err < 0) {
-		*valuep = pci_get_ff(size);
-		return 0;
-	}
-
-	switch (size) {
-	case PCI_SIZE_8:
-		*valuep = __raw_readb(address);
-		return 0;
-	case PCI_SIZE_16:
-		*valuep = __raw_readw(address);
-		return 0;
-	case PCI_SIZE_32:
-		*valuep = __raw_readl(address);
-		return 0;
-	default:
-		return -EINVAL;
-	}
+	return pci_generic_mmap_read_config(bus, pcie_xilinx_config_address,
+					    bdf, offset, valuep, size);
 }
 
 /**
@@ -144,27 +124,8 @@
 				    uint offset, ulong value,
 				    enum pci_size_t size)
 {
-	struct xilinx_pcie *pcie = dev_get_priv(bus);
-	void *address;
-	int err;
-
-	err = pcie_xilinx_config_address(pcie, bdf, offset, &address);
-	if (err < 0)
-		return 0;
-
-	switch (size) {
-	case PCI_SIZE_8:
-		__raw_writeb(value, address);
-		return 0;
-	case PCI_SIZE_16:
-		__raw_writew(value, address);
-		return 0;
-	case PCI_SIZE_32:
-		__raw_writel(value, address);
-		return 0;
-	default:
-		return -EINVAL;
-	}
+	return pci_generic_mmap_write_config(bus, pcie_xilinx_config_address,
+					     bdf, offset, value, size);
 }
 
 /**
@@ -187,7 +148,7 @@
 	err = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev), "reg",
 			       0, &reg_res);
 	if (err < 0) {
-		error("\"reg\" resource not found\n");
+		pr_err("\"reg\" resource not found\n");
 		return err;
 	}
 
diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c
index 3ac405a..3718788 100644
--- a/drivers/phy/marvell/comphy_cp110.c
+++ b/drivers/phy/marvell/comphy_cp110.c
@@ -509,7 +509,7 @@
 				debug("Read from reg = %p - value = 0x%x\n",
 				      hpipe_addr + HPIPE_LANE_STATUS1_REG,
 				      data);
-				error("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n");
+				pr_err("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n");
 				ret = 0;
 			}
 		}
@@ -633,7 +633,7 @@
 	if (data != 0) {
 		debug("Read from reg = %p - value = 0x%x\n",
 		      hpipe_addr + HPIPE_LANE_STATUS1_REG, data);
-		error("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n");
+		pr_err("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n");
 		ret = 0;
 	}
 
@@ -666,14 +666,14 @@
 			gd->fdt_blob, sata_node, "marvell,armada-8k-ahci");
 
 	if (sata_node == 0) {
-		error("SATA node not found in FDT\n");
+		pr_err("SATA node not found in FDT\n");
 		return 0;
 	}
 
 	sata_base = (void __iomem *)fdtdec_get_addr_size_auto_noparent(
 		gd->fdt_blob, sata_node, "reg", 0, NULL, true);
 	if (sata_base == NULL) {
-		error("SATA address not found in FDT\n");
+		pr_err("SATA address not found in FDT\n");
 		return 0;
 	}
 
@@ -976,7 +976,7 @@
 	if (data != 0) {
 		debug("Read from reg = %p - value = 0x%x\n",
 		      hpipe_addr + HPIPE_LANE_STATUS1_REG, data);
-		error("SD_EXTERNAL_STATUS0_PLL_TX is %d, SD_EXTERNAL_STATUS0_PLL_RX is %d\n",
+		pr_err("SD_EXTERNAL_STATUS0_PLL_TX is %d, SD_EXTERNAL_STATUS0_PLL_RX is %d\n",
 		      (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK),
 		      (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK));
 		ret = 0;
@@ -1099,7 +1099,7 @@
 	if (data != 0) {
 		debug("Read from reg = %p - value = 0x%x\n",
 		      sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
-		error("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n",
+		pr_err("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n",
 		      (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK),
 		      (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK));
 		ret = 0;
@@ -1117,7 +1117,7 @@
 	data = polling_with_timeout(addr, data, mask, 100);
 	if (data != 0) {
 		debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
-		error("SD_EXTERNAL_STATUS0_RX_INIT is 0\n");
+		pr_err("SD_EXTERNAL_STATUS0_RX_INIT is 0\n");
 		ret = 0;
 	}
 
@@ -1398,7 +1398,7 @@
 	data = polling_with_timeout(addr, data, mask, 15000);
 	if (data != 0) {
 		debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
-		error("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n",
+		pr_err("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n",
 		      (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK),
 		      (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK));
 		ret = 0;
@@ -1418,7 +1418,7 @@
 	if (data != 0) {
 		debug("Read from reg = %p - value = 0x%x\n",
 		      sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
-		error("SD_EXTERNAL_STATUS0_RX_INIT is 0\n");
+		pr_err("SD_EXTERNAL_STATUS0_RX_INIT is 0\n");
 		ret = 0;
 	}
 
@@ -1577,7 +1577,7 @@
 	if (data != 0) {
 		debug("Read from reg = %p - value = 0x%x\n",
 		      sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
-		error("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n",
+		pr_err("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n",
 		      (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK),
 		      (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK));
 		ret = 0;
@@ -1596,7 +1596,7 @@
 	if (data != 0) {
 		debug("Read from reg = %p - value = 0x%x\n",
 		      sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data);
-		error("SD_EXTERNAL_STATUS0_RX_INIT is 0\n");
+		pr_err("SD_EXTERNAL_STATUS0_RX_INIT is 0\n");
 		ret = 0;
 	}
 
@@ -1742,7 +1742,7 @@
 	mask = data;
 	data = polling_with_timeout(addr, data, mask, 100);
 	if (data != 0) {
-		error("Impedance calibration is not done\n");
+		pr_err("Impedance calibration is not done\n");
 		debug("Read from reg = %p - value = 0x%x\n", addr, data);
 		ret = 0;
 	}
@@ -1751,7 +1751,7 @@
 	mask = data;
 	data = polling_with_timeout(addr, data, mask, 100);
 	if (data != 0) {
-		error("PLL calibration is not done\n");
+		pr_err("PLL calibration is not done\n");
 		debug("Read from reg = %p - value = 0x%x\n", addr, data);
 		ret = 0;
 	}
@@ -1761,7 +1761,7 @@
 	mask = data;
 	data = polling_with_timeout(addr, data, mask, 100);
 	if (data != 0) {
-		error("PLL is not ready\n");
+		pr_err("PLL is not ready\n");
 		debug("Read from reg = %p - value = 0x%x\n", addr, data);
 		ret = 0;
 	}
@@ -1818,7 +1818,7 @@
 					  cp110_utmi_data[i].usb_cfg_addr,
 					  cp110_utmi_data[i].utmi_cfg_addr,
 					  cp110_utmi_data[i].utmi_phy_port)) {
-			error("Failed to initialize UTMI PHY %d\n", i);
+			pr_err("Failed to initialize UTMI PHY %d\n", i);
 			continue;
 		}
 		printf("UTMI PHY %d initialized to ", i);
@@ -1864,7 +1864,7 @@
 			(void __iomem *)fdtdec_get_addr_size_auto_noparent(
 				gd->fdt_blob, node, "reg", 0, NULL, true);
 		if (cp110_utmi_data[i].utmi_base_addr == NULL) {
-			error("UTMI PHY base address is invalid\n");
+			pr_err("UTMI PHY base address is invalid\n");
 			i++;
 			continue;
 		}
@@ -1874,7 +1874,7 @@
 			(void __iomem *)fdtdec_get_addr_size_auto_noparent(
 				gd->fdt_blob, node, "reg", 1, NULL, true);
 		if (cp110_utmi_data[i].usb_cfg_addr == NULL) {
-			error("UTMI PHY base address is invalid\n");
+			pr_err("UTMI PHY base address is invalid\n");
 			i++;
 			continue;
 		}
@@ -1884,7 +1884,7 @@
 			(void __iomem *)fdtdec_get_addr_size_auto_noparent(
 				gd->fdt_blob, node, "reg", 2, NULL, true);
 		if (cp110_utmi_data[i].utmi_cfg_addr == NULL) {
-			error("UTMI PHY base address is invalid\n");
+			pr_err("UTMI PHY base address is invalid\n");
 			i++;
 			continue;
 		}
@@ -1896,7 +1896,7 @@
 		cp110_utmi_data[i].utmi_phy_port = fdtdec_get_int(
 			gd->fdt_blob, node, "utmi-port", UTMI_PHY_INVALID);
 		if (cp110_utmi_data[i].utmi_phy_port == UTMI_PHY_INVALID) {
-			error("UTMI PHY port type is invalid\n");
+			pr_err("UTMI PHY port type is invalid\n");
 			i++;
 			continue;
 		}
@@ -2049,7 +2049,7 @@
 			 * PHY_TYPE_UNCONNECTED state.
 			 */
 			ptr_comphy_map->type = PHY_TYPE_UNCONNECTED;
-			error("PLL is not locked - Failed to initialize lane %d\n",
+			pr_err("PLL is not locked - Failed to initialize lane %d\n",
 			      lane);
 		}
 	}
diff --git a/drivers/phy/sti_usb_phy.c b/drivers/phy/sti_usb_phy.c
index 0e0b1c0..88fcfbb 100644
--- a/drivers/phy/sti_usb_phy.c
+++ b/drivers/phy/sti_usb_phy.c
@@ -47,13 +47,13 @@
 
 	ret = reset_deassert(&phy->global_ctl);
 	if (ret < 0) {
-		error("PHY global deassert failed: %d", ret);
+		pr_err("PHY global deassert failed: %d", ret);
 		return ret;
 	}
 
 	ret = reset_deassert(&phy->port_ctl);
 	if (ret < 0)
-		error("PHY port deassert failed: %d", ret);
+		pr_err("PHY port deassert failed: %d", ret);
 
 	return ret;
 }
@@ -85,13 +85,13 @@
 
 	ret = reset_assert(&phy->port_ctl);
 	if (ret < 0) {
-		error("PHY port assert failed: %d", ret);
+		pr_err("PHY port assert failed: %d", ret);
 		return ret;
 	}
 
 	ret = reset_assert(&phy->global_ctl);
 	if (ret < 0)
-		error("PHY global assert failed: %d", ret);
+		pr_err("PHY global assert failed: %d", ret);
 
 	return ret;
 }
@@ -114,20 +114,20 @@
 					 &syscfg_phandle);
 
 	if (ret < 0) {
-		error("Can't get syscfg phandle: %d\n", ret);
+		pr_err("Can't get syscfg phandle: %d\n", ret);
 		return ret;
 	}
 
 	ret = uclass_get_device_by_ofnode(UCLASS_SYSCON, syscfg_phandle.node,
 					  &syscon);
 	if (ret) {
-		error("unable to find syscon device (%d)\n", ret);
+		pr_err("unable to find syscon device (%d)\n", ret);
 		return ret;
 	}
 
 	priv->regmap = syscon_get_regmap(syscon);
 	if (!priv->regmap) {
-		error("unable to find regmap\n");
+		pr_err("unable to find regmap\n");
 		return -ENODEV;
 	}
 
@@ -137,12 +137,12 @@
 					   ARRAY_SIZE(cells));
 
 	if (count < 0) {
-		error("Bad PHY st,syscfg property %d\n", count);
+		pr_err("Bad PHY st,syscfg property %d\n", count);
 		return -EINVAL;
 	}
 
 	if (count > PHYPARAM_NB) {
-		error("Unsupported PHY param count %d\n", count);
+		pr_err("Unsupported PHY param count %d\n", count);
 		return -EINVAL;
 	}
 
@@ -152,14 +152,14 @@
 	/* get global reset control */
 	ret = reset_get_by_name(dev, "global", &priv->global_ctl);
 	if (ret) {
-		error("can't get global reset for %s (%d)", dev->name, ret);
+		pr_err("can't get global reset for %s (%d)", dev->name, ret);
 		return ret;
 	}
 
 	/* get port reset control */
 	ret = reset_get_by_name(dev, "port", &priv->port_ctl);
 	if (ret) {
-		error("can't get port reset for %s (%d)", dev->name, ret);
+		pr_err("can't get port reset for %s (%d)", dev->name, ret);
 		return ret;
 	}
 
diff --git a/drivers/phy/ti-pipe3-phy.c b/drivers/phy/ti-pipe3-phy.c
index 680e32f..babf2ff 100644
--- a/drivers/phy/ti-pipe3-phy.c
+++ b/drivers/phy/ti-pipe3-phy.c
@@ -261,7 +261,7 @@
 	} while (--timeout);
 
 	if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
-		error("%s: Failed to power down DPLL: PLL_STATUS 0x%x\n",
+		pr_err("%s: Failed to power down DPLL: PLL_STATUS 0x%x\n",
 		      __func__, val);
 		return -EBUSY;
 	}
@@ -284,14 +284,14 @@
 	err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
 					   name, &syscon);
 	if (err) {
-		error("unable to find syscon device for %s (%d)\n",
+		pr_err("unable to find syscon device for %s (%d)\n",
 		      name, err);
 		return NULL;
 	}
 
 	regmap = syscon_get_regmap(syscon);
 	if (IS_ERR(regmap)) {
-		error("unable to find regmap for %s (%ld)\n",
+		pr_err("unable to find regmap for %s (%ld)\n",
 		      name, PTR_ERR(regmap));
 		return NULL;
 	}
@@ -299,7 +299,7 @@
 	cell = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), name,
 			   &len);
 	if (len < 2*sizeof(fdt32_t)) {
-		error("offset not available for %s\n", name);
+		pr_err("offset not available for %s\n", name);
 		return NULL;
 	}
 
@@ -318,13 +318,13 @@
 
 	addr = devfdt_get_addr_size_index(dev, 2, &sz);
 	if (addr == FDT_ADDR_T_NONE) {
-		error("missing pll ctrl address\n");
+		pr_err("missing pll ctrl address\n");
 		return -EINVAL;
 	}
 
 	pipe3->pll_ctrl_base = map_physmem(addr, sz, MAP_NOCACHE);
 	if (!pipe3->pll_ctrl_base) {
-		error("unable to remap pll ctrl\n");
+		pr_err("unable to remap pll ctrl\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index 27165b0..2bf853e 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -578,7 +578,7 @@
 
 	info->base = (void __iomem *)devfdt_get_addr(dev);
 	if (!info->base) {
-		error("unable to find regmap\n");
+		pr_err("unable to find regmap\n");
 		return -ENODEV;
 	}
 
diff --git a/drivers/pinctrl/pinctrl-sti.c b/drivers/pinctrl/pinctrl-sti.c
index 40341b4..735e412 100644
--- a/drivers/pinctrl/pinctrl-sti.c
+++ b/drivers/pinctrl/pinctrl-sti.c
@@ -142,7 +142,7 @@
 		break;
 
 	default:
-		error("%s invalid direction value: 0x%x\n",
+		pr_err("%s invalid direction value: 0x%x\n",
 		      __func__, pin_desc->dir);
 		BUG();
 		break;
@@ -237,14 +237,14 @@
 						     prop_name, "#gpio-cells",
 						     0, 0, &args);
 		if (ret < 0) {
-			error("Can't get the gpio bank phandle: %d\n", ret);
+			pr_err("Can't get the gpio bank phandle: %d\n", ret);
 			return ret;
 		}
 
 		bank_name = fdt_getprop(blob, args.node, "st,bank-name",
 					&count);
 		if (count < 0) {
-			error("Can't find bank-name property %d\n", count);
+			pr_err("Can't find bank-name property %d\n", count);
 			return -EINVAL;
 		}
 
@@ -254,12 +254,12 @@
 						   prop_name, cells,
 						   ARRAY_SIZE(cells));
 		if (count < 0) {
-			error("Bad pin configuration array %d\n", count);
+			pr_err("Bad pin configuration array %d\n", count);
 			return -EINVAL;
 		}
 
 		if (count > MAX_STI_PINCONF_ENTRIES) {
-			error("Unsupported pinconf array count %d\n", count);
+			pr_err("Unsupported pinconf array count %d\n", count);
 			return -EINVAL;
 		}
 
@@ -284,13 +284,13 @@
 	err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
 					   "st,syscfg", &syscon);
 	if (err) {
-		error("unable to find syscon device\n");
+		pr_err("unable to find syscon device\n");
 		return err;
 	}
 
 	plat->regmap = syscon_get_regmap(syscon);
 	if (!plat->regmap) {
-		error("unable to find regmap\n");
+		pr_err("unable to find regmap\n");
 		return -ENODEV;
 	}
 
diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
index bf2a86c..51fdfb3 100644
--- a/drivers/pinctrl/pinctrl_stm32.c
+++ b/drivers/pinctrl/pinctrl_stm32.c
@@ -160,7 +160,7 @@
 
 		config_node = fdt_node_offset_by_phandle(fdt, phandle);
 		if (config_node < 0) {
-			error("prop pinctrl-0 index %d invalid phandle\n", i);
+			pr_err("prop pinctrl-0 index %d invalid phandle\n", i);
 			return -EINVAL;
 		}
 
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3368.c b/drivers/pinctrl/rockchip/pinctrl_rk3368.c
index b1f5704..25249e3 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3368.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3368.c
@@ -208,6 +208,29 @@
 	GPIO2A0_FLASH_CSN0      = (1 << GPIO2A0_SHIFT),
 };
 
+/*GRF_GPIO2B_IOMUX*/
+enum {
+	GPIO2B3_SHIFT           = 6,
+	GPIO2B3_MASK            = GENMASK(GPIO2B3_SHIFT + 1, GPIO2B3_SHIFT),
+	GPIO2B3_GPIO            = 0,
+	GPIO2B3_SDMMC0_DTECTN   = (1 << GPIO2B3_SHIFT),
+
+	GPIO2B2_SHIFT           = 4,
+	GPIO2B2_MASK            = GENMASK(GPIO2B2_SHIFT + 1, GPIO2B2_SHIFT),
+	GPIO2B2_GPIO            = 0,
+	GPIO2B2_SDMMC0_CMD      = (1 << GPIO2B2_SHIFT),
+
+	GPIO2B1_SHIFT           = 2,
+	GPIO2B1_MASK            = GENMASK(GPIO2B1_SHIFT + 1, GPIO2B1_SHIFT),
+	GPIO2B1_GPIO            = 0,
+	GPIO2B1_SDMMC0_CLKOUT   = (1 << GPIO2B1_SHIFT),
+
+	GPIO2B0_SHIFT           = 0,
+	GPIO2B0_MASK            = GENMASK(GPIO2B0_SHIFT + 1, GPIO2B0_SHIFT),
+	GPIO2B0_GPIO            = 0,
+	GPIO2B0_SDMMC0_D3       = (1 << GPIO2B0_SHIFT),
+};
+
 /*GRF_GPIO2D_IOMUX*/
 enum {
 	GPIO2D7_SHIFT           = 14,
@@ -580,11 +603,17 @@
 			     GPIO2A4_EMMC_CLKOUT);
 		break;
 	case PERIPH_ID_SDCARD:
-		/*
-		 * We assume that the BROM has already set this up
-		 * correctly for us and that there's nothing to do
-		 * here.
-		 */
+		debug("mmc id = %d setting registers!\n", mmc_id);
+		rk_clrsetreg(&grf->gpio2a_iomux,
+			     GPIO2A5_MASK | GPIO2A7_MASK |
+			     GPIO2A7_MASK,
+			     GPIO2A5_SDMMC0_D0 | GPIO2A6_SDMMC0_D1 |
+			     GPIO2A7_SDMMC0_D2);
+		rk_clrsetreg(&grf->gpio2b_iomux,
+			     GPIO2B0_MASK | GPIO2B1_MASK |
+			     GPIO2B2_MASK | GPIO2B3_MASK,
+			     GPIO2B0_SDMMC0_D3 | GPIO2B1_SDMMC0_CLKOUT |
+			     GPIO2B2_SDMMC0_CMD | GPIO2B3_SDMMC0_DTECTN);
 		break;
 	default:
 		debug("mmc id = %d iomux error!\n", mmc_id);
diff --git a/drivers/power/pmic/as3722.c b/drivers/power/pmic/as3722.c
index 4efe8ee..3b0427e 100644
--- a/drivers/power/pmic/as3722.c
+++ b/drivers/power/pmic/as3722.c
@@ -46,14 +46,14 @@
 
 	ret = pmic_reg_read(dev, AS3722_ASIC_ID1);
 	if (ret < 0) {
-		error("failed to read ID1 register: %d", ret);
+		pr_err("failed to read ID1 register: %d", ret);
 		return ret;
 	}
 	*idp = ret;
 
 	ret = pmic_reg_read(dev, AS3722_ASIC_ID2);
 	if (ret < 0) {
-		error("failed to read ID2 register: %d", ret);
+		pr_err("failed to read ID2 register: %d", ret);
 		return ret;
 	}
 	*revisionp = ret;
@@ -71,7 +71,7 @@
 
 	ret = pmic_reg_write(dev, AS3722_SD_VOLTAGE(sd), value);
 	if (ret < 0) {
-		error("failed to write SD%u voltage register: %d", sd, ret);
+		pr_err("failed to write SD%u voltage register: %d", sd, ret);
 		return ret;
 	}
 
@@ -87,7 +87,7 @@
 
 	ret = pmic_reg_write(dev, AS3722_LDO_VOLTAGE(ldo), value);
 	if (ret < 0) {
-		error("failed to write LDO%u voltage register: %d", ldo,
+		pr_err("failed to write LDO%u voltage register: %d", ldo,
 		      ret);
 		return ret;
 	}
@@ -102,12 +102,12 @@
 
 	ret = as3722_read_id(dev, &id, &revision);
 	if (ret < 0) {
-		error("failed to read ID: %d", ret);
+		pr_err("failed to read ID: %d", ret);
 		return ret;
 	}
 
 	if (id != AS3722_DEVICE_ID) {
-		error("unknown device");
+		pr_err("unknown device");
 		return -ENOENT;
 	}
 
diff --git a/drivers/power/pmic/as3722_gpio.c b/drivers/power/pmic/as3722_gpio.c
index d0b681c..5cf4cb6 100644
--- a/drivers/power/pmic/as3722_gpio.c
+++ b/drivers/power/pmic/as3722_gpio.c
@@ -26,7 +26,7 @@
 
 	err = pmic_reg_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
 	if (err) {
-		error("failed to configure GPIO#%u: %d", gpio, err);
+		pr_err("failed to configure GPIO#%u: %d", gpio, err);
 		return err;
 	}
 
@@ -46,7 +46,7 @@
 
 	err = pmic_reg_read(pmic, AS3722_GPIO_SIGNAL_OUT);
 	if (err < 0) {
-		error("failed to read GPIO signal out register: %d", err);
+		pr_err("failed to read GPIO signal out register: %d", err);
 		return err;
 	}
 	value = err;
@@ -61,7 +61,7 @@
 
 	err = pmic_reg_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
 	if (err) {
-		error("failed to set GPIO#%u %s: %d", gpio, l, err);
+		pr_err("failed to set GPIO#%u %s: %d", gpio, l, err);
 		return err;
 	}
 
@@ -84,13 +84,13 @@
 
 	err = pmic_reg_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
 	if (err) {
-		error("failed to configure GPIO#%u as output: %d", gpio, err);
+		pr_err("failed to configure GPIO#%u as output: %d", gpio, err);
 		return err;
 	}
 
 	err = as3722_gpio_set_value(pmic, gpio, value);
 	if (err < 0) {
-		error("failed to set GPIO#%u high: %d", gpio, err);
+		pr_err("failed to set GPIO#%u high: %d", gpio, err);
 		return err;
 	}
 
diff --git a/drivers/power/pmic/i2c_pmic_emul.c b/drivers/power/pmic/i2c_pmic_emul.c
index 2d35d09..38a2a04 100644
--- a/drivers/power/pmic/i2c_pmic_emul.c
+++ b/drivers/power/pmic/i2c_pmic_emul.c
@@ -31,7 +31,7 @@
 	struct sandbox_i2c_pmic_plat_data *plat = dev_get_platdata(emul);
 
 	if (plat->rw_reg + len > SANDBOX_PMIC_REG_COUNT) {
-		error("Request exceeds PMIC register range! Max register: %#x",
+		pr_err("Request exceeds PMIC register range! Max register: %#x",
 		      SANDBOX_PMIC_REG_COUNT);
 		return -EFAULT;
 	}
@@ -68,7 +68,7 @@
 	len--;
 
 	if (plat->rw_reg + len > SANDBOX_PMIC_REG_COUNT) {
-		error("Request exceeds PMIC register range! Max register: %#x",
+		pr_err("Request exceeds PMIC register range! Max register: %#x",
 		      SANDBOX_PMIC_REG_COUNT);
 	}
 
@@ -111,7 +111,7 @@
 					     SANDBOX_PMIC_REG_COUNT);
 
 	if (!reg_defaults) {
-		error("Property \"reg-defaults\" not found for device: %s!",
+		pr_err("Property \"reg-defaults\" not found for device: %s!",
 		      emul->name);
 		return -EINVAL;
 	}
diff --git a/drivers/power/pmic/lp873x.c b/drivers/power/pmic/lp873x.c
index f505468..95c2b7e 100644
--- a/drivers/power/pmic/lp873x.c
+++ b/drivers/power/pmic/lp873x.c
@@ -27,7 +27,7 @@
 			  int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		error("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!", dev, reg);
 		return -EIO;
 	}
 
@@ -37,7 +37,7 @@
 static int lp873x_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
 {
 	if (dm_i2c_read(dev, reg, buff, len)) {
-		error("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!", dev, reg);
 		return -EIO;
 	}
 
diff --git a/drivers/power/pmic/lp87565.c b/drivers/power/pmic/lp87565.c
index 782a46c..506769e 100644
--- a/drivers/power/pmic/lp87565.c
+++ b/drivers/power/pmic/lp87565.c
@@ -29,7 +29,7 @@
 
 	ret = dm_i2c_write(dev, reg, buff, len);
 	if (ret)
-		error("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!", dev, reg);
 
 	return ret;
 }
@@ -40,7 +40,7 @@
 
 	ret = dm_i2c_read(dev, reg, buff, len);
 	if (ret)
-		error("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!", dev, reg);
 
 	return ret;
 }
diff --git a/drivers/power/pmic/max77686.c b/drivers/power/pmic/max77686.c
index ceca9f9..b3ed849 100644
--- a/drivers/power/pmic/max77686.c
+++ b/drivers/power/pmic/max77686.c
@@ -31,7 +31,7 @@
 			  int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		error("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!", dev, reg);
 		return -EIO;
 	}
 
@@ -41,7 +41,7 @@
 static int max77686_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
 {
 	if (dm_i2c_read(dev, reg, buff, len)) {
-		error("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!", dev, reg);
 		return -EIO;
 	}
 
diff --git a/drivers/power/pmic/max8997.c b/drivers/power/pmic/max8997.c
index f749d7d..5ebeb8a 100644
--- a/drivers/power/pmic/max8997.c
+++ b/drivers/power/pmic/max8997.c
@@ -26,7 +26,7 @@
 
 	ret = dm_i2c_write(dev, reg, buff, len);
 	if (ret)
-		error("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!", dev, reg);
 
 	return ret;
 }
@@ -37,7 +37,7 @@
 
 	ret = dm_i2c_read(dev, reg, buff, len);
 	if (ret)
-		error("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!", dev, reg);
 
 	return ret;
 }
diff --git a/drivers/power/pmic/max8998.c b/drivers/power/pmic/max8998.c
index 7c4773c..a7e0469 100644
--- a/drivers/power/pmic/max8998.c
+++ b/drivers/power/pmic/max8998.c
@@ -26,7 +26,7 @@
 
 	ret = dm_i2c_write(dev, reg, buff, len);
 	if (ret)
-		error("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!", dev, reg);
 
 	return ret;
 }
@@ -37,7 +37,7 @@
 
 	ret = dm_i2c_read(dev, reg, buff, len);
 	if (ret)
-		error("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!", dev, reg);
 
 	return ret;
 }
diff --git a/drivers/power/pmic/palmas.c b/drivers/power/pmic/palmas.c
index 804c0d1..1e1ecb3 100644
--- a/drivers/power/pmic/palmas.c
+++ b/drivers/power/pmic/palmas.c
@@ -27,7 +27,7 @@
 			  int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		error("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!", dev, reg);
 		return -EIO;
 	}
 
@@ -37,7 +37,7 @@
 static int palmas_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
 {
 	if (dm_i2c_read(dev, reg, buff, len)) {
-		error("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!", dev, reg);
 		return -EIO;
 	}
 
diff --git a/drivers/power/pmic/pfuze100.c b/drivers/power/pmic/pfuze100.c
index 5f361c7..a06cbc0 100644
--- a/drivers/power/pmic/pfuze100.c
+++ b/drivers/power/pmic/pfuze100.c
@@ -33,7 +33,7 @@
 			  int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		error("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!", dev, reg);
 		return -EIO;
 	}
 
@@ -43,7 +43,7 @@
 static int pfuze100_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
 {
 	if (dm_i2c_read(dev, reg, buff, len)) {
-		error("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!", dev, reg);
 		return -EIO;
 	}
 
diff --git a/drivers/power/pmic/s2mps11.c b/drivers/power/pmic/s2mps11.c
index 9d83059..522105e 100644
--- a/drivers/power/pmic/s2mps11.c
+++ b/drivers/power/pmic/s2mps11.c
@@ -27,7 +27,7 @@
 
 	ret = dm_i2c_write(dev, reg, buff, len);
 	if (ret)
-		error("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!", dev, reg);
 
 	return ret;
 }
@@ -38,7 +38,7 @@
 
 	ret = dm_i2c_read(dev, reg, buff, len);
 	if (ret)
-		error("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!", dev, reg);
 
 	return ret;
 }
diff --git a/drivers/power/pmic/s5m8767.c b/drivers/power/pmic/s5m8767.c
index f8ae5ea..3812e24 100644
--- a/drivers/power/pmic/s5m8767.c
+++ b/drivers/power/pmic/s5m8767.c
@@ -30,7 +30,7 @@
 			  int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		error("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!", dev, reg);
 		return -EIO;
 	}
 
@@ -40,7 +40,7 @@
 static int s5m8767_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
 {
 	if (dm_i2c_read(dev, reg, buff, len)) {
-		error("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!", dev, reg);
 		return -EIO;
 	}
 
diff --git a/drivers/power/pmic/sandbox.c b/drivers/power/pmic/sandbox.c
index 6763303..e8d6fac 100644
--- a/drivers/power/pmic/sandbox.c
+++ b/drivers/power/pmic/sandbox.c
@@ -31,7 +31,7 @@
 			      const uint8_t *buff, int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		error("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!", dev, reg);
 		return -EIO;
 	}
 
@@ -42,7 +42,7 @@
 			     uint8_t *buff, int len)
 {
 	if (dm_i2c_read(dev, reg, buff, len)) {
-		error("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!", dev, reg);
 		return -EIO;
 	}
 
@@ -52,7 +52,7 @@
 static int sandbox_pmic_bind(struct udevice *dev)
 {
 	if (!pmic_bind_children(dev, dev_ofnode(dev), pmic_children_info))
-		error("%s:%d PMIC: %s - no child found!", __func__, __LINE__,
+		pr_err("%s:%d PMIC: %s - no child found!", __func__, __LINE__,
 							  dev->name);
 
 	/* Always return success for this device - allows for PMIC I/O */
diff --git a/drivers/power/pmic/tps65090.c b/drivers/power/pmic/tps65090.c
index 4565e3b..ee5358b 100644
--- a/drivers/power/pmic/tps65090.c
+++ b/drivers/power/pmic/tps65090.c
@@ -29,7 +29,7 @@
 			  int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		error("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!", dev, reg);
 		return -EIO;
 	}
 
@@ -42,7 +42,7 @@
 
 	ret = dm_i2c_read(dev, reg, buff, len);
 	if (ret) {
-		error("read error %d from device: %p register: %#x!", ret, dev,
+		pr_err("read error %d from device: %p register: %#x!", ret, dev,
 		      reg);
 		return -EIO;
 	}
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 2cfade1..8892fa1 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -77,6 +77,13 @@
 	features for fixed value regulators. The driver implements get/set api
 	for enable and get only for voltage value.
 
+config SPL_DM_REGULATOR_FIXED
+	bool "Enable Driver Model for REGULATOR Fixed value in SPL"
+	depends on DM_REGULATOR_FIXED
+	---help---
+	This config enables implementation of driver-model regulator uclass
+	features for fixed value regulators in SPL.
+
 config DM_REGULATOR_GPIO
 	bool "Enable Driver Model for GPIO REGULATOR"
 	depends on DM_REGULATOR
diff --git a/drivers/power/regulator/fixed.c b/drivers/power/regulator/fixed.c
index 35c2922..97b4a98 100644
--- a/drivers/power/regulator/fixed.c
+++ b/drivers/power/regulator/fixed.c
@@ -117,7 +117,7 @@
 
 	ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
 	if (ret) {
-		error("Can't set regulator : %s gpio to: %d\n", dev->name,
+		pr_err("Can't set regulator : %s gpio to: %d\n", dev->name,
 		      enable);
 		return ret;
 	}
diff --git a/drivers/power/regulator/gpio-regulator.c b/drivers/power/regulator/gpio-regulator.c
index 42391c6..1031a03 100644
--- a/drivers/power/regulator/gpio-regulator.c
+++ b/drivers/power/regulator/gpio-regulator.c
@@ -109,7 +109,7 @@
 
 	ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
 	if (ret) {
-		error("Can't set regulator : %s gpio to: %d\n", dev->name,
+		pr_err("Can't set regulator : %s gpio to: %d\n", dev->name,
 		      enable);
 		return ret;
 	}
diff --git a/drivers/power/regulator/max77686.c b/drivers/power/regulator/max77686.c
index 8780806..2212d36 100644
--- a/drivers/power/regulator/max77686.c
+++ b/drivers/power/regulator/max77686.c
@@ -98,7 +98,7 @@
 	if (hex >= 0 && hex <= hex_max)
 		return hex;
 
-	error("Value: %d uV is wrong for BUCK%d", uV, buck);
+	pr_err("Value: %d uV is wrong for BUCK%d", uV, buck);
 	return -EINVAL;
 }
 
@@ -134,7 +134,7 @@
 	return uV;
 
 bad_hex:
-	error("Value: %#x is wrong for BUCK%d", hex, buck);
+	pr_err("Value: %#x is wrong for BUCK%d", hex, buck);
 	return -EINVAL;
 }
 
@@ -160,7 +160,7 @@
 	if (hex >= 0 && hex <= MAX77686_LDO_VOLT_MAX_HEX)
 		return hex;
 
-	error("Value: %d uV is wrong for LDO%d", uV, ldo);
+	pr_err("Value: %d uV is wrong for LDO%d", uV, ldo);
 	return -EINVAL;
 }
 
@@ -189,7 +189,7 @@
 	return uV;
 
 bad_hex:
-	error("Value: %#x is wrong for ldo%d", hex, ldo);
+	pr_err("Value: %#x is wrong for ldo%d", hex, ldo);
 	return -EINVAL;
 }
 
@@ -328,7 +328,7 @@
 
 	ldo = dev->driver_data;
 	if (ldo < 1 || ldo > MAX77686_LDO_NUM) {
-		error("Wrong ldo number: %d", ldo);
+		pr_err("Wrong ldo number: %d", ldo);
 		return -EINVAL;
 	}
 
@@ -366,7 +366,7 @@
 
 	buck = dev->driver_data;
 	if (buck < 1 || buck > MAX77686_BUCK_NUM) {
-		error("Wrong buck number: %d", buck);
+		pr_err("Wrong buck number: %d", buck);
 		return -EINVAL;
 	}
 
@@ -423,7 +423,7 @@
 
 	ldo = dev->driver_data;
 	if (ldo < 1 || ldo > MAX77686_LDO_NUM) {
-		error("Wrong ldo number: %d", ldo);
+		pr_err("Wrong ldo number: %d", ldo);
 		return -EINVAL;
 	}
 
@@ -493,7 +493,7 @@
 	}
 
 	if (mode == 0xff) {
-		error("Wrong mode: %d for ldo%d", *opmode, ldo);
+		pr_err("Wrong mode: %d for ldo%d", *opmode, ldo);
 		return -EINVAL;
 	}
 
@@ -545,7 +545,7 @@
 
 	buck = dev->driver_data;
 	if (buck < 1 || buck > MAX77686_BUCK_NUM) {
-		error("Wrong buck number: %d", buck);
+		pr_err("Wrong buck number: %d", buck);
 		return -EINVAL;
 	}
 
@@ -614,7 +614,7 @@
 	}
 
 	if (mode == 0xff) {
-		error("Wrong mode: %d for buck: %d\n", *opmode, buck);
+		pr_err("Wrong mode: %d for buck: %d\n", *opmode, buck);
 		return -EINVAL;
 	}
 
diff --git a/drivers/power/regulator/pbias_regulator.c b/drivers/power/regulator/pbias_regulator.c
index 914500b..116b7f4 100644
--- a/drivers/power/regulator/pbias_regulator.c
+++ b/drivers/power/regulator/pbias_regulator.c
@@ -70,14 +70,14 @@
 	err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
 					   "syscon", &syscon);
 	if (err) {
-		error("%s: unable to find syscon device (%d)\n", __func__,
+		pr_err("%s: unable to find syscon device (%d)\n", __func__,
 		      err);
 		return err;
 	}
 
 	regmap = syscon_get_regmap(syscon);
 	if (IS_ERR(regmap)) {
-		error("%s: unable to find regmap (%ld)\n", __func__,
+		pr_err("%s: unable to find regmap (%ld)\n", __func__,
 		      PTR_ERR(regmap));
 		return PTR_ERR(regmap);
 	}
@@ -85,7 +85,7 @@
 
 	err = dev_read_resource(dev, 0, &res);
 	if (err) {
-		error("%s: unable to find offset (%d)\n", __func__, err);
+		pr_err("%s: unable to find offset (%d)\n", __func__, err);
 		return err;
 	}
 	priv->offset = res.start;
diff --git a/drivers/power/regulator/sandbox.c b/drivers/power/regulator/sandbox.c
index 06c09fd..f980a17 100644
--- a/drivers/power/regulator/sandbox.c
+++ b/drivers/power/regulator/sandbox.c
@@ -87,7 +87,7 @@
 	int ret;
 
 	if (dev->driver_data > output_count) {
-		error("Unknown regulator number: %lu for PMIC %s!",
+		pr_err("Unknown regulator number: %lu for PMIC %s!",
 		      dev->driver_data, dev->name);
 		return -EINVAL;
 	}
@@ -95,7 +95,7 @@
 	reg = (dev->driver_data - 1) * OUT_REG_COUNT + reg_type;
 	ret = pmic_read(dev->parent, reg, &reg_val, 1);
 	if (ret) {
-		error("PMIC read failed: %d\n",  ret);
+		pr_err("PMIC read failed: %d\n",  ret);
 		return ret;
 	}
 
@@ -115,14 +115,14 @@
 	int max_value;
 
 	if (dev->driver_data > output_count) {
-		error("Unknown regulator number: %lu for PMIC %s!",
+		pr_err("Unknown regulator number: %lu for PMIC %s!",
 		      dev->driver_data, dev->name);
 		return -EINVAL;
 	}
 
 	max_value = range[dev->driver_data - 1].max;
 	if (value > max_value) {
-		error("Wrong value for %s: %lu. Max is: %d.",
+		pr_err("Wrong value for %s: %lu. Max is: %d.",
 		      dev->name, dev->driver_data, max_value);
 		return -EINVAL;
 	}
@@ -134,7 +134,7 @@
 	reg = (dev->driver_data - 1) * OUT_REG_COUNT + reg_type;
 	ret = pmic_write(dev->parent, reg, &reg_val, 1);
 	if (ret) {
-		error("PMIC write failed: %d\n",  ret);
+		pr_err("PMIC write failed: %d\n",  ret);
 		return ret;
 	}
 
@@ -154,7 +154,7 @@
 	reg = (dev->driver_data - 1) * OUT_REG_COUNT + OUT_REG_OM;
 	ret = pmic_read(dev->parent, reg, &reg_val, 1);
 	if (ret) {
-		error("PMIC read failed: %d\n",  ret);
+		pr_err("PMIC read failed: %d\n",  ret);
 		return ret;
 	}
 
@@ -163,7 +163,7 @@
 			return uc_pdata->mode[i].id;
 	}
 
-	error("Unknown operation mode for %s!", dev->name);
+	pr_err("Unknown operation mode for %s!", dev->name);
 	return -EINVAL;
 }
 
@@ -188,14 +188,14 @@
 	}
 
 	if (reg_val == -1) {
-		error("Unknown operation mode for %s!", dev->name);
+		pr_err("Unknown operation mode for %s!", dev->name);
 		return -EINVAL;
 	}
 
 	reg = (dev->driver_data - 1) * OUT_REG_COUNT + OUT_REG_OM;
 	ret = pmic_write(dev->parent, reg, (uint8_t *)&reg_val, 1);
 	if (ret) {
-		error("PMIC write failed: %d\n",  ret);
+		pr_err("PMIC write failed: %d\n",  ret);
 		return ret;
 	}
 
diff --git a/drivers/ram/rockchip/Makefile b/drivers/ram/rockchip/Makefile
index b09d03c..45b5fe7 100644
--- a/drivers/ram/rockchip/Makefile
+++ b/drivers/ram/rockchip/Makefile
@@ -5,3 +5,8 @@
 #
 
 obj-$(CONFIG_ROCKCHIP_RK3368) = dmc-rk3368.o
+obj-$(CONFIG_ROCKCHIP_RK3188) = sdram_rk3188.o
+obj-$(CONFIG_ROCKCHIP_RK322X) = sdram_rk322x.o
+obj-$(CONFIG_ROCKCHIP_RK3288) = sdram_rk3288.o
+obj-$(CONFIG_ROCKCHIP_RK3328) = sdram_rk3328.o
+obj-$(CONFIG_ROCKCHIP_RK3399) = sdram_rk3399.o
diff --git a/drivers/ram/rockchip/dmc-rk3368.c b/drivers/ram/rockchip/dmc-rk3368.c
index 7577ff0..bfcb1dd 100644
--- a/drivers/ram/rockchip/dmc-rk3368.c
+++ b/drivers/ram/rockchip/dmc-rk3368.c
@@ -230,7 +230,7 @@
 	tmp = get_timer(0);
 	do {
 		if (get_timer(tmp) > timeout_ms) {
-			error("%s: POWER_UP_START did not complete in %ld ms\n",
+			pr_err("%s: POWER_UP_START did not complete in %ld ms\n",
 			      __func__, timeout_ms);
 			return -ETIME;
 		}
@@ -422,7 +422,7 @@
 	tmp = get_timer(0);
 	do {
 		if (get_timer(tmp) > timeout_ms) {
-			error("%s: DFI init did not complete within %ld ms\n",
+			pr_err("%s: DFI init did not complete within %ld ms\n",
 			      __func__, timeout_ms);
 			return -ETIME;
 		}
@@ -457,7 +457,7 @@
 	u32 tfaw_as_ps;
 
 	if (params->ddr_speed_bin != DDR3_1600K) {
-		error("%s: unimplemented DDR3 speed bin %d\n",
+		pr_err("%s: unimplemented DDR3 speed bin %d\n",
 		      __func__, params->ddr_speed_bin);
 		return -1;
 	}
@@ -585,7 +585,7 @@
 	tmp = get_timer(0);
 	do {
 		if (get_timer(tmp) > timeout_ms) {
-			error("%s: did not complete within %ld ms\n",
+			pr_err("%s: did not complete within %ld ms\n",
 			      __func__, timeout_ms);
 			return -ETIME;
 		}
@@ -625,7 +625,7 @@
 	}
 
 	if (col == 8) {
-		error("%s: col detect error\n", __func__);
+		pr_err("%s: col detect error\n", __func__);
 		return -EINVAL;
 	}
 
@@ -644,7 +644,7 @@
 	}
 
 	if (row == 11) {
-		error("%s: row detect error\n", __func__);
+		pr_err("%s: row detect error\n", __func__);
 		return -EINVAL;
 	}
 
@@ -764,7 +764,7 @@
 		}
 	}
 
-	error("%s: ddrconf (NIU config) not found\n", __func__);
+	pr_err("%s: ddrconf (NIU config) not found\n", __func__);
 	return -EINVAL;
 }
 
diff --git a/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c b/drivers/ram/rockchip/sdram_rk3188.c
similarity index 98%
rename from arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
rename to drivers/ram/rockchip/sdram_rk3188.c
index 9d8b225..365d00e 100644
--- a/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
+++ b/drivers/ram/rockchip/sdram_rk3188.c
@@ -682,11 +682,18 @@
 
 static int sdram_get_niu_config(struct rk3188_sdram_params *sdram_params)
 {
-	int i, tmp, size, ret = 0;
+	int i, tmp, size, row, ret = 0;
 
+	row = sdram_params->ch[0].cs0_row;
+	/*
+	 * RK3188 share the rank and row bit15, we use same ddr config for 15bit
+	 * and 16bit row
+	 */
+	if (row == 16)
+		row = 15;
 	tmp = sdram_params->ch[0].col - 9;
 	tmp -= (sdram_params->ch[0].bw == 2) ? 0 : 1;
-	tmp |= ((sdram_params->ch[0].cs0_row - 13) << 4);
+	tmp |= ((row - 13) << 4);
 	size = sizeof(ddrconf_table)/sizeof(ddrconf_table[0]);
 	for (i = 0; i < size; i++)
 		if (tmp == ddrconf_table[i])
diff --git a/drivers/ram/rockchip/sdram_rk322x.c b/drivers/ram/rockchip/sdram_rk322x.c
new file mode 100644
index 0000000..cc3138b
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_rk322x.c
@@ -0,0 +1,855 @@
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:     GPL-2.0
+ */
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <errno.h>
+#include <ram.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk322x.h>
+#include <asm/arch/grf_rk322x.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sdram_rk322x.h>
+#include <asm/arch/timer.h>
+#include <asm/arch/uart.h>
+#include <asm/arch/sdram_common.h>
+#include <asm/types.h>
+#include <linux/err.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+struct chan_info {
+	struct rk322x_ddr_pctl *pctl;
+	struct rk322x_ddr_phy *phy;
+	struct rk322x_service_sys *msch;
+};
+
+struct dram_info {
+	struct chan_info chan[1];
+	struct ram_info info;
+	struct clk ddr_clk;
+	struct rk322x_cru *cru;
+	struct rk322x_grf *grf;
+};
+
+struct rk322x_sdram_params {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+		struct dtd_rockchip_rk3228_dmc of_plat;
+#endif
+		struct rk322x_sdram_channel ch[1];
+		struct rk322x_pctl_timing pctl_timing;
+		struct rk322x_phy_timing phy_timing;
+		struct rk322x_base_params base;
+		int num_channels;
+		struct regmap *map;
+};
+
+#ifdef CONFIG_TPL_BUILD
+/*
+ * [7:6]  bank(n:n bit bank)
+ * [5:4]  row(13+n)
+ * [3]    cs(0:1 cs, 1:2 cs)
+ * [2:1]  bank(n:n bit bank)
+ * [0]    col(10+n)
+ */
+const char ddr_cfg_2_rbc[] = {
+	((0 << 6) | (0 << 4) | (0 << 3) | (1 << 2) | 1),
+	((0 << 6) | (1 << 4) | (0 << 3) | (1 << 2) | 1),
+	((0 << 6) | (2 << 4) | (0 << 3) | (1 << 2) | 1),
+	((0 << 6) | (3 << 4) | (0 << 3) | (1 << 2) | 1),
+	((0 << 6) | (1 << 4) | (0 << 3) | (1 << 2) | 2),
+	((0 << 6) | (2 << 4) | (0 << 3) | (1 << 2) | 2),
+	((0 << 6) | (3 << 4) | (0 << 3) | (1 << 2) | 2),
+	((0 << 6) | (0 << 4) | (0 << 3) | (1 << 2) | 0),
+	((0 << 6) | (1 << 4) | (0 << 3) | (1 << 2) | 0),
+	((0 << 6) | (2 << 4) | (0 << 3) | (1 << 2) | 0),
+	((0 << 6) | (3 << 4) | (0 << 3) | (1 << 2) | 0),
+	((0 << 6) | (2 << 4) | (0 << 3) | (0 << 2) | 1),
+	((1 << 6) | (1 << 4) | (0 << 3) | (0 << 2) | 2),
+	((1 << 6) | (1 << 4) | (0 << 3) | (0 << 2) | 1),
+	((0 << 6) | (3 << 4) | (1 << 3) | (1 << 2) | 1),
+	((0 << 6) | (3 << 4) | (1 << 3) | (1 << 2) | 0),
+};
+
+static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
+{
+	int i;
+
+	for (i = 0; i < n / sizeof(u32); i++) {
+		writel(*src, dest);
+		src++;
+		dest++;
+	}
+}
+
+void phy_pctrl_reset(struct rk322x_cru *cru,
+		     struct rk322x_ddr_phy *ddr_phy)
+{
+	rk_clrsetreg(&cru->cru_softrst_con[5], 1 << DDRCTRL_PSRST_SHIFT |
+			1 << DDRCTRL_SRST_SHIFT | 1 << DDRPHY_PSRST_SHIFT |
+			1 << DDRPHY_SRST_SHIFT,
+			1 << DDRCTRL_PSRST_SHIFT | 1 << DDRCTRL_SRST_SHIFT |
+			1 << DDRPHY_PSRST_SHIFT | 1 << DDRPHY_SRST_SHIFT);
+
+	rockchip_udelay(10);
+
+	rk_clrreg(&cru->cru_softrst_con[5], 1 << DDRPHY_PSRST_SHIFT |
+						  1 << DDRPHY_SRST_SHIFT);
+	rockchip_udelay(10);
+
+	rk_clrreg(&cru->cru_softrst_con[5], 1 << DDRCTRL_PSRST_SHIFT |
+						  1 << DDRCTRL_SRST_SHIFT);
+	rockchip_udelay(10);
+
+	clrbits_le32(&ddr_phy->ddrphy_reg[0],
+		     SOFT_RESET_MASK << SOFT_RESET_SHIFT);
+	rockchip_udelay(10);
+	setbits_le32(&ddr_phy->ddrphy_reg[0],
+		     SOFT_DERESET_ANALOG);
+	rockchip_udelay(5);
+	setbits_le32(&ddr_phy->ddrphy_reg[0],
+		     SOFT_DERESET_DIGITAL);
+
+	rockchip_udelay(1);
+}
+
+void phy_dll_bypass_set(struct rk322x_ddr_phy *ddr_phy, u32 freq)
+{
+	u32 tmp;
+
+	setbits_le32(&ddr_phy->ddrphy_reg[0x13], 0x10);
+	setbits_le32(&ddr_phy->ddrphy_reg[0x26], 0x10);
+	setbits_le32(&ddr_phy->ddrphy_reg[0x36], 0x10);
+	setbits_le32(&ddr_phy->ddrphy_reg[0x46], 0x10);
+	setbits_le32(&ddr_phy->ddrphy_reg[0x56], 0x10);
+
+	clrbits_le32(&ddr_phy->ddrphy_reg[0x14], 0x8);
+	clrbits_le32(&ddr_phy->ddrphy_reg[0x27], 0x8);
+	clrbits_le32(&ddr_phy->ddrphy_reg[0x37], 0x8);
+	clrbits_le32(&ddr_phy->ddrphy_reg[0x47], 0x8);
+	clrbits_le32(&ddr_phy->ddrphy_reg[0x57], 0x8);
+
+	if (freq <= 400)
+		setbits_le32(&ddr_phy->ddrphy_reg[0xa4], 0x1f);
+	else
+		clrbits_le32(&ddr_phy->ddrphy_reg[0xa4], 0x1f);
+
+	if (freq <= 680)
+		tmp = 3;
+	else
+		tmp = 2;
+
+	writel(tmp, &ddr_phy->ddrphy_reg[0x28]);
+	writel(tmp, &ddr_phy->ddrphy_reg[0x38]);
+	writel(tmp, &ddr_phy->ddrphy_reg[0x48]);
+	writel(tmp, &ddr_phy->ddrphy_reg[0x58]);
+}
+
+static void send_command(struct rk322x_ddr_pctl *pctl,
+			 u32 rank, u32 cmd, u32 arg)
+{
+	writel((START_CMD | (rank << 20) | arg | cmd), &pctl->mcmd);
+	rockchip_udelay(1);
+	while (readl(&pctl->mcmd) & START_CMD)
+		;
+}
+
+static void memory_init(struct chan_info *chan,
+			struct rk322x_sdram_params *sdram_params)
+{
+	struct rk322x_ddr_pctl *pctl = chan->pctl;
+	u32 dramtype = sdram_params->base.dramtype;
+
+	if (dramtype == DDR3) {
+		send_command(pctl, 3, DESELECT_CMD, 0);
+		rockchip_udelay(1);
+		send_command(pctl, 3, PREA_CMD, 0);
+		send_command(pctl, 3, MRS_CMD,
+			     (0x02 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
+			     (sdram_params->phy_timing.mr[2] & CMD_ADDR_MASK) <<
+			     CMD_ADDR_SHIFT);
+
+		send_command(pctl, 3, MRS_CMD,
+			     (0x03 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
+			     (sdram_params->phy_timing.mr[3] & CMD_ADDR_MASK) <<
+			     CMD_ADDR_SHIFT);
+
+		send_command(pctl, 3, MRS_CMD,
+			     (0x01 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
+			     (sdram_params->phy_timing.mr[1] & CMD_ADDR_MASK) <<
+			     CMD_ADDR_SHIFT);
+
+		send_command(pctl, 3, MRS_CMD,
+			     (0x00 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
+			     ((sdram_params->phy_timing.mr[0] |
+			       DDR3_DLL_RESET) &
+			     CMD_ADDR_MASK) << CMD_ADDR_SHIFT);
+
+		send_command(pctl, 3, ZQCL_CMD, 0);
+	} else {
+		send_command(pctl, 3, MRS_CMD,
+			     (0x63 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
+			     (0 & LPDDR23_OP_MASK) <<
+			     LPDDR23_OP_SHIFT);
+		rockchip_udelay(10);
+		send_command(pctl, 3, MRS_CMD,
+			     (0x10 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
+			     (0xff & LPDDR23_OP_MASK) <<
+			     LPDDR23_OP_SHIFT);
+		rockchip_udelay(1);
+		send_command(pctl, 3, MRS_CMD,
+			     (0x10 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
+			     (0xff & LPDDR23_OP_MASK) <<
+			     LPDDR23_OP_SHIFT);
+		rockchip_udelay(1);
+		send_command(pctl, 3, MRS_CMD,
+			     (1 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
+			     (sdram_params->phy_timing.mr[1] &
+			      LPDDR23_OP_MASK) << LPDDR23_OP_SHIFT);
+		send_command(pctl, 3, MRS_CMD,
+			     (2 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
+			     (sdram_params->phy_timing.mr[2] &
+			      LPDDR23_OP_MASK) << LPDDR23_OP_SHIFT);
+		send_command(pctl, 3, MRS_CMD,
+			     (3 & LPDDR23_MA_MASK) << LPDDR23_MA_SHIFT |
+			     (sdram_params->phy_timing.mr[3] &
+			      LPDDR23_OP_MASK) << LPDDR23_OP_SHIFT);
+		if (dramtype == LPDDR3)
+			send_command(pctl, 3, MRS_CMD, (11 & LPDDR23_MA_MASK) <<
+				     LPDDR23_MA_SHIFT |
+				     (sdram_params->phy_timing.mr11 &
+				      LPDDR23_OP_MASK) << LPDDR23_OP_SHIFT);
+	}
+}
+
+static u32 data_training(struct chan_info *chan)
+{
+	struct rk322x_ddr_phy *ddr_phy = chan->phy;
+	struct rk322x_ddr_pctl *pctl = chan->pctl;
+	u32 value;
+	u32 bw = (readl(&ddr_phy->ddrphy_reg[0]) >> 4) & 0xf;
+	u32 ret;
+
+	/* disable auto refresh */
+	value = readl(&pctl->trefi) | (1 << 31);
+	writel(1 << 31, &pctl->trefi);
+
+	clrsetbits_le32(&ddr_phy->ddrphy_reg[2], 0x30,
+			DQS_SQU_CAL_SEL_CS0);
+	setbits_le32(&ddr_phy->ddrphy_reg[2], DQS_SQU_CAL_START);
+
+	rockchip_udelay(30);
+	ret = readl(&ddr_phy->ddrphy_reg[0xff]);
+
+	clrbits_le32(&ddr_phy->ddrphy_reg[2],
+		     DQS_SQU_CAL_START);
+
+	/*
+	 * since data training will take about 20us, so send some auto
+	 * refresh(about 7.8us) to complement the lost time
+	 */
+	send_command(pctl, 3, PREA_CMD, 0);
+	send_command(pctl, 3, REF_CMD, 0);
+
+	writel(value, &pctl->trefi);
+
+	if (ret & 0x10) {
+		ret = -1;
+	} else {
+		ret = (ret & 0xf) ^ bw;
+		ret = (ret == 0) ? 0 : -1;
+	}
+	return ret;
+}
+
+static void move_to_config_state(struct rk322x_ddr_pctl *pctl)
+{
+	unsigned int state;
+
+	while (1) {
+		state = readl(&pctl->stat) & PCTL_STAT_MASK;
+		switch (state) {
+		case LOW_POWER:
+			writel(WAKEUP_STATE, &pctl->sctl);
+			while ((readl(&pctl->stat) & PCTL_STAT_MASK)
+				!= ACCESS)
+				;
+			/*
+			 * If at low power state, need wakeup first, and then
+			 * enter the config, so fallthrough
+			 */
+		case ACCESS:
+			/* fallthrough */
+		case INIT_MEM:
+			writel(CFG_STATE, &pctl->sctl);
+			while ((readl(&pctl->stat) & PCTL_STAT_MASK) != CONFIG)
+				;
+			break;
+		case CONFIG:
+			return;
+		default:
+			break;
+		}
+	}
+}
+
+static void move_to_access_state(struct rk322x_ddr_pctl *pctl)
+{
+	unsigned int state;
+
+	while (1) {
+		state = readl(&pctl->stat) & PCTL_STAT_MASK;
+		switch (state) {
+		case LOW_POWER:
+			writel(WAKEUP_STATE, &pctl->sctl);
+			while ((readl(&pctl->stat) & PCTL_STAT_MASK) != ACCESS)
+				;
+			break;
+		case INIT_MEM:
+			writel(CFG_STATE, &pctl->sctl);
+			while ((readl(&pctl->stat) & PCTL_STAT_MASK) != CONFIG)
+				;
+			/* fallthrough */
+		case CONFIG:
+			writel(GO_STATE, &pctl->sctl);
+			while ((readl(&pctl->stat) & PCTL_STAT_MASK) != ACCESS)
+				;
+			break;
+		case ACCESS:
+			return;
+		default:
+			break;
+		}
+	}
+}
+
+static void move_to_lowpower_state(struct rk322x_ddr_pctl *pctl)
+{
+	unsigned int state;
+
+	while (1) {
+		state = readl(&pctl->stat) & PCTL_STAT_MASK;
+		switch (state) {
+		case INIT_MEM:
+			writel(CFG_STATE, &pctl->sctl);
+			while ((readl(&pctl->stat) & PCTL_STAT_MASK) != CONFIG)
+				;
+			/* fallthrough */
+		case CONFIG:
+			writel(GO_STATE, &pctl->sctl);
+			while ((readl(&pctl->stat) & PCTL_STAT_MASK) != ACCESS)
+				;
+			break;
+		case ACCESS:
+			writel(SLEEP_STATE, &pctl->sctl);
+			while ((readl(&pctl->stat) & PCTL_STAT_MASK) !=
+			       LOW_POWER)
+				;
+			break;
+		case LOW_POWER:
+			return;
+		default:
+			break;
+		}
+	}
+}
+
+/* pctl should in low power mode when call this function */
+static void phy_softreset(struct dram_info *dram)
+{
+	struct rk322x_ddr_phy *ddr_phy = dram->chan[0].phy;
+	struct rk322x_grf *grf = dram->grf;
+
+	writel(GRF_DDRPHY_BUFFEREN_CORE_EN, &grf->soc_con[0]);
+	clrbits_le32(&ddr_phy->ddrphy_reg[0], 0x3 << 2);
+	rockchip_udelay(1);
+	setbits_le32(&ddr_phy->ddrphy_reg[0], 1 << 2);
+	rockchip_udelay(5);
+	setbits_le32(&ddr_phy->ddrphy_reg[0], 1 << 3);
+	writel(GRF_DDRPHY_BUFFEREN_CORE_DIS, &grf->soc_con[0]);
+}
+
+/* bw: 2: 32bit, 1:16bit */
+static void set_bw(struct dram_info *dram, u32 bw)
+{
+	struct rk322x_ddr_pctl *pctl = dram->chan[0].pctl;
+	struct rk322x_ddr_phy *ddr_phy = dram->chan[0].phy;
+	struct rk322x_grf *grf = dram->grf;
+
+	if (bw == 1) {
+		setbits_le32(&pctl->ppcfg, 1);
+		clrbits_le32(&ddr_phy->ddrphy_reg[0], 0xc << 4);
+		writel(GRF_MSCH_NOC_16BIT_EN, &grf->soc_con[0]);
+		clrbits_le32(&ddr_phy->ddrphy_reg[0x46], 0x8);
+		clrbits_le32(&ddr_phy->ddrphy_reg[0x56], 0x8);
+	} else {
+		clrbits_le32(&pctl->ppcfg, 1);
+		setbits_le32(&ddr_phy->ddrphy_reg[0], 0xf << 4);
+		writel(GRF_DDR_32BIT_EN | GRF_MSCH_NOC_32BIT_EN,
+		       &grf->soc_con[0]);
+		setbits_le32(&ddr_phy->ddrphy_reg[0x46], 0x8);
+		setbits_le32(&ddr_phy->ddrphy_reg[0x56], 0x8);
+	}
+}
+
+static void pctl_cfg(struct rk322x_ddr_pctl *pctl,
+		     struct rk322x_sdram_params *sdram_params,
+		     struct rk322x_grf *grf)
+{
+	u32 burst_len;
+	u32 bw;
+	u32 dramtype = sdram_params->base.dramtype;
+
+	if (sdram_params->ch[0].bw == 2)
+		bw = GRF_DDR_32BIT_EN | GRF_MSCH_NOC_32BIT_EN;
+	else
+		bw = GRF_MSCH_NOC_16BIT_EN;
+
+	writel(DFI_INIT_START | DFI_DATA_BYTE_DISABLE_EN, &pctl->dfistcfg0);
+	writel(DFI_DRAM_CLK_SR_EN | DFI_DRAM_CLK_DPD_EN, &pctl->dfistcfg1);
+	writel(DFI_PARITY_INTR_EN | DFI_PARITY_EN, &pctl->dfistcfg2);
+	writel(0x51010, &pctl->dfilpcfg0);
+
+	writel(1, &pctl->dfitphyupdtype0);
+	writel(0x0d, &pctl->dfitphyrdlat);
+	writel(0, &pctl->dfitphywrdata);
+
+	writel(0, &pctl->dfiupdcfg);
+	copy_to_reg(&pctl->togcnt1u, &sdram_params->pctl_timing.togcnt1u,
+		    sizeof(struct rk322x_pctl_timing));
+	if (dramtype == DDR3) {
+		writel((1 << 3) | (1 << 11),
+		       &pctl->dfiodtcfg);
+		writel(7 << 16, &pctl->dfiodtcfg1);
+		writel((readl(&pctl->tcl) - 1) / 2 - 1, &pctl->dfitrddataen);
+		writel((readl(&pctl->tcwl) - 1) / 2 - 1, &pctl->dfitphywrlat);
+		writel(500, &pctl->trsth);
+		writel(0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT | DDR3_EN |
+		       DDR2_DDR3_BL_8 | (6 - 4) << TFAW_SHIFT | PD_EXIT_SLOW |
+		       1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT,
+		       &pctl->mcfg);
+		writel(bw | GRF_DDR3_EN, &grf->soc_con[0]);
+	} else {
+		if (sdram_params->phy_timing.bl & PHT_BL_8)
+			burst_len = MDDR_LPDDR2_BL_8;
+		else
+			burst_len = MDDR_LPDDR2_BL_4;
+
+		writel(readl(&pctl->tcl) / 2 - 1, &pctl->dfitrddataen);
+		writel(readl(&pctl->tcwl) / 2 - 1, &pctl->dfitphywrlat);
+		writel(0, &pctl->trsth);
+		if (dramtype == LPDDR2) {
+			writel(0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT |
+			       LPDDR2_S4 | LPDDR2_EN | burst_len |
+			       (6 - 4) << TFAW_SHIFT | PD_EXIT_FAST |
+			       1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT,
+			       &pctl->mcfg);
+			writel(0, &pctl->dfiodtcfg);
+			writel(0, &pctl->dfiodtcfg1);
+		} else {
+			writel(0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT |
+			       LPDDR2_S4 | LPDDR3_EN | burst_len |
+			       (6 - 4) << TFAW_SHIFT | PD_EXIT_FAST |
+			       1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT,
+			       &pctl->mcfg);
+			writel((1 << 3) | (1 << 2), &pctl->dfiodtcfg);
+			writel((7 << 16) | 4, &pctl->dfiodtcfg1);
+		}
+		writel(bw | GRF_LPDDR2_3_EN, &grf->soc_con[0]);
+	}
+	setbits_le32(&pctl->scfg, 1);
+}
+
+static void phy_cfg(struct chan_info *chan,
+		    struct rk322x_sdram_params *sdram_params)
+{
+	struct rk322x_ddr_phy *ddr_phy = chan->phy;
+	struct rk322x_service_sys *axi_bus = chan->msch;
+	struct rk322x_msch_timings *noc_timing = &sdram_params->base.noc_timing;
+	struct rk322x_phy_timing *phy_timing = &sdram_params->phy_timing;
+	struct rk322x_pctl_timing *pctl_timing = &sdram_params->pctl_timing;
+	u32 cmd_drv, clk_drv, dqs_drv, dqs_odt;
+
+	writel(noc_timing->ddrtiming, &axi_bus->ddrtiming);
+	writel(noc_timing->ddrmode, &axi_bus->ddrmode);
+	writel(noc_timing->readlatency, &axi_bus->readlatency);
+	writel(noc_timing->activate, &axi_bus->activate);
+	writel(noc_timing->devtodev, &axi_bus->devtodev);
+
+	switch (sdram_params->base.dramtype) {
+	case DDR3:
+		writel(PHY_DDR3 | phy_timing->bl, &ddr_phy->ddrphy_reg[1]);
+		break;
+	case LPDDR2:
+		writel(PHY_LPDDR2 | phy_timing->bl, &ddr_phy->ddrphy_reg[1]);
+		break;
+	default:
+		writel(PHY_LPDDR2 | phy_timing->bl, &ddr_phy->ddrphy_reg[1]);
+		break;
+	}
+
+	writel(phy_timing->cl_al, &ddr_phy->ddrphy_reg[0xb]);
+	writel(pctl_timing->tcwl, &ddr_phy->ddrphy_reg[0xc]);
+
+	cmd_drv = PHY_RON_RTT_34OHM;
+	clk_drv = PHY_RON_RTT_45OHM;
+	dqs_drv = PHY_RON_RTT_34OHM;
+	if (sdram_params->base.dramtype == LPDDR2)
+		dqs_odt = PHY_RON_RTT_DISABLE;
+	else
+		dqs_odt = PHY_RON_RTT_225OHM;
+
+	writel(cmd_drv, &ddr_phy->ddrphy_reg[0x11]);
+	clrsetbits_le32(&ddr_phy->ddrphy_reg[0x12], (0x1f << 3), cmd_drv << 3);
+	writel(clk_drv, &ddr_phy->ddrphy_reg[0x16]);
+	writel(clk_drv, &ddr_phy->ddrphy_reg[0x18]);
+
+	writel(dqs_drv, &ddr_phy->ddrphy_reg[0x20]);
+	writel(dqs_drv, &ddr_phy->ddrphy_reg[0x2f]);
+	writel(dqs_drv, &ddr_phy->ddrphy_reg[0x30]);
+	writel(dqs_drv, &ddr_phy->ddrphy_reg[0x3f]);
+	writel(dqs_drv, &ddr_phy->ddrphy_reg[0x40]);
+	writel(dqs_drv, &ddr_phy->ddrphy_reg[0x4f]);
+	writel(dqs_drv, &ddr_phy->ddrphy_reg[0x50]);
+	writel(dqs_drv, &ddr_phy->ddrphy_reg[0x5f]);
+
+	writel(dqs_odt, &ddr_phy->ddrphy_reg[0x21]);
+	writel(dqs_odt, &ddr_phy->ddrphy_reg[0x2e]);
+	writel(dqs_odt, &ddr_phy->ddrphy_reg[0x31]);
+	writel(dqs_odt, &ddr_phy->ddrphy_reg[0x3e]);
+	writel(dqs_odt, &ddr_phy->ddrphy_reg[0x41]);
+	writel(dqs_odt, &ddr_phy->ddrphy_reg[0x4e]);
+	writel(dqs_odt, &ddr_phy->ddrphy_reg[0x51]);
+	writel(dqs_odt, &ddr_phy->ddrphy_reg[0x5e]);
+}
+
+void dram_cfg_rbc(struct chan_info *chan,
+		  struct rk322x_sdram_params *sdram_params)
+{
+	char noc_config;
+	int i = 0;
+	struct rk322x_sdram_channel *config = &sdram_params->ch[0];
+	struct rk322x_service_sys *axi_bus = chan->msch;
+
+	move_to_config_state(chan->pctl);
+
+	if ((config->rank == 2) && (config->cs1_row == config->cs0_row)) {
+		if ((config->col + config->bw) == 12) {
+			i = 14;
+			goto finish;
+		} else if ((config->col + config->bw) == 11) {
+			i = 15;
+			goto finish;
+		}
+	}
+	noc_config = ((config->cs0_row - 13) << 4) | ((config->bk - 2) << 2) |
+				(config->col + config->bw - 11);
+	for (i = 0; i < 11; i++) {
+		if (noc_config == ddr_cfg_2_rbc[i])
+			break;
+	}
+
+	if (i < 11)
+		goto finish;
+
+	noc_config = ((config->bk - 2) << 6) | ((config->cs0_row - 13) << 4) |
+				(config->col + config->bw - 11);
+
+	for (i = 11; i < 14; i++) {
+		if (noc_config == ddr_cfg_2_rbc[i])
+			break;
+	}
+	if (i < 14)
+		goto finish;
+	else
+		i = 0;
+
+finish:
+	writel(i, &axi_bus->ddrconf);
+	move_to_access_state(chan->pctl);
+}
+
+static void dram_all_config(const struct dram_info *dram,
+			    struct rk322x_sdram_params *sdram_params)
+{
+	struct rk322x_sdram_channel *info = &sdram_params->ch[0];
+	u32 sys_reg = 0;
+
+	sys_reg |= sdram_params->base.dramtype << SYS_REG_DDRTYPE_SHIFT;
+	sys_reg |= (1 - 1) << SYS_REG_NUM_CH_SHIFT;
+	sys_reg |= info->row_3_4 << SYS_REG_ROW_3_4_SHIFT(0);
+	sys_reg |= 1 << SYS_REG_CHINFO_SHIFT(0);
+	sys_reg |= (info->rank - 1) << SYS_REG_RANK_SHIFT(0);
+	sys_reg |= (info->col - 9) << SYS_REG_COL_SHIFT(0);
+	sys_reg |= info->bk == 3 ? 0 : 1 << SYS_REG_BK_SHIFT(0);
+	sys_reg |= (info->cs0_row - 13) << SYS_REG_CS0_ROW_SHIFT(0);
+	sys_reg |= (info->cs1_row - 13) << SYS_REG_CS1_ROW_SHIFT(0);
+	sys_reg |= (2 >> info->bw) << SYS_REG_BW_SHIFT(0);
+	sys_reg |= (2 >> info->dbw) << SYS_REG_DBW_SHIFT(0);
+
+	writel(sys_reg, &dram->grf->os_reg[2]);
+}
+
+#define TEST_PATTEN	0x5aa5f00f
+
+static int dram_cap_detect(struct dram_info *dram,
+			   struct rk322x_sdram_params *sdram_params)
+{
+	u32 bw, row, col, addr;
+	u32 ret = 0;
+	struct rk322x_service_sys *axi_bus = dram->chan[0].msch;
+
+	if (sdram_params->base.dramtype == DDR3)
+		sdram_params->ch[0].dbw = 1;
+	else
+		sdram_params->ch[0].dbw = 2;
+
+	move_to_config_state(dram->chan[0].pctl);
+	/* bw detect */
+	set_bw(dram, 2);
+	if (data_training(&dram->chan[0]) == 0) {
+		bw = 2;
+	} else {
+		bw = 1;
+		set_bw(dram, 1);
+		move_to_lowpower_state(dram->chan[0].pctl);
+		phy_softreset(dram);
+		move_to_config_state(dram->chan[0].pctl);
+		if (data_training(&dram->chan[0])) {
+			printf("BW detect error\n");
+			ret = -EINVAL;
+		}
+	}
+	sdram_params->ch[0].bw = bw;
+	sdram_params->ch[0].bk = 3;
+
+	if (bw == 2)
+		writel(6, &axi_bus->ddrconf);
+	else
+		writel(3, &axi_bus->ddrconf);
+	move_to_access_state(dram->chan[0].pctl);
+	for (col = 11; col >= 9; col--) {
+		writel(0, CONFIG_SYS_SDRAM_BASE);
+		addr = CONFIG_SYS_SDRAM_BASE +
+			(1 << (col + bw - 1));
+		writel(TEST_PATTEN, addr);
+		if ((readl(addr) == TEST_PATTEN) &&
+		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+			break;
+	}
+	if (col == 8) {
+		printf("Col detect error\n");
+		ret = -EINVAL;
+		goto out;
+	} else {
+		sdram_params->ch[0].col = col;
+	}
+
+	writel(10, &axi_bus->ddrconf);
+
+	/* Detect row*/
+	for (row = 16; row >= 12; row--) {
+		writel(0, CONFIG_SYS_SDRAM_BASE);
+		addr = CONFIG_SYS_SDRAM_BASE + (1u << (row + 11 + 3 - 1));
+		writel(TEST_PATTEN, addr);
+		if ((readl(addr) == TEST_PATTEN) &&
+		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+			break;
+	}
+	if (row == 11) {
+		printf("Row detect error\n");
+		ret = -EINVAL;
+	} else {
+		sdram_params->ch[0].cs1_row = row;
+		sdram_params->ch[0].row_3_4 = 0;
+		sdram_params->ch[0].cs0_row = row;
+	}
+	/* cs detect */
+	writel(0, CONFIG_SYS_SDRAM_BASE);
+	writel(TEST_PATTEN, CONFIG_SYS_SDRAM_BASE + (1u << 30));
+	writel(~TEST_PATTEN, CONFIG_SYS_SDRAM_BASE + (1u << 30) + 4);
+	if ((readl(CONFIG_SYS_SDRAM_BASE + (1u << 30)) == TEST_PATTEN) &&
+	    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
+		sdram_params->ch[0].rank = 2;
+	else
+		sdram_params->ch[0].rank = 1;
+out:
+	return ret;
+}
+
+static int sdram_init(struct dram_info *dram,
+		      struct rk322x_sdram_params *sdram_params)
+{
+	int ret;
+
+	ret = clk_set_rate(&dram->ddr_clk,
+			   sdram_params->base.ddr_freq * MHz * 2);
+	if (ret < 0) {
+		printf("Could not set DDR clock\n");
+		return ret;
+	}
+
+	phy_pctrl_reset(dram->cru, dram->chan[0].phy);
+	phy_dll_bypass_set(dram->chan[0].phy, sdram_params->base.ddr_freq);
+	pctl_cfg(dram->chan[0].pctl, sdram_params, dram->grf);
+	phy_cfg(&dram->chan[0], sdram_params);
+	writel(POWER_UP_START, &dram->chan[0].pctl->powctl);
+	while (!(readl(&dram->chan[0].pctl->powstat) & POWER_UP_DONE))
+		;
+	memory_init(&dram->chan[0], sdram_params);
+	move_to_access_state(dram->chan[0].pctl);
+	ret = dram_cap_detect(dram, sdram_params);
+	if (ret)
+		goto out;
+	dram_cfg_rbc(&dram->chan[0], sdram_params);
+	dram_all_config(dram, sdram_params);
+out:
+	return ret;
+}
+
+static int rk322x_dmc_ofdata_to_platdata(struct udevice *dev)
+{
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct rk322x_sdram_params *params = dev_get_platdata(dev);
+	const void *blob = gd->fdt_blob;
+	int node = dev_of_offset(dev);
+	int ret;
+
+	params->num_channels = 1;
+
+	ret = fdtdec_get_int_array(blob, node, "rockchip,pctl-timing",
+				   (u32 *)&params->pctl_timing,
+				   sizeof(params->pctl_timing) / sizeof(u32));
+	if (ret) {
+		printf("%s: Cannot read rockchip,pctl-timing\n", __func__);
+		return -EINVAL;
+	}
+	ret = fdtdec_get_int_array(blob, node, "rockchip,phy-timing",
+				   (u32 *)&params->phy_timing,
+				   sizeof(params->phy_timing) / sizeof(u32));
+	if (ret) {
+		printf("%s: Cannot read rockchip,phy-timing\n", __func__);
+		return -EINVAL;
+	}
+	ret = fdtdec_get_int_array(blob, node, "rockchip,sdram-params",
+				   (u32 *)&params->base,
+				   sizeof(params->base) / sizeof(u32));
+	if (ret) {
+		printf("%s: Cannot read rockchip,sdram-params\n", __func__);
+		return -EINVAL;
+	}
+	ret = regmap_init_mem(dev, &params->map);
+	if (ret)
+		return ret;
+#endif
+
+	return 0;
+}
+#endif /* CONFIG_TPL_BUILD */
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int conv_of_platdata(struct udevice *dev)
+{
+	struct rk322x_sdram_params *plat = dev_get_platdata(dev);
+	struct dtd_rockchip_rk322x_dmc *of_plat = &plat->of_plat;
+	int ret;
+
+	memcpy(&plat->pctl_timing, of_plat->rockchip_pctl_timing,
+	       sizeof(plat->pctl_timing));
+	memcpy(&plat->phy_timing, of_plat->rockchip_phy_timing,
+	       sizeof(plat->phy_timing));
+	memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base));
+
+	plat->num_channels = 1;
+	ret = regmap_init_mem_platdata(dev, of_plat->reg,
+				       ARRAY_SIZE(of_plat->reg) / 2,
+				       &plat->map);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+#endif
+
+static int rk322x_dmc_probe(struct udevice *dev)
+{
+#ifdef CONFIG_TPL_BUILD
+	struct rk322x_sdram_params *plat = dev_get_platdata(dev);
+	int ret;
+	struct udevice *dev_clk;
+#endif
+	struct dram_info *priv = dev_get_priv(dev);
+
+	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+#ifdef CONFIG_TPL_BUILD
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	ret = conv_of_platdata(dev);
+	if (ret)
+		return ret;
+#endif
+
+	priv->chan[0].msch = syscon_get_first_range(ROCKCHIP_SYSCON_MSCH);
+	priv->chan[0].pctl = regmap_get_range(plat->map, 0);
+	priv->chan[0].phy = regmap_get_range(plat->map, 1);
+	ret = rockchip_get_clk(&dev_clk);
+	if (ret)
+		return ret;
+	priv->ddr_clk.id = CLK_DDR;
+	ret = clk_request(dev_clk, &priv->ddr_clk);
+	if (ret)
+		return ret;
+
+	priv->cru = rockchip_get_cru();
+	if (IS_ERR(priv->cru))
+		return PTR_ERR(priv->cru);
+	ret = sdram_init(priv, plat);
+	if (ret)
+		return ret;
+#else
+	priv->info.base = CONFIG_SYS_SDRAM_BASE;
+	priv->info.size = rockchip_sdram_size(
+			(phys_addr_t)&priv->grf->os_reg[2]);
+#endif
+
+	return 0;
+}
+
+static int rk322x_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+
+	*info = priv->info;
+
+	return 0;
+}
+
+static struct ram_ops rk322x_dmc_ops = {
+	.get_info = rk322x_dmc_get_info,
+};
+
+static const struct udevice_id rk322x_dmc_ids[] = {
+	{ .compatible = "rockchip,rk3228-dmc" },
+	{ }
+};
+
+U_BOOT_DRIVER(dmc_rk322x) = {
+	.name = "rockchip_rk322x_dmc",
+	.id = UCLASS_RAM,
+	.of_match = rk322x_dmc_ids,
+	.ops = &rk322x_dmc_ops,
+#ifdef CONFIG_TPL_BUILD
+	.ofdata_to_platdata = rk322x_dmc_ofdata_to_platdata,
+#endif
+	.probe = rk322x_dmc_probe,
+	.priv_auto_alloc_size = sizeof(struct dram_info),
+#ifdef CONFIG_TPL_BUILD
+	.platdata_auto_alloc_size = sizeof(struct rk322x_sdram_params),
+#endif
+};
+
diff --git a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c b/drivers/ram/rockchip/sdram_rk3288.c
similarity index 100%
rename from arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
rename to drivers/ram/rockchip/sdram_rk3288.c
diff --git a/arch/arm/mach-rockchip/rk3328/sdram_rk3328.c b/drivers/ram/rockchip/sdram_rk3328.c
similarity index 100%
rename from arch/arm/mach-rockchip/rk3328/sdram_rk3328.c
rename to drivers/ram/rockchip/sdram_rk3328.c
diff --git a/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
similarity index 99%
rename from arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
rename to drivers/ram/rockchip/sdram_rk3399.c
index 5ed4b03..76c1fe8 100644
--- a/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -551,7 +551,7 @@
 	tmp = get_timer(0);
 	do {
 		if (get_timer(tmp) > timeout_ms) {
-			error("DRAM (%s): phy failed to lock within  %ld ms\n",
+			pr_err("DRAM (%s): phy failed to lock within  %ld ms\n",
 			      __func__, timeout_ms);
 			return -ETIME;
 		}
diff --git a/drivers/ram/stm32_sdram.c b/drivers/ram/stm32_sdram.c
index b1b0289..fdf088e 100644
--- a/drivers/ram/stm32_sdram.c
+++ b/drivers/ram/stm32_sdram.c
@@ -262,7 +262,7 @@
 		bank_name = (char *)ofnode_get_name(bank_node);
 		strsep(&bank_name, "@");
 		if (!bank_name) {
-			error("missing sdram bank index");
+			pr_err("missing sdram bank index");
 			return -EINVAL;
 		}
 
@@ -271,7 +271,7 @@
 			       (long unsigned int *)&bank_params->target_bank);
 
 		if (bank_params->target_bank >= MAX_SDRAM_BANK) {
-			error("Found bank %d , but only bank 0 and 1 are supported",
+			pr_err("Found bank %d , but only bank 0 and 1 are supported",
 			      bank_params->target_bank);
 			return -EINVAL;
 		}
@@ -285,7 +285,7 @@
 						  sizeof(struct stm32_sdram_control));
 
 		if (!params->bank_params[bank].sdram_control) {
-			error("st,sdram-control not found for %s",
+			pr_err("st,sdram-control not found for %s",
 			      ofnode_get_name(bank_node));
 			return -EINVAL;
 		}
@@ -298,7 +298,7 @@
 						  sizeof(struct stm32_sdram_timing));
 
 		if (!params->bank_params[bank].sdram_timing) {
-			error("st,sdram-timing not found for %s",
+			pr_err("st,sdram-timing not found for %s",
 			      ofnode_get_name(bank_node));
 			return -EINVAL;
 		}
diff --git a/drivers/reset/sti-reset.c b/drivers/reset/sti-reset.c
index a79708c..024b996 100644
--- a/drivers/reset/sti-reset.c
+++ b/drivers/reset/sti-reset.c
@@ -201,20 +201,20 @@
 	node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
 					     compatible);
 	if (node < 0) {
-		error("unable to find %s node\n", compatible);
+		pr_err("unable to find %s node\n", compatible);
 		return node;
 	}
 
 	ret = uclass_get_device_by_of_offset(UCLASS_SYSCON, node, &syscon);
 	if (ret) {
-		error("%s: uclass_get_device_by_of_offset failed: %d\n",
+		pr_err("%s: uclass_get_device_by_of_offset failed: %d\n",
 		      __func__, ret);
 		return ret;
 	}
 
 	regmap = syscon_get_regmap(syscon);
 	if (!regmap) {
-		error("unable to get regmap for %s\n", syscon->name);
+		pr_err("unable to get regmap for %s\n", syscon->name);
 		return -ENODEV;
 	}
 
@@ -251,7 +251,7 @@
 			if (ch->deassert_cnt > 0)
 				return 0;
 		} else
-			error("Reset balancing error: reset_ctl=%p dev=%p id=%lu\n",
+			pr_err("Reset balancing error: reset_ctl=%p dev=%p id=%lu\n",
 			      reset_ctl, reset_ctl->dev, reset_ctl->id);
 	}
 
@@ -268,7 +268,7 @@
 	reg = (void __iomem *)base + ch->ack_offset;
 	if (wait_for_bit(__func__, reg, BIT(ch->ack_bit), ctrl_val,
 			 1000, false)) {
-		error("Stuck on waiting ack reset_ctl=%p dev=%p id=%lu\n",
+		pr_err("Stuck on waiting ack reset_ctl=%p dev=%p id=%lu\n",
 		      reset_ctl, reset_ctl->dev, reset_ctl->id);
 
 		return -ETIMEDOUT;
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 9bf2e26..7c54a49 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -531,9 +531,9 @@
 
 config STM32X7_SERIAL
 	bool "STMicroelectronics STM32 SoCs on-chip UART"
-	depends on DM_SERIAL && (STM32F7 || STM32H7)
+	depends on DM_SERIAL && (STM32F4 || STM32F7 || STM32H7)
 	help
-	  If you have a machine based on a STM32 F7 or H7 SoC you can
+	  If you have a machine based on a STM32 F4, F7 or H7 SoC you can
 	  enable its onboard serial ports, say Y to this option.
 	  If unsure, say N.
 
diff --git a/drivers/serial/serial_stm32x7.c b/drivers/serial/serial_stm32x7.c
index 2f4eafa..a5d529c 100644
--- a/drivers/serial/serial_stm32x7.c
+++ b/drivers/serial/serial_stm32x7.c
@@ -17,71 +17,81 @@
 
 static int stm32_serial_setbrg(struct udevice *dev, int baudrate)
 {
-	struct stm32x7_serial_platdata *plat = dev->platdata;
-	struct stm32_usart *const usart = plat->base;
+	struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
+	bool stm32f4 = plat->uart_info->stm32f4;
+	fdt_addr_t base = plat->base;
 	u32 int_div, mantissa, fraction, oversampling;
 
 	int_div = DIV_ROUND_CLOSEST(plat->clock_rate, baudrate);
 
 	if (int_div < 16) {
 		oversampling = 8;
-		setbits_le32(&usart->cr1, USART_CR1_OVER8);
+		setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_OVER8);
 	} else {
 		oversampling = 16;
-		clrbits_le32(&usart->cr1, USART_CR1_OVER8);
+		clrbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_OVER8);
 	}
 
 	mantissa = (int_div / oversampling) << USART_BRR_M_SHIFT;
 	fraction = int_div % oversampling;
 
-	writel(mantissa | fraction, &usart->brr);
+	writel(mantissa | fraction, base + BRR_OFFSET(stm32f4));
 
 	return 0;
 }
 
 static int stm32_serial_getc(struct udevice *dev)
 {
-	struct stm32x7_serial_platdata *plat = dev->platdata;
-	struct stm32_usart *const usart = plat->base;
+	struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
+	bool stm32f4 = plat->uart_info->stm32f4;
+	fdt_addr_t base = plat->base;
 
-	if ((readl(&usart->sr) & USART_SR_FLAG_RXNE) == 0)
+	if ((readl(base + ISR_OFFSET(stm32f4)) & USART_SR_FLAG_RXNE) == 0)
 		return -EAGAIN;
 
-	return readl(&usart->rd_dr);
+	return readl(base + RDR_OFFSET(stm32f4));
 }
 
 static int stm32_serial_putc(struct udevice *dev, const char c)
 {
-	struct stm32x7_serial_platdata *plat = dev->platdata;
-	struct stm32_usart *const usart = plat->base;
+	struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
+	bool stm32f4 = plat->uart_info->stm32f4;
+	fdt_addr_t base = plat->base;
 
-	if ((readl(&usart->sr) & USART_SR_FLAG_TXE) == 0)
+	if ((readl(base + ISR_OFFSET(stm32f4)) & USART_SR_FLAG_TXE) == 0)
 		return -EAGAIN;
 
-	writel(c, &usart->tx_dr);
+	writel(c, base + TDR_OFFSET(stm32f4));
 
 	return 0;
 }
 
 static int stm32_serial_pending(struct udevice *dev, bool input)
 {
-	struct stm32x7_serial_platdata *plat = dev->platdata;
-	struct stm32_usart *const usart = plat->base;
+	struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
+	bool stm32f4 = plat->uart_info->stm32f4;
+	fdt_addr_t base = plat->base;
 
 	if (input)
-		return readl(&usart->sr) & USART_SR_FLAG_RXNE ? 1 : 0;
+		return readl(base + ISR_OFFSET(stm32f4)) &
+			USART_SR_FLAG_RXNE ? 1 : 0;
 	else
-		return readl(&usart->sr) & USART_SR_FLAG_TXE ? 0 : 1;
+		return readl(base + ISR_OFFSET(stm32f4)) &
+			USART_SR_FLAG_TXE ? 0 : 1;
 }
 
 static int stm32_serial_probe(struct udevice *dev)
 {
-	struct stm32x7_serial_platdata *plat = dev->platdata;
-	struct stm32_usart *const usart = plat->base;
-
-#ifdef CONFIG_CLK
-	int ret;
+	struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
 	struct clk clk;
+	fdt_addr_t base = plat->base;
+	int ret;
+	bool stm32f4;
+	u8 uart_enable_bit;
+
+	plat->uart_info = (struct stm32_uart_info *)dev_get_driver_data(dev);
+	stm32f4 = plat->uart_info->stm32f4;
+	uart_enable_bit = plat->uart_info->uart_enable_bit;
 
 	ret = clk_get_by_index(dev, 0, &clk);
 	if (ret < 0)
@@ -92,7 +102,6 @@
 		dev_err(dev, "failed to enable clock\n");
 		return ret;
 	}
-#endif
 
 	plat->clock_rate = clk_get_rate(&clk);
 	if (plat->clock_rate < 0) {
@@ -100,37 +109,36 @@
 		return plat->clock_rate;
 	};
 
-	/* Disable usart-> disable overrun-> enable usart */
-	clrbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE);
-	setbits_le32(&usart->cr3, USART_CR3_OVRDIS);
-	setbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE);
+	/* Disable uart-> disable overrun-> enable uart */
+	clrbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_RE | USART_CR1_TE |
+		     BIT(uart_enable_bit));
+	if (plat->uart_info->has_overrun_disable)
+		setbits_le32(base + CR3_OFFSET(stm32f4), USART_CR3_OVRDIS);
+	if (plat->uart_info->has_fifo)
+		setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_FIFOEN);
+	setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_RE | USART_CR1_TE |
+		     BIT(uart_enable_bit));
 
 	return 0;
 }
 
-#if CONFIG_IS_ENABLED(OF_CONTROL)
 static const struct udevice_id stm32_serial_id[] = {
-	{.compatible = "st,stm32f7-usart"},
-	{.compatible = "st,stm32f7-uart"},
-	{.compatible = "st,stm32h7-usart"},
-	{.compatible = "st,stm32h7-uart"},
+	{ .compatible = "st,stm32-uart", .data = (ulong)&stm32f4_info},
+	{ .compatible = "st,stm32f7-uart", .data = (ulong)&stm32f7_info},
+	{ .compatible = "st,stm32h7-uart", .data = (ulong)&stm32h7_info},
 	{}
 };
 
 static int stm32_serial_ofdata_to_platdata(struct udevice *dev)
 {
 	struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
-	fdt_addr_t addr;
 
-	addr = devfdt_get_addr(dev);
-	if (addr == FDT_ADDR_T_NONE)
+	plat->base = devfdt_get_addr(dev);
+	if (plat->base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
-	plat->base = (struct stm32_usart *)addr;
-
 	return 0;
 }
-#endif
 
 static const struct dm_serial_ops stm32_serial_ops = {
 	.putc = stm32_serial_putc,
diff --git a/drivers/serial/serial_stm32x7.h b/drivers/serial/serial_stm32x7.h
index 9fe37af..b914edf 100644
--- a/drivers/serial/serial_stm32x7.h
+++ b/drivers/serial/serial_stm32x7.h
@@ -8,38 +8,65 @@
 #ifndef _SERIAL_STM32_X7_
 #define _SERIAL_STM32_X7_
 
-struct stm32_usart {
-	u32 cr1;
-	u32 cr2;
-	u32 cr3;
-	u32 brr;
-	u32 gtpr;
-	u32 rtor;
-	u32 rqr;
-	u32 sr;
-	u32 icr;
-	u32 rd_dr;
-	u32 tx_dr;
+#define CR1_OFFSET(x)	(x ? 0x0c : 0x00)
+#define CR3_OFFSET(x)	(x ? 0x14 : 0x08)
+#define BRR_OFFSET(x)	(x ? 0x08 : 0x0c)
+#define ISR_OFFSET(x)	(x ? 0x00 : 0x1c)
+/*
+ * STM32F4 has one Data Register (DR) for received or transmitted
+ * data, so map Receive Data Register (RDR) and Transmit Data
+ * Register (TDR) at the same offset
+ */
+#define RDR_OFFSET(x)	(x ? 0x04 : 0x24)
+#define TDR_OFFSET(x)	(x ? 0x04 : 0x28)
+
+struct stm32_uart_info {
+	u8 uart_enable_bit;	/* UART_CR1_UE */
+	bool stm32f4;		/* true for STM32F4, false otherwise */
+	bool has_overrun_disable;
+	bool has_fifo;
+};
+
+struct stm32_uart_info stm32f4_info = {
+	.stm32f4 = true,
+	.uart_enable_bit = 13,
+	.has_overrun_disable = false,
+	.has_fifo = false,
+};
+
+struct stm32_uart_info stm32f7_info = {
+	.uart_enable_bit = 0,
+	.stm32f4 = false,
+	.has_overrun_disable = true,
+	.has_fifo = false,
+};
+
+struct stm32_uart_info stm32h7_info = {
+	.uart_enable_bit = 0,
+	.stm32f4 = false,
+	.has_overrun_disable = true,
+	.has_fifo = true,
 };
 
 /* Information about a serial port */
 struct stm32x7_serial_platdata {
-	struct stm32_usart *base;  /* address of registers in physical memory */
+	fdt_addr_t base;  /* address of registers in physical memory */
+	struct stm32_uart_info *uart_info;
 	unsigned long int clock_rate;
 };
 
-#define USART_CR1_OVER8			(1 << 15)
-#define USART_CR1_TE			(1 << 3)
-#define USART_CR1_RE			(1 << 2)
-#define USART_CR1_UE			(1 << 0)
+#define USART_CR1_FIFOEN		BIT(29)
+#define USART_CR1_OVER8			BIT(15)
+#define USART_CR1_TE			BIT(3)
+#define USART_CR1_RE			BIT(2)
 
-#define USART_CR3_OVRDIS		(1 << 12)
+#define USART_CR3_OVRDIS		BIT(12)
 
-#define USART_SR_FLAG_RXNE		(1 << 5)
-#define USART_SR_FLAG_TXE		(1 << 7)
+#define USART_SR_FLAG_RXNE		BIT(5)
+#define USART_SR_FLAG_TXE		BIT(7)
 
-#define USART_BRR_F_MASK		0xFF
+#define USART_BRR_F_MASK		GENMASK(7, 0)
 #define USART_BRR_M_SHIFT		4
-#define USART_BRR_M_MASK		0xFFF0
+#define USART_BRR_M_MASK		GENMASK(15, 4)
 
 #endif
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index e2f8342..228e714 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -474,7 +474,7 @@
 	ret = gpio_request_list_by_name(bus, "cs-gpios", priv->cs_gpios,
 					ARRAY_SIZE(priv->cs_gpios), 0);
 	if (ret < 0) {
-		error("Can't get %s gpios! Error: %d", bus->name, ret);
+		pr_err("Can't get %s gpios! Error: %d", bus->name, ret);
 		return ret;
 	}
 
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index 291ef95..eda252d 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -563,6 +563,7 @@
 static const struct udevice_id davinci_spi_ids[] = {
 	{ .compatible = "ti,keystone-spi" },
 	{ .compatible = "ti,dm6441-spi" },
+	{ .compatible = "ti,da830-spi" },
 	{ }
 };
 
diff --git a/drivers/spi/lpc32xx_ssp.c b/drivers/spi/lpc32xx_ssp.c
index c5b766c..e2a593b 100644
--- a/drivers/spi/lpc32xx_ssp.c
+++ b/drivers/spi/lpc32xx_ssp.c
@@ -66,17 +66,17 @@
 	/* we only set up SSP0 for now, so ignore bus */
 
 	if (mode & SPI_3WIRE) {
-		error("3-wire mode not supported");
+		pr_err("3-wire mode not supported");
 		return NULL;
 	}
 
 	if (mode & SPI_SLAVE) {
-		error("slave mode not supported\n");
+		pr_err("slave mode not supported\n");
 		return NULL;
 	}
 
 	if (mode & SPI_PREAMBLE) {
-		error("preamble byte skipping not supported\n");
+		pr_err("preamble byte skipping not supported\n");
 		return NULL;
 	}
 
diff --git a/drivers/sysreset/sysreset_sti.c b/drivers/sysreset/sysreset_sti.c
index 9b58aa8..bf698a7 100644
--- a/drivers/sysreset/sysreset_sti.c
+++ b/drivers/sysreset/sysreset_sti.c
@@ -39,7 +39,7 @@
 					     "st,syscfg", NULL, 0, 0,
 					     &syscfg_phandle);
 	if (ret < 0) {
-		error("Can't get syscfg phandle: %d\n", ret);
+		pr_err("Can't get syscfg phandle: %d\n", ret);
 		return ret;
 	}
 
@@ -47,14 +47,14 @@
 					     syscfg_phandle.node,
 					     &syscon);
 	if (ret) {
-		error("%s: uclass_get_device_by_of_offset failed: %d\n",
+		pr_err("%s: uclass_get_device_by_of_offset failed: %d\n",
 		      __func__, ret);
 		return ret;
 	}
 
 	regmap = syscon_get_regmap(syscon);
 	if (!regmap) {
-		error("unable to get regmap for %s\n", syscon->name);
+		pr_err("unable to get regmap for %s\n", syscon->name);
 		return -ENODEV;
 	}
 
diff --git a/drivers/sysreset/sysreset_syscon.c b/drivers/sysreset/sysreset_syscon.c
index 3818fae..3abce7f 100644
--- a/drivers/sysreset/sysreset_syscon.c
+++ b/drivers/sysreset/sysreset_syscon.c
@@ -45,13 +45,13 @@
 	err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
 					   "regmap", &syscon);
 	if (err) {
-		error("unable to find syscon device\n");
+		pr_err("unable to find syscon device\n");
 		return err;
 	}
 
 	priv->regmap = syscon_get_regmap(syscon);
 	if (!priv->regmap) {
-		error("unable to find regmap\n");
+		pr_err("unable to find regmap\n");
 		return -ENODEV;
 	}
 
diff --git a/drivers/sysreset/sysreset_watchdog.c b/drivers/sysreset/sysreset_watchdog.c
index 304ed05..ab250ae 100644
--- a/drivers/sysreset/sysreset_watchdog.c
+++ b/drivers/sysreset/sysreset_watchdog.c
@@ -38,7 +38,7 @@
 	err = uclass_get_device_by_phandle(UCLASS_WDT, dev,
 					   "wdt", &priv->wdt);
 	if (err) {
-		error("unable to find wdt device\n");
+		pr_err("unable to find wdt device\n");
 		return err;
 	}
 
diff --git a/drivers/tpm/tpm_tis_infineon.c b/drivers/tpm/tpm_tis_infineon.c
index ef3ff0d..e3e20d8 100644
--- a/drivers/tpm/tpm_tis_infineon.c
+++ b/drivers/tpm/tpm_tis_infineon.c
@@ -539,7 +539,7 @@
 	}
 
 	if (chip->chip_type != UNKNOWN && vendor != expected_did_vid) {
-		error("Vendor id did not match! ID was %08x\n", vendor);
+		pr_err("Vendor id did not match! ID was %08x\n", vendor);
 		return -ENODEV;
 	}
 
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index 35c2dc1..e8432bb 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -28,7 +28,7 @@
 
 	dr_mode = fdt_getprop(fdt, node, "dr_mode", NULL);
 	if (!dr_mode) {
-		error("usb dr_mode not found\n");
+		pr_err("usb dr_mode not found\n");
 		return USB_DR_MODE_UNKNOWN;
 	}
 
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index a291ceb..ae7fc1c 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -37,6 +37,13 @@
 
 	  Say 'Y' here if you have one such device
 
+config USB_DWC3_UNIPHIER
+	bool "DesignWare USB3 Host Support on UniPhier Platforms"
+	depends on ARCH_UNIPHIER && USB_XHCI_DWC3
+	help
+	  Support of USB2/3 functionality in Socionext UniPhier platforms.
+	  Say 'Y' here if you have one such device.
+
 menu "PHY Subsystem"
 
 config USB_DWC3_PHY_OMAP
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 2964bae..5149776 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -9,5 +9,6 @@
 obj-$(CONFIG_USB_DWC3_GADGET)		+= gadget.o ep0.o
 
 obj-$(CONFIG_USB_DWC3_OMAP)		+= dwc3-omap.o
+obj-$(CONFIG_USB_DWC3_UNIPHIER)		+= dwc3-uniphier.o
 obj-$(CONFIG_USB_DWC3_PHY_OMAP)		+= ti_usb_phy.o
 obj-$(CONFIG_USB_DWC3_PHY_SAMSUNG)	+= samsung_usb_phy.o
diff --git a/drivers/usb/dwc3/dwc3-uniphier.c b/drivers/usb/dwc3/dwc3-uniphier.c
new file mode 100644
index 0000000..0d13770
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-uniphier.c
@@ -0,0 +1,120 @@
+/*
+ * UniPhier Specific Glue Layer for DWC3
+ *
+ * Copyright (C) 2016-2017 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+#define UNIPHIER_PRO4_DWC3_RESET	0x40
+#define   UNIPHIER_PRO4_DWC3_RESET_XIOMMU	BIT(5)
+#define   UNIPHIER_PRO4_DWC3_RESET_XLINK	BIT(4)
+#define   UNIPHIER_PRO4_DWC3_RESET_PHY_SS	BIT(2)
+
+#define UNIPHIER_PRO5_DWC3_RESET	0x00
+#define   UNIPHIER_PRO5_DWC3_RESET_PHY_S1	BIT(17)
+#define   UNIPHIER_PRO5_DWC3_RESET_PHY_S0	BIT(16)
+#define   UNIPHIER_PRO5_DWC3_RESET_XLINK	BIT(15)
+#define   UNIPHIER_PRO5_DWC3_RESET_XIOMMU	BIT(14)
+
+#define UNIPHIER_PXS2_DWC3_RESET	0x00
+#define   UNIPHIER_PXS2_DWC3_RESET_XLINK	BIT(15)
+
+static int uniphier_pro4_dwc3_init(void __iomem *regs)
+{
+	u32 tmp;
+
+	tmp = readl(regs + UNIPHIER_PRO4_DWC3_RESET);
+	tmp &= ~UNIPHIER_PRO4_DWC3_RESET_PHY_SS;
+	tmp |= UNIPHIER_PRO4_DWC3_RESET_XIOMMU | UNIPHIER_PRO4_DWC3_RESET_XLINK;
+	writel(tmp, regs + UNIPHIER_PRO4_DWC3_RESET);
+
+	return 0;
+}
+
+static int uniphier_pro5_dwc3_init(void __iomem *regs)
+{
+	u32 tmp;
+
+	tmp = readl(regs + UNIPHIER_PRO5_DWC3_RESET);
+	tmp &= ~(UNIPHIER_PRO5_DWC3_RESET_PHY_S1 |
+		 UNIPHIER_PRO5_DWC3_RESET_PHY_S0);
+	tmp |= UNIPHIER_PRO5_DWC3_RESET_XLINK | UNIPHIER_PRO5_DWC3_RESET_XIOMMU;
+	writel(tmp, regs + UNIPHIER_PRO5_DWC3_RESET);
+
+	return 0;
+}
+
+static int uniphier_pxs2_dwc3_init(void __iomem *regs)
+{
+	u32 tmp;
+
+	tmp = readl(regs + UNIPHIER_PXS2_DWC3_RESET);
+	tmp |= UNIPHIER_PXS2_DWC3_RESET_XLINK;
+	writel(tmp, regs + UNIPHIER_PXS2_DWC3_RESET);
+
+	return 0;
+}
+
+static int uniphier_dwc3_probe(struct udevice *dev)
+{
+	fdt_addr_t base;
+	void __iomem *regs;
+	int (*init)(void __iomem *regs);
+	int ret;
+
+	base = devfdt_get_addr(dev);
+	if (base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	regs = ioremap(base, SZ_32K);
+	if (!regs)
+		return -ENOMEM;
+
+	init = (typeof(init))dev_get_driver_data(dev);
+	ret = init(regs);
+	if (ret)
+		dev_err(dev, "failed to init glue layer\n");
+
+	iounmap(regs);
+
+	return ret;
+}
+
+static const struct udevice_id uniphier_dwc3_match[] = {
+	{
+		.compatible = "socionext,uniphier-pro4-dwc3",
+		.data = (ulong)uniphier_pro4_dwc3_init,
+	},
+	{
+		.compatible = "socionext,uniphier-pro5-dwc3",
+		.data = (ulong)uniphier_pro5_dwc3_init,
+	},
+	{
+		.compatible = "socionext,uniphier-pxs2-dwc3",
+		.data = (ulong)uniphier_pxs2_dwc3_init,
+	},
+	{
+		.compatible = "socionext,uniphier-ld20-dwc3",
+		.data = (ulong)uniphier_pxs2_dwc3_init,
+	},
+	{
+		.compatible = "socionext,uniphier-pxs3-dwc3",
+		.data = (ulong)uniphier_pxs2_dwc3_init,
+	},
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(usb_xhci) = {
+	.name = "uniphier-dwc3",
+	.id = UCLASS_SIMPLE_BUS,
+	.of_match = uniphier_dwc3_match,
+	.probe = uniphier_dwc3_probe,
+};
diff --git a/drivers/usb/dwc3/linux-compat.h b/drivers/usb/dwc3/linux-compat.h
index 9e944a3..5cbe377 100644
--- a/drivers/usb/dwc3/linux-compat.h
+++ b/drivers/usb/dwc3/linux-compat.h
@@ -12,10 +12,8 @@
 #ifndef __DWC3_LINUX_COMPAT__
 #define __DWC3_LINUX_COMPAT__
 
-#define pr_debug(format)                debug(format)
 #define WARN(val, format, arg...)	debug(format, ##arg)
 #define dev_WARN(dev, format, arg...)	debug(format, ##arg)
-#define WARN_ON_ONCE(val)		debug("Error %d\n", val)
 
 static inline size_t strlcat(char *dest, const char *src, size_t n)
 {
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c
index 98d20c0..2f84b36 100644
--- a/drivers/usb/emul/sandbox_flash.c
+++ b/drivers/usb/emul/sandbox_flash.c
@@ -390,8 +390,7 @@
 	fs[2].id = STRINGID_SERIAL;
 	fs[2].s = dev->name;
 
-	return usb_emul_setup_device(dev, PACKET_SIZE_64, plat->flash_strings,
-				     flash_desc_list);
+	return usb_emul_setup_device(dev, plat->flash_strings, flash_desc_list);
 }
 
 static int sandbox_flash_probe(struct udevice *dev)
diff --git a/drivers/usb/emul/sandbox_hub.c b/drivers/usb/emul/sandbox_hub.c
index 1432858..9a0f47b 100644
--- a/drivers/usb/emul/sandbox_hub.c
+++ b/drivers/usb/emul/sandbox_hub.c
@@ -121,9 +121,12 @@
 	int change[SANDBOX_NUM_PORTS];
 };
 
-static struct udevice *hub_find_device(struct udevice *hub, int port)
+static struct udevice *hub_find_device(struct udevice *hub, int port,
+				       enum usb_device_speed *speed)
 {
 	struct udevice *dev;
+	struct usb_generic_descriptor **gen_desc;
+	struct usb_device_descriptor **dev_desc;
 
 	for (device_find_first_child(hub, &dev);
 	     dev;
@@ -131,8 +134,27 @@
 		struct sandbox_hub_platdata *plat;
 
 		plat = dev_get_parent_platdata(dev);
-		if (plat->port == port)
+		if (plat->port == port) {
+			gen_desc = plat->plat.desc_list;
+			gen_desc = usb_emul_find_descriptor(gen_desc,
+							    USB_DT_DEVICE, 0);
+			dev_desc = (struct usb_device_descriptor **)gen_desc;
+
+			switch (le16_to_cpu((*dev_desc)->bcdUSB)) {
+			case 0x0100:
+				*speed = USB_SPEED_LOW;
+				break;
+			case 0x0101:
+				*speed = USB_SPEED_FULL;
+				break;
+			case 0x0200:
+			default:
+				*speed = USB_SPEED_HIGH;
+				break;
+			}
+
 			return dev;
+		}
 	}
 
 	return NULL;
@@ -146,7 +168,8 @@
 	int ret = 0;
 
 	if ((clear | set) & USB_PORT_STAT_POWER) {
-		struct udevice *dev = hub_find_device(hub, port);
+		enum usb_device_speed speed;
+		struct udevice *dev = hub_find_device(hub, port, &speed);
 
 		if (dev) {
 			if (set & USB_PORT_STAT_POWER) {
@@ -156,6 +179,10 @@
 				if (!ret) {
 					set |= USB_PORT_STAT_CONNECTION |
 						USB_PORT_STAT_ENABLE;
+					if (speed == USB_SPEED_LOW)
+						set |= USB_PORT_STAT_LOW_SPEED;
+					else if (speed == USB_SPEED_HIGH)
+						set |= USB_PORT_STAT_HIGH_SPEED;
 				}
 
 			} else if (clear & USB_PORT_STAT_POWER) {
@@ -274,15 +301,16 @@
 
 static int sandbox_hub_bind(struct udevice *dev)
 {
-	return usb_emul_setup_device(dev, PACKET_SIZE_64, hub_strings,
-				     hub_desc_list);
+	return usb_emul_setup_device(dev, hub_strings, hub_desc_list);
 }
 
 static int sandbox_child_post_bind(struct udevice *dev)
 {
 	struct sandbox_hub_platdata *plat = dev_get_parent_platdata(dev);
+	struct usb_emul_platdata *emul = dev_get_uclass_platdata(dev);
 
 	plat->port = dev_read_u32_default(dev, "reg", -1);
+	emul->port1 = plat->port + 1;
 
 	return 0;
 }
diff --git a/drivers/usb/emul/sandbox_keyb.c b/drivers/usb/emul/sandbox_keyb.c
index 2735985..cff0176 100644
--- a/drivers/usb/emul/sandbox_keyb.c
+++ b/drivers/usb/emul/sandbox_keyb.c
@@ -208,8 +208,7 @@
 	fs[2].id = STRINGID_SERIAL;
 	fs[2].s = dev->name;
 
-	return usb_emul_setup_device(dev, PACKET_SIZE_8, plat->keyb_strings,
-				     keyb_desc_list);
+	return usb_emul_setup_device(dev, plat->keyb_strings, keyb_desc_list);
 }
 
 static int sandbox_keyb_probe(struct udevice *dev)
diff --git a/drivers/usb/emul/usb-emul-uclass.c b/drivers/usb/emul/usb-emul-uclass.c
index 6e03c1e..fbe11f3 100644
--- a/drivers/usb/emul/usb-emul-uclass.c
+++ b/drivers/usb/emul/usb-emul-uclass.c
@@ -52,7 +52,7 @@
 	return -EINVAL;
 }
 
-static struct usb_generic_descriptor **find_descriptor(
+struct usb_generic_descriptor **usb_emul_find_descriptor(
 		struct usb_generic_descriptor **ptr, int type, int index)
 {
 	debug("%s: type=%x, index=%d\n", __func__, type, index);
@@ -91,8 +91,7 @@
 					   length);
 	}
 
-	ptr = find_descriptor((struct usb_generic_descriptor **)plat->desc_list,
-			      type, index);
+	ptr = usb_emul_find_descriptor(plat->desc_list, type, index);
 	if (!ptr) {
 		debug("%s: Could not find descriptor type %d, index %d\n",
 		      __func__, type, index);
@@ -107,7 +106,7 @@
 	return upto ? upto : length ? -EIO : 0;
 }
 
-static int usb_emul_find_devnum(int devnum, struct udevice **emulp)
+static int usb_emul_find_devnum(int devnum, int port1, struct udevice **emulp)
 {
 	struct udevice *dev;
 	struct uclass *uc;
@@ -120,7 +119,37 @@
 	uclass_foreach_dev(dev, uc) {
 		struct usb_dev_platdata *udev = dev_get_parent_platdata(dev);
 
-		if (udev->devnum == devnum) {
+		/*
+		 * devnum is initialzied to zero at the beginning of the
+		 * enumeration process in usb_setup_device(). At this
+		 * point, udev->devnum has not been assigned to any valid
+		 * USB address either, so we can't rely on the comparison
+		 * result between udev->devnum and devnum to select an
+		 * emulator device.
+		 */
+		if (!devnum) {
+			struct usb_emul_platdata *plat;
+
+			/*
+			 * If the parent is sandbox USB controller, we are
+			 * the root hub. And there is only one root hub
+			 * in the system.
+			 */
+			if (device_get_uclass_id(dev->parent) == UCLASS_USB) {
+				debug("%s: Found emulator '%s'\n",
+				      __func__, dev->name);
+				*emulp = dev;
+				return 0;
+			}
+
+			plat = dev_get_uclass_platdata(dev);
+			if (plat->port1 == port1) {
+				debug("%s: Found emulator '%s', port %d\n",
+				      __func__, dev->name, port1);
+				*emulp = dev;
+				return 0;
+			}
+		} else if (udev->devnum == devnum) {
 			debug("%s: Found emulator '%s', addr %d\n", __func__,
 			      dev->name, udev->devnum);
 			*emulp = dev;
@@ -132,18 +161,19 @@
 	return -ENOENT;
 }
 
-int usb_emul_find(struct udevice *bus, ulong pipe, struct udevice **emulp)
+int usb_emul_find(struct udevice *bus, ulong pipe, int port1,
+		  struct udevice **emulp)
 {
 	int devnum = usb_pipedevice(pipe);
 
-	return usb_emul_find_devnum(devnum, emulp);
+	return usb_emul_find_devnum(devnum, port1, emulp);
 }
 
 int usb_emul_find_for_dev(struct udevice *dev, struct udevice **emulp)
 {
 	struct usb_dev_platdata *udev = dev_get_parent_platdata(dev);
 
-	return usb_emul_find_devnum(udev->devnum, emulp);
+	return usb_emul_find_devnum(udev->devnum, 0, emulp);
 }
 
 int usb_emul_control(struct udevice *emul, struct usb_device *udev,
@@ -229,8 +259,8 @@
 	return ops->interrupt(emul, udev, pipe, buffer, length, interval);
 }
 
-int usb_emul_setup_device(struct udevice *dev, int maxpacketsize,
-			  struct usb_string *strings, void **desc_list)
+int usb_emul_setup_device(struct udevice *dev, struct usb_string *strings,
+			  void **desc_list)
 {
 	struct usb_dev_platdata *plat = dev_get_parent_platdata(dev);
 	struct usb_generic_descriptor **ptr;
@@ -264,18 +294,11 @@
 	return 0;
 }
 
-void usb_emul_reset(struct udevice *dev)
-{
-	struct usb_dev_platdata *plat = dev_get_parent_platdata(dev);
-
-	plat->devnum = 0;
-	plat->configno = 0;
-}
-
 UCLASS_DRIVER(usb_emul) = {
 	.id		= UCLASS_USB_EMUL,
 	.name		= "usb_emul",
 	.post_bind	= dm_scan_fdt_dev,
+	.per_device_platdata_auto_alloc_size = sizeof(struct usb_emul_platdata),
 	.per_child_auto_alloc_size = sizeof(struct usb_device),
 	.per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata),
 };
diff --git a/drivers/usb/eth/mcs7830.c b/drivers/usb/eth/mcs7830.c
index 4abef5d..941d612 100644
--- a/drivers/usb/eth/mcs7830.c
+++ b/drivers/usb/eth/mcs7830.c
@@ -418,25 +418,25 @@
 
 	rc = mcs7830_set_autoneg(udev);
 	if (rc < 0) {
-		error("setting autoneg failed\n");
+		pr_err("setting autoneg failed\n");
 		return rc;
 	}
 
 	rc = mcs7830_write_mchash(udev, priv);
 	if (rc < 0) {
-		error("failed to set multicast hash\n");
+		pr_err("failed to set multicast hash\n");
 		return rc;
 	}
 
 	rc = mcs7830_write_config(udev, priv);
 	if (rc < 0) {
-		error("failed to set configuration\n");
+		pr_err("failed to set configuration\n");
 		return rc;
 	}
 
 	rc = mcs7830_apply_fixup(udev);
 	if (rc < 0) {
-		error("fixup application failed\n");
+		pr_err("fixup application failed\n");
 		return rc;
 	}
 
@@ -541,11 +541,11 @@
 	debug("%s() RX want len %d, got len %d, rc %d\n",
 	      __func__, wantlen, gotlen, rc);
 	if (rc != 0) {
-		error("RX: failed to receive\n");
+		pr_err("RX: failed to receive\n");
 		return rc;
 	}
 	if (gotlen > wantlen) {
-		error("RX: got too many bytes (%d)\n", gotlen);
+		pr_err("RX: got too many bytes (%d)\n", gotlen);
 		return -EIO;
 	}
 
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 225b66b..102a63b 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -36,6 +36,30 @@
 
 if USB_GADGET
 
+config USB_GADGET_MANUFACTURER
+	string "Vendor name of the USB device"
+	default "Allwinner Technology" if ARCH_SUNXI
+	default "U-Boot"
+	help
+	  Vendor name of the USB device emulated, reported to the host device.
+	  This is usually either the manufacturer of the device or the SoC.
+
+config USB_GADGET_VENDOR_NUM
+	hex "Vendor ID of the USB device"
+	default 0x1f3a if ARCH_SUNXI
+	default 0x0
+	help
+	  Vendor ID of the USB device emulated, reported to the host device.
+	  This is usually the board or SoC vendor's, unless you've registered
+	  for one.
+
+config USB_GADGET_PRODUCT_NUM
+	hex "Product ID of the USB device"
+	default 0x1010 if ARCH_SUNXI
+	default 0x0
+	help
+	  Product ID of the USB device emulated, reported to the host device.
+
 config USB_GADGET_ATMEL_USBA
 	bool "Atmel USBA"
 	select USB_GADGET_DUALSPEED
@@ -110,19 +134,63 @@
 	  allows to download images into memory and execute (jump to) them
 	  using the same protocol as implemented by the i.MX family's boot ROM.
 
-config G_DNL_MANUFACTURER
-	string "Vendor name of USB device"
+endif # USB_GADGET_DOWNLOAD
 
-config G_DNL_VENDOR_NUM
-	hex "Vendor ID of USB device"
+config USB_ETHER
+	bool "USB Ethernet Gadget"
+	default y if ARCH_SUNXI && USB_MUSB_GADGET
+	help
+	  Creates an Ethernet network device through a USB peripheral
+	  controller. This will create a network interface on both the device
+	  (U-Boot) and the host (remote device) that can be used just like any
+	  other nework interface.
+	  It will bind on the peripheral USB controller, ignoring the USB hosts
+	  controllers in the system.
 
-config G_DNL_PRODUCT_NUM
-	hex "Product ID of USB device"
+if USB_ETHER
+
+choice
+	prompt "USB Ethernet Gadget Model"
+	default USB_ETH_RNDIS
+	help
+	  There is several models (protocols) to implement Ethernet over USB
+	  devices. The main ones are Microsoft's RNDIS and USB's CDC-Ethernet
+	  (also called CDC-ECM). RNDIS is obviously compatible with Windows,
+	  while CDC-ECM is not. Most other operating systems support both, so
+	  if inter-operability is a concern, RNDIS is to be preferred.
+
+config USB_ETH_CDC
+	bool "CDC-ECM Protocol"
+	help
+	  CDC (Communications Device Class) is the standard for Ethernet over
+	  USB devices. While there's several alternatives, the most widely used
+	  protocol is ECM (Ethernet Control Model). However, compatibility with
+	  Windows is not that great.
+
+config USB_ETH_RNDIS
+	bool "RNDIS Protocol"
+	help
+	  The RNDIS (Remote Network Driver Interface Specification) is a
+	  Microsoft proprietary protocol to create an Ethernet device over USB.
+	  Windows obviously supports it, as well as all the major operating
+	  systems, so it's the best option for compatibility.
+
+endchoice
 
 config USBNET_DEVADDR
 	string "USB Gadget Ethernet device mac address"
 	default "de:ad:be:ef:00:01"
+	help
+	  Ethernet MAC address of the device-side (ie. local board's) MAC
+	  address of the usb_ether interface
 
-endif # USB_GADGET_DOWNLOAD
+config USBNET_HOST_ADDR
+	string "USB Gadget Ethernet host mac address"
+	default "de:ad:be:ef:00:00"
+	help
+	  Ethernet MAC address of the host-side (ie. remote device's) MAC
+	  address of the usb_ether interface
+
+endif # USB_ETHER
 
 endif # USB_GADGET
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 9df6d32..ad2f606 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1456,7 +1456,7 @@
 
 	ret = driver->bind(&udc->gadget);
 	if (ret) {
-		error("driver->bind() returned %d\n", ret);
+		pr_err("driver->bind() returned %d\n", ret);
 		udc->driver = NULL;
 	}
 
@@ -1468,7 +1468,7 @@
 	struct at91_udc *udc = controller;
 
 	if (!driver || !driver->unbind || !driver->disconnect) {
-		error("bad paramter\n");
+		pr_err("bad paramter\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index ad31703..c0a95a9 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -1228,7 +1228,7 @@
 
 	ret = driver->bind(&udc->gadget);
 	if (ret) {
-		error("driver->bind() returned %d\n", ret);
+		pr_err("driver->bind() returned %d\n", ret);
 		udc->driver = NULL;
 	}
 
@@ -1240,7 +1240,7 @@
 	struct usba_udc *udc = &controller;
 
 	if (!driver || !driver->unbind || !driver->disconnect) {
-		error("bad paramter\n");
+		pr_err("bad paramter\n");
 		return -EINVAL;
 	}
 
@@ -1261,7 +1261,7 @@
 
 	eps = malloc(sizeof(struct usba_ep) * pdata->num_ep);
 	if (!eps) {
-		error("failed to alloc eps\n");
+		pr_err("failed to alloc eps\n");
 		return NULL;
 	}
 
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
index cb44374..088811c 100644
--- a/drivers/usb/gadget/dwc2_udc_otg.c
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
@@ -835,7 +835,7 @@
 			    ROUND(sizeof(struct usb_ctrlrequest),
 				  CONFIG_SYS_CACHELINE_SIZE));
 	if (!usb_ctrl) {
-		error("No memory available for UDC!\n");
+		pr_err("No memory available for UDC!\n");
 		return -ENOMEM;
 	}
 
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 2cf5c8d..a80486e 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -273,8 +273,8 @@
  * static ushort idProduct;
  */
 
-#if defined(CONFIG_USBNET_MANUFACTURER)
-static char *iManufacturer = CONFIG_USBNET_MANUFACTURER;
+#if defined(CONFIG_USB_GADGET_MANUFACTURER)
+static char *iManufacturer = CONFIG_USB_GADGET_MANUFACTURER;
 #else
 static char *iManufacturer = "U-Boot";
 #endif
@@ -1059,7 +1059,7 @@
 			&& dev->config
 			&& dev->tx_qlen != 0) {
 		/* tx fifo is full, but we can't clear it...*/
-		error("can't change configurations");
+		pr_err("can't change configurations");
 		return -ESPIPE;
 	}
 	eth_reset_config(dev);
@@ -1233,7 +1233,7 @@
 	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
 	status = rndis_msg_parser(dev->rndis_config, (u8 *) req->buf);
 	if (status < 0)
-		error("%s: rndis parse error %d", __func__, status);
+		pr_err("%s: rndis parse error %d", __func__, status);
 }
 
 #endif	/* RNDIS */
@@ -1554,7 +1554,7 @@
 	retval = usb_ep_queue(dev->out_ep, req, gfp_flags);
 
 	if (retval)
-		error("rx submit --> %d", retval);
+		pr_err("rx submit --> %d", retval);
 
 	return retval;
 }
@@ -1624,7 +1624,7 @@
 fail2:
 	usb_ep_free_request(dev->in_ep, dev->tx_req);
 fail1:
-	error("can't alloc requests");
+	pr_err("can't alloc requests");
 	return -1;
 }
 
@@ -2060,7 +2060,7 @@
 		 * anything less functional on CDC-capable hardware,
 		 * so we fail in this case.
 		 */
-		error("controller '%s' not recognized",
+		pr_err("controller '%s' not recognized",
 			gadget->name);
 		return -ENODEV;
 	}
@@ -2073,11 +2073,11 @@
 	 * to choose the right configuration otherwise.
 	 */
 	if (rndis) {
-#if defined(CONFIG_USB_RNDIS_VENDOR_ID) && defined(CONFIG_USB_RNDIS_PRODUCT_ID)
+#if defined(CONFIG_USB_GADGET_VENDOR_NUM) && defined(CONFIG_USB_GADGET_PRODUCT_NUM)
 		device_desc.idVendor =
-			__constant_cpu_to_le16(CONFIG_USB_RNDIS_VENDOR_ID);
+			__constant_cpu_to_le16(CONFIG_USB_GADGET_VENDOR_NUM);
 		device_desc.idProduct =
-			__constant_cpu_to_le16(CONFIG_USB_RNDIS_PRODUCT_ID);
+			__constant_cpu_to_le16(CONFIG_USB_GADGET_PRODUCT_NUM);
 #else
 		device_desc.idVendor =
 			__constant_cpu_to_le16(RNDIS_VENDOR_NUM);
@@ -2092,9 +2092,9 @@
 	 * supporting one submode of the "SAFE" variant of MDLM.)
 	 */
 	} else {
-#if defined(CONFIG_USB_CDC_VENDOR_ID) && defined(CONFIG_USB_CDC_PRODUCT_ID)
-		device_desc.idVendor = cpu_to_le16(CONFIG_USB_CDC_VENDOR_ID);
-		device_desc.idProduct = cpu_to_le16(CONFIG_USB_CDC_PRODUCT_ID);
+#if defined(CONFIG_USB_GADGET_VENDOR_NUM) && defined(CONFIG_USB_GADGET_PRODUCT_NUM)
+		device_desc.idVendor = cpu_to_le16(CONFIG_USB_GADGET_VENDOR_NUM);
+		device_desc.idProduct = cpu_to_le16(CONFIG_USB_GADGET_PRODUCT_NUM);
 #else
 		if (!cdc) {
 			device_desc.idVendor =
@@ -2121,7 +2121,7 @@
 	in_ep = usb_ep_autoconfig(gadget, &fs_source_desc);
 	if (!in_ep) {
 autoconf_fail:
-		error("can't autoconfigure on %s\n",
+		pr_err("can't autoconfigure on %s\n",
 			gadget->name);
 		return -ENODEV;
 	}
@@ -2142,7 +2142,7 @@
 		if (status_ep) {
 			status_ep->driver_data = status_ep;	/* claim */
 		} else if (rndis) {
-			error("can't run RNDIS on %s", gadget->name);
+			pr_err("can't run RNDIS on %s", gadget->name);
 			return -ENODEV;
 #ifdef CONFIG_USB_ETH_CDC
 		} else if (cdc) {
@@ -2244,7 +2244,7 @@
 	if (rndis) {
 		status = rndis_init();
 		if (status < 0) {
-			error("can't init RNDIS, %d", status);
+			pr_err("can't init RNDIS, %d", status);
 			goto fail;
 		}
 	}
@@ -2335,7 +2335,7 @@
 	return 0;
 
 fail:
-	error("%s failed, status = %d", __func__, status);
+	pr_err("%s failed, status = %d", __func__, status);
 	eth_unbind(gadget);
 	return status;
 }
@@ -2350,7 +2350,7 @@
 
 	ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev);
 	if (!dev || ret) {
-		error("No USB device found\n");
+		pr_err("No USB device found\n");
 		return -ENODEV;
 	}
 
@@ -2369,7 +2369,7 @@
 
 #ifdef CONFIG_DM_USB
 	if (dm_usb_init(dev)) {
-		error("USB ether not found\n");
+		pr_err("USB ether not found\n");
 		return -ENODEV;
 	}
 #else
@@ -2393,11 +2393,11 @@
 			sizeof(host_addr));
 
 	if (!is_eth_addr_valid(dev_addr)) {
-		error("Need valid 'usbnet_devaddr' to be set");
+		pr_err("Need valid 'usbnet_devaddr' to be set");
 		goto fail;
 	}
 	if (!is_eth_addr_valid(host_addr)) {
-		error("Need valid 'usbnet_hostaddr' to be set");
+		pr_err("Need valid 'usbnet_hostaddr' to be set");
 		goto fail;
 	}
 
@@ -2427,7 +2427,7 @@
 	while (!dev->network_started) {
 		/* Handle control-c and timeouts */
 		if (ctrlc() || (get_timer(ts) > timeout)) {
-			error("The remote end did not respond in time.");
+			pr_err("The remote end did not respond in time.");
 			goto fail;
 		}
 		usb_gadget_handle_interrupts(0);
@@ -2456,7 +2456,7 @@
 		rndis_pkt = malloc(length +
 					sizeof(struct rndis_packet_msg_type));
 		if (!rndis_pkt) {
-			error("No memory to alloc RNDIS packet");
+			pr_err("No memory to alloc RNDIS packet");
 			goto drop;
 		}
 		rndis_add_hdr(rndis_pkt, length);
@@ -2574,7 +2574,7 @@
 
 	ret = _usb_eth_recv(priv);
 	if (ret) {
-		error("error packet receive\n");
+		pr_err("error packet receive\n");
 		return ret;
 	}
 
@@ -2585,7 +2585,7 @@
 		net_process_received_packet(net_rx_packets[0],
 					    dev->rx_req->length);
 	} else {
-		error("dev->rx_req invalid");
+		pr_err("dev->rx_req invalid");
 	}
 	packet_received = 0;
 	rx_submit(dev, dev->rx_req, 0);
@@ -2641,7 +2641,7 @@
 
 	ret = _usb_eth_recv(priv);
 	if (ret) {
-		error("error packet receive\n");
+		pr_err("error packet receive\n");
 		return ret;
 	}
 
@@ -2650,7 +2650,7 @@
 			*packetp = (uchar *)net_rx_packets[0];
 			return ethdev->rx_req->length;
 		} else {
-			error("dev->rx_req invalid");
+			pr_err("dev->rx_req invalid");
 			return -EFAULT;
 		}
 	}
@@ -2706,13 +2706,13 @@
 
 	ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &usb_dev);
 	if (!usb_dev || ret) {
-		error("No USB device found\n");
+		pr_err("No USB device found\n");
 		return ret;
 	}
 
 	ret = device_bind_driver(usb_dev, "usb_ether", "usb_ether", &dev);
 	if (!dev || ret) {
-		error("usb - not able to bind usb_ether device\n");
+		pr_err("usb - not able to bind usb_ether device\n");
 		return ret;
 	}
 
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index f3382a9..7acffb6 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -410,7 +410,7 @@
 
 	strsep(&cmd, ":");
 	if (!cmd) {
-		error("missing variable");
+		pr_err("missing variable");
 		fastboot_tx_write_str("FAILmissing var");
 		return;
 	}
@@ -593,7 +593,7 @@
 
 	strsep(&cmd, ":");
 	if (!cmd) {
-		error("missing partition name");
+		pr_err("missing partition name");
 		fastboot_tx_write_str("FAILmissing partition name");
 		return;
 	}
@@ -645,7 +645,7 @@
 
 	strsep(&cmd, ":");
 	if (!cmd) {
-		error("missing partition name");
+		pr_err("missing partition name");
 		fastboot_tx_write_str("FAILmissing partition name");
 		return;
 	}
@@ -718,7 +718,7 @@
 	}
 
 	if (!func_cb) {
-		error("unknown command: %.*s", req->actual, cmdbuf);
+		pr_err("unknown command: %.*s", req->actual, cmdbuf);
 		fastboot_tx_write_str("FAILunknown command");
 	} else {
 		if (req->actual < req->length) {
@@ -726,7 +726,7 @@
 			buf[req->actual] = 0;
 			func_cb(ep, req);
 		} else {
-			error("buffer overflow");
+			pr_err("buffer overflow");
 			fastboot_tx_write_str("FAILbuffer overflow");
 		}
 	}
diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c
index 0fae66b..fd3da92 100644
--- a/drivers/usb/gadget/f_sdp.c
+++ b/drivers/usb/gadget/f_sdp.c
@@ -237,12 +237,12 @@
 	u8 report = data[0];
 
 	if (status != 0) {
-		error("Status: %d", status);
+		pr_err("Status: %d", status);
 		return;
 	}
 
 	if (report != 1) {
-		error("Unexpected report %d", report);
+		pr_err("Unexpected report %d", report);
 		return;
 	}
 
@@ -309,7 +309,7 @@
 		sdp->next_state = SDP_STATE_IDLE;
 		break;
 	default:
-		error("Unknown command: %04x\n", be16_to_cpu(cmd->cmd));
+		pr_err("Unknown command: %04x\n", be16_to_cpu(cmd->cmd));
 	}
 }
 
@@ -322,12 +322,12 @@
 	int datalen = req->length - 1;
 
 	if (status != 0) {
-		error("Status: %d", status);
+		pr_err("Status: %d", status);
 		return;
 	}
 
 	if (report != 2) {
-		error("Unexpected report %d", report);
+		pr_err("Unexpected report %d", report);
 		return;
 	}
 
@@ -360,7 +360,7 @@
 		sdp->state = SDP_STATE_TX_SEC_CONF;
 		break;
 	default:
-		error("Invalid state: %d", sdp->state);
+		pr_err("Invalid state: %d", sdp->state);
 	}
 }
 
@@ -370,7 +370,7 @@
 	int status = req->status;
 
 	if (status != 0) {
-		error("Status: %d", status);
+		pr_err("Status: %d", status);
 		return;
 	}
 
@@ -393,7 +393,7 @@
 			sdp->state = SDP_STATE_IDLE;
 		break;
 	default:
-		error("Wrong State: %d", sdp->state);
+		pr_err("Wrong State: %d", sdp->state);
 		sdp->state = SDP_STATE_IDLE;
 		break;
 	}
diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
index cd4d9e6..18f233a 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -174,7 +174,7 @@
 					transfer_buffer, THOR_STORE_UNIT_SIZE,
 					(*cnt)++);
 			if (ret) {
-				error("DFU write failed [%d] cnt: %d",
+				pr_err("DFU write failed [%d] cnt: %d",
 				      ret, *cnt);
 				return ret;
 			}
@@ -218,20 +218,20 @@
 
 	dfu_entity = dfu_get_entity(alt_setting_num);
 	if (!dfu_entity) {
-		error("Alt setting: %d entity not found!\n", alt_setting_num);
+		pr_err("Alt setting: %d entity not found!\n", alt_setting_num);
 		return -ENOENT;
 	}
 
 	transfer_buffer = dfu_get_buf(dfu_entity);
 	if (!transfer_buffer) {
-		error("Transfer buffer not allocated!");
+		pr_err("Transfer buffer not allocated!");
 		return -ENXIO;
 	}
 
 	if (left) {
 		ret = dfu_write(dfu_entity, transfer_buffer, left, cnt++);
 		if (ret) {
-			error("DFU write failed [%d]: left: %llu", ret, left);
+			pr_err("DFU write failed [%d]: left: %llu", ret, left);
 			return ret;
 		}
 	}
@@ -245,7 +245,7 @@
 	 */
 	ret = dfu_flush(dfu_entity, transfer_buffer, 0, cnt);
 	if (ret)
-		error("DFU flush failed!");
+		pr_err("DFU flush failed!");
 
 	return ret;
 }
@@ -285,7 +285,7 @@
 
 		alt_setting_num = dfu_get_alt(f_name);
 		if (alt_setting_num < 0) {
-			error("Alt setting [%d] to write not found!",
+			pr_err("Alt setting [%d] to write not found!",
 			      alt_setting_num);
 			rsp->ack = -ENODEV;
 			ret = rsp->ack;
@@ -311,7 +311,7 @@
 		debug("DL EXIT\n");
 		break;
 	default:
-		error("Operation not supported: %d", rqt->rqt_data);
+		pr_err("Operation not supported: %d", rqt->rqt_data);
 		ret = -ENOTSUPP;
 	}
 
@@ -342,7 +342,7 @@
 		puts("RQT: UPLOAD not supported!\n");
 		break;
 	default:
-		error("unknown request (%d)", rqt->rqt);
+		pr_err("unknown request (%d)", rqt->rqt);
 	}
 
 	return ret;
@@ -541,7 +541,7 @@
 
 		status = usb_ep_queue(dev->out_ep, dev->out_req, 0);
 		if (status) {
-			error("kill %s:  resubmit %d bytes --> %d",
+			pr_err("kill %s:  resubmit %d bytes --> %d",
 			      dev->out_ep->name, dev->out_req->length, status);
 			usb_ep_set_halt(dev->out_ep);
 			return -EAGAIN;
@@ -575,7 +575,7 @@
 
 	status = usb_ep_queue(dev->in_ep, dev->in_req, 0);
 	if (status) {
-		error("kill %s:  resubmit %d bytes --> %d",
+		pr_err("kill %s:  resubmit %d bytes --> %d",
 		      dev->in_ep->name, dev->in_req->length, status);
 		usb_ep_set_halt(dev->in_ep);
 	}
@@ -608,7 +608,7 @@
 	case -ESHUTDOWN:		/* disconnect from host */
 	case -EREMOTEIO:                /* short read */
 	case -EOVERFLOW:
-		error("ERROR:%d", status);
+		pr_err("ERROR:%d", status);
 		break;
 	}
 
@@ -664,7 +664,7 @@
 		break;
 
 	default:
-		error("thor_setup: unknown request: %d", ctrl->bRequest);
+		pr_err("thor_setup: unknown request: %d", ctrl->bRequest);
 	}
 
 	if (value >= 0) {
@@ -973,7 +973,7 @@
 		debug("Communication Data interface\n");
 		result = thor_eps_setup(f);
 		if (result)
-			error("%s: EPs setup failed!", __func__);
+			pr_err("%s: EPs setup failed!", __func__);
 		dev->configuration_done = 1;
 		break;
 	}
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index 039331a..99d500a 100644
--- a/drivers/usb/gadget/g_dnl.c
+++ b/drivers/usb/gadget/g_dnl.c
@@ -26,9 +26,9 @@
 
 /*
  * One needs to define the following:
- * CONFIG_G_DNL_VENDOR_NUM
- * CONFIG_G_DNL_PRODUCT_NUM
- * CONFIG_G_DNL_MANUFACTURER
+ * CONFIG_USB_GADGET_VENDOR_NUM
+ * CONFIG_USB_GADGET_PRODUCT_NUM
+ * CONFIG_USB_GADGET_MANUFACTURER
  * at e.g. ./configs/<board>_defconfig
  */
 
@@ -46,7 +46,7 @@
 
 static const char product[] = "USB download gadget";
 static char g_dnl_serial[MAX_STRING_SERIAL];
-static const char manufacturer[] = CONFIG_G_DNL_MANUFACTURER;
+static const char manufacturer[] = CONFIG_USB_GADGET_MANUFACTURER;
 
 void g_dnl_set_serialnumber(char *s)
 {
@@ -62,8 +62,8 @@
 	.bDeviceClass = USB_CLASS_PER_INTERFACE,
 	.bDeviceSubClass = 0, /*0x02:CDC-modem , 0x00:CDC-serial*/
 
-	.idVendor = __constant_cpu_to_le16(CONFIG_G_DNL_VENDOR_NUM),
-	.idProduct = __constant_cpu_to_le16(CONFIG_G_DNL_PRODUCT_NUM),
+	.idVendor = __constant_cpu_to_le16(CONFIG_USB_GADGET_VENDOR_NUM),
+	.idProduct = __constant_cpu_to_le16(CONFIG_USB_GADGET_PRODUCT_NUM),
 	/* .iProduct = DYNAMIC */
 	/* .iSerialNumber = DYNAMIC */
 	.bNumConfigurations = 1,
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 0ed72d5..1293e18 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -179,7 +179,7 @@
 
 	ret = regulator_set_enable(vbus_supply, true);
 	if (ret) {
-		error("Error enabling vbus supply\n");
+		pr_err("Error enabling vbus supply\n");
 		return ret;
 	}
 
diff --git a/drivers/usb/host/dwc3-sti-glue.c b/drivers/usb/host/dwc3-sti-glue.c
index 02ad311..6dc656a 100644
--- a/drivers/usb/host/dwc3-sti-glue.c
+++ b/drivers/usb/host/dwc3-sti-glue.c
@@ -71,7 +71,7 @@
 		break;
 
 	default:
-		error("Unsupported mode of operation %d\n", plat->mode);
+		pr_err("Unsupported mode of operation %d\n", plat->mode);
 		return -EINVAL;
 	}
 	writel(val, plat->syscfg_base + plat->syscfg_offset);
@@ -113,7 +113,7 @@
 	ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
 				   "reg", reg, ARRAY_SIZE(reg));
 	if (ret) {
-		error("unable to find st,stih407-dwc3 reg property(%d)\n", ret);
+		pr_err("unable to find st,stih407-dwc3 reg property(%d)\n", ret);
 		return ret;
 	}
 
@@ -124,14 +124,14 @@
 	ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "st,syscfg",
 					   &syscon);
 	if (ret) {
-		error("unable to find syscon device (%d)\n", ret);
+		pr_err("unable to find syscon device (%d)\n", ret);
 		return ret;
 	}
 
 	/* get syscfg-reg base address */
 	regmap = syscon_get_regmap(syscon);
 	if (!regmap) {
-		error("unable to find regmap\n");
+		pr_err("unable to find regmap\n");
 		return -ENODEV;
 	}
 	plat->syscfg_base = regmap->base;
@@ -139,14 +139,14 @@
 	/* get powerdown reset */
 	ret = reset_get_by_name(dev, "powerdown", &plat->powerdown_ctl);
 	if (ret) {
-		error("can't get powerdown reset for %s (%d)", dev->name, ret);
+		pr_err("can't get powerdown reset for %s (%d)", dev->name, ret);
 		return ret;
 	}
 
 	/* get softreset reset */
 	ret = reset_get_by_name(dev, "softreset", &plat->softreset_ctl);
 	if (ret)
-		error("can't get soft reset for %s (%d)", dev->name, ret);
+		pr_err("can't get soft reset for %s (%d)", dev->name, ret);
 
 	return ret;
 };
@@ -159,14 +159,14 @@
 	/* check if one subnode is present */
 	dwc3_node = fdt_first_subnode(gd->fdt_blob, dev_of_offset(dev));
 	if (dwc3_node <= 0) {
-		error("Can't find subnode for %s\n", dev->name);
+		pr_err("Can't find subnode for %s\n", dev->name);
 		return -ENODEV;
 	}
 
 	/* check if the subnode compatible string is the dwc3 one*/
 	if (fdt_node_check_compatible(gd->fdt_blob, dwc3_node,
 				      "snps,dwc3") != 0) {
-		error("Can't find dwc3 subnode for %s\n", dev->name);
+		pr_err("Can't find dwc3 subnode for %s\n", dev->name);
 		return -ENODEV;
 	}
 
@@ -187,13 +187,13 @@
 	/* deassert both powerdown and softreset */
 	ret = reset_deassert(&plat->powerdown_ctl);
 	if (ret < 0) {
-		error("DWC3 powerdown reset deassert failed: %d", ret);
+		pr_err("DWC3 powerdown reset deassert failed: %d", ret);
 		return ret;
 	}
 
 	ret = reset_deassert(&plat->softreset_ctl);
 	if (ret < 0) {
-		error("DWC3 soft reset deassert failed: %d", ret);
+		pr_err("DWC3 soft reset deassert failed: %d", ret);
 		goto softreset_err;
 	}
 
@@ -208,14 +208,14 @@
 init_err:
 	ret = reset_assert(&plat->softreset_ctl);
 	if (ret < 0) {
-		error("DWC3 soft reset deassert failed: %d", ret);
+		pr_err("DWC3 soft reset deassert failed: %d", ret);
 		return ret;
 	}
 
 softreset_err:
 	ret = reset_assert(&plat->powerdown_ctl);
 	if (ret < 0)
-		error("DWC3 powerdown reset deassert failed: %d", ret);
+		pr_err("DWC3 powerdown reset deassert failed: %d", ret);
 
 	return ret;
 }
@@ -228,13 +228,13 @@
 	/* assert both powerdown and softreset */
 	ret = reset_assert(&plat->powerdown_ctl);
 	if (ret < 0) {
-		error("DWC3 powerdown reset deassert failed: %d", ret);
+		pr_err("DWC3 powerdown reset deassert failed: %d", ret);
 		return ret;
 	}
 
 	ret = reset_assert(&plat->softreset_ctl);
 	if (ret < 0)
-		error("DWC3 soft reset deassert failed: %d", ret);
+		pr_err("DWC3 soft reset deassert failed: %d", ret);
 
 	return ret;
 }
diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
index 18e1e0e..1cb92c0 100644
--- a/drivers/usb/host/ehci-generic.c
+++ b/drivers/usb/host/ehci-generic.c
@@ -51,7 +51,7 @@
 				break;
 			err = clk_enable(&priv->clocks[i]);
 			if (err) {
-				error("failed to enable clock %d\n", i);
+				pr_err("failed to enable clock %d\n", i);
 				clk_free(&priv->clocks[i]);
 				goto clk_err;
 			}
@@ -59,7 +59,7 @@
 		}
 	} else {
 		if (clock_nb != -ENOENT) {
-			error("failed to get clock phandle(%d)\n", clock_nb);
+			pr_err("failed to get clock phandle(%d)\n", clock_nb);
 			return clock_nb;
 		}
 	}
@@ -80,7 +80,7 @@
 				break;
 
 			if (reset_deassert(&priv->resets[i])) {
-				error("failed to deassert reset %d\n", i);
+				pr_err("failed to deassert reset %d\n", i);
 				reset_free(&priv->resets[i]);
 				goto reset_err;
 			}
@@ -88,7 +88,7 @@
 		}
 	} else {
 		if (reset_nb != -ENOENT) {
-			error("failed to get reset phandle(%d)\n", reset_nb);
+			pr_err("failed to get reset phandle(%d)\n", reset_nb);
 			goto clk_err;
 		}
 	}
@@ -96,14 +96,14 @@
 	err = generic_phy_get_by_index(dev, 0, &priv->phy);
 	if (err) {
 		if (err != -ENOENT) {
-			error("failed to get usb phy\n");
+			pr_err("failed to get usb phy\n");
 			goto reset_err;
 		}
 	} else {
 
 		err = generic_phy_init(&priv->phy);
 		if (err) {
-			error("failed to init usb phy\n");
+			pr_err("failed to init usb phy\n");
 			goto reset_err;
 		}
 	}
@@ -122,17 +122,17 @@
 	if (generic_phy_valid(&priv->phy)) {
 		ret = generic_phy_exit(&priv->phy);
 		if (ret)
-			error("failed to release phy\n");
+			pr_err("failed to release phy\n");
 	}
 
 reset_err:
 	ret = reset_release_all(priv->resets, priv->reset_count);
 	if (ret)
-		error("failed to assert all resets\n");
+		pr_err("failed to assert all resets\n");
 clk_err:
 	ret = clk_release_all(priv->clocks, priv->clock_count);
 	if (ret)
-		error("failed to disable all clocks\n");
+		pr_err("failed to disable all clocks\n");
 
 	return err;
 }
diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
index e22ee97..bf55a71 100644
--- a/drivers/usb/host/ohci-generic.c
+++ b/drivers/usb/host/ohci-generic.c
@@ -47,14 +47,14 @@
 
 			err = clk_enable(&priv->clocks[i]);
 			if (err) {
-				error("failed to enable clock %d\n", i);
+				pr_err("failed to enable clock %d\n", i);
 				clk_free(&priv->clocks[i]);
 				goto clk_err;
 			}
 			priv->clock_count++;
 		}
 	} else if (clock_nb != -ENOENT) {
-		error("failed to get clock phandle(%d)\n", clock_nb);
+		pr_err("failed to get clock phandle(%d)\n", clock_nb);
 		return clock_nb;
 	}
 
@@ -74,28 +74,28 @@
 
 			err = reset_deassert(&priv->resets[i]);
 			if (err) {
-				error("failed to deassert reset %d\n", i);
+				pr_err("failed to deassert reset %d\n", i);
 				reset_free(&priv->resets[i]);
 				goto reset_err;
 			}
 			priv->reset_count++;
 		}
 	} else if (reset_nb != -ENOENT) {
-		error("failed to get reset phandle(%d)\n", reset_nb);
+		pr_err("failed to get reset phandle(%d)\n", reset_nb);
 		goto clk_err;
 	}
 
 	err = generic_phy_get_by_index(dev, 0, &priv->phy);
 	if (err) {
 		if (err != -ENOENT) {
-			error("failed to get usb phy\n");
+			pr_err("failed to get usb phy\n");
 			goto reset_err;
 		}
 	} else {
 
 		err = generic_phy_init(&priv->phy);
 		if (err) {
-			error("failed to init usb phy\n");
+			pr_err("failed to init usb phy\n");
 			goto reset_err;
 		}
 	}
@@ -110,17 +110,17 @@
 	if (generic_phy_valid(&priv->phy)) {
 		ret = generic_phy_exit(&priv->phy);
 		if (ret)
-			error("failed to release phy\n");
+			pr_err("failed to release phy\n");
 	}
 
 reset_err:
 	ret = reset_release_all(priv->resets, priv->reset_count);
 	if (ret)
-		error("failed to assert all resets\n");
+		pr_err("failed to assert all resets\n");
 clk_err:
 	ret = clk_release_all(priv->clocks, priv->clock_count);
 	if (ret)
-		error("failed to disable all clocks\n");
+		pr_err("failed to disable all clocks\n");
 
 	return err;
 }
diff --git a/drivers/usb/host/usb-sandbox.c b/drivers/usb/host/usb-sandbox.c
index 5e3d96c..15055b3 100644
--- a/drivers/usb/host/usb-sandbox.c
+++ b/drivers/usb/host/usb-sandbox.c
@@ -12,6 +12,10 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+struct sandbox_usb_ctrl {
+	int rootdev;
+};
+
 static void usbmon_trace(struct udevice *bus, ulong pipe,
 			 struct devrequest *setup, struct udevice *emul)
 {
@@ -40,15 +44,24 @@
 				      void *buffer, int length,
 				      struct devrequest *setup)
 {
+	struct sandbox_usb_ctrl *ctrl = dev_get_priv(bus);
 	struct udevice *emul;
 	int ret;
 
 	/* Just use child of dev as emulator? */
 	debug("%s: bus=%s\n", __func__, bus->name);
-	ret = usb_emul_find(bus, pipe, &emul);
+	ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
 	usbmon_trace(bus, pipe, setup, emul);
 	if (ret)
 		return ret;
+
+	if (usb_pipedevice(pipe) == ctrl->rootdev) {
+		if (setup->request == USB_REQ_SET_ADDRESS) {
+			debug("%s: Set root hub's USB address\n", __func__);
+			ctrl->rootdev = le16_to_cpu(setup->value);
+		}
+	}
+
 	ret = usb_emul_control(emul, udev, pipe, buffer, length, setup);
 	if (ret < 0) {
 		debug("ret=%d\n", ret);
@@ -70,7 +83,7 @@
 
 	/* Just use child of dev as emulator? */
 	debug("%s: bus=%s\n", __func__, bus->name);
-	ret = usb_emul_find(bus, pipe, &emul);
+	ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
 	usbmon_trace(bus, pipe, NULL, emul);
 	if (ret)
 		return ret;
@@ -96,7 +109,7 @@
 
 	/* Just use child of dev as emulator? */
 	debug("%s: bus=%s\n", __func__, bus->name);
-	ret = usb_emul_find(bus, pipe, &emul);
+	ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
 	usbmon_trace(bus, pipe, NULL, emul);
 	if (ret)
 		return ret;
@@ -107,6 +120,16 @@
 
 static int sandbox_alloc_device(struct udevice *dev, struct usb_device *udev)
 {
+	struct sandbox_usb_ctrl *ctrl = dev_get_priv(dev);
+
+	/*
+	 * Root hub will be the first device to be initailized.
+	 * If this device is a root hub, initialize its device speed
+	 * to high speed as we are a USB 2.0 controller.
+	 */
+	if (ctrl->rootdev == 0)
+		udev->speed = USB_SPEED_HIGH;
+
 	return 0;
 }
 
@@ -133,4 +156,5 @@
 	.of_match = sandbox_usb_ids,
 	.probe = sandbox_usb_probe,
 	.ops	= &sandbox_usb_ops,
+	.priv_auto_alloc_size = sizeof(struct sandbox_usb_ctrl),
 };
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
index bc44fc3..4e40f4b 100644
--- a/drivers/usb/host/usb-uclass.c
+++ b/drivers/usb/host/usb-uclass.c
@@ -164,6 +164,7 @@
 int usb_stop(void)
 {
 	struct udevice *bus;
+	struct udevice *rh;
 	struct uclass *uc;
 	struct usb_uclass_priv *uc_priv;
 	int err = 0, ret;
@@ -179,23 +180,20 @@
 		ret = device_remove(bus, DM_REMOVE_NORMAL);
 		if (ret && !err)
 			err = ret;
+
+		/* Locate root hub device */
+		device_find_first_child(bus, &rh);
+		if (rh) {
+			/*
+			 * All USB devices are children of root hub.
+			 * Unbinding root hub will unbind all of its children.
+			 */
+			ret = device_unbind(rh);
+			if (ret && !err)
+				err = ret;
+		}
 	}
-#ifdef CONFIG_BLK
-	ret = blk_unbind_all(IF_TYPE_USB);
-	if (ret && !err)
-		err = ret;
-#endif
-#ifdef CONFIG_SANDBOX
-	struct udevice *dev;
 
-	/* Reset all enulation devices */
-	ret = uclass_get(UCLASS_USB_EMUL, &uc);
-	if (ret)
-		return ret;
-
-	uclass_foreach_dev(dev, uc)
-		usb_emul_reset(dev);
-#endif
 #ifdef CONFIG_USB_STORAGE
 	usb_stor_reset();
 #endif
@@ -262,6 +260,21 @@
 		/* init low_level USB */
 		printf("USB%d:   ", count);
 		count++;
+
+#ifdef CONFIG_SANDBOX
+		/*
+		 * For Sandbox, we need scan the device tree each time when we
+		 * start the USB stack, in order to re-create the emulated USB
+		 * devices and bind drivers for them before we actually do the
+		 * driver probe.
+		 */
+		ret = dm_scan_fdt_dev(bus);
+		if (ret) {
+			printf("Sandbox USB device scan failed (%d)\n", ret);
+			continue;
+		}
+#endif
+
 		ret = device_probe(bus);
 		if (ret == -ENODEV) {	/* No such device. */
 			puts("Port not available.\n");
diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c
index 4191a89..258d1cd 100644
--- a/drivers/usb/host/xhci-dwc3.c
+++ b/drivers/usb/host/xhci-dwc3.c
@@ -128,13 +128,13 @@
 	ret = generic_phy_get_by_index(dev, 0, &plat->usb_phy);
 	if (ret) {
 		if (ret != -ENOENT) {
-			error("Failed to get USB PHY for %s\n", dev->name);
+			pr_err("Failed to get USB PHY for %s\n", dev->name);
 			return ret;
 		}
 	} else {
 		ret = generic_phy_init(&plat->usb_phy);
 		if (ret) {
-			error("Can't init USB PHY for %s\n", dev->name);
+			pr_err("Can't init USB PHY for %s\n", dev->name);
 			return ret;
 		}
 	}
@@ -161,7 +161,7 @@
 	if (generic_phy_valid(&plat->usb_phy)) {
 		ret = generic_phy_exit(&plat->usb_phy);
 		if (ret) {
-			error("Can't deinit USB PHY for %s\n", dev->name);
+			pr_err("Can't deinit USB PHY for %s\n", dev->name);
 			return ret;
 		}
 	}
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index d5eab3a..0582a9b 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -786,12 +786,22 @@
 #ifdef CONFIG_DM_USB
 	/* Set up TT fields to support FS/LS devices */
 	if (speed == USB_SPEED_LOW || speed == USB_SPEED_FULL) {
-		dev = dev_get_parent_priv(udev->dev);
-		if (dev->speed == USB_SPEED_HIGH) {
-			hub = dev_get_uclass_priv(udev->dev);
+		struct udevice *parent = udev->dev;
+
+		dev = udev;
+		do {
+			port_num = dev->portnr;
+			dev = dev_get_parent_priv(parent);
+			if (usb_hub_is_root_hub(dev->dev))
+				break;
+			parent = dev->dev->parent;
+		} while (dev->speed != USB_SPEED_HIGH);
+
+		if (!usb_hub_is_root_hub(dev->dev)) {
+			hub = dev_get_uclass_priv(dev->dev);
 			if (hub->tt.multi)
 				slot_ctx->dev_info |= cpu_to_le32(DEV_MTT);
-			slot_ctx->tt_info |= cpu_to_le32(TT_PORT(udev->portnr));
+			slot_ctx->tt_info |= cpu_to_le32(TT_PORT(port_num));
 			slot_ctx->tt_info |= cpu_to_le32(TT_SLOT(dev->slot_id));
 		}
 	}
@@ -840,6 +850,12 @@
 	trb_64 = (uintptr_t)virt_dev->eps[0].ring->first_seg->trbs;
 	ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state);
 
+	/*
+	 * xHCI spec 6.2.3:
+	 * software shall set 'Average TRB Length' to 8 for control endpoints.
+	 */
+	ep0_ctx->tx_info = cpu_to_le32(EP_AVG_TRB_LENGTH(8));
+
 	/* Steps 7 and 8 were done in xhci_alloc_virt_device() */
 
 	xhci_flush_cache((uintptr_t)ep0_ctx, sizeof(struct xhci_ep_ctx));
diff --git a/drivers/usb/host/xhci-rockchip.c b/drivers/usb/host/xhci-rockchip.c
index ca3abff..b1f9884 100644
--- a/drivers/usb/host/xhci-rockchip.c
+++ b/drivers/usb/host/xhci-rockchip.c
@@ -46,7 +46,7 @@
 	 */
 	plat->hcd_base = dev_read_addr(dev);
 	if (plat->hcd_base == FDT_ADDR_T_NONE) {
-		error("Can't get the XHCI register base address\n");
+		pr_err("Can't get the XHCI register base address\n");
 		return -ENXIO;
 	}
 
@@ -60,7 +60,7 @@
 	}
 
 	if (plat->phy_base == FDT_ADDR_T_NONE) {
-		error("Can't get the usbphy register address\n");
+		pr_err("Can't get the usbphy register address\n");
 		return -ENXIO;
 	}
 
@@ -117,7 +117,7 @@
 
 	ret = dwc3_core_init(rkxhci->dwc3_reg);
 	if (ret) {
-		error("failed to initialize core\n");
+		pr_err("failed to initialize core\n");
 		return ret;
 	}
 
@@ -149,14 +149,14 @@
 	if (plat->vbus_supply) {
 		ret = regulator_set_enable(plat->vbus_supply, true);
 		if (ret) {
-			error("XHCI: failed to set VBus supply\n");
+			pr_err("XHCI: failed to set VBus supply\n");
 			return ret;
 		}
 	}
 
 	ret = rockchip_xhci_core_init(ctx, dev);
 	if (ret) {
-		error("XHCI: failed to initialize controller\n");
+		pr_err("XHCI: failed to initialize controller\n");
 		return ret;
 	}
 
@@ -179,7 +179,7 @@
 	if (plat->vbus_supply) {
 		ret = regulator_set_enable(plat->vbus_supply, false);
 		if (ret)
-			error("XHCI: failed to set VBus supply\n");
+			pr_err("XHCI: failed to set VBus supply\n");
 	}
 
 	return ret;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 04eb1eb..4673738 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -257,6 +257,188 @@
 	return index;
 }
 
+/*
+ * Convert bInterval expressed in microframes (in 1-255 range) to exponent of
+ * microframes, rounded down to nearest power of 2.
+ */
+static unsigned int xhci_microframes_to_exponent(unsigned int desc_interval,
+						 unsigned int min_exponent,
+						 unsigned int max_exponent)
+{
+	unsigned int interval;
+
+	interval = fls(desc_interval) - 1;
+	interval = clamp_val(interval, min_exponent, max_exponent);
+	if ((1 << interval) != desc_interval)
+		debug("rounding interval to %d microframes, "\
+		      "ep desc says %d microframes\n",
+		      1 << interval, desc_interval);
+
+	return interval;
+}
+
+static unsigned int xhci_parse_microframe_interval(struct usb_device *udev,
+	struct usb_endpoint_descriptor *endpt_desc)
+{
+	if (endpt_desc->bInterval == 0)
+		return 0;
+
+	return xhci_microframes_to_exponent(endpt_desc->bInterval, 0, 15);
+}
+
+static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
+	struct usb_endpoint_descriptor *endpt_desc)
+{
+	return xhci_microframes_to_exponent(endpt_desc->bInterval * 8, 3, 10);
+}
+
+/*
+ * Convert interval expressed as 2^(bInterval - 1) == interval into
+ * straight exponent value 2^n == interval.
+ */
+static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
+	struct usb_endpoint_descriptor *endpt_desc)
+{
+	unsigned int interval;
+
+	interval = clamp_val(endpt_desc->bInterval, 1, 16) - 1;
+	if (interval != endpt_desc->bInterval - 1)
+		debug("ep %#x - rounding interval to %d %sframes\n",
+		      endpt_desc->bEndpointAddress, 1 << interval,
+		      udev->speed == USB_SPEED_FULL ? "" : "micro");
+
+	if (udev->speed == USB_SPEED_FULL) {
+		/*
+		 * Full speed isoc endpoints specify interval in frames,
+		 * not microframes. We are using microframes everywhere,
+		 * so adjust accordingly.
+		 */
+		interval += 3;	/* 1 frame = 2^3 uframes */
+	}
+
+	return interval;
+}
+
+/*
+ * Return the polling or NAK interval.
+ *
+ * The polling interval is expressed in "microframes". If xHCI's Interval field
+ * is set to N, it will service the endpoint every 2^(Interval)*125us.
+ *
+ * The NAK interval is one NAK per 1 to 255 microframes, or no NAKs if interval
+ * is set to 0.
+ */
+static unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
+	struct usb_endpoint_descriptor *endpt_desc)
+{
+	unsigned int interval = 0;
+
+	switch (udev->speed) {
+	case USB_SPEED_HIGH:
+		/* Max NAK rate */
+		if (usb_endpoint_xfer_control(endpt_desc) ||
+		    usb_endpoint_xfer_bulk(endpt_desc)) {
+			interval = xhci_parse_microframe_interval(udev,
+								  endpt_desc);
+			break;
+		}
+		/* Fall through - SS and HS isoc/int have same decoding */
+
+	case USB_SPEED_SUPER:
+		if (usb_endpoint_xfer_int(endpt_desc) ||
+		    usb_endpoint_xfer_isoc(endpt_desc)) {
+			interval = xhci_parse_exponent_interval(udev,
+								endpt_desc);
+		}
+		break;
+
+	case USB_SPEED_FULL:
+		if (usb_endpoint_xfer_isoc(endpt_desc)) {
+			interval = xhci_parse_exponent_interval(udev,
+								endpt_desc);
+			break;
+		}
+		/*
+		 * Fall through for interrupt endpoint interval decoding
+		 * since it uses the same rules as low speed interrupt
+		 * endpoints.
+		 */
+
+	case USB_SPEED_LOW:
+		if (usb_endpoint_xfer_int(endpt_desc) ||
+		    usb_endpoint_xfer_isoc(endpt_desc)) {
+			interval = xhci_parse_frame_interval(udev, endpt_desc);
+		}
+		break;
+
+	default:
+		BUG();
+	}
+
+	return interval;
+}
+
+/*
+ * The "Mult" field in the endpoint context is only set for SuperSpeed isoc eps.
+ * High speed endpoint descriptors can define "the number of additional
+ * transaction opportunities per microframe", but that goes in the Max Burst
+ * endpoint context field.
+ */
+static u32 xhci_get_endpoint_mult(struct usb_device *udev,
+	struct usb_endpoint_descriptor *endpt_desc,
+	struct usb_ss_ep_comp_descriptor *ss_ep_comp_desc)
+{
+	if (udev->speed < USB_SPEED_SUPER ||
+	    !usb_endpoint_xfer_isoc(endpt_desc))
+		return 0;
+
+	return ss_ep_comp_desc->bmAttributes;
+}
+
+static u32 xhci_get_endpoint_max_burst(struct usb_device *udev,
+	struct usb_endpoint_descriptor *endpt_desc,
+	struct usb_ss_ep_comp_descriptor *ss_ep_comp_desc)
+{
+	/* Super speed and Plus have max burst in ep companion desc */
+	if (udev->speed >= USB_SPEED_SUPER)
+		return ss_ep_comp_desc->bMaxBurst;
+
+	if (udev->speed == USB_SPEED_HIGH &&
+	    (usb_endpoint_xfer_isoc(endpt_desc) ||
+	     usb_endpoint_xfer_int(endpt_desc)))
+		return usb_endpoint_maxp_mult(endpt_desc) - 1;
+
+	return 0;
+}
+
+/*
+ * Return the maximum endpoint service interval time (ESIT) payload.
+ * Basically, this is the maxpacket size, multiplied by the burst size
+ * and mult size.
+ */
+static u32 xhci_get_max_esit_payload(struct usb_device *udev,
+	struct usb_endpoint_descriptor *endpt_desc,
+	struct usb_ss_ep_comp_descriptor *ss_ep_comp_desc)
+{
+	int max_burst;
+	int max_packet;
+
+	/* Only applies for interrupt or isochronous endpoints */
+	if (usb_endpoint_xfer_control(endpt_desc) ||
+	    usb_endpoint_xfer_bulk(endpt_desc))
+		return 0;
+
+	/* SuperSpeed Isoc ep with less than 48k per esit */
+	if (udev->speed >= USB_SPEED_SUPER)
+		return le16_to_cpu(ss_ep_comp_desc->wBytesPerInterval);
+
+	max_packet = usb_endpoint_maxp(endpt_desc);
+	max_burst = usb_endpoint_maxp_mult(endpt_desc);
+
+	/* A 0 in max burst means 1 transfer per ESIT */
+	return max_packet * max_burst;
+}
+
 /**
  * Issue a configure endpoint command or evaluate context command
  * and wait for it to finish.
@@ -324,6 +506,12 @@
 	int slot_id = udev->slot_id;
 	struct xhci_virt_device *virt_dev = ctrl->devs[slot_id];
 	struct usb_interface *ifdesc;
+	u32 max_esit_payload;
+	unsigned int interval;
+	unsigned int mult;
+	unsigned int max_burst;
+	unsigned int avg_trb_len;
+	unsigned int err_count = 0;
 
 	out_ctx = virt_dev->out_ctx;
 	in_ctx = virt_dev->in_ctx;
@@ -357,10 +545,28 @@
 	/* filling up ep contexts */
 	for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) {
 		struct usb_endpoint_descriptor *endpt_desc = NULL;
+		struct usb_ss_ep_comp_descriptor *ss_ep_comp_desc = NULL;
 
 		endpt_desc = &ifdesc->ep_desc[cur_ep];
+		ss_ep_comp_desc = &ifdesc->ss_ep_comp_desc[cur_ep];
 		trb_64 = 0;
 
+		/*
+		 * Get values to fill the endpoint context, mostly from ep
+		 * descriptor. The average TRB buffer lengt for bulk endpoints
+		 * is unclear as we have no clue on scatter gather list entry
+		 * size. For Isoc and Int, set it to max available.
+		 * See xHCI 1.1 spec 4.14.1.1 for details.
+		 */
+		max_esit_payload = xhci_get_max_esit_payload(udev, endpt_desc,
+							     ss_ep_comp_desc);
+		interval = xhci_get_endpoint_interval(udev, endpt_desc);
+		mult = xhci_get_endpoint_mult(udev, endpt_desc,
+					      ss_ep_comp_desc);
+		max_burst = xhci_get_endpoint_max_burst(udev, endpt_desc,
+							ss_ep_comp_desc);
+		avg_trb_len = max_esit_payload;
+
 		ep_index = xhci_get_ep_index(endpt_desc);
 		ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index);
 
@@ -372,20 +578,38 @@
 		/*NOTE: ep_desc[0] actually represents EP1 and so on */
 		dir = (((endpt_desc->bEndpointAddress) & (0x80)) >> 7);
 		ep_type = (((endpt_desc->bmAttributes) & (0x3)) | (dir << 2));
+
+		ep_ctx[ep_index]->ep_info =
+			cpu_to_le32(EP_MAX_ESIT_PAYLOAD_HI(max_esit_payload) |
+			EP_INTERVAL(interval) | EP_MULT(mult));
+
 		ep_ctx[ep_index]->ep_info2 =
 			cpu_to_le32(ep_type << EP_TYPE_SHIFT);
 		ep_ctx[ep_index]->ep_info2 |=
 			cpu_to_le32(MAX_PACKET
 			(get_unaligned(&endpt_desc->wMaxPacketSize)));
 
+		/* Allow 3 retries for everything but isoc, set CErr = 3 */
+		if (!usb_endpoint_xfer_isoc(endpt_desc))
+			err_count = 3;
 		ep_ctx[ep_index]->ep_info2 |=
-			cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) |
-			((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT));
+			cpu_to_le32(MAX_BURST(max_burst) |
+			ERROR_COUNT(err_count));
 
 		trb_64 = (uintptr_t)
 				virt_dev->eps[ep_index].ring->enqueue;
 		ep_ctx[ep_index]->deq = cpu_to_le64(trb_64 |
 				virt_dev->eps[ep_index].ring->cycle_state);
+
+		/*
+		 * xHCI spec 6.2.3:
+		 * 'Average TRB Length' should be 8 for control endpoints.
+		 */
+		if (usb_endpoint_xfer_control(endpt_desc))
+			avg_trb_len = 8;
+		ep_ctx[ep_index]->tx_info =
+			cpu_to_le32(EP_MAX_ESIT_PAYLOAD_LO(max_esit_payload) |
+			EP_AVG_TRB_LENGTH(avg_trb_len));
 	}
 
 	return xhci_configure_endpoints(udev, false);
@@ -546,16 +770,13 @@
 	int max_packet_size;
 	int hw_max_packet_size;
 	int ret = 0;
-	struct usb_interface *ifdesc;
-
-	ifdesc = &udev->config.if_desc[0];
 
 	out_ctx = ctrl->devs[slot_id]->out_ctx;
 	xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size);
 
 	ep_ctx = xhci_get_ep_ctx(ctrl, out_ctx, ep_index);
 	hw_max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
-	max_packet_size = usb_endpoint_maxp(&ifdesc->ep_desc[0]);
+	max_packet_size = udev->epmaxpacketin[0];
 	if (hw_max_packet_size != max_packet_size) {
 		debug("Max Packet Size for ep 0 changed.\n");
 		debug("Max packet size in usb_device = %d\n", max_packet_size);
@@ -567,7 +788,8 @@
 				ctrl->devs[slot_id]->out_ctx, ep_index);
 		in_ctx = ctrl->devs[slot_id]->in_ctx;
 		ep_ctx = xhci_get_ep_ctx(ctrl, in_ctx, ep_index);
-		ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK);
+		ep_ctx->ep_info2 &= cpu_to_le32(~((0xffff & MAX_PACKET_MASK)
+						<< MAX_PACKET_SHIFT));
 		ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size));
 
 		/*
@@ -890,11 +1112,18 @@
 static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe,
 				void *buffer, int length, int interval)
 {
+	if (usb_pipetype(pipe) != PIPE_INTERRUPT) {
+		printf("non-interrupt pipe (type=%lu)", usb_pipetype(pipe));
+		return -EINVAL;
+	}
+
 	/*
-	 * TODO: Not addressing any interrupt type transfer requests
-	 * Add support for it later.
+	 * xHCI uses normal TRBs for both bulk and interrupt. When the
+	 * interrupt endpoint is to be serviced, the xHC will consume
+	 * (at most) one TD. A TD (comprised of sg list entries) can
+	 * take several service intervals to transmit.
 	 */
-	return -EINVAL;
+	return xhci_bulk_tx(udev, pipe, length, buffer);
 }
 
 /**
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 3377450..ba5f650 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -663,8 +663,9 @@
 #define GET_MAX_PACKET(p)	((p) & 0x7ff)
 
 /* tx_info bitmasks */
-#define AVG_TRB_LENGTH_FOR_EP(p)	((p) & 0xffff)
-#define MAX_ESIT_PAYLOAD_FOR_EP(p)	(((p) & 0xffff) << 16)
+#define EP_AVG_TRB_LENGTH(p)		((p) & 0xffff)
+#define EP_MAX_ESIT_PAYLOAD_LO(p)	(((p) & 0xffff) << 16)
+#define EP_MAX_ESIT_PAYLOAD_HI(p)	((((p) >> 16) & 0xff) << 24)
 #define CTX_TO_MAX_ESIT_PAYLOAD(p)	(((p) >> 16) & 0xffff)
 
 /* deq bitmasks */
diff --git a/drivers/usb/musb-new/linux-compat.h b/drivers/usb/musb-new/linux-compat.h
index 4dae83e..7bb53d2 100644
--- a/drivers/usb/musb-new/linux-compat.h
+++ b/drivers/usb/musb-new/linux-compat.h
@@ -5,8 +5,6 @@
 #include <linux/list.h>
 #include <linux/compat.h>
 
-#define pr_debug(fmt, args...) debug(fmt, ##args)
-
 #define WARN(condition, fmt, args...) ({	\
 	int ret_warn = !!condition;		\
 	if (ret_warn)				\
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index 5c1a902..7ee44ea 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -308,9 +308,6 @@
 	.platform_ops	= &sunxi_musb_ops,
 };
 
-#ifdef CONFIG_USB_MUSB_HOST
-static int musb_usb_remove(struct udevice *dev);
-
 static int musb_usb_probe(struct udevice *dev)
 {
 	struct musb_host_data *host = dev_get_priv(dev);
@@ -319,16 +316,20 @@
 
 	priv->desc_before_addr = true;
 
+#ifdef CONFIG_USB_MUSB_HOST
 	host->host = musb_init_controller(&musb_plat, NULL,
 					  (void *)SUNXI_USB0_BASE);
 	if (!host->host)
 		return -EIO;
 
 	ret = musb_lowlevel_init(host);
-	if (ret == 0)
-		printf("MUSB OTG\n");
-	else
-		musb_usb_remove(dev);
+	if (!ret)
+		printf("Allwinner mUSB OTG (Host)\n");
+#else
+	ret = musb_register(&musb_plat, NULL, (void *)SUNXI_USB0_BASE);
+	if (!ret)
+		printf("Allwinner mUSB OTG (Peripheral)\n");
+#endif
 
 	return ret;
 }
@@ -352,30 +353,27 @@
 	return 0;
 }
 
+static const struct udevice_id sunxi_musb_ids[] = {
+	{ .compatible = "allwinner,sun4i-a10-musb" },
+	{ .compatible = "allwinner,sun6i-a31-musb" },
+	{ .compatible = "allwinner,sun8i-a33-musb" },
+	{ .compatible = "allwinner,sun8i-h3-musb" },
+	{ }
+};
+
 U_BOOT_DRIVER(usb_musb) = {
-	.name	= "sunxi-musb",
-	.id	= UCLASS_USB,
-	.probe = musb_usb_probe,
-	.remove = musb_usb_remove,
-	.ops	= &musb_usb_ops,
+	.name		= "sunxi-musb",
+#ifdef CONFIG_USB_MUSB_HOST
+	.id		= UCLASS_USB,
+#else
+	.id		= UCLASS_USB_DEV_GENERIC,
+#endif
+	.of_match	= sunxi_musb_ids,
+	.probe		= musb_usb_probe,
+	.remove		= musb_usb_remove,
+#ifdef CONFIG_USB_MUSB_HOST
+	.ops		= &musb_usb_ops,
+#endif
 	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
 	.priv_auto_alloc_size = sizeof(struct musb_host_data),
 };
-#endif
-
-void sunxi_musb_board_init(void)
-{
-#ifdef CONFIG_USB_MUSB_HOST
-	struct udevice *dev;
-
-	/*
-	 * Bind the driver directly for now as musb linux kernel support is
-	 * still pending upstream so our dts files do not have the necessary
-	 * nodes yet. TODO: Remove this as soon as the dts nodes are in place
-	 * and bind by compatible instead.
-	 */
-	device_bind_driver(dm_root(), "sunxi-musb", "sunxi-musb", &dev);
-#else
-	musb_register(&musb_plat, NULL, (void *)SUNXI_USB0_BASE);
-#endif
-}
diff --git a/drivers/usb/musb-new/ti-musb.c b/drivers/usb/musb-new/ti-musb.c
index de10131..233857a 100644
--- a/drivers/usb/musb-new/ti-musb.c
+++ b/drivers/usb/musb-new/ti-musb.c
@@ -106,7 +106,7 @@
 							  "mentor,multipoint",
 							  -1);
 	if (platdata->musb_config.multipoint < 0) {
-		error("MUSB multipoint DT entry missing\n");
+		pr_err("MUSB multipoint DT entry missing\n");
 		return -ENOENT;
 	}
 
@@ -115,14 +115,14 @@
 	platdata->musb_config.num_eps = fdtdec_get_int(fdt, node,
 						       "mentor,num-eps", -1);
 	if (platdata->musb_config.num_eps < 0) {
-		error("MUSB num-eps DT entry missing\n");
+		pr_err("MUSB num-eps DT entry missing\n");
 		return -ENOENT;
 	}
 
 	platdata->musb_config.ram_bits = fdtdec_get_int(fdt, node,
 							"mentor,ram-bits", -1);
 	if (platdata->musb_config.ram_bits < 0) {
-		error("MUSB ram-bits DT entry missing\n");
+		pr_err("MUSB ram-bits DT entry missing\n");
 		return -ENOENT;
 	}
 
@@ -132,7 +132,7 @@
 
 	platdata->plat.power = fdtdec_get_int(fdt, node, "mentor,power", -1);
 	if (platdata->plat.power < 0) {
-		error("MUSB mentor,power DT entry missing\n");
+		pr_err("MUSB mentor,power DT entry missing\n");
 		return -ENOENT;
 	}
 
@@ -183,7 +183,7 @@
 
 	ret = ti_musb_ofdata_to_platdata(dev);
 	if (ret) {
-		error("platdata dt parse error\n");
+		pr_err("platdata dt parse error\n");
 		return ret;
 	}
 
@@ -229,7 +229,7 @@
 			ret = device_bind_driver_to_node(parent, "ti-musb-host",
 					name, offset_to_ofnode(node), &dev);
 			if (ret) {
-				error("musb - not able to bind usb host node\n");
+				pr_err("musb - not able to bind usb host node\n");
 				return ret;
 			}
 			break;
diff --git a/drivers/video/am335x-fb.c b/drivers/video/am335x-fb.c
index bb5cc97..a8b3e74 100644
--- a/drivers/video/am335x-fb.c
+++ b/drivers/video/am335x-fb.c
@@ -128,7 +128,7 @@
 		raster_ctrl |= LCD_TFT_24BPP_MODE;
 		break;
 	default:
-		error("am335x-fb: invalid bpp value: %d\n", panel->bpp);
+		pr_err("am335x-fb: invalid bpp value: %d\n", panel->bpp);
 		return -1;
 	}
 
diff --git a/dts/Kconfig b/dts/Kconfig
index 4ee0510..daa757d 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -102,7 +102,7 @@
 
 config OF_LIST
 	string "List of device tree files to include for DT control"
-	depends on SPL_LOAD_FIT || FIT_EMBED
+	depends on SPL_LOAD_FIT || MULTI_DTB_FIT
 	default DEFAULT_DEVICE_TREE
 	help
 	  This option specifies a list of device tree files to use for DT
@@ -112,6 +112,107 @@
 	  device tree files (without the directory or .dtb suffix)
 	  separated by <space>.
 
+
+config DTB_RESELECT
+	bool "Support swapping dtbs at a later point in boot"
+	depends on MULTI_DTB_FIT
+	help
+	  It is possible during initial boot you may need to use a generic
+	  dtb until you can fully determine the board your running on. This
+	  config allows boards to implement a function at a later point
+	  during boot to switch to the "correct" dtb.
+
+config MULTI_DTB_FIT
+	bool "Support embedding several DTBs in a FIT image for u-boot"
+	help
+	  This option provides hooks to allow U-boot to parse an
+	  appended FIT image and enable board specific code to then select
+	  the correct DTB to be used. Use this if you need to support
+	  multiple DTBs but don't use the SPL.
+
+
+config SPL_MULTI_DTB_FIT
+	depends on SPL_LOAD_FIT && SPL_OF_CONTROL && !SPL_OF_PLATDATA
+	bool "Support embedding several DTBs in a FIT image for the SPL"
+	help
+	  This option provides the SPL with the ability to select its own
+	  DTB at runtime from an appended FIT image containing several DTBs.
+	  This allows using the same SPL binary on multiple platforms.
+	  The primary purpose is to handle different versions of
+	  the same platform without tweaking the platform code if the
+	  differences can be expressed in the DTBs (common examples are: bus
+	  capabilities, pad configurations).
+
+config SPL_OF_LIST
+	string "List of device tree files to include for DT control in SPL"
+	depends on SPL_MULTI_DTB_FIT
+	default OF_LIST
+	help
+	  This option specifies a list of device tree files to use for DT
+	  control in the SPL. These will be packaged into a FIT. At run-time,
+	  the SPL will select the correct DT to use by examining the
+	  hardware (e.g. reading a board ID value). This is a list of
+	  device tree files (without the directory or .dtb suffix)
+	  separated by <space>.
+
+choice
+	prompt "SPL OF LIST compression"
+	depends on SPL_MULTI_DTB_FIT
+	default SPL_MULTI_DTB_FIT_LZO
+
+config SPL_MULTI_DTB_FIT_LZO
+	bool "LZO"
+	depends on SYS_MALLOC_F
+	select SPL_LZO
+	help
+	  Compress the FIT image containing the DTBs available for the SPL
+	  using LZO compression. (requires lzop on host).
+
+config SPL_MULTI_DTB_FIT_GZIP
+	bool "GZIP"
+	depends on SYS_MALLOC_F
+	select SPL_GZIP
+	help
+	  Compress the FIT image containing the DTBs available for the SPL
+	  using GZIP compression. (requires gzip on host)
+
+config SPL_MULTI_DTB_FIT_NO_COMPRESSION
+	bool "No compression"
+	help
+	  Do not compress the FIT image containing the DTBs available for the SPL.
+	  Use this options only if LZO is not available and the DTBs are very small.
+endchoice
+
+choice
+	prompt "Location of uncompressed DTBs "
+	depends on (SPL_MULTI_DTB_FIT_GZIP || SPL_MULTI_DTB_FIT_LZO)
+	default SPL_MULTI_DTB_FIT_DYN_ALLOC if SYS_MALLOC_F
+
+config SPL_MULTI_DTB_FIT_DYN_ALLOC
+	bool "Dynamically allocate the memory"
+	depends on SYS_MALLOC_F
+
+config SPL_MULTI_DTB_FIT_USER_DEFINED_AREA
+	bool "User-defined location"
+endchoice
+
+config SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ
+	hex "Size of memory reserved to uncompress the DTBs"
+	depends on (SPL_MULTI_DTB_FIT_GZIP || SPL_MULTI_DTB_FIT_LZO)
+	default 0x8000
+	help
+	   This is the size of this area where the DTBs are uncompressed.
+	   If this area is dynamically allocated, make sure that
+	   SPL_SYS_MALLOC_F_LEN is big enough to contain it.
+
+config SPL_MULTI_DTB_FIT_USER_DEF_ADDR
+	hex "Address of memory where dtbs are uncompressed"
+	depends on SPL_MULTI_DTB_FIT_USER_DEFINED_AREA
+	help
+	   the FIT image containing the DTBs is uncompressed in an area defined
+	   at compilation time. This is the address of this area. It must be
+	   aligned on 2-byte boundary.
+
 config OF_SPL_REMOVE_PROPS
 	string "List of device tree properties to drop for SPL"
 	depends on SPL_OF_CONTROL
diff --git a/env/common.c b/env/common.c
index b403bd5..70715bb 100644
--- a/env/common.c
+++ b/env/common.c
@@ -84,7 +84,7 @@
 	if (himport_r(&env_htab, (char *)default_environment,
 			sizeof(default_environment), '\0', flags, 0,
 			0, NULL) == 0)
-		error("Environment import failed: errno = %d\n", errno);
+		pr_err("Environment import failed: errno = %d\n", errno);
 
 	gd->flags |= GD_FLG_ENV_READY;
 	gd->flags |= GD_FLG_ENV_DEFAULT;
@@ -172,7 +172,7 @@
 	/* Decrypt the env if desired. */
 	ret = env_aes_cbc_crypt(ep, 0);
 	if (ret) {
-		error("Failed to decrypt env!\n");
+		pr_err("Failed to decrypt env!\n");
 		set_default_env("!import failed");
 		return ret;
 	}
@@ -183,7 +183,7 @@
 		return 1;
 	}
 
-	error("Cannot import environment: errno = %d\n", errno);
+	pr_err("Cannot import environment: errno = %d\n", errno);
 
 	set_default_env("!import failed");
 
@@ -247,7 +247,7 @@
 	res = (char *)env_out->data;
 	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 	if (len < 0) {
-		error("Cannot export environment: errno = %d\n", errno);
+		pr_err("Cannot export environment: errno = %d\n", errno);
 		return 1;
 	}
 
diff --git a/env/sf.c b/env/sf.c
index 6f74371..e51b1ae 100644
--- a/env/sf.c
+++ b/env/sf.c
@@ -236,7 +236,7 @@
 
 	ret = env_import((char *)ep, 0);
 	if (!ret) {
-		error("Cannot import environment: errno = %d\n", errno);
+		pr_err("Cannot import environment: errno = %d\n", errno);
 		set_default_env("!env_import failed");
 	}
 
diff --git a/fs/Kconfig b/fs/Kconfig
index e6803ac..1cb9831 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -4,6 +4,8 @@
 
 menu "File systems"
 
+source "fs/btrfs/Kconfig"
+
 source "fs/cbfs/Kconfig"
 
 source "fs/ext4/Kconfig"
diff --git a/fs/Makefile b/fs/Makefile
index 5770f41..8a8175b 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -12,6 +12,7 @@
 else
 obj-y				+= fs.o
 
+obj-$(CONFIG_FS_BTRFS) += btrfs/
 obj-$(CONFIG_FS_CBFS) += cbfs/
 obj-$(CONFIG_CMD_CRAMFS) += cramfs/
 obj-$(CONFIG_FS_EXT4) += ext4/
@@ -23,3 +24,4 @@
 obj-$(CONFIG_YAFFS2) += yaffs2/
 obj-$(CONFIG_CMD_ZFS) += zfs/
 endif
+obj-y += fs_internal.o
diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig
new file mode 100644
index 0000000..22909d9
--- /dev/null
+++ b/fs/btrfs/Kconfig
@@ -0,0 +1,9 @@
+config FS_BTRFS
+	bool "Enable BTRFS filesystem support"
+	select CRC32C
+	select LZO
+	select RBTREE
+	help
+	  This provides a single-device read-only BTRFS support. BTRFS is a
+	  next-generation Linux file system based on the copy-on-write
+	  principle.
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile
new file mode 100644
index 0000000..0173155
--- /dev/null
+++ b/fs/btrfs/Makefile
@@ -0,0 +1,8 @@
+#
+# 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y := btrfs.o chunk-map.o compression.o ctree.o dev.o dir-item.o \
+	extent-io.o hash.o inode.o root.o subvolume.o super.o
diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c
new file mode 100644
index 0000000..4140e2b
--- /dev/null
+++ b/fs/btrfs/btrfs.c
@@ -0,0 +1,227 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "btrfs.h"
+#include <config.h>
+#include <malloc.h>
+#include <linux/time.h>
+
+struct btrfs_info btrfs_info;
+
+static int readdir_callback(const struct btrfs_root *root,
+			    struct btrfs_dir_item *item)
+{
+	static const char typestr[BTRFS_FT_MAX][4] = {
+		[BTRFS_FT_UNKNOWN]  = " ? ",
+		[BTRFS_FT_REG_FILE] = "   ",
+		[BTRFS_FT_DIR]      = "DIR",
+		[BTRFS_FT_CHRDEV]   = "CHR",
+		[BTRFS_FT_BLKDEV]   = "BLK",
+		[BTRFS_FT_FIFO]     = "FIF",
+		[BTRFS_FT_SOCK]     = "SCK",
+		[BTRFS_FT_SYMLINK]  = "SYM",
+		[BTRFS_FT_XATTR]    = " ? ",
+	};
+	struct btrfs_inode_item inode;
+	const char *name = (const char *) (item + 1);
+	char filetime[32], *target = NULL;
+	time_t mtime;
+
+	if (btrfs_lookup_inode(root, &item->location, &inode, NULL)) {
+		printf("%s: Cannot find inode item for directory entry %.*s!\n",
+		       __func__, item->name_len, name);
+		return 0;
+	}
+
+	mtime = inode.mtime.sec;
+	ctime_r(&mtime, filetime);
+
+	if (item->type == BTRFS_FT_SYMLINK) {
+		target = malloc(min(inode.size + 1,
+				    (u64) btrfs_info.sb.sectorsize));
+
+		if (target && btrfs_readlink(root, item->location.objectid,
+					     target)) {
+			free(target);
+			target = NULL;
+		}
+
+		if (!target)
+			printf("%s: Cannot read symlink target!\n", __func__);
+	}
+
+	printf("<%s> ", typestr[item->type]);
+	if (item->type == BTRFS_FT_CHRDEV || item->type == BTRFS_FT_BLKDEV)
+		printf("%4u,%5u  ", (unsigned int) (inode.rdev >> 20),
+			(unsigned int) (inode.rdev & 0xfffff));
+	else
+		printf("%10llu  ", inode.size);
+
+	printf("%24.24s  %.*s", filetime, item->name_len, name);
+
+	if (item->type == BTRFS_FT_SYMLINK) {
+		printf(" -> %s", target ? target : "?");
+		if (target)
+			free(target);
+	}
+
+	printf("\n");
+
+	return 0;
+}
+
+int btrfs_probe(struct blk_desc *fs_dev_desc, disk_partition_t *fs_partition)
+{
+	btrfs_blk_desc = fs_dev_desc;
+	btrfs_part_info = fs_partition;
+
+	memset(&btrfs_info, 0, sizeof(btrfs_info));
+
+	btrfs_hash_init();
+	if (btrfs_read_superblock())
+		return -1;
+
+	if (btrfs_chunk_map_init()) {
+		printf("%s: failed to init chunk map\n", __func__);
+		return -1;
+	}
+
+	btrfs_info.tree_root.objectid = 0;
+	btrfs_info.tree_root.bytenr = btrfs_info.sb.root;
+	btrfs_info.chunk_root.objectid = 0;
+	btrfs_info.chunk_root.bytenr = btrfs_info.sb.chunk_root;
+
+	if (btrfs_read_chunk_tree()) {
+		printf("%s: failed to read chunk tree\n", __func__);
+		return -1;
+	}
+
+	if (btrfs_find_root(btrfs_get_default_subvol_objectid(),
+			    &btrfs_info.fs_root, NULL)) {
+		printf("%s: failed to find default subvolume\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
+
+int btrfs_ls(const char *path)
+{
+	struct btrfs_root root = btrfs_info.fs_root;
+	u64 inr;
+	u8 type;
+
+	inr = btrfs_lookup_path(&root, root.root_dirid, path, &type, NULL, 40);
+
+	if (inr == -1ULL) {
+		printf("Cannot lookup path %s\n", path);
+		return 1;
+	}
+
+	if (type != BTRFS_FT_DIR) {
+		printf("Not a directory: %s\n", path);
+		return 1;
+	}
+
+	if (btrfs_readdir(&root, inr, readdir_callback)) {
+		printf("An error occured while listing directory %s\n", path);
+		return 1;
+	}
+
+	return 0;
+}
+
+int btrfs_exists(const char *file)
+{
+	struct btrfs_root root = btrfs_info.fs_root;
+	u64 inr;
+	u8 type;
+
+	inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, NULL, 40);
+
+	return (inr != -1ULL && type == BTRFS_FT_REG_FILE);
+}
+
+int btrfs_size(const char *file, loff_t *size)
+{
+	struct btrfs_root root = btrfs_info.fs_root;
+	struct btrfs_inode_item inode;
+	u64 inr;
+	u8 type;
+
+	inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
+				40);
+
+	if (inr == -1ULL) {
+		printf("Cannot lookup file %s\n", file);
+		return 1;
+	}
+
+	if (type != BTRFS_FT_REG_FILE) {
+		printf("Not a regular file: %s\n", file);
+		return 1;
+	}
+
+	*size = inode.size;
+	return 0;
+}
+
+int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
+	       loff_t *actread)
+{
+	struct btrfs_root root = btrfs_info.fs_root;
+	struct btrfs_inode_item inode;
+	u64 inr, rd;
+	u8 type;
+
+	inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
+				40);
+
+	if (inr == -1ULL) {
+		printf("Cannot lookup file %s\n", file);
+		return 1;
+	}
+
+	if (type != BTRFS_FT_REG_FILE) {
+		printf("Not a regular file: %s\n", file);
+		return 1;
+	}
+
+	if (!len)
+		len = inode.size;
+
+	if (len > inode.size - offset)
+		len = inode.size - offset;
+
+	rd = btrfs_file_read(&root, inr, offset, len, buf);
+	if (rd == -1ULL) {
+		printf("An error occured while reading file %s\n", file);
+		return 1;
+	}
+
+	*actread = rd;
+	return 0;
+}
+
+void btrfs_close(void)
+{
+	btrfs_chunk_map_exit();
+}
+
+int btrfs_uuid(char *uuid_str)
+{
+#ifdef CONFIG_LIB_UUID
+	uuid_bin_to_str(btrfs_info.sb.fsid, uuid_str, UUID_STR_FORMAT_STD);
+	return 0;
+#endif
+	return -ENOSYS;
+}
+
+/*
+		btrfs_list_subvols();
+*/
diff --git a/fs/btrfs/btrfs.h b/fs/btrfs/btrfs.h
new file mode 100644
index 0000000..4247cbb
--- /dev/null
+++ b/fs/btrfs/btrfs.h
@@ -0,0 +1,89 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __BTRFS_BTRFS_H__
+#define __BTRFS_BTRFS_H__
+
+#include <linux/rbtree.h>
+#include "conv-funcs.h"
+
+struct btrfs_info {
+	struct btrfs_super_block sb;
+	struct btrfs_root_backup *root_backup;
+
+	struct btrfs_root tree_root;
+	struct btrfs_root fs_root;
+	struct btrfs_root chunk_root;
+
+	struct rb_root chunks_root;
+};
+
+extern struct btrfs_info btrfs_info;
+
+/* hash.c */
+void btrfs_hash_init(void);
+u32 btrfs_crc32c(u32, const void *, size_t);
+u32 btrfs_csum_data(char *, u32, size_t);
+void btrfs_csum_final(u32, void *);
+
+static inline u64 btrfs_name_hash(const char *name, int len)
+{
+	return btrfs_crc32c((u32) ~1, name, len);
+}
+
+/* dev.c */
+extern struct blk_desc *btrfs_blk_desc;
+extern disk_partition_t *btrfs_part_info;
+
+int btrfs_devread(u64, int, void *);
+
+/* chunk-map.c */
+u64 btrfs_map_logical_to_physical(u64);
+int btrfs_chunk_map_init(void);
+void btrfs_chunk_map_exit(void);
+int btrfs_read_chunk_tree(void);
+
+/* compression.c */
+u32 btrfs_decompress(u8 type, const char *, u32, char *, u32);
+
+/* super.c */
+int btrfs_read_superblock(void);
+
+/* dir-item.c */
+typedef int (*btrfs_readdir_callback_t)(const struct btrfs_root *,
+					struct btrfs_dir_item *);
+
+int btrfs_lookup_dir_item(const struct btrfs_root *, u64, const char *, int,
+			   struct btrfs_dir_item *);
+int btrfs_readdir(const struct btrfs_root *, u64, btrfs_readdir_callback_t);
+
+/* root.c */
+int btrfs_find_root(u64, struct btrfs_root *, struct btrfs_root_item *);
+u64 btrfs_lookup_root_ref(u64, struct btrfs_root_ref *, char *);
+
+/* inode.c */
+u64 btrfs_lookup_inode_ref(struct btrfs_root *, u64, struct btrfs_inode_ref *,
+			    char *);
+int btrfs_lookup_inode(const struct btrfs_root *, struct btrfs_key *,
+		        struct btrfs_inode_item *, struct btrfs_root *);
+int btrfs_readlink(const struct btrfs_root *, u64, char *);
+u64 btrfs_lookup_path(struct btrfs_root *, u64, const char *, u8 *,
+		       struct btrfs_inode_item *, int);
+u64 btrfs_file_read(const struct btrfs_root *, u64, u64, u64, char *);
+
+/* subvolume.c */
+u64 btrfs_get_default_subvol_objectid(void);
+
+/* extent-io.c */
+u64 btrfs_read_extent_inline(struct btrfs_path *,
+			      struct btrfs_file_extent_item *, u64, u64,
+			      char *);
+u64 btrfs_read_extent_reg(struct btrfs_path *, struct btrfs_file_extent_item *,
+			   u64, u64, char *);
+
+#endif /* !__BTRFS_BTRFS_H__ */
diff --git a/fs/btrfs/btrfs_tree.h b/fs/btrfs/btrfs_tree.h
new file mode 100644
index 0000000..f171b24
--- /dev/null
+++ b/fs/btrfs/btrfs_tree.h
@@ -0,0 +1,766 @@
+/*
+ * From linux/include/uapi/linux/btrfs_tree.h
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __BTRFS_BTRFS_TREE_H__
+#define __BTRFS_BTRFS_TREE_H__
+
+#include <common.h>
+
+#define BTRFS_VOL_NAME_MAX 255
+#define BTRFS_NAME_MAX 255
+#define BTRFS_LABEL_SIZE 256
+#define BTRFS_FSID_SIZE 16
+#define BTRFS_UUID_SIZE 16
+
+/*
+ * This header contains the structure definitions and constants used
+ * by file system objects that can be retrieved using
+ * the BTRFS_IOC_SEARCH_TREE ioctl.  That means basically anything that
+ * is needed to describe a leaf node's key or item contents.
+ */
+
+/* holds pointers to all of the tree roots */
+#define BTRFS_ROOT_TREE_OBJECTID 1ULL
+
+/* stores information about which extents are in use, and reference counts */
+#define BTRFS_EXTENT_TREE_OBJECTID 2ULL
+
+/*
+ * chunk tree stores translations from logical -> physical block numbering
+ * the super block points to the chunk tree
+ */
+#define BTRFS_CHUNK_TREE_OBJECTID 3ULL
+
+/*
+ * stores information about which areas of a given device are in use.
+ * one per device.  The tree of tree roots points to the device tree
+ */
+#define BTRFS_DEV_TREE_OBJECTID 4ULL
+
+/* one per subvolume, storing files and directories */
+#define BTRFS_FS_TREE_OBJECTID 5ULL
+
+/* directory objectid inside the root tree */
+#define BTRFS_ROOT_TREE_DIR_OBJECTID 6ULL
+
+/* holds checksums of all the data extents */
+#define BTRFS_CSUM_TREE_OBJECTID 7ULL
+
+/* holds quota configuration and tracking */
+#define BTRFS_QUOTA_TREE_OBJECTID 8ULL
+
+/* for storing items that use the BTRFS_UUID_KEY* types */
+#define BTRFS_UUID_TREE_OBJECTID 9ULL
+
+/* tracks free space in block groups. */
+#define BTRFS_FREE_SPACE_TREE_OBJECTID 10ULL
+
+/* device stats in the device tree */
+#define BTRFS_DEV_STATS_OBJECTID 0ULL
+
+/* for storing balance parameters in the root tree */
+#define BTRFS_BALANCE_OBJECTID -4ULL
+
+/* orhpan objectid for tracking unlinked/truncated files */
+#define BTRFS_ORPHAN_OBJECTID -5ULL
+
+/* does write ahead logging to speed up fsyncs */
+#define BTRFS_TREE_LOG_OBJECTID -6ULL
+#define BTRFS_TREE_LOG_FIXUP_OBJECTID -7ULL
+
+/* for space balancing */
+#define BTRFS_TREE_RELOC_OBJECTID -8ULL
+#define BTRFS_DATA_RELOC_TREE_OBJECTID -9ULL
+
+/*
+ * extent checksums all have this objectid
+ * this allows them to share the logging tree
+ * for fsyncs
+ */
+#define BTRFS_EXTENT_CSUM_OBJECTID -10ULL
+
+/* For storing free space cache */
+#define BTRFS_FREE_SPACE_OBJECTID -11ULL
+
+/*
+ * The inode number assigned to the special inode for storing
+ * free ino cache
+ */
+#define BTRFS_FREE_INO_OBJECTID -12ULL
+
+/* dummy objectid represents multiple objectids */
+#define BTRFS_MULTIPLE_OBJECTIDS -255ULL
+
+/*
+ * All files have objectids in this range.
+ */
+#define BTRFS_FIRST_FREE_OBJECTID 256ULL
+#define BTRFS_LAST_FREE_OBJECTID -256ULL
+#define BTRFS_FIRST_CHUNK_TREE_OBJECTID 256ULL
+
+
+/*
+ * the device items go into the chunk tree.  The key is in the form
+ * [ 1 BTRFS_DEV_ITEM_KEY device_id ]
+ */
+#define BTRFS_DEV_ITEMS_OBJECTID 1ULL
+
+#define BTRFS_BTREE_INODE_OBJECTID 1
+
+#define BTRFS_EMPTY_SUBVOL_DIR_OBJECTID 2
+
+#define BTRFS_DEV_REPLACE_DEVID 0ULL
+
+/*
+ * inode items have the data typically returned from stat and store other
+ * info about object characteristics.  There is one for every file and dir in
+ * the FS
+ */
+#define BTRFS_INODE_ITEM_KEY		1
+#define BTRFS_INODE_REF_KEY		12
+#define BTRFS_INODE_EXTREF_KEY		13
+#define BTRFS_XATTR_ITEM_KEY		24
+#define BTRFS_ORPHAN_ITEM_KEY		48
+/* reserve 2-15 close to the inode for later flexibility */
+
+/*
+ * dir items are the name -> inode pointers in a directory.  There is one
+ * for every name in a directory.
+ */
+#define BTRFS_DIR_LOG_ITEM_KEY  60
+#define BTRFS_DIR_LOG_INDEX_KEY 72
+#define BTRFS_DIR_ITEM_KEY	84
+#define BTRFS_DIR_INDEX_KEY	96
+/*
+ * extent data is for file data
+ */
+#define BTRFS_EXTENT_DATA_KEY	108
+
+/*
+ * extent csums are stored in a separate tree and hold csums for
+ * an entire extent on disk.
+ */
+#define BTRFS_EXTENT_CSUM_KEY	128
+
+/*
+ * root items point to tree roots.  They are typically in the root
+ * tree used by the super block to find all the other trees
+ */
+#define BTRFS_ROOT_ITEM_KEY	132
+
+/*
+ * root backrefs tie subvols and snapshots to the directory entries that
+ * reference them
+ */
+#define BTRFS_ROOT_BACKREF_KEY	144
+
+/*
+ * root refs make a fast index for listing all of the snapshots and
+ * subvolumes referenced by a given root.  They point directly to the
+ * directory item in the root that references the subvol
+ */
+#define BTRFS_ROOT_REF_KEY	156
+
+/*
+ * extent items are in the extent map tree.  These record which blocks
+ * are used, and how many references there are to each block
+ */
+#define BTRFS_EXTENT_ITEM_KEY	168
+
+/*
+ * The same as the BTRFS_EXTENT_ITEM_KEY, except it's metadata we already know
+ * the length, so we save the level in key->offset instead of the length.
+ */
+#define BTRFS_METADATA_ITEM_KEY	169
+
+#define BTRFS_TREE_BLOCK_REF_KEY	176
+
+#define BTRFS_EXTENT_DATA_REF_KEY	178
+
+#define BTRFS_EXTENT_REF_V0_KEY		180
+
+#define BTRFS_SHARED_BLOCK_REF_KEY	182
+
+#define BTRFS_SHARED_DATA_REF_KEY	184
+
+/*
+ * block groups give us hints into the extent allocation trees.  Which
+ * blocks are free etc etc
+ */
+#define BTRFS_BLOCK_GROUP_ITEM_KEY 192
+
+/*
+ * Every block group is represented in the free space tree by a free space info
+ * item, which stores some accounting information. It is keyed on
+ * (block_group_start, FREE_SPACE_INFO, block_group_length).
+ */
+#define BTRFS_FREE_SPACE_INFO_KEY 198
+
+/*
+ * A free space extent tracks an extent of space that is free in a block group.
+ * It is keyed on (start, FREE_SPACE_EXTENT, length).
+ */
+#define BTRFS_FREE_SPACE_EXTENT_KEY 199
+
+/*
+ * When a block group becomes very fragmented, we convert it to use bitmaps
+ * instead of extents. A free space bitmap is keyed on
+ * (start, FREE_SPACE_BITMAP, length); the corresponding item is a bitmap with
+ * (length / sectorsize) bits.
+ */
+#define BTRFS_FREE_SPACE_BITMAP_KEY 200
+
+#define BTRFS_DEV_EXTENT_KEY	204
+#define BTRFS_DEV_ITEM_KEY	216
+#define BTRFS_CHUNK_ITEM_KEY	228
+
+/*
+ * Records the overall state of the qgroups.
+ * There's only one instance of this key present,
+ * (0, BTRFS_QGROUP_STATUS_KEY, 0)
+ */
+#define BTRFS_QGROUP_STATUS_KEY         240
+/*
+ * Records the currently used space of the qgroup.
+ * One key per qgroup, (0, BTRFS_QGROUP_INFO_KEY, qgroupid).
+ */
+#define BTRFS_QGROUP_INFO_KEY           242
+/*
+ * Contains the user configured limits for the qgroup.
+ * One key per qgroup, (0, BTRFS_QGROUP_LIMIT_KEY, qgroupid).
+ */
+#define BTRFS_QGROUP_LIMIT_KEY          244
+/*
+ * Records the child-parent relationship of qgroups. For
+ * each relation, 2 keys are present:
+ * (childid, BTRFS_QGROUP_RELATION_KEY, parentid)
+ * (parentid, BTRFS_QGROUP_RELATION_KEY, childid)
+ */
+#define BTRFS_QGROUP_RELATION_KEY       246
+
+/*
+ * Obsolete name, see BTRFS_TEMPORARY_ITEM_KEY.
+ */
+#define BTRFS_BALANCE_ITEM_KEY	248
+
+/*
+ * The key type for tree items that are stored persistently, but do not need to
+ * exist for extended period of time. The items can exist in any tree.
+ *
+ * [subtype, BTRFS_TEMPORARY_ITEM_KEY, data]
+ *
+ * Existing items:
+ *
+ * - balance status item
+ *   (BTRFS_BALANCE_OBJECTID, BTRFS_TEMPORARY_ITEM_KEY, 0)
+ */
+#define BTRFS_TEMPORARY_ITEM_KEY	248
+
+/*
+ * Obsolete name, see BTRFS_PERSISTENT_ITEM_KEY
+ */
+#define BTRFS_DEV_STATS_KEY		249
+
+/*
+ * The key type for tree items that are stored persistently and usually exist
+ * for a long period, eg. filesystem lifetime. The item kinds can be status
+ * information, stats or preference values. The item can exist in any tree.
+ *
+ * [subtype, BTRFS_PERSISTENT_ITEM_KEY, data]
+ *
+ * Existing items:
+ *
+ * - device statistics, store IO stats in the device tree, one key for all
+ *   stats
+ *   (BTRFS_DEV_STATS_OBJECTID, BTRFS_DEV_STATS_KEY, 0)
+ */
+#define BTRFS_PERSISTENT_ITEM_KEY	249
+
+/*
+ * Persistantly stores the device replace state in the device tree.
+ * The key is built like this: (0, BTRFS_DEV_REPLACE_KEY, 0).
+ */
+#define BTRFS_DEV_REPLACE_KEY	250
+
+/*
+ * Stores items that allow to quickly map UUIDs to something else.
+ * These items are part of the filesystem UUID tree.
+ * The key is built like this:
+ * (UUID_upper_64_bits, BTRFS_UUID_KEY*, UUID_lower_64_bits).
+ */
+#if BTRFS_UUID_SIZE != 16
+#error "UUID items require BTRFS_UUID_SIZE == 16!"
+#endif
+#define BTRFS_UUID_KEY_SUBVOL	251	/* for UUIDs assigned to subvols */
+#define BTRFS_UUID_KEY_RECEIVED_SUBVOL	252	/* for UUIDs assigned to
+						 * received subvols */
+
+/*
+ * string items are for debugging.  They just store a short string of
+ * data in the FS
+ */
+#define BTRFS_STRING_ITEM_KEY	253
+
+
+
+/* 32 bytes in various csum fields */
+#define BTRFS_CSUM_SIZE 32
+
+/* csum types */
+#define BTRFS_CSUM_TYPE_CRC32	0
+
+/*
+ * flags definitions for directory entry item type
+ *
+ * Used by:
+ * struct btrfs_dir_item.type
+ */
+#define BTRFS_FT_UNKNOWN	0
+#define BTRFS_FT_REG_FILE	1
+#define BTRFS_FT_DIR		2
+#define BTRFS_FT_CHRDEV		3
+#define BTRFS_FT_BLKDEV		4
+#define BTRFS_FT_FIFO		5
+#define BTRFS_FT_SOCK		6
+#define BTRFS_FT_SYMLINK	7
+#define BTRFS_FT_XATTR		8
+#define BTRFS_FT_MAX		9
+
+/*
+ * The key defines the order in the tree, and so it also defines (optimal)
+ * block layout.
+ *
+ * objectid corresponds to the inode number.
+ *
+ * type tells us things about the object, and is a kind of stream selector.
+ * so for a given inode, keys with type of 1 might refer to the inode data,
+ * type of 2 may point to file data in the btree and type == 3 may point to
+ * extents.
+ *
+ * offset is the starting byte offset for this key in the stream.
+ */
+
+struct btrfs_key {
+	__u64 objectid;
+	__u8 type;
+	__u64 offset;
+} __attribute__ ((__packed__));
+
+struct btrfs_dev_item {
+	/* the internal btrfs device id */
+	__u64 devid;
+
+	/* size of the device */
+	__u64 total_bytes;
+
+	/* bytes used */
+	__u64 bytes_used;
+
+	/* optimal io alignment for this device */
+	__u32 io_align;
+
+	/* optimal io width for this device */
+	__u32 io_width;
+
+	/* minimal io size for this device */
+	__u32 sector_size;
+
+	/* type and info about this device */
+	__u64 type;
+
+	/* expected generation for this device */
+	__u64 generation;
+
+	/*
+	 * starting byte of this partition on the device,
+	 * to allow for stripe alignment in the future
+	 */
+	__u64 start_offset;
+
+	/* grouping information for allocation decisions */
+	__u32 dev_group;
+
+	/* seek speed 0-100 where 100 is fastest */
+	__u8 seek_speed;
+
+	/* bandwidth 0-100 where 100 is fastest */
+	__u8 bandwidth;
+
+	/* btrfs generated uuid for this device */
+	__u8 uuid[BTRFS_UUID_SIZE];
+
+	/* uuid of FS who owns this device */
+	__u8 fsid[BTRFS_UUID_SIZE];
+} __attribute__ ((__packed__));
+
+struct btrfs_stripe {
+	__u64 devid;
+	__u64 offset;
+	__u8 dev_uuid[BTRFS_UUID_SIZE];
+} __attribute__ ((__packed__));
+
+struct btrfs_chunk {
+	/* size of this chunk in bytes */
+	__u64 length;
+
+	/* objectid of the root referencing this chunk */
+	__u64 owner;
+
+	__u64 stripe_len;
+	__u64 type;
+
+	/* optimal io alignment for this chunk */
+	__u32 io_align;
+
+	/* optimal io width for this chunk */
+	__u32 io_width;
+
+	/* minimal io size for this chunk */
+	__u32 sector_size;
+
+	/* 2^16 stripes is quite a lot, a second limit is the size of a single
+	 * item in the btree
+	 */
+	__u16 num_stripes;
+
+	/* sub stripes only matter for raid10 */
+	__u16 sub_stripes;
+	struct btrfs_stripe stripe;
+	/* additional stripes go here */
+} __attribute__ ((__packed__));
+
+#define BTRFS_FREE_SPACE_EXTENT	1
+#define BTRFS_FREE_SPACE_BITMAP	2
+
+struct btrfs_free_space_entry {
+	__u64 offset;
+	__u64 bytes;
+	__u8 type;
+} __attribute__ ((__packed__));
+
+struct btrfs_free_space_header {
+	struct btrfs_key location;
+	__u64 generation;
+	__u64 num_entries;
+	__u64 num_bitmaps;
+} __attribute__ ((__packed__));
+
+#define BTRFS_HEADER_FLAG_WRITTEN	(1ULL << 0)
+#define BTRFS_HEADER_FLAG_RELOC		(1ULL << 1)
+
+/* Super block flags */
+/* Errors detected */
+#define BTRFS_SUPER_FLAG_ERROR		(1ULL << 2)
+
+#define BTRFS_SUPER_FLAG_SEEDING	(1ULL << 32)
+#define BTRFS_SUPER_FLAG_METADUMP	(1ULL << 33)
+
+
+/*
+ * items in the extent btree are used to record the objectid of the
+ * owner of the block and the number of references
+ */
+
+struct btrfs_extent_item {
+	__u64 refs;
+	__u64 generation;
+	__u64 flags;
+} __attribute__ ((__packed__));
+
+
+#define BTRFS_EXTENT_FLAG_DATA		(1ULL << 0)
+#define BTRFS_EXTENT_FLAG_TREE_BLOCK	(1ULL << 1)
+
+/* following flags only apply to tree blocks */
+
+/* use full backrefs for extent pointers in the block */
+#define BTRFS_BLOCK_FLAG_FULL_BACKREF	(1ULL << 8)
+
+/*
+ * this flag is only used internally by scrub and may be changed at any time
+ * it is only declared here to avoid collisions
+ */
+#define BTRFS_EXTENT_FLAG_SUPER		(1ULL << 48)
+
+struct btrfs_tree_block_info {
+	struct btrfs_key key;
+	__u8 level;
+} __attribute__ ((__packed__));
+
+struct btrfs_extent_data_ref {
+	__u64 root;
+	__u64 objectid;
+	__u64 offset;
+	__u32 count;
+} __attribute__ ((__packed__));
+
+struct btrfs_shared_data_ref {
+	__u32 count;
+} __attribute__ ((__packed__));
+
+struct btrfs_extent_inline_ref {
+	__u8 type;
+	__u64 offset;
+} __attribute__ ((__packed__));
+
+/* dev extents record free space on individual devices.  The owner
+ * field points back to the chunk allocation mapping tree that allocated
+ * the extent.  The chunk tree uuid field is a way to double check the owner
+ */
+struct btrfs_dev_extent {
+	__u64 chunk_tree;
+	__u64 chunk_objectid;
+	__u64 chunk_offset;
+	__u64 length;
+	__u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
+} __attribute__ ((__packed__));
+
+struct btrfs_inode_ref {
+	__u64 index;
+	__u16 name_len;
+	/* name goes here */
+} __attribute__ ((__packed__));
+
+struct btrfs_inode_extref {
+	__u64 parent_objectid;
+	__u64 index;
+	__u16 name_len;
+	__u8   name[0];
+	/* name goes here */
+} __attribute__ ((__packed__));
+
+struct btrfs_timespec {
+	__u64 sec;
+	__u32 nsec;
+} __attribute__ ((__packed__));
+
+struct btrfs_inode_item {
+	/* nfs style generation number */
+	__u64 generation;
+	/* transid that last touched this inode */
+	__u64 transid;
+	__u64 size;
+	__u64 nbytes;
+	__u64 block_group;
+	__u32 nlink;
+	__u32 uid;
+	__u32 gid;
+	__u32 mode;
+	__u64 rdev;
+	__u64 flags;
+
+	/* modification sequence number for NFS */
+	__u64 sequence;
+
+	/*
+	 * a little future expansion, for more than this we can
+	 * just grow the inode item and version it
+	 */
+	__u64 reserved[4];
+	struct btrfs_timespec atime;
+	struct btrfs_timespec ctime;
+	struct btrfs_timespec mtime;
+	struct btrfs_timespec otime;
+} __attribute__ ((__packed__));
+
+struct btrfs_dir_log_item {
+	__u64 end;
+} __attribute__ ((__packed__));
+
+struct btrfs_dir_item {
+	struct btrfs_key location;
+	__u64 transid;
+	__u16 data_len;
+	__u16 name_len;
+	__u8 type;
+} __attribute__ ((__packed__));
+
+#define BTRFS_ROOT_SUBVOL_RDONLY	(1ULL << 0)
+
+/*
+ * Internal in-memory flag that a subvolume has been marked for deletion but
+ * still visible as a directory
+ */
+#define BTRFS_ROOT_SUBVOL_DEAD		(1ULL << 48)
+
+struct btrfs_root_item {
+	struct btrfs_inode_item inode;
+	__u64 generation;
+	__u64 root_dirid;
+	__u64 bytenr;
+	__u64 byte_limit;
+	__u64 bytes_used;
+	__u64 last_snapshot;
+	__u64 flags;
+	__u32 refs;
+	struct btrfs_key drop_progress;
+	__u8 drop_level;
+	__u8 level;
+
+	/*
+	 * The following fields appear after subvol_uuids+subvol_times
+	 * were introduced.
+	 */
+
+	/*
+	 * This generation number is used to test if the new fields are valid
+	 * and up to date while reading the root item. Every time the root item
+	 * is written out, the "generation" field is copied into this field. If
+	 * anyone ever mounted the fs with an older kernel, we will have
+	 * mismatching generation values here and thus must invalidate the
+	 * new fields. See btrfs_update_root and btrfs_find_last_root for
+	 * details.
+	 * the offset of generation_v2 is also used as the start for the memset
+	 * when invalidating the fields.
+	 */
+	__u64 generation_v2;
+	__u8 uuid[BTRFS_UUID_SIZE];
+	__u8 parent_uuid[BTRFS_UUID_SIZE];
+	__u8 received_uuid[BTRFS_UUID_SIZE];
+	__u64 ctransid; /* updated when an inode changes */
+	__u64 otransid; /* trans when created */
+	__u64 stransid; /* trans when sent. non-zero for received subvol */
+	__u64 rtransid; /* trans when received. non-zero for received subvol */
+	struct btrfs_timespec ctime;
+	struct btrfs_timespec otime;
+	struct btrfs_timespec stime;
+	struct btrfs_timespec rtime;
+	__u64 reserved[8]; /* for future */
+} __attribute__ ((__packed__));
+
+/*
+ * this is used for both forward and backward root refs
+ */
+struct btrfs_root_ref {
+	__u64 dirid;
+	__u64 sequence;
+	__u16 name_len;
+} __attribute__ ((__packed__));
+
+#define BTRFS_FILE_EXTENT_INLINE 0
+#define BTRFS_FILE_EXTENT_REG 1
+#define BTRFS_FILE_EXTENT_PREALLOC 2
+
+enum btrfs_compression_type {
+	BTRFS_COMPRESS_NONE  = 0,
+	BTRFS_COMPRESS_ZLIB  = 1,
+	BTRFS_COMPRESS_LZO   = 2,
+	BTRFS_COMPRESS_TYPES = 2,
+	BTRFS_COMPRESS_LAST  = 3,
+};
+
+struct btrfs_file_extent_item {
+	/*
+	 * transaction id that created this extent
+	 */
+	__u64 generation;
+	/*
+	 * max number of bytes to hold this extent in ram
+	 * when we split a compressed extent we can't know how big
+	 * each of the resulting pieces will be.  So, this is
+	 * an upper limit on the size of the extent in ram instead of
+	 * an exact limit.
+	 */
+	__u64 ram_bytes;
+
+	/*
+	 * 32 bits for the various ways we might encode the data,
+	 * including compression and encryption.  If any of these
+	 * are set to something a given disk format doesn't understand
+	 * it is treated like an incompat flag for reading and writing,
+	 * but not for stat.
+	 */
+	__u8 compression;
+	__u8 encryption;
+	__u16 other_encoding; /* spare for later use */
+
+	/* are we inline data or a real extent? */
+	__u8 type;
+
+	/*
+	 * disk space consumed by the extent, checksum blocks are included
+	 * in these numbers
+	 *
+	 * At this offset in the structure, the inline extent data start.
+	 */
+	__u64 disk_bytenr;
+	__u64 disk_num_bytes;
+	/*
+	 * the logical offset in file blocks (no csums)
+	 * this extent record is for.  This allows a file extent to point
+	 * into the middle of an existing extent on disk, sharing it
+	 * between two snapshots (useful if some bytes in the middle of the
+	 * extent have changed
+	 */
+	__u64 offset;
+	/*
+	 * the logical number of file blocks (no csums included).  This
+	 * always reflects the size uncompressed and without encoding.
+	 */
+	__u64 num_bytes;
+
+} __attribute__ ((__packed__));
+
+struct btrfs_csum_item {
+	__u8 csum;
+} __attribute__ ((__packed__));
+
+/* different types of block groups (and chunks) */
+#define BTRFS_BLOCK_GROUP_DATA		(1ULL << 0)
+#define BTRFS_BLOCK_GROUP_SYSTEM	(1ULL << 1)
+#define BTRFS_BLOCK_GROUP_METADATA	(1ULL << 2)
+#define BTRFS_BLOCK_GROUP_RAID0		(1ULL << 3)
+#define BTRFS_BLOCK_GROUP_RAID1		(1ULL << 4)
+#define BTRFS_BLOCK_GROUP_DUP		(1ULL << 5)
+#define BTRFS_BLOCK_GROUP_RAID10	(1ULL << 6)
+#define BTRFS_BLOCK_GROUP_RAID5         (1ULL << 7)
+#define BTRFS_BLOCK_GROUP_RAID6         (1ULL << 8)
+#define BTRFS_BLOCK_GROUP_RESERVED	(BTRFS_AVAIL_ALLOC_BIT_SINGLE | \
+					 BTRFS_SPACE_INFO_GLOBAL_RSV)
+
+enum btrfs_raid_types {
+	BTRFS_RAID_RAID10,
+	BTRFS_RAID_RAID1,
+	BTRFS_RAID_DUP,
+	BTRFS_RAID_RAID0,
+	BTRFS_RAID_SINGLE,
+	BTRFS_RAID_RAID5,
+	BTRFS_RAID_RAID6,
+	BTRFS_NR_RAID_TYPES
+};
+
+#define BTRFS_BLOCK_GROUP_TYPE_MASK	(BTRFS_BLOCK_GROUP_DATA |    \
+					 BTRFS_BLOCK_GROUP_SYSTEM |  \
+					 BTRFS_BLOCK_GROUP_METADATA)
+
+#define BTRFS_BLOCK_GROUP_PROFILE_MASK	(BTRFS_BLOCK_GROUP_RAID0 |   \
+					 BTRFS_BLOCK_GROUP_RAID1 |   \
+					 BTRFS_BLOCK_GROUP_RAID5 |   \
+					 BTRFS_BLOCK_GROUP_RAID6 |   \
+					 BTRFS_BLOCK_GROUP_DUP |     \
+					 BTRFS_BLOCK_GROUP_RAID10)
+#define BTRFS_BLOCK_GROUP_RAID56_MASK	(BTRFS_BLOCK_GROUP_RAID5 |   \
+					 BTRFS_BLOCK_GROUP_RAID6)
+
+/*
+ * We need a bit for restriper to be able to tell when chunks of type
+ * SINGLE are available.  This "extended" profile format is used in
+ * fs_info->avail_*_alloc_bits (in-memory) and balance item fields
+ * (on-disk).  The corresponding on-disk bit in chunk.type is reserved
+ * to avoid remappings between two formats in future.
+ */
+#define BTRFS_AVAIL_ALLOC_BIT_SINGLE	(1ULL << 48)
+
+/*
+ * A fake block group type that is used to communicate global block reserve
+ * size to userspace via the SPACE_INFO ioctl.
+ */
+#define BTRFS_SPACE_INFO_GLOBAL_RSV	(1ULL << 49)
+
+#define BTRFS_EXTENDED_PROFILE_MASK	(BTRFS_BLOCK_GROUP_PROFILE_MASK | \
+					 BTRFS_AVAIL_ALLOC_BIT_SINGLE)
+
+#endif /* __BTRFS_BTRFS_TREE_H__ */
diff --git a/fs/btrfs/chunk-map.c b/fs/btrfs/chunk-map.c
new file mode 100644
index 0000000..48407f3
--- /dev/null
+++ b/fs/btrfs/chunk-map.c
@@ -0,0 +1,178 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "btrfs.h"
+#include <malloc.h>
+
+struct chunk_map_item {
+	struct rb_node node;
+	u64 logical;
+	u64 length;
+	u64 physical;
+};
+
+static int add_chunk_mapping(struct btrfs_key *key, struct btrfs_chunk *chunk)
+{
+	struct btrfs_stripe *stripe;
+	u64 block_profile = chunk->type & BTRFS_BLOCK_GROUP_PROFILE_MASK;
+	struct rb_node **new = &(btrfs_info.chunks_root.rb_node), *prnt = NULL;
+	struct chunk_map_item *map_item;
+
+	if (block_profile && block_profile != BTRFS_BLOCK_GROUP_DUP) {
+		printf("%s: unsupported chunk profile %llu\n", __func__,
+		       block_profile);
+		return -1;
+	} else if (!chunk->length) {
+		printf("%s: zero length chunk\n", __func__);
+		return -1;
+	}
+
+	stripe = &chunk->stripe;
+	btrfs_stripe_to_cpu(stripe);
+
+	while (*new) {
+		struct chunk_map_item *this;
+
+		this = rb_entry(*new, struct chunk_map_item, node);
+
+		prnt = *new;
+		if (key->offset < this->logical) {
+			new = &((*new)->rb_left);
+		} else if (key->offset > this->logical) {
+			new = &((*new)->rb_right);
+		} else {
+			debug("%s: Logical address %llu already in map!\n",
+			      __func__, key->offset);
+			return 0;
+		}
+	}
+
+	map_item = malloc(sizeof(struct chunk_map_item));
+	if (!map_item)
+		return -1;
+
+	map_item->logical = key->offset;
+	map_item->length = chunk->length;
+	map_item->physical = le64_to_cpu(chunk->stripe.offset);
+	rb_link_node(&map_item->node, prnt, new);
+	rb_insert_color(&map_item->node, &btrfs_info.chunks_root);
+
+	debug("%s: Mapping %llu to %llu\n", __func__, map_item->logical,
+	      map_item->physical);
+
+	return 0;
+}
+
+u64 btrfs_map_logical_to_physical(u64 logical)
+{
+	struct rb_node *node = btrfs_info.chunks_root.rb_node;
+
+	while (node) {
+		struct chunk_map_item *item;
+
+		item = rb_entry(node, struct chunk_map_item, node);
+
+		if (item->logical > logical)
+			node = node->rb_left;
+		else if (logical > item->logical + item->length)
+			node = node->rb_right;
+		else
+			return item->physical + logical - item->logical;
+	}
+
+	printf("%s: Cannot map logical address %llu to physical\n", __func__,
+	       logical);
+
+	return -1ULL;
+}
+
+void btrfs_chunk_map_exit(void)
+{
+	struct rb_node *now, *next;
+	struct chunk_map_item *item;
+
+	for (now = rb_first_postorder(&btrfs_info.chunks_root); now; now = next)
+	{
+		item = rb_entry(now, struct chunk_map_item, node);
+		next = rb_next_postorder(now);
+		free(item);
+	}
+}
+
+int btrfs_chunk_map_init(void)
+{
+	u8 sys_chunk_array_copy[sizeof(btrfs_info.sb.sys_chunk_array)];
+	u8 * const start = sys_chunk_array_copy;
+	u8 * const end = start + btrfs_info.sb.sys_chunk_array_size;
+	u8 *cur;
+	struct btrfs_key *key;
+	struct btrfs_chunk *chunk;
+
+	btrfs_info.chunks_root = RB_ROOT;
+
+	memcpy(sys_chunk_array_copy, btrfs_info.sb.sys_chunk_array,
+	       sizeof(sys_chunk_array_copy));
+
+	for (cur = start; cur < end;) {
+		key = (struct btrfs_key *) cur;
+		cur += sizeof(struct btrfs_key);
+		chunk = (struct btrfs_chunk *) cur;
+
+		btrfs_key_to_cpu(key);
+		btrfs_chunk_to_cpu(chunk);
+
+		if (key->type != BTRFS_CHUNK_ITEM_KEY) {
+			printf("%s: invalid key type %u\n", __func__,
+			       key->type);
+			return -1;
+		}
+
+		if (add_chunk_mapping(key, chunk))
+			return -1;
+
+		cur += sizeof(struct btrfs_chunk);
+		cur += sizeof(struct btrfs_stripe) * (chunk->num_stripes - 1);
+	}
+
+	return 0;
+}
+
+int btrfs_read_chunk_tree(void)
+{
+	struct btrfs_path path;
+	struct btrfs_key key, *found_key;
+	struct btrfs_chunk *chunk;
+	int res;
+
+	key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
+	key.type = BTRFS_CHUNK_ITEM_KEY;
+	key.offset = 0;
+
+	if (btrfs_search_tree(&btrfs_info.chunk_root, &key, &path))
+		return -1;
+
+	do {
+		found_key = btrfs_path_leaf_key(&path);
+		if (btrfs_comp_keys_type(&key, found_key))
+			break;
+
+		chunk = btrfs_path_item_ptr(&path, struct btrfs_chunk);
+		btrfs_chunk_to_cpu(chunk);
+		if (add_chunk_mapping(found_key, chunk)) {
+			res = -1;
+			break;
+		}
+	} while (!(res = btrfs_next_slot(&path)));
+
+	btrfs_free_path(&path);
+
+	if (res < 0)
+		return -1;
+
+	return 0;
+}
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
new file mode 100644
index 0000000..a59ff5a
--- /dev/null
+++ b/fs/btrfs/compression.c
@@ -0,0 +1,134 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "btrfs.h"
+#include <linux/lzo.h>
+#include <u-boot/zlib.h>
+
+static u32 decompress_lzo(const u8 *cbuf, u32 clen, u8 *dbuf, u32 dlen)
+{
+	u32 tot_len, in_len, res;
+	size_t out_len;
+	int ret;
+
+	if (clen < 4)
+		return -1;
+
+	tot_len = le32_to_cpu(*(u32 *) cbuf);
+	cbuf += 4;
+	clen -= 4;
+	tot_len -= 4;
+
+	if (tot_len == 0 && dlen)
+		return -1;
+	if (tot_len < 4)
+		return -1;
+
+	res = 0;
+
+	while (tot_len > 4) {
+		in_len = le32_to_cpu(*(u32 *) cbuf);
+		cbuf += 4;
+		clen -= 4;
+
+		if (in_len > clen || tot_len < 4 + in_len)
+			return -1;
+
+		tot_len -= 4 + in_len;
+
+		out_len = dlen;
+		ret = lzo1x_decompress_safe(cbuf, in_len, dbuf, &out_len);
+		if (ret != LZO_E_OK)
+			return -1;
+
+		cbuf += in_len;
+		clen -= in_len;
+		dbuf += out_len;
+		dlen -= out_len;
+
+		res += out_len;
+	}
+
+	return res;
+}
+
+/* from zutil.h */
+#define PRESET_DICT 0x20
+
+static u32 decompress_zlib(const u8 *_cbuf, u32 clen, u8 *dbuf, u32 dlen)
+{
+	int wbits = MAX_WBITS, ret = -1;
+	z_stream stream;
+	u8 *cbuf;
+	u32 res;
+
+	memset(&stream, 0, sizeof(stream));
+
+	cbuf = (u8 *) _cbuf;
+
+	stream.total_in = 0;
+
+	stream.next_out = dbuf;
+	stream.avail_out = dlen;
+	stream.total_out = 0;
+
+	/* skip adler32 check if deflate and no dictionary */
+	if (clen > 2 && !(cbuf[1] & PRESET_DICT) &&
+	    ((cbuf[0] & 0x0f) == Z_DEFLATED) &&
+	    !(((cbuf[0] << 8) + cbuf[1]) % 31)) {
+		wbits = -((cbuf[0] >> 4) + 8);
+		cbuf += 2;
+		clen -= 2;
+	}
+
+	if (Z_OK != inflateInit2(&stream, wbits))
+		return -1;
+
+	while (stream.total_in < clen) {
+		stream.next_in = cbuf + stream.total_in;
+		stream.avail_in = min((u32) (clen - stream.total_in),
+				      (u32) btrfs_info.sb.sectorsize);
+
+		ret = inflate(&stream, Z_NO_FLUSH);
+		if (ret != Z_OK)
+			break;
+	}
+
+	res = stream.total_out;
+	inflateEnd(&stream);
+
+	if (ret != Z_STREAM_END)
+		return -1;
+
+	return res;
+}
+
+u32 btrfs_decompress(u8 type, const char *c, u32 clen, char *d, u32 dlen)
+{
+	u32 res;
+	const u8 *cbuf;
+	u8 *dbuf;
+
+	cbuf = (const u8 *) c;
+	dbuf = (u8 *) d;
+
+	switch (type) {
+	case BTRFS_COMPRESS_NONE:
+		res = dlen < clen ? dlen : clen;
+		memcpy(dbuf, cbuf, res);
+		return res;
+	case BTRFS_COMPRESS_ZLIB:
+		return decompress_zlib(cbuf, clen, dbuf, dlen);
+	case BTRFS_COMPRESS_LZO:
+		return decompress_lzo(cbuf, clen, dbuf, dlen);
+	default:
+		printf("%s: Unsupported compression in extent: %i\n", __func__,
+		       type);
+		return -1;
+	}
+}
diff --git a/fs/btrfs/conv-funcs.h b/fs/btrfs/conv-funcs.h
new file mode 100644
index 0000000..f2e7944
--- /dev/null
+++ b/fs/btrfs/conv-funcs.h
@@ -0,0 +1,176 @@
+/*
+ * Functions to convert BTRFS structures from disk to CPU endianness and back.
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __BTRFS_CONV_FUNCS_H__
+#define __BTRFS_CONV_FUNCS_H__
+
+#include "ctree.h"
+#include <u-boot/variadic-macro.h>
+#include <asm/byteorder.h>
+
+/* We are using variadic macros and C11 _Generic to achieve compact code.
+
+   We want to define macro DEFINE_CONV(x, ...), where the first argument is the
+   name of the structure for which it shall define conversion functions (the
+   names of the functions shall be x_to_cpu and x_to_disk), and the other
+   arguments are names of the members on which the functions shall do
+   endianness conversion. */
+
+#if defined(__LITTLE_ENDIAN)
+
+/* If the target machine is little endian, the conversion functions do
+   nothing, since the on disk format is little endian. */
+
+# define DEFINE_CONV(n,...)					\
+	static inline struct n *n##_to_disk(struct n * r)	\
+	{							\
+		return r;					\
+	}							\
+	static inline struct n *n##_to_cpu(struct n * r)	\
+	{							\
+		return r;					\
+	}
+
+# define DEFINE_CONV_ALT(n,a,...)				\
+	static inline struct n *n##_to_disk_##a(struct n * r)	\
+	{							\
+		return r;					\
+	}							\
+	static inline struct n *n##_to_cpu_##a(struct n * r)	\
+	{							\
+		return r;					\
+	}
+
+#else /* !defined(__LITTLE_ENDIAN) */
+
+/* Some structures contain not only scalar members, but compound types as well
+   (for example, struct btrfs_inode_item contains members of type struct
+   btrfs_timespec.
+
+   For these members we want to call the conversion function recursively, so
+   first we declare the functions taking pointers to this types (these function
+   will be defined later by the DEFINE_CONV macro) and then we define
+   correspond functions taking non-pointers, so that they can be used in the
+   expansion of the _Generic. */
+# define DEFINE_CONV_FOR_STRUCT(n)				\
+	static inline struct n * n##_to_disk(struct n *);	\
+	static inline struct n * n##_to_cpu(struct n *);	\
+	static inline struct n n##_to_disk_v(struct n x) {	\
+		return *n##_to_disk(&x);			\
+	}							\
+	static inline struct n n##_to_cpu_v(struct n x) {	\
+		return *n##_to_cpu(&x);				\
+	}
+
+DEFINE_CONV_FOR_STRUCT(btrfs_key)
+DEFINE_CONV_FOR_STRUCT(btrfs_stripe)
+DEFINE_CONV_FOR_STRUCT(btrfs_timespec)
+DEFINE_CONV_FOR_STRUCT(btrfs_inode_item)
+DEFINE_CONV_FOR_STRUCT(btrfs_root_backup)
+DEFINE_CONV_FOR_STRUCT(btrfs_dev_item)
+
+/* Now define the _Generic for both CPU to LE and LE to CPU */
+# define DEFINE_CONV_CPU_TO_LE(x)					\
+	(d->x) = _Generic((d->x),					\
+		__u16: cpu_to_le16,					\
+		__u32: cpu_to_le32,					\
+		__u64: cpu_to_le64,					\
+		struct btrfs_key: btrfs_key_to_disk_v,			\
+		struct btrfs_stripe: btrfs_stripe_to_disk_v,		\
+		struct btrfs_timespec: btrfs_timespec_to_disk_v,	\
+		struct btrfs_inode_item: btrfs_inode_item_to_disk_v,	\
+		struct btrfs_root_backup: btrfs_root_backup_to_disk_v,	\
+		struct btrfs_dev_item: btrfs_dev_item_to_disk_v		\
+		)((d->x));
+
+# define DEFINE_CONV_LE_TO_CPU(x)					\
+	(d->x) = _Generic((d->x),					\
+		__u16: le16_to_cpu,					\
+		__u32: le32_to_cpu,					\
+		__u64: le64_to_cpu,					\
+		struct btrfs_key: btrfs_key_to_cpu_v,			\
+		struct btrfs_stripe: btrfs_stripe_to_cpu_v,		\
+		struct btrfs_timespec: btrfs_timespec_to_cpu_v,		\
+		struct btrfs_inode_item: btrfs_inode_item_to_cpu_v,	\
+		struct btrfs_root_backup: btrfs_root_backup_to_cpu_v,	\
+		struct btrfs_dev_item: btrfs_dev_item_to_cpu_v		\
+		)((d->x));
+
+# define DEFINE_CONV_ONE(t,n,m,...)			\
+	static inline struct t * n(struct t * d) {	\
+		CALL_MACRO_FOR_EACH(m, ##__VA_ARGS__)	\
+		return d;				\
+	}
+
+/* Finally define the DEFINE_CONV macro */
+# define DEFINE_CONV(n,...) \
+	DEFINE_CONV_ONE(n,n##_to_disk,DEFINE_CONV_CPU_TO_LE,##__VA_ARGS__) \
+	DEFINE_CONV_ONE(n,n##_to_cpu,DEFINE_CONV_LE_TO_CPU,##__VA_ARGS__)
+
+# define DEFINE_CONV_ALT(n,a,...) \
+	DEFINE_CONV_ONE(n,n##_to_disk_##a,DEFINE_CONV_CPU_TO_LE, \
+		##__VA_ARGS__) \
+	DEFINE_CONV_ONE(n,n##_to_cpu_##a,DEFINE_CONV_LE_TO_CPU,##__VA_ARGS__)
+
+#endif /* !defined(__LITTLE_ENDIAN) */
+
+DEFINE_CONV(btrfs_key, objectid, offset)
+DEFINE_CONV(btrfs_dev_item, devid, total_bytes, bytes_used, io_align, io_width,
+	    sector_size, type, generation, start_offset, dev_group)
+DEFINE_CONV(btrfs_stripe, devid, offset)
+DEFINE_CONV(btrfs_chunk, length, owner, stripe_len, type, io_align, io_width,
+	    sector_size, num_stripes, sub_stripes)
+DEFINE_CONV(btrfs_free_space_entry, offset, bytes)
+DEFINE_CONV(btrfs_free_space_header, location, generation, num_entries,
+	    num_bitmaps)
+DEFINE_CONV(btrfs_extent_item, refs, generation, flags)
+DEFINE_CONV(btrfs_tree_block_info, key)
+DEFINE_CONV(btrfs_extent_data_ref, root, objectid, offset, count)
+DEFINE_CONV(btrfs_shared_data_ref, count)
+DEFINE_CONV(btrfs_extent_inline_ref, offset)
+DEFINE_CONV(btrfs_dev_extent, chunk_tree, chunk_objectid, chunk_offset, length)
+DEFINE_CONV(btrfs_inode_ref, index, name_len)
+DEFINE_CONV(btrfs_inode_extref, parent_objectid, index, name_len)
+DEFINE_CONV(btrfs_timespec, sec, nsec)
+DEFINE_CONV(btrfs_inode_item, generation, transid, size, nbytes, block_group,
+	    nlink, uid, gid, mode, rdev, flags, sequence, atime, ctime, mtime,
+	    otime)
+DEFINE_CONV(btrfs_dir_log_item, end)
+DEFINE_CONV(btrfs_dir_item, location, transid, data_len, name_len)
+DEFINE_CONV(btrfs_root_item, inode, generation, root_dirid, bytenr, byte_limit,
+	    bytes_used, last_snapshot, flags, refs, drop_progress,
+	    generation_v2, ctransid, otransid, stransid, rtransid, ctime,
+	    otime, stime, rtime)
+DEFINE_CONV(btrfs_root_ref, dirid, sequence, name_len)
+DEFINE_CONV(btrfs_file_extent_item, generation, ram_bytes, other_encoding,
+	    disk_bytenr, disk_num_bytes, offset, num_bytes)
+DEFINE_CONV_ALT(btrfs_file_extent_item, inl, generation, ram_bytes,
+		other_encoding)
+DEFINE_CONV(btrfs_dev_replace_item, src_devid, cursor_left, cursor_right,
+	    cont_reading_from_srcdev_mode, replace_state, time_started,
+	    time_stopped, num_write_errors, num_uncorrectable_read_errors)
+DEFINE_CONV(btrfs_block_group_item, used, chunk_objectid, flags)
+DEFINE_CONV(btrfs_free_space_info, extent_count, flags)
+
+DEFINE_CONV(btrfs_header, bytenr, flags, generation, owner, nritems)
+DEFINE_CONV(btrfs_root_backup, tree_root, tree_root_gen, chunk_root,
+	    chunk_root_gen, extent_root, extent_root_gen, fs_root, fs_root_gen,
+	    dev_root, dev_root_gen, csum_root, csum_root_gen, total_bytes,
+	    bytes_used, num_devices)
+DEFINE_CONV(btrfs_super_block, bytenr, flags, magic, generation, root,
+	    chunk_root, log_root, log_root_transid, total_bytes, bytes_used,
+	    root_dir_objectid, num_devices, sectorsize, nodesize,
+	    __unused_leafsize, stripesize, sys_chunk_array_size,
+	    chunk_root_generation, compat_flags, compat_ro_flags,
+	    incompat_flags, csum_type, dev_item, cache_generation,
+	    uuid_tree_generation, super_roots[0], super_roots[1], 
+	    super_roots[2], super_roots[3])
+DEFINE_CONV(btrfs_item, key, offset, size)
+DEFINE_CONV(btrfs_key_ptr, key, blockptr, generation)
+
+#endif /* __BTRFS_CONV_FUNCS_H__ */
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
new file mode 100644
index 0000000..b13ecb9
--- /dev/null
+++ b/fs/btrfs/ctree.c
@@ -0,0 +1,289 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "btrfs.h"
+#include <malloc.h>
+
+int btrfs_comp_keys(struct btrfs_key *a, struct btrfs_key *b)
+{
+	if (a->objectid > b->objectid)
+		return 1;
+	if (a->objectid < b->objectid)
+		return -1;
+	if (a->type > b->type)
+		return 1;
+	if (a->type < b->type)
+		return -1;
+	if (a->offset > b->offset)
+		return 1;
+	if (a->offset < b->offset)
+		return -1;
+	return 0;
+}
+
+int btrfs_comp_keys_type(struct btrfs_key *a, struct btrfs_key *b)
+{
+	if (a->objectid > b->objectid)
+		return 1;
+	if (a->objectid < b->objectid)
+		return -1;
+	if (a->type > b->type)
+		return 1;
+	if (a->type < b->type)
+		return -1;
+	return 0;
+}
+
+static int generic_bin_search(void *addr, int item_size, struct btrfs_key *key,
+			      int max, int *slot)
+{
+	int low = 0, high = max, mid, ret;
+	struct btrfs_key *tmp;
+
+	if (0) {
+		int i;
+		printf("\tsearching %llu %i\n", key->objectid, key->type);
+		for (i = 0; i < max; ++i) {
+			tmp = (struct btrfs_key *) ((u8 *) addr + i*item_size);
+			printf("\t\t%llu %i\n", tmp->objectid, tmp->type);
+		}
+		printf("\n");
+	}
+
+	while (low < high) {
+		mid = (low + high) / 2;
+
+		tmp = (struct btrfs_key *) ((u8 *) addr + mid*item_size);
+		ret = btrfs_comp_keys(tmp, key);
+
+		if (ret < 0) {
+			low = mid + 1;
+		} else if (ret > 0) {
+			high = mid;
+		} else {
+			*slot = mid;
+			return 0;
+		}
+	}
+
+	*slot = low;
+	return 1;
+}
+
+int btrfs_bin_search(union btrfs_tree_node *p, struct btrfs_key *key,
+		     int *slot)
+{
+	void *addr;
+	unsigned long size;
+
+	if (p->header.level) {
+		addr = p->node.ptrs;
+		size = sizeof(struct btrfs_key_ptr);
+	} else {
+		addr = p->leaf.items;
+		size = sizeof(struct btrfs_item);
+	}
+
+	return generic_bin_search(addr, size, key, p->header.nritems, slot);
+}
+
+static void clear_path(struct btrfs_path *p)
+{
+	int i;
+
+	for (i = 0; i < BTRFS_MAX_LEVEL; ++i) {
+		p->nodes[i] = NULL;
+		p->slots[i] = 0;
+	}
+}
+
+void btrfs_free_path(struct btrfs_path *p)
+{
+	int i;
+
+	for (i = 0; i < BTRFS_MAX_LEVEL; ++i) {
+		if (p->nodes[i])
+			free(p->nodes[i]);
+	}
+
+	clear_path(p);
+}
+
+static int read_tree_node(u64 physical, union btrfs_tree_node **buf)
+{
+	struct btrfs_header hdr;
+	unsigned long size, offset = sizeof(hdr);
+	union btrfs_tree_node *res;
+	u32 i;
+
+	if (!btrfs_devread(physical, sizeof(hdr), &hdr))
+		return -1;
+
+	btrfs_header_to_cpu(&hdr);
+
+	if (hdr.level)
+		size = sizeof(struct btrfs_node)
+		       + hdr.nritems * sizeof(struct btrfs_key_ptr);
+	else
+		size = btrfs_info.sb.nodesize;
+
+	res = malloc(size);
+	if (!res) {
+		debug("%s: malloc failed\n", __func__);
+		return -1;
+	}
+
+	if (!btrfs_devread(physical + offset, size - offset,
+			   ((u8 *) res) + offset)) {
+		free(res);
+		return -1;
+	}
+
+	res->header = hdr;
+	if (hdr.level)
+		for (i = 0; i < hdr.nritems; ++i)
+			btrfs_key_ptr_to_cpu(&res->node.ptrs[i]);
+	else
+		for (i = 0; i < hdr.nritems; ++i)
+			btrfs_item_to_cpu(&res->leaf.items[i]);
+
+	*buf = res;
+
+	return 0;
+}
+
+int btrfs_search_tree(const struct btrfs_root *root, struct btrfs_key *key,
+		      struct btrfs_path *p)
+{
+	u8 lvl, prev_lvl;
+	int i, slot, ret;
+	u64 logical, physical;
+	union btrfs_tree_node *buf;
+
+	clear_path(p);
+
+	logical = root->bytenr;
+
+	for (i = 0; i < BTRFS_MAX_LEVEL; ++i) {
+		physical = btrfs_map_logical_to_physical(logical);
+		if (physical == -1ULL)
+			goto err;
+
+		if (read_tree_node(physical, &buf))
+			goto err;
+
+		lvl = buf->header.level;
+		if (i && prev_lvl != lvl + 1) {
+			printf("%s: invalid level in header at %llu\n",
+			       __func__, logical);
+			goto err;
+		}
+		prev_lvl = lvl;
+
+		ret = btrfs_bin_search(buf, key, &slot);
+		if (ret < 0)
+			goto err;
+		if (ret && slot > 0 && lvl)
+			slot -= 1;
+
+		p->slots[lvl] = slot;
+		p->nodes[lvl] = buf;
+
+		if (lvl)
+			logical = buf->node.ptrs[slot].blockptr;
+		else
+			break;
+	}
+
+	return 0;
+err:
+	btrfs_free_path(p);
+	return -1;
+}
+
+static int jump_leaf(struct btrfs_path *path, int dir)
+{
+	struct btrfs_path p;
+	u32 slot;
+	int level = 1, from_level, i;
+
+	dir = dir >= 0 ? 1 : -1;
+
+	p = *path;
+
+	while (level < BTRFS_MAX_LEVEL) {
+		if (!p.nodes[level])
+			return 1;
+
+		slot = p.slots[level];
+		if ((dir > 0 && slot + dir >= p.nodes[level]->header.nritems)
+		    || (dir < 0 && !slot))
+			level++;
+		else
+			break;
+	}
+
+	if (level == BTRFS_MAX_LEVEL)
+		return 1;
+
+	p.slots[level] = slot + dir;
+	level--;
+	from_level = level;
+
+	while (level >= 0) {
+		u64 logical, physical;
+
+		slot = p.slots[level + 1];
+		logical = p.nodes[level + 1]->node.ptrs[slot].blockptr;
+		physical = btrfs_map_logical_to_physical(logical);
+		if (physical == -1ULL)
+			goto err;
+
+		if (read_tree_node(physical, &p.nodes[level]))
+			goto err;
+
+		if (dir > 0)
+			p.slots[level] = 0;
+		else
+			p.slots[level] = p.nodes[level]->header.nritems - 1;
+		level--;
+	}
+
+	/* Free rewritten nodes in path */
+	for (i = 0; i <= from_level; ++i)
+		free(path->nodes[i]);
+
+	*path = p;
+	return 0;
+
+err:
+	/* Free rewritten nodes in p */
+	for (i = level + 1; i <= from_level; ++i)
+		free(p.nodes[i]);
+	return -1;
+}
+
+int btrfs_prev_slot(struct btrfs_path *p)
+{
+	if (!p->slots[0])
+		return jump_leaf(p, -1);
+
+	p->slots[0]--;
+	return 0;
+}
+
+int btrfs_next_slot(struct btrfs_path *p)
+{
+	struct btrfs_leaf *leaf = &p->nodes[0]->leaf;
+
+	if (p->slots[0] >= leaf->header.nritems)
+		return jump_leaf(p, 1);
+
+	p->slots[0]++;
+	return 0;
+}
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
new file mode 100644
index 0000000..39f4473
--- /dev/null
+++ b/fs/btrfs/ctree.h
@@ -0,0 +1,334 @@
+/*
+ * From linux/fs/btrfs/ctree.h
+ *   Copyright (C) 2007,2008 Oracle.  All rights reserved.
+ *
+ * Modified in 2017 by Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __BTRFS_CTREE_H__
+#define __BTRFS_CTREE_H__
+
+#include <common.h>
+#include <compiler.h>
+#include "btrfs_tree.h"
+
+#define BTRFS_MAGIC 0x4D5F53665248425FULL /* ascii _BHRfS_M, no null */
+
+#define BTRFS_MAX_MIRRORS 3
+
+#define BTRFS_MAX_LEVEL 8
+
+#define BTRFS_COMPAT_EXTENT_TREE_V0
+
+/*
+ * the max metadata block size.  This limit is somewhat artificial,
+ * but the memmove costs go through the roof for larger blocks.
+ */
+#define BTRFS_MAX_METADATA_BLOCKSIZE 65536
+
+/*
+ * we can actually store much bigger names, but lets not confuse the rest
+ * of linux
+ */
+#define BTRFS_NAME_LEN 255
+
+/*
+ * Theoretical limit is larger, but we keep this down to a sane
+ * value. That should limit greatly the possibility of collisions on
+ * inode ref items.
+ */
+#define BTRFS_LINK_MAX 65535U
+
+static const int btrfs_csum_sizes[] = { 4 };
+
+/* four bytes for CRC32 */
+#define BTRFS_EMPTY_DIR_SIZE 0
+
+/* ioprio of readahead is set to idle */
+#define BTRFS_IOPRIO_READA (IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0))
+
+#define BTRFS_DIRTY_METADATA_THRESH	SZ_32M
+
+#define BTRFS_MAX_EXTENT_SIZE SZ_128M
+
+/*
+ * File system states
+ */
+#define BTRFS_FS_STATE_ERROR		0
+#define BTRFS_FS_STATE_REMOUNTING	1
+#define BTRFS_FS_STATE_TRANS_ABORTED	2
+#define BTRFS_FS_STATE_DEV_REPLACING	3
+#define BTRFS_FS_STATE_DUMMY_FS_INFO	4
+
+#define BTRFS_BACKREF_REV_MAX		256
+#define BTRFS_BACKREF_REV_SHIFT		56
+#define BTRFS_BACKREF_REV_MASK		(((u64)BTRFS_BACKREF_REV_MAX - 1) << \
+					 BTRFS_BACKREF_REV_SHIFT)
+
+#define BTRFS_OLD_BACKREF_REV		0
+#define BTRFS_MIXED_BACKREF_REV		1
+
+/*
+ * every tree block (leaf or node) starts with this header.
+ */
+struct btrfs_header {
+	/* these first four must match the super block */
+	__u8 csum[BTRFS_CSUM_SIZE];
+	__u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
+	__u64 bytenr; /* which block this node is supposed to live in */
+	__u64 flags;
+
+	/* allowed to be different from the super from here on down */
+	__u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
+	__u64 generation;
+	__u64 owner;
+	__u32 nritems;
+	__u8 level;
+} __attribute__ ((__packed__));
+
+/*
+ * this is a very generous portion of the super block, giving us
+ * room to translate 14 chunks with 3 stripes each.
+ */
+#define BTRFS_SYSTEM_CHUNK_ARRAY_SIZE 2048
+
+/*
+ * just in case we somehow lose the roots and are not able to mount,
+ * we store an array of the roots from previous transactions
+ * in the super.
+ */
+#define BTRFS_NUM_BACKUP_ROOTS 4
+struct btrfs_root_backup {
+	__u64 tree_root;
+	__u64 tree_root_gen;
+
+	__u64 chunk_root;
+	__u64 chunk_root_gen;
+
+	__u64 extent_root;
+	__u64 extent_root_gen;
+
+	__u64 fs_root;
+	__u64 fs_root_gen;
+
+	__u64 dev_root;
+	__u64 dev_root_gen;
+
+	__u64 csum_root;
+	__u64 csum_root_gen;
+
+	__u64 total_bytes;
+	__u64 bytes_used;
+	__u64 num_devices;
+	/* future */
+	__u64 unused_64[4];
+
+	__u8 tree_root_level;
+	__u8 chunk_root_level;
+	__u8 extent_root_level;
+	__u8 fs_root_level;
+	__u8 dev_root_level;
+	__u8 csum_root_level;
+	/* future and to align */
+	__u8 unused_8[10];
+} __attribute__ ((__packed__));
+
+/*
+ * the super block basically lists the main trees of the FS
+ * it currently lacks any block count etc etc
+ */
+struct btrfs_super_block {
+	__u8 csum[BTRFS_CSUM_SIZE];
+	/* the first 4 fields must match struct btrfs_header */
+	__u8 fsid[BTRFS_FSID_SIZE];    /* FS specific uuid */
+	__u64 bytenr; /* this block number */
+	__u64 flags;
+
+	/* allowed to be different from the btrfs_header from here own down */
+	__u64 magic;
+	__u64 generation;
+	__u64 root;
+	__u64 chunk_root;
+	__u64 log_root;
+
+	/* this will help find the new super based on the log root */
+	__u64 log_root_transid;
+	__u64 total_bytes;
+	__u64 bytes_used;
+	__u64 root_dir_objectid;
+	__u64 num_devices;
+	__u32 sectorsize;
+	__u32 nodesize;
+	__u32 __unused_leafsize;
+	__u32 stripesize;
+	__u32 sys_chunk_array_size;
+	__u64 chunk_root_generation;
+	__u64 compat_flags;
+	__u64 compat_ro_flags;
+	__u64 incompat_flags;
+	__u16 csum_type;
+	__u8 root_level;
+	__u8 chunk_root_level;
+	__u8 log_root_level;
+	struct btrfs_dev_item dev_item;
+
+	char label[BTRFS_LABEL_SIZE];
+
+	__u64 cache_generation;
+	__u64 uuid_tree_generation;
+
+	/* future expansion */
+	__u64 reserved[30];
+	__u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
+	struct btrfs_root_backup super_roots[BTRFS_NUM_BACKUP_ROOTS];
+} __attribute__ ((__packed__));
+
+/*
+ * Compat flags that we support.  If any incompat flags are set other than the
+ * ones specified below then we will fail to mount
+ */
+#define BTRFS_FEATURE_COMPAT_SUPP		0ULL
+#define BTRFS_FEATURE_COMPAT_SAFE_SET		0ULL
+#define BTRFS_FEATURE_COMPAT_SAFE_CLEAR		0ULL
+
+#define BTRFS_FEATURE_COMPAT_RO_SUPP			\
+	(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE |	\
+	 BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID)
+
+#define BTRFS_FEATURE_COMPAT_RO_SAFE_SET	0ULL
+#define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR	0ULL
+
+#define BTRFS_FEATURE_INCOMPAT_SUPP			\
+	(BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF |		\
+	 BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL |	\
+	 BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS |		\
+	 BTRFS_FEATURE_INCOMPAT_BIG_METADATA |		\
+	 BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO |		\
+	 BTRFS_FEATURE_INCOMPAT_RAID56 |		\
+	 BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF |		\
+	 BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA |	\
+	 BTRFS_FEATURE_INCOMPAT_NO_HOLES)
+
+#define BTRFS_FEATURE_INCOMPAT_SAFE_SET			\
+	(BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF)
+#define BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR		0ULL
+
+/*
+ * A leaf is full of items. offset and size tell us where to find
+ * the item in the leaf (relative to the start of the data area)
+ */
+struct btrfs_item {
+	struct btrfs_key key;
+	__u32 offset;
+	__u32 size;
+} __attribute__ ((__packed__));
+
+/*
+ * leaves have an item area and a data area:
+ * [item0, item1....itemN] [free space] [dataN...data1, data0]
+ *
+ * The data is separate from the items to get the keys closer together
+ * during searches.
+ */
+struct btrfs_leaf {
+	struct btrfs_header header;
+	struct btrfs_item items[];
+} __attribute__ ((__packed__));
+
+/*
+ * all non-leaf blocks are nodes, they hold only keys and pointers to
+ * other blocks
+ */
+struct btrfs_key_ptr {
+	struct btrfs_key key;
+	__u64 blockptr;
+	__u64 generation;
+} __attribute__ ((__packed__));
+
+struct btrfs_node {
+	struct btrfs_header header;
+	struct btrfs_key_ptr ptrs[];
+} __attribute__ ((__packed__));
+
+union btrfs_tree_node {
+	struct btrfs_header header;
+	struct btrfs_leaf leaf;
+	struct btrfs_node node;
+};
+
+typedef __u8 u8;
+typedef __u16 u16;
+typedef __u32 u32;
+typedef __u64 u64;
+
+struct btrfs_path {
+	union btrfs_tree_node *nodes[BTRFS_MAX_LEVEL];
+	u32 slots[BTRFS_MAX_LEVEL];
+};
+
+struct btrfs_root {
+	u64 objectid;
+	u64 bytenr;
+	u64 root_dirid;
+};
+
+int btrfs_comp_keys(struct btrfs_key *, struct btrfs_key *);
+int btrfs_comp_keys_type(struct btrfs_key *, struct btrfs_key *);
+int btrfs_bin_search(union btrfs_tree_node *, struct btrfs_key *, int *);
+void btrfs_free_path(struct btrfs_path *);
+int btrfs_search_tree(const struct btrfs_root *, struct btrfs_key *,
+		      struct btrfs_path *);
+int btrfs_prev_slot(struct btrfs_path *);
+int btrfs_next_slot(struct btrfs_path *);
+
+static inline struct btrfs_key *btrfs_path_leaf_key(struct btrfs_path *p) {
+	return &p->nodes[0]->leaf.items[p->slots[0]].key;
+}
+
+static inline struct btrfs_key *
+btrfs_search_tree_key_type(const struct btrfs_root *root, u64 objectid,
+			   u8 type, struct btrfs_path *path)
+{
+	struct btrfs_key key, *res;
+
+	key.objectid = objectid;
+	key.type = type;
+	key.offset = 0;
+
+	if (btrfs_search_tree(root, &key, path))
+		return NULL;
+
+	res = btrfs_path_leaf_key(path);
+	if (btrfs_comp_keys_type(&key, res)) {
+		btrfs_free_path(path);
+		return NULL;
+	}
+
+	return res;
+}
+
+static inline u32 btrfs_path_item_size(struct btrfs_path *p)
+{
+	return p->nodes[0]->leaf.items[p->slots[0]].size;
+}
+
+static inline void *btrfs_leaf_data(struct btrfs_leaf *leaf, u32 slot)
+{
+	return ((u8 *) leaf) + sizeof(struct btrfs_header)
+	       + leaf->items[slot].offset;
+}
+
+static inline void *btrfs_path_leaf_data(struct btrfs_path *p)
+{
+	return btrfs_leaf_data(&p->nodes[0]->leaf, p->slots[0]);
+}
+
+#define btrfs_item_ptr(l,s,t)			\
+	((t *) btrfs_leaf_data((l),(s)))
+
+#define btrfs_path_item_ptr(p,t)		\
+	((t *) btrfs_path_leaf_data((p)))
+
+#endif /* __BTRFS_CTREE_H__ */
diff --git a/fs/btrfs/dev.c b/fs/btrfs/dev.c
new file mode 100644
index 0000000..fd2e9b6
--- /dev/null
+++ b/fs/btrfs/dev.c
@@ -0,0 +1,26 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <compiler.h>
+#include <fs_internal.h>
+
+struct blk_desc *btrfs_blk_desc;
+disk_partition_t *btrfs_part_info;
+
+int btrfs_devread(u64 address, int byte_len, void *buf)
+{
+	lbaint_t sector;
+	int byte_offset;
+
+	sector = address >> btrfs_blk_desc->log2blksz;
+	byte_offset = address % btrfs_blk_desc->blksz;
+
+	return fs_devread(btrfs_blk_desc, btrfs_part_info, sector, byte_offset,
+			  byte_len, buf);
+}
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
new file mode 100644
index 0000000..decf86e
--- /dev/null
+++ b/fs/btrfs/dir-item.c
@@ -0,0 +1,125 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "btrfs.h"
+
+static int verify_dir_item(struct btrfs_dir_item *item, u32 start, u32 total)
+{
+	u16 max_len = BTRFS_NAME_LEN;
+	u32 end;
+
+	if (item->type >= BTRFS_FT_MAX) {
+		printf("%s: invalid dir item type: %i\n", __func__, item->type);
+		return 1;
+	}
+
+	if (item->type == BTRFS_FT_XATTR)
+		max_len = 255; /* XATTR_NAME_MAX */
+
+	end = start + sizeof(*item) + item->name_len;
+	if (item->name_len > max_len || end > total) {
+		printf("%s: invalid dir item name len: %u\n", __func__,
+		       item->name_len);
+		return 1;
+	}
+
+	return 0;
+}
+
+static struct btrfs_dir_item *
+btrfs_match_dir_item_name(struct btrfs_path *path, const char *name,
+			  int name_len)
+{
+	struct btrfs_dir_item *item;
+	u32 total_len, cur = 0, this_len;
+	const char *name_ptr;
+
+	item = btrfs_path_item_ptr(path, struct btrfs_dir_item);
+
+	total_len = btrfs_path_item_size(path);
+
+	while (cur < total_len) {
+		btrfs_dir_item_to_cpu(item);
+		this_len = sizeof(*item) + item->name_len + item->data_len;
+		name_ptr = (const char *) (item + 1);
+
+		if (verify_dir_item(item, cur, total_len))
+			return NULL;
+		if (item->name_len == name_len && !memcmp(name_ptr, name,
+							  name_len))
+			return item;
+
+		cur += this_len;
+		item = (struct btrfs_dir_item *) ((u8 *) item + this_len);
+	}
+
+	return NULL;
+}
+
+int btrfs_lookup_dir_item(const struct btrfs_root *root, u64 dir,
+			  const char *name, int name_len,
+			  struct btrfs_dir_item *item)
+{
+	struct btrfs_path path;
+	struct btrfs_key key;
+	struct btrfs_dir_item *res = NULL;
+
+	key.objectid = dir;
+	key.type = BTRFS_DIR_ITEM_KEY;
+	key.offset = btrfs_name_hash(name, name_len);
+
+	if (btrfs_search_tree(root, &key, &path))
+		return -1;
+
+	if (btrfs_comp_keys_type(&key, btrfs_path_leaf_key(&path)))
+		goto out;
+
+	res = btrfs_match_dir_item_name(&path, name, name_len);
+	if (res)
+		*item = *res;
+out:
+	btrfs_free_path(&path);
+	return res ? 0 : -1;
+}
+
+int btrfs_readdir(const struct btrfs_root *root, u64 dir,
+		  btrfs_readdir_callback_t callback)
+{
+	struct btrfs_path path;
+	struct btrfs_key key, *found_key;
+	struct btrfs_dir_item *item;
+	int res;
+
+	key.objectid = dir;
+	key.type = BTRFS_DIR_INDEX_KEY;
+	key.offset = 0;
+
+	if (btrfs_search_tree(root, &key, &path))
+		return -1;
+
+	do {
+		found_key = btrfs_path_leaf_key(&path);
+		if (btrfs_comp_keys_type(&key, found_key))
+			break;
+
+		item = btrfs_path_item_ptr(&path, struct btrfs_dir_item);
+		btrfs_dir_item_to_cpu(item);
+
+		if (verify_dir_item(item, 0, sizeof(*item) + item->name_len))
+			continue;
+		if (item->type == BTRFS_FT_XATTR)
+			continue;
+
+		if (callback(root, item))
+			break;
+	} while (!(res = btrfs_next_slot(&path)));
+
+	btrfs_free_path(&path);
+
+	return res < 0 ? -1 : 0;
+}
diff --git a/fs/btrfs/extent-io.c b/fs/btrfs/extent-io.c
new file mode 100644
index 0000000..feb9143
--- /dev/null
+++ b/fs/btrfs/extent-io.c
@@ -0,0 +1,120 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "btrfs.h"
+#include <malloc.h>
+
+u64 btrfs_read_extent_inline(struct btrfs_path *path,
+			     struct btrfs_file_extent_item *extent, u64 offset,
+			     u64 size, char *out)
+{
+	u32 clen, dlen, orig_size = size, res;
+	const char *cbuf;
+	char *dbuf;
+	const int data_off = offsetof(struct btrfs_file_extent_item,
+				      disk_bytenr);
+
+	clen = btrfs_path_item_size(path) - data_off;
+	cbuf = (const char *) extent + data_off;
+	dlen = extent->ram_bytes;
+
+	if (offset > dlen)
+		return -1ULL;
+
+	if (size > dlen - offset)
+		size = dlen - offset;
+
+	if (extent->compression == BTRFS_COMPRESS_NONE) {
+		memcpy(out, cbuf + offset, size);
+		return size;
+	}
+
+	if (dlen > orig_size) {
+		dbuf = malloc(dlen);
+		if (!dbuf)
+			return -1ULL;
+	} else {
+		dbuf = out;
+	}
+
+	res = btrfs_decompress(extent->compression, cbuf, clen, dbuf, dlen);
+	if (res == -1 || res != dlen)
+		goto err;
+
+	if (dlen > orig_size) {
+		memcpy(out, dbuf + offset, size);
+		free(dbuf);
+	} else if (offset) {
+		memmove(out, dbuf + offset, size);
+	}
+
+	return size;
+
+err:
+	if (dlen > orig_size)
+		free(dbuf);
+	return -1ULL;
+}
+
+u64 btrfs_read_extent_reg(struct btrfs_path *path,
+			  struct btrfs_file_extent_item *extent, u64 offset,
+			  u64 size, char *out)
+{
+	u64 physical, clen, dlen, orig_size = size;
+	u32 res;
+	char *cbuf, *dbuf;
+
+	clen = extent->disk_num_bytes;
+	dlen = extent->num_bytes;
+
+	if (offset > dlen)
+		return -1ULL;
+
+	if (size > dlen - offset)
+		size = dlen - offset;
+
+	physical = btrfs_map_logical_to_physical(extent->disk_bytenr);
+	if (physical == -1ULL)
+		return -1ULL;
+
+	if (extent->compression == BTRFS_COMPRESS_NONE) {
+		physical += extent->offset + offset;
+		if (!btrfs_devread(physical, size, out))
+			return -1ULL;
+
+		return size;
+	}
+
+	cbuf = malloc(dlen > size ? clen + dlen : clen);
+	if (!cbuf)
+		return -1ULL;
+
+	if (dlen > orig_size)
+		dbuf = cbuf + clen;
+	else
+		dbuf = out;
+
+	if (!btrfs_devread(physical, clen, cbuf))
+		goto err;
+
+	res = btrfs_decompress(extent->compression, cbuf, clen, dbuf, dlen);
+	if (res == -1)
+		goto err;
+
+	if (dlen > orig_size)
+		memcpy(out, dbuf + offset, size);
+	else
+		memmove(out, dbuf + offset, size);
+
+	free(cbuf);
+	return res;
+
+err:
+	free(cbuf);
+	return -1ULL;
+}
diff --git a/fs/btrfs/hash.c b/fs/btrfs/hash.c
new file mode 100644
index 0000000..f8a50e5
--- /dev/null
+++ b/fs/btrfs/hash.c
@@ -0,0 +1,38 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "btrfs.h"
+#include <u-boot/crc.h>
+
+static u32 btrfs_crc32c_table[256];
+
+void btrfs_hash_init(void)
+{
+	static int inited = 0;
+
+	if (!inited) {
+		crc32c_init(btrfs_crc32c_table, 0x82F63B78);
+		inited = 1;
+	}
+}
+
+u32 btrfs_crc32c(u32 crc, const void *data, size_t length)
+{
+	return crc32c_cal(crc, (const char *) data, length,
+			  btrfs_crc32c_table);
+}
+
+u32 btrfs_csum_data(char *data, u32 seed, size_t len)
+{
+	return btrfs_crc32c(seed, data, len);
+}
+
+void btrfs_csum_final(u32 crc, void *result)
+{
+	*((u32 *) result) = cpu_to_le32(~crc);
+}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
new file mode 100644
index 0000000..0d3da28
--- /dev/null
+++ b/fs/btrfs/inode.c
@@ -0,0 +1,385 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "btrfs.h"
+#include <malloc.h>
+
+u64 btrfs_lookup_inode_ref(struct btrfs_root *root, u64 inr,
+			   struct btrfs_inode_ref *refp, char *name)
+{
+	struct btrfs_path path;
+	struct btrfs_key *key;
+	struct btrfs_inode_ref *ref;
+	u64 res = -1ULL;
+
+	key = btrfs_search_tree_key_type(root, inr, BTRFS_INODE_REF_KEY,
+					       &path);
+
+	if (!key)
+		return -1ULL;
+
+	ref = btrfs_path_item_ptr(&path, struct btrfs_inode_ref);
+	btrfs_inode_ref_to_cpu(ref);
+
+	if (refp)
+		*refp = *ref;
+
+	if (name) {
+		if (ref->name_len > BTRFS_NAME_MAX) {
+			printf("%s: inode name too long: %u\n", __func__,
+			        ref->name_len);
+			goto out;
+		}
+
+		memcpy(name, ref + 1, ref->name_len);
+	}
+
+	res = key->offset;
+out:
+	btrfs_free_path(&path);
+	return res;
+}
+
+int btrfs_lookup_inode(const struct btrfs_root *root,
+		       struct btrfs_key *location,
+		       struct btrfs_inode_item *item,
+		       struct btrfs_root *new_root)
+{
+	struct btrfs_root tmp_root = *root;
+	struct btrfs_path path;
+	int res = -1;
+
+	if (location->type == BTRFS_ROOT_ITEM_KEY) {
+		if (btrfs_find_root(location->objectid, &tmp_root, NULL))
+			return -1;
+
+		location->objectid = tmp_root.root_dirid;
+		location->type = BTRFS_INODE_ITEM_KEY;
+		location->offset = 0;
+	}
+
+	if (btrfs_search_tree(&tmp_root, location, &path))
+		return res;
+
+	if (btrfs_comp_keys(location, btrfs_path_leaf_key(&path)))
+		goto out;
+
+	if (item) {
+		*item = *btrfs_path_item_ptr(&path, struct btrfs_inode_item);
+		btrfs_inode_item_to_cpu(item);
+	}
+
+	if (new_root)
+		*new_root = tmp_root;
+
+	res = 0;
+
+out:
+	btrfs_free_path(&path);
+	return res;
+}
+
+int btrfs_readlink(const struct btrfs_root *root, u64 inr, char *target)
+{
+	struct btrfs_path path;
+	struct btrfs_key key;
+	struct btrfs_file_extent_item *extent;
+	const char *data_ptr;
+	int res = -1;
+
+	key.objectid = inr;
+	key.type = BTRFS_EXTENT_DATA_KEY;
+	key.offset = 0;
+
+	if (btrfs_search_tree(root, &key, &path))
+		return -1;
+
+	if (btrfs_comp_keys(&key, btrfs_path_leaf_key(&path)))
+		goto out;
+
+	extent = btrfs_path_item_ptr(&path, struct btrfs_file_extent_item);
+	if (extent->type != BTRFS_FILE_EXTENT_INLINE) {
+		printf("%s: Extent for symlink %llu not of INLINE type\n",
+		       __func__, inr);
+		goto out;
+	}
+
+	btrfs_file_extent_item_to_cpu_inl(extent);
+
+	if (extent->compression != BTRFS_COMPRESS_NONE) {
+		printf("%s: Symlink %llu extent data compressed!\n", __func__,
+		       inr);
+		goto out;
+	} else if (extent->encryption != 0) {
+		printf("%s: Symlink %llu extent data encrypted!\n", __func__,
+		       inr);
+		goto out;
+	} else if (extent->ram_bytes >= btrfs_info.sb.sectorsize) {
+		printf("%s: Symlink %llu extent data too long (%llu)!\n",
+		       __func__, inr, extent->ram_bytes);
+		goto out;
+	}
+
+	data_ptr = (const char *) extent
+		   + offsetof(struct btrfs_file_extent_item, disk_bytenr);
+
+	memcpy(target, data_ptr, extent->ram_bytes);
+	target[extent->ram_bytes] = '\0';
+	res = 0;
+out:
+	btrfs_free_path(&path);
+	return res;
+}
+
+/* inr must be a directory (for regular files with multiple hard links this
+   function returns only one of the parents of the file) */
+static u64 get_parent_inode(struct btrfs_root *root, u64 inr,
+			    struct btrfs_inode_item *inode_item)
+{
+	struct btrfs_key key;
+	u64 res;
+
+	if (inr == BTRFS_FIRST_FREE_OBJECTID) {
+		if (root->objectid != btrfs_info.fs_root.objectid) {
+			u64 parent;
+			struct btrfs_root_ref ref;
+
+			parent = btrfs_lookup_root_ref(root->objectid, &ref,
+						       NULL);
+			if (parent == -1ULL)
+				return -1ULL;
+
+			if (btrfs_find_root(parent, root, NULL))
+				return -1ULL;
+
+			inr = ref.dirid;
+		}
+
+		if (inode_item) {
+			key.objectid = inr;
+			key.type = BTRFS_INODE_ITEM_KEY;
+			key.offset = 0;
+
+			if (btrfs_lookup_inode(root, &key, inode_item, NULL))
+				return -1ULL;
+		}
+
+		return inr;
+	}
+
+	res = btrfs_lookup_inode_ref(root, inr, NULL, NULL);
+	if (res == -1ULL)
+		return -1ULL;
+
+	if (inode_item) {
+		key.objectid = res;
+		key.type = BTRFS_INODE_ITEM_KEY;
+		key.offset = 0;
+
+		if (btrfs_lookup_inode(root, &key, inode_item, NULL))
+			return -1ULL;
+	}
+
+	return res;
+}
+
+static inline int next_length(const char *path)
+{
+	int res = 0;
+	while (*path != '\0' && *path != '/' && res <= BTRFS_NAME_LEN)
+		++res, ++path;
+	return res;
+}
+
+static inline const char *skip_current_directories(const char *cur)
+{
+	while (1) {
+		if (cur[0] == '/')
+			++cur;
+		else if (cur[0] == '.' && cur[1] == '/')
+			cur += 2;
+		else
+			break;
+	}
+
+	return cur;
+}
+
+/* inode.c, musi vratit aj root stromu kde sa inoda najde */
+u64 btrfs_lookup_path(struct btrfs_root *root, u64 inr, const char *path,
+		      u8 *type_p, struct btrfs_inode_item *inode_item_p,
+		      int symlink_limit)
+{
+	struct btrfs_dir_item item;
+	struct btrfs_inode_item inode_item;
+	u8 type = BTRFS_FT_DIR;
+	int len, have_inode = 0;
+	const char *cur = path;
+
+	if (*cur == '/') {
+		++cur;
+		inr = root->root_dirid;
+	}
+
+	do {
+		cur = skip_current_directories(cur);
+
+		len = next_length(cur);
+		if (len > BTRFS_NAME_LEN) {
+			printf("%s: Name too long at \"%.*s\"\n", __func__,
+			       BTRFS_NAME_LEN, cur);
+			return -1ULL;
+		}
+
+		if (len == 1 && cur[0] == '.')
+			break;
+
+		if (len == 2 && cur[0] == '.' && cur[1] == '.') {
+			cur += 2;
+			inr = get_parent_inode(root, inr, &inode_item);
+			if (inr == -1ULL)
+				return -1ULL;
+
+			type = BTRFS_FT_DIR;
+			continue;
+		}
+
+		if (!*cur)
+			break;
+		
+		if (btrfs_lookup_dir_item(root, inr, cur, len, &item))
+			return -1ULL;
+
+		type = item.type;
+		have_inode = 1;
+		if (btrfs_lookup_inode(root, &item.location, &inode_item, root))
+			return -1ULL;
+
+		if (item.type == BTRFS_FT_SYMLINK && symlink_limit >= 0) {
+			char *target;
+
+			if (!symlink_limit) {
+				printf("%s: Too much symlinks!\n", __func__);
+				return -1ULL;
+			}
+
+			target = malloc(min(inode_item.size + 1,
+					    (u64) btrfs_info.sb.sectorsize));
+			if (!target)
+				return -1ULL;
+
+			if (btrfs_readlink(root, item.location.objectid,
+					   target)) {
+				free(target);
+				return -1ULL;
+			}
+
+			inr = btrfs_lookup_path(root, inr, target, &type,
+						&inode_item, symlink_limit - 1);
+
+			free(target);
+
+			if (inr == -1ULL)
+				return -1ULL;
+		} else if (item.type != BTRFS_FT_DIR && cur[len]) {
+			printf("%s: \"%.*s\" not a directory\n", __func__,
+			       (int) (cur - path + len), path);
+			return -1ULL;
+		} else {
+			inr = item.location.objectid;
+		}
+
+		cur += len;
+	} while (*cur);
+
+	if (type_p)
+		*type_p = type;
+
+	if (inode_item_p) {
+		if (!have_inode) {
+			struct btrfs_key key;
+
+			key.objectid = inr;
+			key.type = BTRFS_INODE_ITEM_KEY;
+			key.offset = 0;
+
+			if (btrfs_lookup_inode(root, &key, &inode_item, NULL))
+				return -1ULL;
+		}
+
+		*inode_item_p = inode_item;
+	}
+
+	return inr;
+}
+
+u64 btrfs_file_read(const struct btrfs_root *root, u64 inr, u64 offset,
+		    u64 size, char *buf)
+{
+	struct btrfs_path path;
+	struct btrfs_key key;
+	struct btrfs_file_extent_item *extent;
+	int res;
+	u64 rd, rd_all = -1ULL;
+
+	key.objectid = inr;
+	key.type = BTRFS_EXTENT_DATA_KEY;
+	key.offset = offset;
+
+	if (btrfs_search_tree(root, &key, &path))
+		return -1ULL;
+
+	if (btrfs_comp_keys(&key, btrfs_path_leaf_key(&path)) < 0) {
+		if (btrfs_prev_slot(&path))
+			goto out;
+
+		if (btrfs_comp_keys_type(&key, btrfs_path_leaf_key(&path)))
+			goto out;
+	}
+
+	rd_all = 0;
+
+	do {
+		if (btrfs_comp_keys_type(&key, btrfs_path_leaf_key(&path)))
+			break;
+
+		extent = btrfs_path_item_ptr(&path,
+					     struct btrfs_file_extent_item);
+
+		if (extent->type == BTRFS_FILE_EXTENT_INLINE) {
+			btrfs_file_extent_item_to_cpu_inl(extent);
+			rd = btrfs_read_extent_inline(&path, extent, offset,
+						      size, buf);
+		} else {
+			btrfs_file_extent_item_to_cpu(extent);
+			rd = btrfs_read_extent_reg(&path, extent, offset, size,
+						   buf);
+		}
+
+		if (rd == -1ULL) {
+			printf("%s: Error reading extent\n", __func__);
+			rd_all = -1;
+			goto out;
+		}
+
+		offset = 0;
+		buf += rd;
+		rd_all += rd;
+		size -= rd;
+
+		if (!size)
+			break;
+	} while (!(res = btrfs_next_slot(&path)));
+
+	if (res)
+		return -1ULL;
+
+out:
+	btrfs_free_path(&path);
+	return rd_all;
+}
diff --git a/fs/btrfs/root.c b/fs/btrfs/root.c
new file mode 100644
index 0000000..c405813
--- /dev/null
+++ b/fs/btrfs/root.c
@@ -0,0 +1,93 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "btrfs.h"
+
+static void read_root_item(struct btrfs_path *p, struct btrfs_root_item *item)
+{
+	u32 len;
+	int reset = 0;
+
+	len = btrfs_path_item_size(p);
+	memcpy(item, btrfs_path_item_ptr(p, struct btrfs_root_item), len);
+	btrfs_root_item_to_cpu(item);
+
+	if (len < sizeof(*item))
+		reset = 1;
+	if (!reset && item->generation != item->generation_v2) {
+		if (item->generation_v2 != 0)
+			printf("%s: generation != generation_v2 in root item",
+			       __func__);
+		reset = 1;
+	}
+	if (reset) {
+		memset(&item->generation_v2, 0,
+		       sizeof(*item) - offsetof(struct btrfs_root_item,
+						generation_v2));
+	}
+}
+
+int btrfs_find_root(u64 objectid, struct btrfs_root *root,
+		    struct btrfs_root_item *root_item)
+{
+	struct btrfs_path path;
+	struct btrfs_root_item my_root_item;
+
+	if (!btrfs_search_tree_key_type(&btrfs_info.tree_root, objectid,
+					BTRFS_ROOT_ITEM_KEY, &path))
+		return -1;
+
+	if (!root_item)
+		root_item = &my_root_item;
+	read_root_item(&path, root_item);
+
+	if (root) {
+		root->objectid = objectid;
+		root->bytenr = root_item->bytenr;
+		root->root_dirid = root_item->root_dirid;
+	}
+
+	btrfs_free_path(&path);
+	return 0;
+}
+
+u64 btrfs_lookup_root_ref(u64 subvolid, struct btrfs_root_ref *refp, char *name)
+{
+	struct btrfs_path path;
+	struct btrfs_key *key;
+	struct btrfs_root_ref *ref;
+	u64 res = -1ULL;
+
+	key = btrfs_search_tree_key_type(&btrfs_info.tree_root, subvolid,
+					       BTRFS_ROOT_BACKREF_KEY, &path);
+
+	if (!key)
+		return -1ULL;
+
+	ref = btrfs_path_item_ptr(&path, struct btrfs_root_ref);
+	btrfs_root_ref_to_cpu(ref);
+
+	if (refp)
+		*refp = *ref;
+
+	if (name) {
+		if (ref->name_len > BTRFS_VOL_NAME_MAX) {
+			printf("%s: volume name too long: %u\n", __func__,
+			       ref->name_len);
+			goto out;
+		}
+
+		memcpy(name, ref + 1, ref->name_len);
+	}
+
+	res = key->offset;
+out:
+	btrfs_free_path(&path);
+	return res;
+}
+
diff --git a/fs/btrfs/subvolume.c b/fs/btrfs/subvolume.c
new file mode 100644
index 0000000..54e0ab45
--- /dev/null
+++ b/fs/btrfs/subvolume.c
@@ -0,0 +1,131 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "btrfs.h"
+#include <malloc.h>
+
+static int get_subvol_name(u64 subvolid, char *name, int max_len)
+{
+	struct btrfs_root_ref rref;
+	struct btrfs_inode_ref iref;
+	struct btrfs_root root;
+	u64 dir;
+	char tmp[max(BTRFS_VOL_NAME_MAX, BTRFS_NAME_MAX)];
+	char *ptr;
+
+	ptr = name + max_len - 1;
+	*ptr = '\0';
+
+	while (subvolid != BTRFS_FS_TREE_OBJECTID) {
+		subvolid = btrfs_lookup_root_ref(subvolid, &rref, tmp);
+
+		if (subvolid == -1ULL)
+			return -1;
+
+		ptr -= rref.name_len + 1;
+		if (ptr < name)
+			goto too_long;
+
+		memcpy(ptr + 1, tmp, rref.name_len);
+		*ptr = '/';
+
+		if (btrfs_find_root(subvolid, &root, NULL))
+			return -1;
+
+		dir = rref.dirid;
+
+		while (dir != BTRFS_FIRST_FREE_OBJECTID) {
+			dir = btrfs_lookup_inode_ref(&root, dir, &iref, tmp);
+
+			if (dir == -1ULL)
+				return -1;
+
+			ptr -= iref.name_len + 1;
+			if (ptr < name)
+				goto too_long;
+
+			memcpy(ptr + 1, tmp, iref.name_len);
+			*ptr = '/';
+		}
+	}
+
+	if (ptr == name + max_len - 1) {
+		name[0] = '/';
+		name[1] = '\0';
+	} else {
+		memmove(name, ptr, name + max_len - ptr);
+	}
+
+	return 0;
+
+too_long:
+	printf("%s: subvolume name too long\n", __func__);
+	return -1;
+}
+
+u64 btrfs_get_default_subvol_objectid(void)
+{
+	struct btrfs_dir_item item;
+
+	if (btrfs_lookup_dir_item(&btrfs_info.tree_root,
+				  btrfs_info.sb.root_dir_objectid, "default", 7,
+				  &item))
+		return BTRFS_FS_TREE_OBJECTID;
+	return item.location.objectid;
+}
+
+static void list_subvols(u64 tree, char *nameptr, int max_name_len, int level)
+{
+	struct btrfs_key key, *found_key;
+	struct btrfs_path path;
+	struct btrfs_root_ref *ref;
+	int res;
+
+	key.objectid = tree;
+	key.type = BTRFS_ROOT_REF_KEY;
+	key.offset = 0;
+
+	if (btrfs_search_tree(&btrfs_info.tree_root, &key, &path))
+		return;
+
+	do {
+		found_key = btrfs_path_leaf_key(&path);
+		if (btrfs_comp_keys_type(&key, found_key))
+			break;
+
+		ref = btrfs_path_item_ptr(&path, struct btrfs_root_ref);
+		btrfs_root_ref_to_cpu(ref);
+
+		printf("ID %llu parent %llu name ", found_key->offset, tree);
+		if (nameptr && !get_subvol_name(found_key->offset, nameptr,
+						max_name_len))
+			printf("%s\n", nameptr);
+		else
+			printf("%.*s\n", (int) ref->name_len,
+			       (const char *) (ref + 1));
+
+		if (level > 0)
+			list_subvols(found_key->offset, nameptr, max_name_len,
+				     level - 1);
+		else
+			printf("%s: Too much recursion, maybe skipping some "
+			       "subvolumes\n", __func__);
+	} while (!(res = btrfs_next_slot(&path)));
+
+	btrfs_free_path(&path);
+}
+
+void btrfs_list_subvols(void)
+{
+	char *nameptr = malloc(4096);
+
+	list_subvols(BTRFS_FS_TREE_OBJECTID, nameptr, nameptr ? 4096 : 0, 40);
+
+	if (nameptr)
+		free(nameptr);
+}
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
new file mode 100644
index 0000000..2529c2b
--- /dev/null
+++ b/fs/btrfs/super.c
@@ -0,0 +1,233 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "btrfs.h"
+
+#define BTRFS_SUPER_FLAG_SUPP	(BTRFS_HEADER_FLAG_WRITTEN	\
+				 | BTRFS_HEADER_FLAG_RELOC	\
+				 | BTRFS_SUPER_FLAG_ERROR	\
+				 | BTRFS_SUPER_FLAG_SEEDING	\
+				 | BTRFS_SUPER_FLAG_METADUMP)
+
+#define BTRFS_SUPER_INFO_SIZE	4096
+
+static int btrfs_newest_root_backup(struct btrfs_super_block *sb)
+{
+	struct btrfs_root_backup *root_backup;
+	int i, newest = -1;
+
+	for (i = 0; i < BTRFS_NUM_BACKUP_ROOTS; ++i) {
+		root_backup = sb->super_roots + i;
+		if (root_backup->tree_root_gen == sb->generation)
+			newest = i;
+	}
+
+	return newest;
+}
+
+static inline int is_power_of_2(u64 x)
+{
+	return !(x & (x - 1));
+}
+
+static int btrfs_check_super_csum(char *raw_disk_sb)
+{
+	struct btrfs_super_block *disk_sb =
+		(struct btrfs_super_block *) raw_disk_sb;
+	u16 csum_type = le16_to_cpu(disk_sb->csum_type);
+
+	if (csum_type == BTRFS_CSUM_TYPE_CRC32) {
+		u32 crc = ~(u32) 0;
+		const int csum_size = sizeof(crc);
+		char result[csum_size];
+
+		crc = btrfs_csum_data(raw_disk_sb + BTRFS_CSUM_SIZE, crc,
+				      BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
+		btrfs_csum_final(crc, result);
+
+		if (memcmp(raw_disk_sb, result, csum_size))
+			return -1;
+	} else {
+		return -1;
+	}
+
+	return 0;
+}
+
+static int btrfs_check_super(struct btrfs_super_block *sb)
+{
+	int ret = 0;
+
+	if (sb->flags & ~BTRFS_SUPER_FLAG_SUPP) {
+		printf("%s: Unsupported flags: %llu\n", __func__,
+		       sb->flags & ~BTRFS_SUPER_FLAG_SUPP);
+	}
+
+	if (sb->root_level > BTRFS_MAX_LEVEL) {
+		printf("%s: tree_root level too big: %d >= %d\n", __func__,
+		       sb->root_level, BTRFS_MAX_LEVEL);
+		ret = -1;
+	}
+
+	if (sb->chunk_root_level > BTRFS_MAX_LEVEL) {
+		printf("%s: chunk_root level too big: %d >= %d\n", __func__,
+		       sb->chunk_root_level, BTRFS_MAX_LEVEL);
+		ret = -1;
+	}
+
+	if (sb->log_root_level > BTRFS_MAX_LEVEL) {
+		printf("%s: log_root level too big: %d >= %d\n", __func__,
+		       sb->log_root_level, BTRFS_MAX_LEVEL);
+		ret = -1;
+	}
+
+	if (!is_power_of_2(sb->sectorsize) || sb->sectorsize < 4096 ||
+	    sb->sectorsize > BTRFS_MAX_METADATA_BLOCKSIZE) {
+		printf("%s: invalid sectorsize %u\n", __func__,
+		       sb->sectorsize);
+		ret = -1;
+	}
+
+	if (!is_power_of_2(sb->nodesize) || sb->nodesize < sb->sectorsize ||
+	    sb->nodesize > BTRFS_MAX_METADATA_BLOCKSIZE) {
+		printf("%s: invalid nodesize %u\n", __func__, sb->nodesize);
+		ret = -1;
+	}
+
+	if (sb->nodesize != sb->__unused_leafsize) {
+		printf("%s: invalid leafsize %u, should be %u\n", __func__,
+		       sb->__unused_leafsize, sb->nodesize);
+		ret = -1;
+	}
+
+	if (!IS_ALIGNED(sb->root, sb->sectorsize)) {
+		printf("%s: tree_root block unaligned: %llu\n", __func__,
+		       sb->root);
+		ret = -1;
+	}
+
+	if (!IS_ALIGNED(sb->chunk_root, sb->sectorsize)) {
+		printf("%s: chunk_root block unaligned: %llu\n", __func__,
+		       sb->chunk_root);
+		ret = -1;
+	}
+
+	if (!IS_ALIGNED(sb->log_root, sb->sectorsize)) {
+		printf("%s: log_root block unaligned: %llu\n", __func__,
+		       sb->log_root);
+		ret = -1;
+	}
+
+	if (memcmp(sb->fsid, sb->dev_item.fsid, BTRFS_UUID_SIZE) != 0) {
+		printf("%s: dev_item UUID does not match fsid\n", __func__);
+		ret = -1;
+	}
+
+	if (sb->bytes_used < 6*sb->nodesize) {
+		printf("%s: bytes_used is too small %llu\n", __func__,
+		       sb->bytes_used);
+		ret = -1;
+	}
+
+	if (!is_power_of_2(sb->stripesize)) {
+		printf("%s: invalid stripesize %u\n", __func__, sb->stripesize);
+		ret = -1;
+	}
+
+	if (sb->sys_chunk_array_size > BTRFS_SYSTEM_CHUNK_ARRAY_SIZE) {
+		printf("%s: system chunk array too big %u > %u\n", __func__,
+		       sb->sys_chunk_array_size, BTRFS_SYSTEM_CHUNK_ARRAY_SIZE);
+		ret = -1;
+	}
+
+	if (sb->sys_chunk_array_size < sizeof(struct btrfs_key) +
+	    sizeof(struct btrfs_chunk)) {
+		printf("%s: system chunk array too small %u < %lu\n", __func__,
+		       sb->sys_chunk_array_size, (u32) sizeof(struct btrfs_key)
+		       + sizeof(struct btrfs_chunk));
+		ret = -1;
+	}
+
+	return ret;
+}
+
+int btrfs_read_superblock(void)
+{
+	const u64 superblock_offsets[4] = {
+		0x10000ull,
+		0x4000000ull,
+		0x4000000000ull,
+		0x4000000000000ull
+	};
+	char raw_sb[BTRFS_SUPER_INFO_SIZE];
+	struct btrfs_super_block *sb = (struct btrfs_super_block *) raw_sb;
+	u64 dev_total_bytes;
+	int i, root_backup_idx;
+
+	dev_total_bytes = (u64) btrfs_part_info->size * btrfs_part_info->blksz;
+
+	btrfs_info.sb.generation = 0;
+
+	for (i = 0; i < 4; ++i) {
+		if (superblock_offsets[i] + sizeof(sb) > dev_total_bytes)
+			break;
+
+		if (!btrfs_devread(superblock_offsets[i], BTRFS_SUPER_INFO_SIZE,
+				   raw_sb))
+			break;
+
+		if (btrfs_check_super_csum(raw_sb)) {
+			printf("%s: invalid checksum at superblock mirror %i\n",
+			       __func__, i);
+			continue;
+		}
+
+		btrfs_super_block_to_cpu(sb);
+
+		if (sb->magic != BTRFS_MAGIC) {
+			printf("%s: invalid BTRFS magic 0x%016llX at "
+			       "superblock mirror %i\n", __func__, sb->magic,
+			       i);
+		} else if (sb->bytenr != superblock_offsets[i]) {
+			printf("%s: invalid bytenr 0x%016llX (expected "
+			       "0x%016llX) at superblock mirror %i\n",
+			       __func__, sb->bytenr, superblock_offsets[i], i);
+		} else if (btrfs_check_super(sb)) {
+			printf("%s: Checking superblock mirror %i failed\n",
+			       __func__, i);
+		} else if (sb->generation > btrfs_info.sb.generation) {
+			memcpy(&btrfs_info.sb, sb, sizeof(*sb));
+		} else {
+			/* Nothing */
+		}
+	}
+
+	if (!btrfs_info.sb.generation) {
+		printf("%s: No valid BTRFS superblock found!\n", __func__);
+		return -1;
+	}
+
+	root_backup_idx = btrfs_newest_root_backup(&btrfs_info.sb);
+	if (root_backup_idx < 0) {
+		printf("%s: No valid root_backup found!\n", __func__);
+		return -1;
+	}
+	btrfs_info.root_backup = btrfs_info.sb.super_roots + root_backup_idx;
+
+	if (btrfs_info.root_backup->num_devices != 1) {
+		printf("%s: Unsupported number of devices (%lli). This driver "
+		       "only supports filesystem on one device.\n", __func__,
+		       btrfs_info.root_backup->num_devices);
+		return -1;
+	}
+
+	debug("Chosen superblock with generation = %llu\n",
+	      btrfs_info.sb.generation);
+
+	return 0;
+}
diff --git a/fs/ext4/dev.c b/fs/ext4/dev.c
index ae2ba6a..f04fa08 100644
--- a/fs/ext4/dev.c
+++ b/fs/ext4/dev.c
@@ -26,7 +26,7 @@
 #include <common.h>
 #include <blk.h>
 #include <config.h>
-#include <memalign.h>
+#include <fs_internal.h>
 #include <ext4fs.h>
 #include <ext_common.h>
 #include "ext4_common.h"
@@ -47,85 +47,11 @@
 		get_fs()->dev_desc->log2blksz;
 }
 
-int ext4fs_devread(lbaint_t sector, int byte_offset, int byte_len, char *buf)
+int ext4fs_devread(lbaint_t sector, int byte_offset, int byte_len,
+		   char *buffer)
 {
-	unsigned block_len;
-	int log2blksz = ext4fs_blk_desc->log2blksz;
-	ALLOC_CACHE_ALIGN_BUFFER(char, sec_buf, (ext4fs_blk_desc ?
-						 ext4fs_blk_desc->blksz :
-						 0));
-	if (ext4fs_blk_desc == NULL) {
-		printf("** Invalid Block Device Descriptor (NULL)\n");
-		return 0;
-	}
-
-	/* Check partition boundaries */
-	if ((sector + ((byte_offset + byte_len - 1) >> log2blksz))
-	    >= part_info->size) {
-		printf("%s read outside partition " LBAFU "\n", __func__,
-		       sector);
-		return 0;
-	}
-
-	/* Get the read to the beginning of a partition */
-	sector += byte_offset >> log2blksz;
-	byte_offset &= ext4fs_blk_desc->blksz - 1;
-
-	debug(" <" LBAFU ", %d, %d>\n", sector, byte_offset, byte_len);
-
-	if (byte_offset != 0) {
-		int readlen;
-		/* read first part which isn't aligned with start of sector */
-		if (blk_dread(ext4fs_blk_desc, part_info->start + sector, 1,
-			      (void *)sec_buf) != 1) {
-			printf(" ** ext2fs_devread() read error **\n");
-			return 0;
-		}
-		readlen = min((int)ext4fs_blk_desc->blksz - byte_offset,
-			      byte_len);
-		memcpy(buf, sec_buf + byte_offset, readlen);
-		buf += readlen;
-		byte_len -= readlen;
-		sector++;
-	}
-
-	if (byte_len == 0)
-		return 1;
-
-	/* read sector aligned part */
-	block_len = byte_len & ~(ext4fs_blk_desc->blksz - 1);
-
-	if (block_len == 0) {
-		ALLOC_CACHE_ALIGN_BUFFER(u8, p, ext4fs_blk_desc->blksz);
-
-		block_len = ext4fs_blk_desc->blksz;
-		blk_dread(ext4fs_blk_desc, part_info->start + sector, 1,
-			  (void *)p);
-		memcpy(buf, p, byte_len);
-		return 1;
-	}
-
-	if (blk_dread(ext4fs_blk_desc, part_info->start + sector,
-		      block_len >> log2blksz, (void *)buf) !=
-			block_len >> log2blksz) {
-		printf(" ** %s read error - block\n", __func__);
-		return 0;
-	}
-	block_len = byte_len & ~(ext4fs_blk_desc->blksz - 1);
-	buf += block_len;
-	byte_len -= block_len;
-	sector += block_len / ext4fs_blk_desc->blksz;
-
-	if (byte_len != 0) {
-		/* read rest of data which are not in whole sector */
-		if (blk_dread(ext4fs_blk_desc, part_info->start + sector, 1,
-			      (void *)sec_buf) != 1) {
-			printf("* %s read error - last part\n", __func__);
-			return 0;
-		}
-		memcpy(buf, sec_buf, byte_len);
-	}
-	return 1;
+	return fs_devread(get_fs()->dev_desc, part_info, sector, byte_offset,
+			  byte_len, buffer);
 }
 
 int ext4_read_superblock(char *buffer)
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 621c61e..31952f4 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -432,6 +432,10 @@
 		crc = ext2fs_crc16(crc, desc, offset);
 		offset += sizeof(desc->bg_checksum);	/* skip checksum */
 		assert(offset == sizeof(*desc));
+		if (offset < fs->gdsize) {
+			crc = ext2fs_crc16(crc, (__u8 *)desc + offset,
+					   fs->gdsize - offset);
+		}
 	}
 
 	return crc;
diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
index 081509d..b0c7303 100644
--- a/fs/ext4/ext4fs.c
+++ b/fs/ext4/ext4fs.c
@@ -167,6 +167,7 @@
 				  FILETYPE_DIRECTORY);
 	if (status != 1) {
 		printf("** Can not find directory. **\n");
+		ext4fs_free_node(dirnode, &ext4fs_root->diropen);
 		return 1;
 	}
 
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 36a309c..7fe7843 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -495,7 +495,7 @@
 		return -1;
 	}
 
-	block = memalign(ARCH_DMA_MINALIGN, cur_dev->blksz);
+	block = malloc_cache_aligned(cur_dev->blksz);
 	if (block == NULL) {
 		debug("Error: allocating block\n");
 		return -1;
@@ -599,7 +599,7 @@
 
 	mydata->fatbufnum = -1;
 	mydata->fat_dirty = 0;
-	mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE);
+	mydata->fatbuf = malloc_cache_aligned(FATBUFSIZE);
 	if (mydata->fatbuf == NULL) {
 		debug("Error: allocating memory\n");
 		return -1;
@@ -710,13 +710,14 @@
 	itr->fsdata = parent->fsdata;
 	if (clustnum > 0) {
 		itr->clust = clustnum;
+		itr->is_root = 0;
 	} else {
 		itr->clust = parent->fsdata->root_cluster;
+		itr->is_root = 1;
 	}
 	itr->dent = NULL;
 	itr->remaining = 0;
 	itr->last_cluster = 0;
-	itr->is_root = 0;
 }
 
 static void *next_cluster(fat_itr *itr)
@@ -1037,13 +1038,16 @@
 	fat_itr *itr;
 	int ret;
 
-	itr = malloc(sizeof(fat_itr));
+	itr = malloc_cache_aligned(sizeof(fat_itr));
+	if (!itr)
+		return 0;
 	ret = fat_itr_root(itr, &fsdata);
 	if (ret)
-		return 0;
+		goto out;
 
 	ret = fat_itr_resolve(itr, filename, TYPE_ANY);
 	free(fsdata.fatbuf);
+out:
 	free(itr);
 	return ret == 0;
 }
@@ -1054,10 +1058,12 @@
 	fat_itr *itr;
 	int ret;
 
-	itr = malloc(sizeof(fat_itr));
+	itr = malloc_cache_aligned(sizeof(fat_itr));
+	if (!itr)
+		return -ENOMEM;
 	ret = fat_itr_root(itr, &fsdata);
 	if (ret)
-		return ret;
+		goto out_free_itr;
 
 	ret = fat_itr_resolve(itr, filename, TYPE_FILE);
 	if (ret) {
@@ -1071,12 +1077,13 @@
 			*size = 0;
 			ret = 0;
 		}
-		goto out;
+		goto out_free_both;
 	}
 
 	*size = FAT2CPU32(itr->dent->size);
+out_free_both:
 	free(fsdata.fatbuf);
-out:
+out_free_itr:
 	free(itr);
 	return ret;
 }
@@ -1088,20 +1095,23 @@
 	fat_itr *itr;
 	int ret;
 
-	itr = malloc(sizeof(fat_itr));
+	itr = malloc_cache_aligned(sizeof(fat_itr));
+	if (!itr)
+		return -ENOMEM;
 	ret = fat_itr_root(itr, &fsdata);
 	if (ret)
-		return ret;
+		goto out_free_itr;
 
 	ret = fat_itr_resolve(itr, filename, TYPE_FILE);
 	if (ret)
-		goto out;
+		goto out_free_both;
 
 	printf("reading %s\n", filename);
 	ret = get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread);
 
-out:
+out_free_both:
 	free(fsdata.fatbuf);
+out_free_itr:
 	free(itr);
 	return ret;
 }
@@ -1147,17 +1157,18 @@
 
 	ret = fat_itr_root(&dir->itr, &dir->fsdata);
 	if (ret)
-		goto fail;
+		goto fail_free_dir;
 
 	ret = fat_itr_resolve(&dir->itr, filename, TYPE_DIR);
 	if (ret)
-		goto fail;
+		goto fail_free_both;
 
 	*dirsp = (struct fs_dir_stream *)dir;
 	return 0;
 
-fail:
+fail_free_both:
 	free(dir->fsdata.fatbuf);
+fail_free_dir:
 	free(dir);
 	return ret;
 }
diff --git a/fs/fs.c b/fs/fs.c
index 3481229..84349f3 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -14,6 +14,7 @@
 #include <fs.h>
 #include <sandboxfs.h>
 #include <ubifs_uboot.h>
+#include <btrfs.h>
 #include <asm/io.h>
 #include <div64.h>
 #include <linux/math64.h>
@@ -219,6 +220,21 @@
 		.opendir = fs_opendir_unsupported,
 	},
 #endif
+#ifdef CONFIG_FS_BTRFS
+	{
+		.fstype = FS_TYPE_BTRFS,
+		.name = "btrfs",
+		.null_dev_desc_ok = false,
+		.probe = btrfs_probe,
+		.close = btrfs_close,
+		.ls = btrfs_ls,
+		.exists = btrfs_exists,
+		.size = btrfs_size,
+		.read = btrfs_read,
+		.write = fs_write_unsupported,
+		.uuid = btrfs_uuid,
+	},
+#endif
 	{
 		.fstype = FS_TYPE_ANY,
 		.name = "unsupported",
diff --git a/fs/fs_internal.c b/fs/fs_internal.c
new file mode 100644
index 0000000..58b4410
--- /dev/null
+++ b/fs/fs_internal.c
@@ -0,0 +1,92 @@
+/*
+ * 2017 by Marek Behun <marek.behun@nic.cz>
+ *
+ * Derived from code in ext4/dev.c, which was based on reiserfs/dev.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <compiler.h>
+#include <part.h>
+#include <memalign.h>
+
+int fs_devread(struct blk_desc *blk, disk_partition_t *partition,
+	       lbaint_t sector, int byte_offset, int byte_len, char *buf)
+{
+	unsigned block_len;
+	int log2blksz = blk->log2blksz;
+	ALLOC_CACHE_ALIGN_BUFFER(char, sec_buf, (blk ? blk->blksz : 0));
+	if (blk == NULL) {
+		printf("** Invalid Block Device Descriptor (NULL)\n");
+		return 0;
+	}
+
+	/* Check partition boundaries */
+	if ((sector + ((byte_offset + byte_len - 1) >> log2blksz))
+	    >= partition->size) {
+		printf("%s read outside partition " LBAFU "\n", __func__,
+		       sector);
+		return 0;
+	}
+
+	/* Get the read to the beginning of a partition */
+	sector += byte_offset >> log2blksz;
+	byte_offset &= blk->blksz - 1;
+
+	debug(" <" LBAFU ", %d, %d>\n", sector, byte_offset, byte_len);
+
+	if (byte_offset != 0) {
+		int readlen;
+		/* read first part which isn't aligned with start of sector */
+		if (blk_dread(blk, partition->start + sector, 1,
+			      (void *)sec_buf) != 1) {
+			printf(" ** %s read error **\n", __func__);
+			return 0;
+		}
+		readlen = min((int)blk->blksz - byte_offset,
+			      byte_len);
+		memcpy(buf, sec_buf + byte_offset, readlen);
+		buf += readlen;
+		byte_len -= readlen;
+		sector++;
+	}
+
+	if (byte_len == 0)
+		return 1;
+
+	/* read sector aligned part */
+	block_len = byte_len & ~(blk->blksz - 1);
+
+	if (block_len == 0) {
+		ALLOC_CACHE_ALIGN_BUFFER(u8, p, blk->blksz);
+
+		block_len = blk->blksz;
+		blk_dread(blk, partition->start + sector, 1,
+			  (void *)p);
+		memcpy(buf, p, byte_len);
+		return 1;
+	}
+
+	if (blk_dread(blk, partition->start + sector,
+		      block_len >> log2blksz, (void *)buf) !=
+			block_len >> log2blksz) {
+		printf(" ** %s read error - block\n", __func__);
+		return 0;
+	}
+	block_len = byte_len & ~(blk->blksz - 1);
+	buf += block_len;
+	byte_len -= block_len;
+	sector += block_len / blk->blksz;
+
+	if (byte_len != 0) {
+		/* read rest of data which are not in whole sector */
+		if (blk_dread(blk, partition->start + sector, 1,
+			      (void *)sec_buf) != 1) {
+			printf("* %s read error - last part\n", __func__);
+			return 0;
+		}
+		memcpy(buf, sec_buf, byte_len);
+	}
+	return 1;
+}
diff --git a/fs/jffs2/jffs2_nand_1pass.c b/fs/jffs2/jffs2_nand_1pass.c
index 1d63fc9..b16005e 100644
--- a/fs/jffs2/jffs2_nand_1pass.c
+++ b/fs/jffs2/jffs2_nand_1pass.c
@@ -798,7 +798,7 @@
 	struct mtdids *id = part->dev->id;
 	mtd = get_nand_dev_by_index(id->num);
 	if (!mtd) {
-		error("\nno NAND devices available\n");
+		pr_err("\nno NAND devices available\n");
 		return 0;
 	}
 
diff --git a/fs/reiserfs/dev.c b/fs/reiserfs/dev.c
index 5a1ab0a..7b786e4 100644
--- a/fs/reiserfs/dev.c
+++ b/fs/reiserfs/dev.c
@@ -9,7 +9,7 @@
 #include <common.h>
 #include <config.h>
 #include <reiserfs.h>
-
+#include <fs_internal.h>
 #include "reiserfs_private.h"
 
 static struct blk_desc *reiserfs_blk_desc;
@@ -22,78 +22,8 @@
 	part_info = info;
 }
 
-
-int reiserfs_devread (int sector, int byte_offset, int byte_len, char *buf)
+int reiserfs_devread(int sector, int byte_offset, int byte_len, char *buf)
 {
-	char sec_buf[SECTOR_SIZE];
-	unsigned block_len;
-/*
-	unsigned len = byte_len;
-	u8 *start = buf;
-*/
-	/*
-	*  Check partition boundaries
-	*/
-	if (sector < 0
-	    || ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS))
-	    >= part_info->size)) {
-/*		errnum = ERR_OUTSIDE_PART; */
-		printf (" ** reiserfs_devread() read outside partition\n");
-		return 0;
-	}
-
-	/*
-	 *  Get the read to the beginning of a partition.
-	 */
-	sector += byte_offset >> SECTOR_BITS;
-	byte_offset &= SECTOR_SIZE - 1;
-
-#if defined(DEBUG)
-	printf (" <%d, %d, %d> ", sector, byte_offset, byte_len);
-#endif
-
-
-	if (reiserfs_blk_desc == NULL)
-		return 0;
-
-
-	if (byte_offset != 0) {
-		/* read first part which isn't aligned with start of sector */
-		if (reiserfs_blk_desc->block_read(reiserfs_blk_desc,
-						  part_info->start + sector,
-						  1, (void *)sec_buf) != 1) {
-			printf (" ** reiserfs_devread() read error\n");
-			return 0;
-		}
-		memcpy(buf, sec_buf+byte_offset, min(SECTOR_SIZE-byte_offset, byte_len));
-		buf+=min(SECTOR_SIZE-byte_offset, byte_len);
-		byte_len-=min(SECTOR_SIZE-byte_offset, byte_len);
-		sector++;
-	}
-
-	/* read sector aligned part */
-	block_len = byte_len & ~(SECTOR_SIZE-1);
-	if (reiserfs_blk_desc->block_read(reiserfs_blk_desc,
-					  part_info->start + sector,
-					  block_len / SECTOR_SIZE, (void *)buf)
-			!= block_len/SECTOR_SIZE) {
-		printf (" ** reiserfs_devread() read error - block\n");
-		return 0;
-	}
-	buf+=block_len;
-	byte_len-=block_len;
-	sector+= block_len/SECTOR_SIZE;
-
-	if ( byte_len != 0 ) {
-		/* read rest of data which are not in whole sector */
-		if (reiserfs_blk_desc->block_read(reiserfs_blk_desc,
-						  part_info->start + sector,
-						  1, (void *)sec_buf) != 1) {
-			printf (" ** reiserfs_devread() read error - last part\n");
-			return 0;
-		}
-		memcpy(buf, sec_buf, byte_len);
-	}
-
-	return 1;
+	return fs_devread(reiserfs_blk_desc, part_info, sector, byte_offset,
+			  byte_len, buf);
 }
diff --git a/fs/yaffs2/yaffs_uboot_glue.c b/fs/yaffs2/yaffs_uboot_glue.c
index bd66d316..2a70e4a 100644
--- a/fs/yaffs2/yaffs_uboot_glue.c
+++ b/fs/yaffs2/yaffs_uboot_glue.c
@@ -168,7 +168,7 @@
 
 	mtd = get_nand_dev_by_index(flash_dev);
 	if (!mtd) {
-		error("\nno NAND devices available\n");
+		pr_err("\nno NAND devices available\n");
 		return;
 	}
 
diff --git a/fs/zfs/dev.c b/fs/zfs/dev.c
index 2f409e6..7dda42b 100644
--- a/fs/zfs/dev.c
+++ b/fs/zfs/dev.c
@@ -11,6 +11,7 @@
 
 #include <common.h>
 #include <config.h>
+#include <fs_internal.h>
 #include <zfs_common.h>
 
 static struct blk_desc *zfs_blk_desc;
@@ -25,87 +26,6 @@
 /* err */
 int zfs_devread(int sector, int byte_offset, int byte_len, char *buf)
 {
-	short sec_buffer[SECTOR_SIZE/sizeof(short)];
-	char *sec_buf = (char *)sec_buffer;
-	unsigned block_len;
-
-	/*
-	 *	Check partition boundaries
-	 */
-	if ((sector < 0) ||
-		((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS)) >=
-		 part_info->size)) {
-		/*		errnum = ERR_OUTSIDE_PART; */
-		printf(" ** zfs_devread() read outside partition sector %d\n", sector);
-		return 1;
-	}
-
-	/*
-	 *	Get the read to the beginning of a partition.
-	 */
-	sector += byte_offset >> SECTOR_BITS;
-	byte_offset &= SECTOR_SIZE - 1;
-
-	debug(" <%d, %d, %d>\n", sector, byte_offset, byte_len);
-
-	if (zfs_blk_desc == NULL) {
-		printf("** Invalid Block Device Descriptor (NULL)\n");
-		return 1;
-	}
-
-	if (byte_offset != 0) {
-		/* read first part which isn't aligned with start of sector */
-		if (zfs_blk_desc->block_read(zfs_blk_desc,
-					     part_info->start + sector, 1,
-					     (void *)sec_buf) != 1) {
-			printf(" ** zfs_devread() read error **\n");
-			return 1;
-		}
-		memcpy(buf, sec_buf + byte_offset,
-			   min(SECTOR_SIZE - byte_offset, byte_len));
-		buf += min(SECTOR_SIZE - byte_offset, byte_len);
-		byte_len -= min(SECTOR_SIZE - byte_offset, byte_len);
-		sector++;
-	}
-
-	if (byte_len == 0)
-		return 0;
-
-	/*	read sector aligned part */
-	block_len = byte_len & ~(SECTOR_SIZE - 1);
-
-	if (block_len == 0) {
-		u8 p[SECTOR_SIZE];
-
-		block_len = SECTOR_SIZE;
-		zfs_blk_desc->block_read(zfs_blk_desc,
-					 part_info->start + sector,
-					 1, (void *)p);
-		memcpy(buf, p, byte_len);
-		return 0;
-	}
-
-	if (zfs_blk_desc->block_read(zfs_blk_desc, part_info->start + sector,
-				     block_len / SECTOR_SIZE,
-				     (void *)buf) != block_len / SECTOR_SIZE) {
-		printf(" ** zfs_devread() read error - block\n");
-		return 1;
-	}
-
-	block_len = byte_len & ~(SECTOR_SIZE - 1);
-	buf += block_len;
-	byte_len -= block_len;
-	sector += block_len / SECTOR_SIZE;
-
-	if (byte_len != 0) {
-		/* read rest of data which are not in whole sector */
-		if (zfs_blk_desc->block_read(zfs_blk_desc,
-					     part_info->start + sector,
-					     1, (void *)sec_buf) != 1) {
-			printf(" ** zfs_devread() read error - last part\n");
-			return 1;
-		}
-		memcpy(buf, sec_buf, byte_len);
-	}
-	return 0;
+	return fs_devread(zfs_blk_desc, part_info, sector, byte_offset,
+			  byte_len, buf);
 }
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
new file mode 100644
index 0000000..0f5160c
--- /dev/null
+++ b/include/asm-generic/io.h
@@ -0,0 +1,110 @@
+/*
+ * Generic I/O functions.
+ *
+ * Copyright (c) 2016 Imagination Technologies Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __ASM_GENERIC_IO_H__
+#define __ASM_GENERIC_IO_H__
+
+/*
+ * This file should be included at the end of each architecture-specific
+ * asm/io.h such that we may provide generic implementations without
+ * conflicting with architecture-specific code.
+ */
+
+#ifndef __ASSEMBLY__
+
+/**
+ * phys_to_virt() - Return a virtual address mapped to a given physical address
+ * @paddr: the physical address
+ *
+ * Returns a virtual address which the CPU can access that maps to the physical
+ * address @paddr. This should only be used where it is known that no dynamic
+ * mapping is required. In general, map_physmem should be used instead.
+ *
+ * Returns: a virtual address which maps to @paddr
+ */
+#ifndef phys_to_virt
+static inline void *phys_to_virt(phys_addr_t paddr)
+{
+	return (void *)(unsigned long)paddr;
+}
+#endif
+
+/**
+ * virt_to_phys() - Return the physical address that a virtual address maps to
+ * @vaddr: the virtual address
+ *
+ * Returns the physical address which the CPU-accessible virtual address @vaddr
+ * maps to.
+ *
+ * Returns: the physical address which @vaddr maps to
+ */
+#ifndef virt_to_phys
+static inline phys_addr_t virt_to_phys(void *vaddr)
+{
+	return (phys_addr_t)((unsigned long)vaddr);
+}
+#endif
+
+/*
+ * Flags for use with map_physmem() & unmap_physmem(). Architectures need not
+ * support all of these, in which case they will be defined as zero here &
+ * ignored. Callers that may run on multiple architectures should therefore
+ * treat them as hints rather than requirements.
+ */
+#ifndef MAP_NOCACHE
+# define MAP_NOCACHE	0	/* Produce an uncached mapping */
+#endif
+#ifndef MAP_WRCOMBINE
+# define MAP_WRCOMBINE	0	/* Allow write-combining on the mapping */
+#endif
+#ifndef MAP_WRBACK
+# define MAP_WRBACK	0	/* Map using write-back caching */
+#endif
+#ifndef MAP_WRTHROUGH
+# define MAP_WRTHROUGH	0	/* Map using write-through caching */
+#endif
+
+/**
+ * map_physmem() - Return a virtual address mapped to a given physical address
+ * @paddr: the physical address
+ * @len: the length of the required mapping
+ * @flags: flags affecting the type of mapping
+ *
+ * Return a virtual address through which the CPU may access the memory at
+ * physical address @paddr. The mapping will be valid for at least @len bytes,
+ * and may be affected by flags passed to the @flags argument. This function
+ * may create new mappings, so should generally be paired with a matching call
+ * to unmap_physmem once the caller is finished with the memory in question.
+ *
+ * Returns: a virtual address suitably mapped to @paddr
+ */
+#ifndef map_physmem
+static inline void *map_physmem(phys_addr_t paddr, unsigned long len,
+				unsigned long flags)
+{
+	return phys_to_virt(paddr);
+}
+#endif
+
+/**
+ * unmap_physmem() - Remove mappings created by a prior call to map_physmem()
+ * @vaddr: the virtual address which map_physmem() previously returned
+ * @flags: flags matching those originally passed to map_physmem()
+ *
+ * Unmap memory which was previously mapped by a call to map_physmem(). If
+ * map_physmem() dynamically created a mapping for the memory in question then
+ * unmap_physmem() will remove that mapping.
+ */
+#ifndef unmap_physmem
+static inline void unmap_physmem(void *vaddr, unsigned long flags)
+{
+}
+#endif
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_GENERIC_IO_H__ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index daf021b..b653570 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -22,8 +22,8 @@
 extern char __entry_text_start[], __entry_text_end[];
 extern char __initdata_begin[], __initdata_end[];
 extern char __start_rodata[], __end_rodata[];
-extern char __efi_hello_world_begin[];
-extern char __efi_hello_world_end[];
+extern char __efi_helloworld_begin[];
+extern char __efi_helloworld_end[];
 
 /* Start and end of .ctors section - used for constructor calls. */
 extern char __ctors_start[], __ctors_end[];
diff --git a/include/blk.h b/include/blk.h
index 1965812..41b4d7e 100644
--- a/include/blk.h
+++ b/include/blk.h
@@ -8,6 +8,8 @@
 #ifndef BLK_H
 #define BLK_H
 
+#include <efi.h>
+
 #ifdef CONFIG_SYS_64BIT_LBA
 typedef uint64_t lbaint_t;
 #define LBAFlength "ll"
@@ -41,6 +43,17 @@
 #define BLK_REV_SIZE		8
 
 /*
+ * Identifies the partition table type (ie. MBR vs GPT GUID) signature
+ */
+enum sig_type {
+	SIG_TYPE_NONE,
+	SIG_TYPE_MBR,
+	SIG_TYPE_GUID,
+
+	SIG_TYPE_COUNT			/* Number of signature types */
+};
+
+/*
  * With driver model (CONFIG_BLK) this is uclass platform data, accessible
  * with dev_get_uclass_platdata(dev)
  */
@@ -67,6 +80,11 @@
 	char		vendor[BLK_VEN_SIZE + 1]; /* device vendor string */
 	char		product[BLK_PRD_SIZE + 1]; /* device product number */
 	char		revision[BLK_REV_SIZE + 1]; /* firmware revision */
+	enum sig_type	sig_type;	/* Partition table signature type */
+	union {
+		uint32_t mbr_sig;	/* MBR integer signature */
+		efi_guid_t guid_sig;	/* GPT GUID Signature */
+	};
 #if CONFIG_IS_ENABLED(BLK)
 	/*
 	 * For now we have a few functions which take struct blk_desc as a
diff --git a/include/boot_fit.h b/include/boot_fit.h
index b7d2462..e16ae5b 100644
--- a/include/boot_fit.h
+++ b/include/boot_fit.h
@@ -5,5 +5,10 @@
  * SPDX-License-Identifier:     GPL-2.0+
  */
 
-int fdt_offset(void *fit);
-void *locate_dtb_in_fit(void *fit);
+/**
+ * locate_dtb_in_fit - Find a DTB matching the board in a FIT image
+ * @fit:	pointer to the FIT image
+ *
+ * @return a pointer to a matching DTB blob if found, NULL otherwise
+ */
+void *locate_dtb_in_fit(const void *fit);
diff --git a/include/btrfs.h b/include/btrfs.h
new file mode 100644
index 0000000..7390975
--- /dev/null
+++ b/include/btrfs.h
@@ -0,0 +1,21 @@
+/*
+ * BTRFS filesystem implementation for U-Boot
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __U_BOOT_BTRFS_H__
+#define __U_BOOT_BTRFS_H__
+
+int btrfs_probe(struct blk_desc *, disk_partition_t *);
+int btrfs_ls(const char *);
+int btrfs_exists(const char *);
+int btrfs_size(const char *, loff_t *);
+int btrfs_read(const char *, void *, loff_t, loff_t, loff_t *);
+void btrfs_close(void);
+int btrfs_uuid(char *);
+void btrfs_list_subvols(void);
+
+#endif /* __U_BOOT_BTRFS_H__ */
diff --git a/include/common.h b/include/common.h
index aaed131..4b521e1 100644
--- a/include/common.h
+++ b/include/common.h
@@ -23,12 +23,15 @@
 #include <time.h>
 #include <asm-offsets.h>
 #include <linux/bitops.h>
+#include <linux/bug.h>
 #include <linux/delay.h>
 #include <linux/types.h>
+#include <linux/printk.h>
 #include <linux/string.h>
 #include <linux/stringify.h>
 #include <asm/ptrace.h>
 #include <stdarg.h>
+#include <stdio.h>
 #include <linux/kernel.h>
 
 #include <part.h>
@@ -54,11 +57,6 @@
 #define _SPL_BUILD	0
 #endif
 
-/* Define this at the top of a file to add a prefix to debug messages */
-#ifndef pr_fmt
-#define pr_fmt(fmt) fmt
-#endif
-
 /*
  * Output a debug text when condition "cond" is met. The "cond" should be
  * computed by a preprocessor in the best case, allowing for the best
@@ -93,19 +91,6 @@
 	({ if (!(x) && _DEBUG) \
 		__assert_fail(#x, __FILE__, __LINE__, __func__); })
 
-#define error(fmt, args...) do {					\
-		printf("ERROR: " pr_fmt(fmt) "\nat %s:%d/%s()\n",	\
-			##args, __FILE__, __LINE__, __func__);		\
-} while (0)
-
-#ifndef BUG
-#define BUG() do { \
-	printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \
-	panic("BUG!"); \
-} while (0)
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-#endif /* BUG */
-
 typedef void (interrupt_handler_t)(void *);
 
 #include <asm/u-boot.h> /* boot information for Linux kernel */
@@ -624,6 +609,7 @@
 ulong	ticks2usec    (unsigned long ticks);
 
 /* lib/gunzip.c */
+int gzip_parse_header(const unsigned char *src, unsigned long len);
 int gunzip(void *, int, unsigned char *, unsigned long *);
 int zunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp,
 						int stoponerr, int offset);
@@ -699,46 +685,6 @@
 /* serial stuff */
 int	serial_printf (const char *fmt, ...)
 		__attribute__ ((format (__printf__, 1, 2)));
-/* stdin */
-int	getc(void);
-int	tstc(void);
-
-/* stdout */
-#if !defined(CONFIG_SPL_BUILD) || \
-	(defined(CONFIG_TPL_BUILD) && defined(CONFIG_TPL_SERIAL_SUPPORT)) || \
-	(defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD) && \
-		defined(CONFIG_SPL_SERIAL_SUPPORT))
-void	putc(const char c);
-void	puts(const char *s);
-int	printf(const char *fmt, ...)
-		__attribute__ ((format (__printf__, 1, 2)));
-int	vprintf(const char *fmt, va_list args);
-#else
-#define	putc(...) do { } while (0)
-#define puts(...) do { } while (0)
-#define printf(...) do { } while (0)
-#define vprintf(...) do { } while (0)
-#endif
-
-/* stderr */
-#define eputc(c)		fputc(stderr, c)
-#define eputs(s)		fputs(stderr, s)
-#define eprintf(fmt,args...)	fprintf(stderr,fmt ,##args)
-
-/*
- * FILE based functions (can only be used AFTER relocation!)
- */
-#define stdin		0
-#define stdout		1
-#define stderr		2
-#define MAX_FILES	3
-
-int	fprintf(int file, const char *fmt, ...)
-		__attribute__ ((format (__printf__, 2, 3)));
-void	fputs(int file, const char *s);
-void	fputc(int file, const char c);
-int	ftstc(int file);
-int	fgetc(int file);
 
 /* lib/gzip.c */
 int gzip(void *dst, unsigned long *lenp,
diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
index 9ed6b98..e0d0034 100644
--- a/include/config_distro_bootcmd.h
+++ b/include/config_distro_bootcmd.h
@@ -112,6 +112,11 @@
 
 #define BOOTENV_SHARED_EFI                                                \
 	"boot_efi_binary="                                                \
+		"if fdt addr ${fdt_addr_r}; then "                        \
+			"bootefi bootmgr ${fdt_addr_r};"                  \
+		"else "                                                   \
+			"bootefi bootmgr ${fdtcontroladdr};"              \
+		"fi;"                                                     \
 		"load ${devtype} ${devnum}:${distro_bootpart} "           \
 			"${kernel_addr_r} efi/boot/"BOOTEFI_NAME"; "      \
 		"if fdt addr ${fdt_addr_r}; then "                        \
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index 415ce46..9629467 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -263,12 +263,6 @@
 #define CONFIG_AM335X_USB1
 #define CONFIG_AM335X_USB1_MODE MUSB_HOST
 
-#ifdef CONFIG_USB_MUSB_GADGET
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_RNDIS
-#define CONFIG_USBNET_HOST_ADDR	"de:ad:be:af:00:00"
-#endif /* CONFIG_USB_MUSB_GADGET */
-
 /*
  * Disable MMC DM for SPL build and can be re-enabled after adding
  * DM support in SPL
diff --git a/include/configs/am3517_evm.h b/include/configs/am3517_evm.h
index 708a98f..43fcfb2 100644
--- a/include/configs/am3517_evm.h
+++ b/include/configs/am3517_evm.h
@@ -21,6 +21,7 @@
  * header. That is 0x800FFFC0--0x80100000 should not be used for any
  * other needs.
  */
+
 #define CONFIG_SYS_TEXT_BASE		0x80100000
 #define CONFIG_SYS_SPL_MALLOC_START	0x80208000
 #define CONFIG_SYS_SPL_MALLOC_SIZE	0x100000
@@ -33,16 +34,6 @@
 
 /* Hardware drivers */
 
-/* NS16550 Configuration */
-#define CONFIG_SYS_NS16550_SERIAL
-#define CONFIG_SYS_NS16550_REG_SIZE	(-4)
-
-/* select serial console configuration */
-#define CONFIG_CONS_INDEX		3
-#define CONFIG_SYS_NS16550_COM3		OMAP34XX_UART3
-#define CONFIG_SERIAL3			3	/* UART3 on AM3517 EVM */
-
-
 /* allow to overwrite serial and ethaddr */
 #define CONFIG_ENV_OVERWRITE
 
@@ -64,15 +55,9 @@
 
 #endif /* CONFIG_USB_MUSB_HOST */
 
-#ifdef CONFIG_USB_MUSB_GADGET
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_RNDIS
-#endif /* CONFIG_USB_MUSB_GADGET */
-
 #endif /* CONFIG_USB_MUSB_AM35X */
 
 /* I2C */
-#define CONFIG_SYS_I2C
 #define CONFIG_SYS_OMAP24_I2C_SPEED	100000
 #define CONFIG_SYS_OMAP24_I2C_SLAVE	1
 
@@ -250,8 +235,6 @@
 #define CONFIG_SPL_FRAMEWORK
 #undef CONFIG_SPL_TEXT_BASE
 #define CONFIG_SPL_TEXT_BASE		0x40200000
-#define CONFIG_SPL_MAX_SIZE		(SRAM_SCRATCH_SPACE_ADDR - \
-					 CONFIG_SPL_TEXT_BASE)
 
 #undef CONFIG_SPL_BSS_START_ADDR
 #define CONFIG_SPL_BSS_START_ADDR	0x80000000
diff --git a/include/configs/am43xx_evm.h b/include/configs/am43xx_evm.h
index b84f6e3..743f953 100644
--- a/include/configs/am43xx_evm.h
+++ b/include/configs/am43xx_evm.h
@@ -89,9 +89,9 @@
 
 #undef CONFIG_USB_GADGET_DOWNLOAD
 #undef CONFIG_USB_GADGET_VBUS_DRAW
-#undef CONFIG_G_DNL_MANUFACTURER
-#undef CONFIG_G_DNL_VENDOR_NUM
-#undef CONFIG_G_DNL_PRODUCT_NUM
+#undef CONFIG_USB_GADGET_MANUFACTURER
+#undef CONFIG_USB_GADGET_VENDOR_NUM
+#undef CONFIG_USB_GADGET_PRODUCT_NUM
 #undef CONFIG_USB_GADGET_DUALSPEED
 #endif
 
@@ -326,4 +326,9 @@
 #define NANDBOOT
 #endif /* CONFIG_NAND */
 
+#if defined(CONFIG_TI_SECURE_DEVICE)
+/* Avoid relocating onto firewalled area at end of DRAM */
+#define CONFIG_PRAM (64 * 1024)
+#endif /* CONFIG_TI_SECURE_DEVICE */
+
 #endif	/* __CONFIG_AM43XX_EVM_H */
diff --git a/include/configs/am57xx_evm.h b/include/configs/am57xx_evm.h
index 0c70c53..5427974 100644
--- a/include/configs/am57xx_evm.h
+++ b/include/configs/am57xx_evm.h
@@ -44,7 +44,8 @@
 #define PARTS_DEFAULT \
 	/* Linux partitions */ \
 	"uuid_disk=${uuid_gpt_disk};" \
-	"name=rootfs,start=2MiB,size=-,uuid=${uuid_gpt_rootfs}\0" \
+	"name=bootloader,start=384K,size=1792K,uuid=${uuid_gpt_bootloader};" \
+	"name=rootfs,start=2688K,size=-,uuid=${uuid_gpt_rootfs}\0" \
 	/* Android partitions */ \
 	"partitions_android=" \
 	"uuid_disk=${uuid_gpt_disk};" \
@@ -72,7 +73,6 @@
 #include <configs/ti_omap5_common.h>
 
 /* Enhance our eMMC support / experience. */
-#define CONFIG_RANDOM_UUID
 #define CONFIG_HSMMC2_8BIT
 
 /* CPSW Ethernet */
diff --git a/include/configs/baltos.h b/include/configs/baltos.h
index 185c749..44af4d3 100644
--- a/include/configs/baltos.h
+++ b/include/configs/baltos.h
@@ -283,12 +283,6 @@
 #define CONFIG_AM335X_USB1
 #define CONFIG_AM335X_USB1_MODE MUSB_OTG
 
-#ifdef CONFIG_USB_MUSB_GADGET
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_RNDIS
-#define CONFIG_USBNET_HOST_ADDR	"de:ad:be:af:00:00"
-#endif /* CONFIG_USB_MUSB_GADGET */
-
 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_USBETH_SUPPORT)
 /* disable host part of MUSB in SPL */
 /* disable EFI partitions and partition UUID support */
diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h
index c05c64c..821b1fe 100644
--- a/include/configs/da850evm.h
+++ b/include/configs/da850evm.h
@@ -21,6 +21,16 @@
 #endif
 
 /*
+* Disable DM_* for SPL build and can be re-enabled after adding
+* DM support in SPL
+*/
+#ifdef CONFIG_SPL_BUILD
+#undef CONFIG_DM_SPI
+#undef CONFIG_DM_SPI_FLASH
+#undef CONFIG_DM_I2C
+#undef CONFIG_DM_I2C_COMPAT
+#endif
+/*
  * SoC Configuration
  */
 #define CONFIG_MACH_DAVINCI_DA850_EVM
@@ -130,18 +140,23 @@
 /*
  * Serial Driver info
  */
+
+#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_DIRECT_NOR_BOOT)
 #define CONFIG_SYS_NS16550_SERIAL
 #define CONFIG_SYS_NS16550_REG_SIZE	-4	/* NS16550 register size */
 #define CONFIG_SYS_NS16550_COM1	DAVINCI_UART2_BASE /* Base address of UART2 */
+#endif
 #define CONFIG_SYS_NS16550_CLK	clk_get(DAVINCI_UART2_CLKID)
 #define CONFIG_CONS_INDEX	1		/* use UART0 for console */
 
 #define CONFIG_SPI
 #define CONFIG_DAVINCI_SPI
-#define CONFIG_SYS_SPI_BASE		DAVINCI_SPI1_BASE
 #define CONFIG_SYS_SPI_CLK		clk_get(DAVINCI_SPI1_CLKID)
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_SPI_BASE		DAVINCI_SPI1_BASE
 #define CONFIG_SF_DEFAULT_SPEED		30000000
 #define CONFIG_ENV_SPI_MAX_HZ	CONFIG_SF_DEFAULT_SPEED
+#endif
 
 #ifdef CONFIG_USE_SPIFLASH
 #define CONFIG_SPL_SPI_LOAD
@@ -152,11 +167,10 @@
 /*
  * I2C Configuration
  */
-#define CONFIG_SYS_I2C
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_SYS_I2C_DAVINCI
-#define CONFIG_SYS_DAVINCI_I2C_SPEED		25000
-#define CONFIG_SYS_DAVINCI_I2C_SLAVE   10 /* Bogus, master-only in U-Boot */
 #define CONFIG_SYS_I2C_EXPANDER_ADDR   0x20
+#endif
 
 /*
  * Flash & Environment
@@ -234,6 +248,17 @@
 #define CONFIG_ENV_SIZE			(64 << 10)
 #define CONFIG_ENV_OFFSET		(512 << 10)
 #define CONFIG_ENV_SECT_SIZE		(64 << 10)
+#ifdef CONFIG_SPL_BUILD
+#undef CONFIG_SPI_FLASH_MTD
+#endif
+#define CONFIG_MTD_DEVICE		/* needed for mtdparts commands */
+#define CONFIG_MTD_PARTITIONS		/* required for UBI partition support */
+#define MTDIDS_DEFAULT			"nor0=spi0.0"
+#define MTDPARTS_DEFAULT		"mtdparts=spi0.0:"\
+						"512k(u-boot.ais),"\
+						"64k(u-boot-env),"\
+						"7552k(kernel-spare),"\
+						"64k(MAC-Address)"
 #endif
 
 /*
@@ -257,7 +282,29 @@
 #define CONFIG_CMDLINE_TAG
 #define CONFIG_REVISION_TAG
 #define CONFIG_SETUP_MEMORY_TAGS
-#define CONFIG_EXTRA_ENV_SETTINGS	"hwconfig=dsp:wake=yes"
+
+#define CONFIG_BOOTCOMMAND \
+		"run envboot; " \
+		"run mmcboot; "
+
+#define DEFAULT_LINUX_BOOT_ENV \
+	"loadaddr=0xc0700000\0" \
+	"fdtaddr=0xc0600000\0" \
+	"scriptaddr=0xc0600000\0"
+
+#include <environment/ti/mmc.h>
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	DEFAULT_LINUX_BOOT_ENV \
+	DEFAULT_MMC_TI_ARGS \
+	"bootpart=0:2\0" \
+	"bootdir=/boot\0" \
+	"bootfile=zImage\0" \
+	"fdtfile=da850-evm.dtb\0" \
+	"boot_fdt=yes\0" \
+	"boot_fit=0\0" \
+	"console=ttyS2,115200n8\0" \
+	"hwconfig=dsp:wake=yes"
 
 #ifdef CONFIG_CMD_BDI
 #define CONFIG_CLOCKS
diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h
index 6c0fc35..717861f 100644
--- a/include/configs/dra7xx_evm.h
+++ b/include/configs/dra7xx_evm.h
@@ -51,7 +51,8 @@
 #define PARTS_DEFAULT \
 	/* Linux partitions */ \
 	"uuid_disk=${uuid_gpt_disk};" \
-	"name=rootfs,start=2MiB,size=-,uuid=${uuid_gpt_rootfs}\0" \
+	"name=bootloader,start=384K,size=1792K,uuid=${uuid_gpt_bootloader};" \
+	"name=rootfs,start=2688K,size=-,uuid=${uuid_gpt_rootfs}\0" \
 	/* Android partitions */ \
 	"partitions_android=" \
 	"uuid_disk=${uuid_gpt_disk};" \
@@ -91,7 +92,6 @@
 #include <configs/ti_omap5_common.h>
 
 /* Enhance our eMMC support / experience. */
-#define CONFIG_RANDOM_UUID
 #define CONFIG_HSMMC2_8BIT
 
 /* CPSW Ethernet */
diff --git a/include/configs/edison.h b/include/configs/edison.h
index d25b50c..79dd690 100644
--- a/include/configs/edison.h
+++ b/include/configs/edison.h
@@ -9,11 +9,13 @@
 
 #include <asm/ibmpc.h>
 
+/* ACPI */
+#define CONFIG_LAST_STAGE_INIT
+
 /* Boot */
 #define CONFIG_BOOTCOMMAND "run bootcmd"
 
 /* DISK Partition support */
-#define CONFIG_RANDOM_UUID
 
 /* Miscellaneous configurable options */
 #define CONFIG_SYS_LONGHELP
diff --git a/include/configs/evb_rk3399.h b/include/configs/evb_rk3399.h
index 015f25a..66ead6c 100644
--- a/include/configs/evb_rk3399.h
+++ b/include/configs/evb_rk3399.h
@@ -10,12 +10,6 @@
 #include <configs/rk3399_common.h>
 
 #define CONFIG_SYS_MMC_ENV_DEV 1
-/*
- * SPL @ 32k for ~36k
- * ENV @ 96k
- * u-boot @ 128K
- */
-#define CONFIG_ENV_OFFSET (96 * 1024)
 
 #define SDRAM_BANK_SIZE			(2UL << 30)
 
diff --git a/include/configs/gw_ventana.h b/include/configs/gw_ventana.h
index 128a6e5..a93172a 100644
--- a/include/configs/gw_ventana.h
+++ b/include/configs/gw_ventana.h
@@ -146,8 +146,6 @@
 #define CONFIG_MXC_USB_PORTSC     (PORT_PTS_UTMI | PORT_PTS_PTW)
 #define CONFIG_MXC_USB_FLAGS      0
 #define CONFIG_USBD_HS
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_CDC
 #define CONFIG_NETCONSOLE
 
 /* USB Mass Storage Gadget */
diff --git a/include/configs/h2200.h b/include/configs/h2200.h
index 870014d..24ff53f 100644
--- a/include/configs/h2200.h
+++ b/include/configs/h2200.h
@@ -123,11 +123,9 @@
 	"bootm ; "
 
 #define CONFIG_USB_GADGET_PXA2XX
-#define CONFIG_USB_ETHER
 #define CONFIG_USB_ETH_SUBSET
 
 #define CONFIG_USBNET_DEV_ADDR		"de:ad:be:ef:00:01"
-#define CONFIG_USBNET_HOST_ADDR	"de:ad:be:ef:00:02"
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	"stdin=serial\0" \
 	"stdout=serial\0" \
diff --git a/include/configs/k2g_evm.h b/include/configs/k2g_evm.h
index 1950740..df81c09 100644
--- a/include/configs/k2g_evm.h
+++ b/include/configs/k2g_evm.h
@@ -38,7 +38,7 @@
 			 "setenv name_fdt keystone-k2g-ice.dtb; " \
 		"else if test $name_fdt = undefined; then " \
 			"echo WARNING: Could not determine device tree to use;"\
-		"fi;fi;fi;\0" \
+		"fi;fi;fi; setenv fdtfile ${name_fdt}\0" \
 	"name_mon=skern-k2g.bin\0"					\
 	"name_ubi=k2g-evm-ubifs.ubi\0"					\
 	"name_uboot=u-boot-spi-k2g-evm.gph\0"				\
diff --git a/include/configs/ma5d4evk.h b/include/configs/ma5d4evk.h
index 0fe1bc1..5ecc97f 100644
--- a/include/configs/ma5d4evk.h
+++ b/include/configs/ma5d4evk.h
@@ -100,9 +100,6 @@
 #ifdef CONFIG_CMD_USB
 
 /* USB device */
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_RNDIS
-#define CONFIG_USBNET_MANUFACTURER      "AriesEmbedded"
 #define CONFIG_USB_FUNCTION_MASS_STORAGE
 #define CONFIG_SYS_DFU_DATA_BUF_SIZE	(1 * 1024 * 1024)
 #define DFU_DEFAULT_POLL_TIMEOUT	300
diff --git a/include/configs/nitrogen6x.h b/include/configs/nitrogen6x.h
index 520a52c..b847906 100644
--- a/include/configs/nitrogen6x.h
+++ b/include/configs/nitrogen6x.h
@@ -19,8 +19,6 @@
 
 #define CONFIG_MISC_INIT_R
 #define CONFIG_USBD_HS
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_CDC
 #define CONFIG_NETCONSOLE
 
 #define CONFIG_MXC_UART
diff --git a/include/configs/novena.h b/include/configs/novena.h
index 4480aaf..ac00975 100644
--- a/include/configs/novena.h
+++ b/include/configs/novena.h
@@ -129,8 +129,6 @@
 #define CONFIG_MXC_USB_FLAGS		0
 /* Gadget part */
 #define CONFIG_USBD_HS
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_CDC
 #define CONFIG_NETCONSOLE
 #endif
 
diff --git a/include/configs/odroid.h b/include/configs/odroid.h
index 2afb19f..22e9c82 100644
--- a/include/configs/odroid.h
+++ b/include/configs/odroid.h
@@ -174,7 +174,6 @@
 	"fdtaddr=40800000\0"
 
 /* GPT */
-#define CONFIG_RANDOM_UUID
 
 /* Security subsystem - enable hw_rand() */
 #define CONFIG_EXYNOS_ACE_SHA
diff --git a/include/configs/odroid_xu3.h b/include/configs/odroid_xu3.h
index 8bc7fbd..13a4501 100644
--- a/include/configs/odroid_xu3.h
+++ b/include/configs/odroid_xu3.h
@@ -45,7 +45,7 @@
 #define DFU_MANIFEST_POLL_TIMEOUT       25000
 
 /* THOR */
-#define CONFIG_G_DNL_THOR_VENDOR_NUM	CONFIG_G_DNL_VENDOR_NUM
+#define CONFIG_G_DNL_THOR_VENDOR_NUM	CONFIG_USB_GADGET_VENDOR_NUM
 #define CONFIG_G_DNL_THOR_PRODUCT_NUM	0x685D
 #define CONFIG_USB_FUNCTION_THOR
 
diff --git a/include/configs/omap3_beagle.h b/include/configs/omap3_beagle.h
index 47a50bd..06232bd 100644
--- a/include/configs/omap3_beagle.h
+++ b/include/configs/omap3_beagle.h
@@ -46,7 +46,6 @@
 #define CONFIG_USB_MUSB_OMAP2PLUS
 #define CONFIG_USB_MUSB_PIO_ONLY
 #define CONFIG_TWL4030_USB		1
-#define CONFIG_USB_ETHER
 
 /* USB EHCI */
 
diff --git a/include/configs/omap3_evm.h b/include/configs/omap3_evm.h
index e9a1cad..3618d0e 100644
--- a/include/configs/omap3_evm.h
+++ b/include/configs/omap3_evm.h
@@ -81,7 +81,6 @@
 #define CONFIG_USB_OMAP3
 #define CONFIG_USB_MUSB_OMAP2PLUS
 #define CONFIG_USB_MUSB_PIO_ONLY
-#define CONFIG_USB_ETHER
 
 /* USB EHCI */
 #define CONFIG_SYS_USB_FAT_BOOT_PARTITION  1
diff --git a/include/configs/omap3_logic.h b/include/configs/omap3_logic.h
index 5b31223..f7db79d 100644
--- a/include/configs/omap3_logic.h
+++ b/include/configs/omap3_logic.h
@@ -57,7 +57,6 @@
 /* USB */
 #define CONFIG_USB_MUSB_OMAP2PLUS
 #define CONFIG_USB_MUSB_PIO_ONLY
-#define CONFIG_USB_ETHER
 
 /* TWL4030 */
 #define CONFIG_TWL4030_USB
diff --git a/include/configs/pcm051.h b/include/configs/pcm051.h
index f678b29..79f3f48 100644
--- a/include/configs/pcm051.h
+++ b/include/configs/pcm051.h
@@ -133,11 +133,6 @@
 #define CONFIG_AM335X_USB1
 #define CONFIG_AM335X_USB1_MODE MUSB_HOST
 
-#ifdef CONFIG_USB_MUSB_GADGET
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_RNDIS
-#endif /* CONFIG_USB_MUSB_GADGET */
-
 #define CONFIG_PHY_SMSC
 
 #endif	/* ! __CONFIG_PCM051_H */
diff --git a/include/configs/qemu-arm.h b/include/configs/qemu-arm.h
new file mode 100644
index 0000000..4376a24
--- /dev/null
+++ b/include/configs/qemu-arm.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017 Tuomas Tynkkynen
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <linux/sizes.h>
+
+/* Physical memory map */
+#define CONFIG_SYS_TEXT_BASE		0x00000000
+
+#define CONFIG_NR_DRAM_BANKS		1
+#define CONFIG_SYS_SDRAM_BASE		0x40000000
+
+/* The DTB generated by QEMU is placed at start of RAM, stay away from there */
+#define CONFIG_SYS_INIT_SP_ADDR         (CONFIG_SYS_SDRAM_BASE + SZ_2M)
+#define CONFIG_SYS_LOAD_ADDR		(CONFIG_SYS_SDRAM_BASE + SZ_2M)
+#define CONFIG_SYS_MALLOC_LEN		SZ_16M
+
+/* QEMU's PL011 serial port is detected via FDT using the device model */
+#define CONFIG_PL01X_SERIAL
+
+/* QEMU implements a 62.5MHz architected timer */
+/* FIXME: can we rely on CNTFREQ instead of hardcoding this fact here? */
+#define CONFIG_SYS_ARCH_TIMER
+#define CONFIG_SYS_HZ                       1000
+#define CONFIG_SYS_HZ_CLOCK                 62500000
+
+/* For block devices, QEMU emulates an ICH9 AHCI controller over PCI */
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID 6
+#define CONFIG_SCSI_AHCI
+#define CONFIG_LIBATA
+
+/* Environment options */
+#define CONFIG_ENV_SIZE				SZ_64K
+
+#include <config_distro_defaults.h>
+
+#define BOOT_TARGET_DEVICES(func) \
+	func(SCSI, scsi, 0)
+
+#include <config_distro_bootcmd.h>
+
+#define CONFIG_PREBOOT "pci enum"
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"fdt_high=0xffffffff\0" \
+	"initrd_high=0xffffffff\0" \
+	"fdt_addr=0x40000000\0" \
+	"scriptaddr=0x40200000\0" \
+	"pxefile_addr_r=0x40300000\0" \
+	"kernel_addr_r=0x40400000\0" \
+	"ramdisk_addr_r=0x44000000\0" \
+	BOOTENV
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
index e9e3c40..34f2558 100644
--- a/include/configs/rk3288_common.h
+++ b/include/configs/rk3288_common.h
@@ -32,7 +32,11 @@
 #define CONFIG_SYS_INIT_SP_ADDR		0x00100000
 #define CONFIG_SYS_LOAD_ADDR		0x00800800
 #define CONFIG_SPL_STACK		0xff718000
-#define CONFIG_SPL_TEXT_BASE		0xff704004
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_TPL_BOOTROM_SUPPORT)
+# define CONFIG_SPL_TEXT_BASE		0x0
+#else
+# define CONFIG_SPL_TEXT_BASE		0xff704004
+#endif
 
 /* MMC/SD IP block */
 #define CONFIG_BOUNCE_BUFFER
diff --git a/include/configs/rockchip-common.h b/include/configs/rockchip-common.h
index b3986c2..5e9b6de 100644
--- a/include/configs/rockchip-common.h
+++ b/include/configs/rockchip-common.h
@@ -27,8 +27,6 @@
 	func(DHCP, dchp, na)
 #endif
 
-#define CONFIG_RANDOM_UUID
-
 #ifdef CONFIG_ARM64
 #define ROOT_UUID "B921B045-1DF0-41C3-AF44-4C6F280D3FAE;\0"
 #else
diff --git a/include/configs/sama5d2_ptc.h b/include/configs/sama5d2_ptc.h
index 3ae16df..c52dcd4 100644
--- a/include/configs/sama5d2_ptc.h
+++ b/include/configs/sama5d2_ptc.h
@@ -62,9 +62,6 @@
 #endif
 
 /* USB device */
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_RNDIS
-#define CONFIG_USBNET_MANUFACTURER      "Atmel SAMA5D2_PTC"
 
 /* Ethernet Hardware */
 #define CONFIG_MACB
diff --git a/include/configs/sansa_fuze_plus.h b/include/configs/sansa_fuze_plus.h
index 250917b..9920014 100644
--- a/include/configs/sansa_fuze_plus.h
+++ b/include/configs/sansa_fuze_plus.h
@@ -39,8 +39,6 @@
 #define CONFIG_EHCI_MXS_PORT0
 #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
 
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_CDC
 #define CONFIG_NETCONSOLE
 #endif
 
diff --git a/include/configs/siemens-am33x-common.h b/include/configs/siemens-am33x-common.h
index 2314a2d..1997c2d 100644
--- a/include/configs/siemens-am33x-common.h
+++ b/include/configs/siemens-am33x-common.h
@@ -178,12 +178,6 @@
 #define CONFIG_AM335X_USB1
 #define CONFIG_AM335X_USB1_MODE MUSB_HOST
 
-#ifdef CONFIG_USB_MUSB_GADGET
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_RNDIS
-#define CONFIG_USBNET_HOST_ADDR	"de:ad:be:af:00:00"
-#endif /* CONFIG_USB_MUSB_GADGET */
-
 /* USB DRACO ID as default */
 #define CONFIG_USBD_HS
 
diff --git a/include/configs/stih410-b2260.h b/include/configs/stih410-b2260.h
index 372c083..958d5cc 100644
--- a/include/configs/stih410-b2260.h
+++ b/include/configs/stih410-b2260.h
@@ -12,16 +12,35 @@
 #define CONFIG_NR_DRAM_BANKS		1
 #define PHYS_SDRAM_1			0x40000000
 #define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
-#define PHYS_SDRAM_1_SIZE		0x3FE00000
+#define PHYS_SDRAM_1_SIZE		0x3E000000
 #define CONFIG_SYS_TEXT_BASE		0x7D600000
 #define CONFIG_SYS_LOAD_ADDR		PHYS_SDRAM_1	/* default load addr */
 
 #define CONFIG_SYS_HZ_CLOCK		1000000000	/* 1 GHz */
 
+#include <config_distro_defaults.h>
 /* Environment */
-#define CONFIG_EXTRA_ENV_SETTINGS \
-	"board= B2260" \
-	"load_addr= #CONFIG_SYS_LOAD_ADDR \0"
+
+#define CONFIG_LOADADDR			CONFIG_SYS_LOAD_ADDR
+
+#define CONFIG_ENV_VARS_UBOOT_CONFIG
+
+#define BOOT_TARGET_DEVICES(func) \
+	func(MMC, mmc, 0) \
+	func(USB, usb, 0) \
+	func(DHCP, dhcp, na)
+#include <config_distro_bootcmd.h>
+#define CONFIG_BOOTFILE			"uImage"
+#define CONFIG_EXTRA_ENV_SETTINGS				\
+			"kernel_addr_r=0x40000000\0"		\
+			"fdtfile=stih410-b2260.dtb\0"		\
+			"fdt_addr_r=0x47000000\0"		\
+			"scriptaddr=0x50000000\0"		\
+			"fdt_high=0xffffffffffffffff\0"		\
+			"initrd_high=0xffffffffffffffff\0"	\
+			"ramdisk_addr_r=0x48000000\0"		\
+			BOOTENV
+
 
 #define CONFIG_ENV_SIZE 0x4000
 
diff --git a/include/configs/stm32h743-disco.h b/include/configs/stm32h743-disco.h
index b0061cd..967c5e5 100644
--- a/include/configs/stm32h743-disco.h
+++ b/include/configs/stm32h743-disco.h
@@ -11,7 +11,7 @@
 #include <config.h>
 
 #define CONFIG_SYS_FLASH_BASE		0x08000000
-#define CONFIG_SYS_INIT_SP_ADDR		0x30020000
+#define CONFIG_SYS_INIT_SP_ADDR		0x24040000
 #define CONFIG_SYS_TEXT_BASE		0x08000000
 
 /*
diff --git a/include/configs/stm32h743-eval.h b/include/configs/stm32h743-eval.h
index b0061cd..967c5e5 100644
--- a/include/configs/stm32h743-eval.h
+++ b/include/configs/stm32h743-eval.h
@@ -11,7 +11,7 @@
 #include <config.h>
 
 #define CONFIG_SYS_FLASH_BASE		0x08000000
-#define CONFIG_SYS_INIT_SP_ADDR		0x30020000
+#define CONFIG_SYS_INIT_SP_ADDR		0x24040000
 #define CONFIG_SYS_TEXT_BASE		0x08000000
 
 /*
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 02d7be0..9175117 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -148,7 +148,13 @@
 #endif
 
 #if defined(CONFIG_ENV_IS_IN_MMC)
-#define CONFIG_SYS_MMC_ENV_DEV		0	/* first detected MMC controller */
+#if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1
+/* If we have two devices (most likely eMMC + MMC), favour the eMMC */
+#define CONFIG_SYS_MMC_ENV_DEV		1
+#else
+/* Otherwise, use the only device we have */
+#define CONFIG_SYS_MMC_ENV_DEV		0
+#endif
 #define CONFIG_SYS_MMC_MAX_DEVICE	4
 #elif defined(CONFIG_ENV_IS_NOWHERE)
 #define CONFIG_ENV_SIZE			(128 << 10)
@@ -382,15 +388,28 @@
 	"ramdisk ram " RAMDISK_ADDR_R " 0x4000000\0"
 
 #ifdef CONFIG_MMC
-#define BOOT_TARGET_DEVICES_MMC(func) func(MMC, mmc, 0)
 #if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1
-#define BOOT_TARGET_DEVICES_MMC_EXTRA(func) func(MMC, mmc, 1)
+#define BOOTENV_DEV_MMC_AUTO(devtypeu, devtypel, instance)		\
+	BOOTENV_DEV_MMC(MMC, mmc, 0)					\
+	BOOTENV_DEV_MMC(MMC, mmc, 1)					\
+	"bootcmd_mmc_auto="						\
+		"if test ${mmc_bootdev} -eq 1; then "			\
+			"run bootcmd_mmc1; "				\
+			"run bootcmd_mmc0; "				\
+		"elif test ${mmc_bootdev} -eq 0; then "			\
+			"run bootcmd_mmc0; "				\
+			"run bootcmd_mmc1; "				\
+		"fi\0"
+
+#define BOOTENV_DEV_NAME_MMC_AUTO(devtypeu, devtypel, instance) \
+	"mmc_auto "
+
+#define BOOT_TARGET_DEVICES_MMC(func) func(MMC_AUTO, mmc_auto, na)
 #else
-#define BOOT_TARGET_DEVICES_MMC_EXTRA(func)
+#define BOOT_TARGET_DEVICES_MMC(func) func(MMC, mmc, 0)
 #endif
 #else
 #define BOOT_TARGET_DEVICES_MMC(func)
-#define BOOT_TARGET_DEVICES_MMC_EXTRA(func)
 #endif
 
 #ifdef CONFIG_AHCI
@@ -418,7 +437,6 @@
 #define BOOT_TARGET_DEVICES(func) \
 	func(FEL, fel, na) \
 	BOOT_TARGET_DEVICES_MMC(func) \
-	BOOT_TARGET_DEVICES_MMC_EXTRA(func) \
 	BOOT_TARGET_DEVICES_SCSI(func) \
 	BOOT_TARGET_DEVICES_USB(func) \
 	func(PXE, pxe, na) \
diff --git a/include/configs/tao3530.h b/include/configs/tao3530.h
index b4311d9..f19a230 100644
--- a/include/configs/tao3530.h
+++ b/include/configs/tao3530.h
@@ -212,8 +212,6 @@
 /* USB EHCI */
 #define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO	162
 
-#define CONFIG_USB_ETHER
-
 /* Defines for SPL */
 #define CONFIG_SPL_FRAMEWORK
 #define CONFIG_SPL_NAND_SIMPLE
diff --git a/include/configs/theadorable-x86-common.h b/include/configs/theadorable-x86-common.h
index 238056a..c20803c 100644
--- a/include/configs/theadorable-x86-common.h
+++ b/include/configs/theadorable-x86-common.h
@@ -46,7 +46,7 @@
 	"yocto_tty=" __stringify(DEF_ENV_YOCTO_TTY) "\0"	\
 	"start_eth=if test -n \"${eth_init}\";"			\
 		"then run eth_init;else sleep 0;fi\0"		\
-	"kernel-ver=4.8.0-54\0"					\
+	"kernel-ver=4.8.0-54-generic\0"				\
 	"boot=zboot 03000000 0 04000000 ${filesize}\0"		\
 	"mtdparts=mtdparts=intel-spi:4k(descriptor),7084k(me)," \
 		"8k(env1),8k(env2),64k(mrc),640k(u-boot),"	\
@@ -58,7 +58,8 @@
 	"addmtd=setenv bootargs ${bootargs} ${mtdparts}\0"	\
 	"addmisc=setenv bootargs ${bootargs} "			\
 		"intel-spi.writeable=1 vmalloc=300M "		\
-		"pci=realloc=on,hpmemsize=0x12000000\0"		\
+		"pci=realloc=on,hpmemsize=0x12000000,"		\
+		"hpmemprefsize=0,hpiosize=0\0"	    		\
 	"bootcmd=if env exists recovery_status;"		\
 		"then run swupdate;"				\
 		"else run yocto_boot;run swupdate;"		\
@@ -68,9 +69,9 @@
 	"ubuntu_args_quiet=setenv bootargs "			\
 		"root=/dev/sda${ubuntu_part} ro quiet\0"	\
 	"ubuntu_load=load scsi 0:${ubuntu_part} 03000000 "	\
-		"/boot/vmlinuz-${kernel-ver}-generic;"		\
+		"/boot/vmlinuz-${kernel-ver};"			\
 		"load scsi 0:${ubuntu_part} 04000000 "		\
-		"/boot/initrd.img-${kernel-ver}-generic\0"	\
+		"/boot/initrd.img-${kernel-ver}\0"		\
 	"ubuntu_boot=run ubuntu_args_quiet addmtd addmisc "	\
 		"ubuntu_load boot\0"				\
 	"ubuntu_boot_console=run ubuntu_args addtty_ubuntu "	\
@@ -79,7 +80,7 @@
 	"net_boot=run start_eth net_args addtty_yocto addmtd addmisc;" \
 		"tftp 03000000 ${tftpdir}/bzImage;"		\
 		"load scsi 0:${ubuntu_part} 04000000 "		\
-		"/boot/initrd.img-${kernel-ver}-generic;"	\
+		"/boot/initrd.img-${kernel-ver};"		\
 		"run boot\0"					\
 	"yocto_args=setenv bootargs root=/dev/sda${yocto_part} " \
 		"panic=1\0"				\
diff --git a/include/configs/ti_armv7_keystone2.h b/include/configs/ti_armv7_keystone2.h
index 2b2b85d..53046a2 100644
--- a/include/configs/ti_armv7_keystone2.h
+++ b/include/configs/ti_armv7_keystone2.h
@@ -270,7 +270,7 @@
 					"${bootdir}/${fit_bootfile}\0"	\
 	"get_uboot_net=dhcp ${loadaddr} ${tftp_root}/${name_uboot}\0"	\
 	"get_uboot_nfs=nfs ${loadaddr} ${nfs_root}/boot/${name_uboot}\0" \
-	"burn_uboot_spi=sf probe; sf erase 0 0x80000; "		\
+	"burn_uboot_spi=sf probe; sf erase 0 0x90000; "		\
 		"sf write ${loadaddr} 0 ${filesize}\0"		\
 	"burn_uboot_nand=nand erase 0 0x100000; "			\
 		"nand write ${loadaddr} 0 ${filesize}\0"		\
diff --git a/include/configs/trats.h b/include/configs/trats.h
index 5d0a324..5b33a3b 100644
--- a/include/configs/trats.h
+++ b/include/configs/trats.h
@@ -168,7 +168,6 @@
 #define CONFIG_SYS_SPL_ARGS_ADDR        CONFIG_SYS_SDRAM_BASE + 0x100
 
 /* GPT */
-#define CONFIG_RANDOM_UUID
 
 /* Security subsystem - enable hw_rand() */
 #define CONFIG_EXYNOS_ACE_SHA
diff --git a/include/configs/trats2.h b/include/configs/trats2.h
index 7f6a61a..95c011f 100644
--- a/include/configs/trats2.h
+++ b/include/configs/trats2.h
@@ -150,7 +150,6 @@
 	"fdtaddr=40800000\0" \
 
 /* GPT */
-#define CONFIG_RANDOM_UUID
 
 /* Security subsystem - enable hw_rand() */
 #define CONFIG_EXYNOS_ACE_SHA
diff --git a/include/configs/vinco.h b/include/configs/vinco.h
index aaed815..0084051 100644
--- a/include/configs/vinco.h
+++ b/include/configs/vinco.h
@@ -62,14 +62,10 @@
 #define CONFIG_SYS_MMC_CLK_OD		500000
 
 /* For generating MMC partitions */
-#define CONFIG_RANDOM_UUID
 
 #endif
 
 /* USB device */
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_RNDIS
-#define CONFIG_USBNET_MANUFACTURER      "L+G VInCo"
 
 /* Ethernet Hardware */
 #define CONFIG_PHY_SMSC
diff --git a/include/configs/vyasa-rk3288.h b/include/configs/vyasa-rk3288.h
index 9d6c80f..8774e42 100644
--- a/include/configs/vyasa-rk3288.h
+++ b/include/configs/vyasa-rk3288.h
@@ -20,4 +20,21 @@
 #define CONFIG_SYS_MMC_ENV_DEV 1
 #undef CONFIG_CMD_USB_MASS_STORAGE
 
+#ifndef CONFIG_TPL_BUILD
+
+#define CONFIG_SPL_OS_BOOT
+
+/* Falcon Mode */
+#define CONFIG_SPL_FS_LOAD_ARGS_NAME	"args"
+#define CONFIG_SPL_FS_LOAD_KERNEL_NAME	"uImage"
+#define CONFIG_CMD_SPL
+#define CONFIG_SYS_SPL_ARGS_ADDR	0x0ffe5000
+#define CONFIG_CMD_SPL_WRITE_SIZE      (128 * SZ_1K)
+
+/* Falcon Mode - MMC support: args@1MB kernel@2MB */
+#define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR  0x800   /* 1MB */
+#define CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS (CONFIG_CMD_SPL_WRITE_SIZE / 512)
+#define CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR        0x1000  /* 2MB */
+#endif
+
 #endif
diff --git a/include/configs/warp7.h b/include/configs/warp7.h
index 75ae8a3..11f1bc3 100644
--- a/include/configs/warp7.h
+++ b/include/configs/warp7.h
@@ -136,10 +136,6 @@
 #define CONFIG_SYS_DFU_DATA_BUF_SIZE	SZ_16M
 #define DFU_DEFAULT_POLL_TIMEOUT	300
 
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_CDC
-#define CONFIG_USB_ETH_RNDIS
-#define CONFIG_USBNET_HOST_ADDR		"de:ad:be:af:00:00"
 #define CONFIG_USBNET_DEV_ADDR		"de:ad:be:af:00:01"
 
 #endif
diff --git a/include/configs/xfi3.h b/include/configs/xfi3.h
index 73f4316..1e70a76 100644
--- a/include/configs/xfi3.h
+++ b/include/configs/xfi3.h
@@ -39,8 +39,6 @@
 #define CONFIG_EHCI_MXS_PORT0
 #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
 
-#define CONFIG_USB_ETHER
-#define CONFIG_USB_ETH_CDC
 #define CONFIG_NETCONSOLE
 #endif
 
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index 6025706..1399dfd 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -103,7 +103,6 @@
 		DFU_ALT_INFO_RAM
 
 #ifndef CONFIG_SPL_BUILD
-# define CONFIG_RANDOM_UUID
 # define PARTS_DEFAULT \
 	"partitions=uuid_disk=${uuid_gpt_disk};" \
 	"name=""boot"",size=16M,uuid=${uuid_gpt_boot};" \
diff --git a/include/dm/device.h b/include/dm/device.h
index 4866f7c..813e49f 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -18,6 +18,7 @@
 #include <linux/compat.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/printk.h>
 
 struct driver_info;
 
@@ -879,4 +880,75 @@
 
 #endif /* ! CONFIG_DEVRES */
 
+/*
+ * REVISIT:
+ * remove the following after resolving conflicts with <linux/compat.h>
+ */
+#ifdef dev_dbg
+#undef dev_dbg
+#endif
+#ifdef dev_vdbg
+#undef dev_vdbg
+#endif
+#ifdef dev_info
+#undef dev_info
+#endif
+#ifdef dev_err
+#undef dev_err
+#endif
+#ifdef dev_warn
+#undef dev_warn
+#endif
+
+/*
+ * REVISIT:
+ * print device name like Linux
+ */
+#define dev_printk(dev, fmt, ...)				\
+({								\
+	printk(fmt, ##__VA_ARGS__);				\
+})
+
+#define __dev_printk(level, dev, fmt, ...)			\
+({								\
+	if (level < CONFIG_VAL(LOGLEVEL))			\
+		dev_printk(dev, fmt, ##__VA_ARGS__);		\
+})
+
+#define dev_emerg(dev, fmt, ...) \
+	__dev_printk(0, dev, fmt, ##__VA_ARGS__)
+#define dev_alert(dev, fmt, ...) \
+	__dev_printk(1, dev, fmt, ##__VA_ARGS__)
+#define dev_crit(dev, fmt, ...) \
+	__dev_printk(2, dev, fmt, ##__VA_ARGS__)
+#define dev_err(dev, fmt, ...) \
+	__dev_printk(3, dev, fmt, ##__VA_ARGS__)
+#define dev_warn(dev, fmt, ...) \
+	__dev_printk(4, dev, fmt, ##__VA_ARGS__)
+#define dev_notice(dev, fmt, ...) \
+	__dev_printk(5, dev, fmt, ##__VA_ARGS__)
+#define dev_info(dev, fmt, ...) \
+	__dev_printk(6, dev, fmt, ##__VA_ARGS__)
+
+#ifdef DEBUG
+#define dev_dbg(dev, fmt, ...) \
+	__dev_printk(7, dev, fmt, ##__VA_ARGS__)
+#else
+#define dev_dbg(dev, fmt, ...)					\
+({								\
+	if (0)							\
+		__dev_printk(7, dev, fmt, ##__VA_ARGS__);	\
+})
+#endif
+
+#ifdef VERBOSE_DEBUG
+#define dev_vdbg	dev_dbg
+#else
+#define dev_vdbg(dev, fmt, ...)					\
+({								\
+	if (0)							\
+		__dev_printk(7, dev, fmt, ##__VA_ARGS__);	\
+})
+#endif
+
 #endif
diff --git a/include/dm/util.h b/include/dm/util.h
index 45529ce..0d4ce8f 100644
--- a/include/dm/util.h
+++ b/include/dm/util.h
@@ -15,14 +15,6 @@
 }
 #endif
 
-#ifdef DEBUG
-void dm_dbg(const char *fmt, ...);
-#else
-static inline void dm_dbg(const char *fmt, ...)
-{
-}
-#endif
-
 struct list_head;
 
 /**
diff --git a/include/dt-bindings/clock/rv1108-cru.h b/include/dt-bindings/clock/rv1108-cru.h
index d2ad3bb..7defc6b 100644
--- a/include/dt-bindings/clock/rv1108-cru.h
+++ b/include/dt-bindings/clock/rv1108-cru.h
@@ -39,6 +39,7 @@
 #define SCLK_MAC_TX			88
 #define SCLK_MACREF			89
 #define SCLK_MACREF_OUT			90
+#define SCLK_SARADC			91
 
 
 /* aclk gates */
@@ -67,6 +68,7 @@
 #define PCLK_TIMER			270
 #define PCLK_PERI			271
 #define PCLK_GMAC			272
+#define PCLK_SARADC			273
 
 /* hclk gates */
 #define HCLK_I2S0_8CH			320
diff --git a/include/dt-bindings/clock/sun8i-a23-a33-ccu.h b/include/dt-bindings/clock/sun8i-a23-a33-ccu.h
new file mode 100644
index 0000000..f8222b6
--- /dev/null
+++ b/include/dt-bindings/clock/sun8i-a23-a33-ccu.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN8I_A23_A33_H_
+#define _DT_BINDINGS_CLK_SUN8I_A23_A33_H_
+
+#define CLK_CPUX		18
+
+#define CLK_BUS_MIPI_DSI	23
+#define CLK_BUS_SS		24
+#define CLK_BUS_DMA		25
+#define CLK_BUS_MMC0		26
+#define CLK_BUS_MMC1		27
+#define CLK_BUS_MMC2		28
+#define CLK_BUS_NAND		29
+#define CLK_BUS_DRAM		30
+#define CLK_BUS_HSTIMER		31
+#define CLK_BUS_SPI0		32
+#define CLK_BUS_SPI1		33
+#define CLK_BUS_OTG		34
+#define CLK_BUS_EHCI		35
+#define CLK_BUS_OHCI		36
+#define CLK_BUS_VE		37
+#define CLK_BUS_LCD		38
+#define CLK_BUS_CSI		39
+#define CLK_BUS_DE_BE		40
+#define CLK_BUS_DE_FE		41
+#define CLK_BUS_GPU		42
+#define CLK_BUS_MSGBOX		43
+#define CLK_BUS_SPINLOCK	44
+#define CLK_BUS_DRC		45
+#define CLK_BUS_SAT		46
+#define CLK_BUS_CODEC		47
+#define CLK_BUS_PIO		48
+#define CLK_BUS_I2S0		49
+#define CLK_BUS_I2S1		50
+#define CLK_BUS_I2C0		51
+#define CLK_BUS_I2C1		52
+#define CLK_BUS_I2C2		53
+#define CLK_BUS_UART0		54
+#define CLK_BUS_UART1		55
+#define CLK_BUS_UART2		56
+#define CLK_BUS_UART3		57
+#define CLK_BUS_UART4		58
+#define CLK_NAND		59
+#define CLK_MMC0		60
+#define CLK_MMC0_SAMPLE		61
+#define CLK_MMC0_OUTPUT		62
+#define CLK_MMC1		63
+#define CLK_MMC1_SAMPLE		64
+#define CLK_MMC1_OUTPUT		65
+#define CLK_MMC2		66
+#define CLK_MMC2_SAMPLE		67
+#define CLK_MMC2_OUTPUT		68
+#define CLK_SS			69
+#define CLK_SPI0		70
+#define CLK_SPI1		71
+#define CLK_I2S0		72
+#define CLK_I2S1		73
+#define CLK_USB_PHY0		74
+#define CLK_USB_PHY1		75
+#define CLK_USB_HSIC		76
+#define CLK_USB_HSIC_12M	77
+#define CLK_USB_OHCI		78
+
+#define CLK_DRAM_VE		80
+#define CLK_DRAM_CSI		81
+#define CLK_DRAM_DRC		82
+#define CLK_DRAM_DE_FE		83
+#define CLK_DRAM_DE_BE		84
+#define CLK_DE_BE		85
+#define CLK_DE_FE		86
+#define CLK_LCD_CH0		87
+#define CLK_LCD_CH1		88
+#define CLK_CSI_SCLK		89
+#define CLK_CSI_MCLK		90
+#define CLK_VE			91
+#define CLK_AC_DIG		92
+#define CLK_AC_DIG_4X		93
+#define CLK_AVS			94
+
+#define CLK_DSI_SCLK		96
+#define CLK_DSI_DPHY		97
+#define CLK_DRC			98
+#define CLK_GPU			99
+#define CLK_ATS			100
+
+#endif /* _DT_BINDINGS_CLK_SUN8I_A23_A33_H_ */
diff --git a/include/dt-bindings/reset/sun8i-a23-a33-ccu.h b/include/dt-bindings/reset/sun8i-a23-a33-ccu.h
new file mode 100644
index 0000000..6121f2b
--- /dev/null
+++ b/include/dt-bindings/reset/sun8i-a23-a33-ccu.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN8I_A23_A33_H_
+#define _DT_BINDINGS_RST_SUN8I_A23_A33_H_
+
+#define RST_USB_PHY0		0
+#define RST_USB_PHY1		1
+#define RST_USB_HSIC		2
+#define RST_MBUS		3
+#define RST_BUS_MIPI_DSI	4
+#define RST_BUS_SS		5
+#define RST_BUS_DMA		6
+#define RST_BUS_MMC0		7
+#define RST_BUS_MMC1		8
+#define RST_BUS_MMC2		9
+#define RST_BUS_NAND		10
+#define RST_BUS_DRAM		11
+#define RST_BUS_HSTIMER		12
+#define RST_BUS_SPI0		13
+#define RST_BUS_SPI1		14
+#define RST_BUS_OTG		15
+#define RST_BUS_EHCI		16
+#define RST_BUS_OHCI		17
+#define RST_BUS_VE		18
+#define RST_BUS_LCD		19
+#define RST_BUS_CSI		20
+#define RST_BUS_DE_BE		21
+#define RST_BUS_DE_FE		22
+#define RST_BUS_GPU		23
+#define RST_BUS_MSGBOX		24
+#define RST_BUS_SPINLOCK	25
+#define RST_BUS_DRC		26
+#define RST_BUS_SAT		27
+#define RST_BUS_LVDS		28
+#define RST_BUS_CODEC		29
+#define RST_BUS_I2S0		30
+#define RST_BUS_I2S1		31
+#define RST_BUS_I2C0		32
+#define RST_BUS_I2C1		33
+#define RST_BUS_I2C2		34
+#define RST_BUS_UART0		35
+#define RST_BUS_UART1		36
+#define RST_BUS_UART2		37
+#define RST_BUS_UART3		38
+#define RST_BUS_UART4		39
+
+#endif /* _DT_BINDINGS_RST_SUN8I_A23_A33_H_ */
diff --git a/include/efi.h b/include/efi.h
index 02b78b3..dc8edc8 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -28,6 +28,10 @@
 
 struct efi_device_path;
 
+typedef struct {
+	u8 b[16];
+} efi_guid_t;
+
 #define EFI_BITS_PER_LONG	BITS_PER_LONG
 
 /*
@@ -77,6 +81,8 @@
 #define EFI_IP_ADDRESS_CONFLICT		(EFI_ERROR_MASK | 34)
 #define EFI_HTTP_ERROR			(EFI_ERROR_MASK | 35)
 
+#define EFI_WARN_DELETE_FAILURE	2
+
 typedef unsigned long efi_status_t;
 typedef u64 efi_physical_addr_t;
 typedef u64 efi_virtual_addr_t;
@@ -116,7 +122,7 @@
 	/* The code portions of a loaded Boot Services Driver */
 	EFI_BOOT_SERVICES_CODE,
 	/*
-	 * The data portions of a loaded Boot Serves Driver and
+	 * The data portions of a loaded Boot Services Driver and
 	 * the default data allocation type used by a Boot Services
 	 * Driver to allocate pool memory.
 	 */
@@ -318,6 +324,25 @@
 /* Start and end of U-Boot image (for payload) */
 extern char _binary_u_boot_bin_start[], _binary_u_boot_bin_end[];
 
+/*
+ * Variable Attributes
+ */
+#define EFI_VARIABLE_NON_VOLATILE       0x0000000000000001
+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
+#define EFI_VARIABLE_RUNTIME_ACCESS     0x0000000000000004
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020
+#define EFI_VARIABLE_APPEND_WRITE	0x0000000000000040
+
+#define EFI_VARIABLE_MASK	(EFI_VARIABLE_NON_VOLATILE | \
+				EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+				EFI_VARIABLE_RUNTIME_ACCESS | \
+				EFI_VARIABLE_HARDWARE_ERROR_RECORD | \
+				EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
+				EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \
+				EFI_VARIABLE_APPEND_WRITE)
+
 /**
  * efi_get_sys_table() - Get access to the main EFI system table
  *
diff --git a/include/efi_api.h b/include/efi_api.h
index ec1b321..c3b9032 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -29,6 +29,8 @@
 };
 
 #define UINTN size_t
+typedef long INTN;
+typedef uint16_t *efi_string_t;
 
 #define EVT_TIMER				0x80000000
 #define EVT_RUNTIME				0x40000000
@@ -211,6 +213,10 @@
 	EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, \
 		 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
 
+#define EFI_GLOBAL_VARIABLE_GUID \
+	EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, \
+		 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c)
+
 #define LOADED_IMAGE_PROTOCOL_GUID \
 	EFI_GUID(0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, \
 		 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
@@ -284,28 +290,93 @@
 	u8 type;
 	u8 sub_type;
 	u16 length;
-};
+} __packed;
 
 struct efi_mac_addr {
 	u8 addr[32];
-};
+} __packed;
+
+#define DEVICE_PATH_TYPE_HARDWARE_DEVICE	0x01
+#  define DEVICE_PATH_SUB_TYPE_VENDOR		0x04
+
+struct efi_device_path_vendor {
+	struct efi_device_path dp;
+	efi_guid_t guid;
+	u8 vendor_data[];
+} __packed;
+
+#define DEVICE_PATH_TYPE_ACPI_DEVICE		0x02
+#  define DEVICE_PATH_SUB_TYPE_ACPI_DEVICE	0x01
+
+#define EFI_PNP_ID(ID)				(u32)(((ID) << 16) | 0x41D0)
+#define EISA_PNP_ID(ID)				EFI_PNP_ID(ID)
+#define EISA_PNP_NUM(ID)			((ID) >> 16)
+
+struct efi_device_path_acpi_path {
+	struct efi_device_path dp;
+	u32 hid;
+	u32 uid;
+} __packed;
 
 #define DEVICE_PATH_TYPE_MESSAGING_DEVICE	0x03
+#  define DEVICE_PATH_SUB_TYPE_MSG_USB		0x05
 #  define DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR	0x0b
+#  define DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS	0x0f
+#  define DEVICE_PATH_SUB_TYPE_MSG_SD		0x1a
+#  define DEVICE_PATH_SUB_TYPE_MSG_MMC		0x1d
+
+struct efi_device_path_usb {
+	struct efi_device_path dp;
+	u8 parent_port_number;
+	u8 usb_interface;
+} __packed;
 
 struct efi_device_path_mac_addr {
 	struct efi_device_path dp;
 	struct efi_mac_addr mac;
 	u8 if_type;
-};
+} __packed;
+
+struct efi_device_path_usb_class {
+	struct efi_device_path dp;
+	u16 vendor_id;
+	u16 product_id;
+	u8 device_class;
+	u8 device_subclass;
+	u8 device_protocol;
+} __packed;
+
+struct efi_device_path_sd_mmc_path {
+	struct efi_device_path dp;
+	u8 slot_number;
+} __packed;
 
 #define DEVICE_PATH_TYPE_MEDIA_DEVICE		0x04
+#  define DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH	0x01
+#  define DEVICE_PATH_SUB_TYPE_CDROM_PATH	0x02
 #  define DEVICE_PATH_SUB_TYPE_FILE_PATH	0x04
 
+struct efi_device_path_hard_drive_path {
+	struct efi_device_path dp;
+	u32 partition_number;
+	u64 partition_start;
+	u64 partition_end;
+	u8 partition_signature[16];
+	u8 partmap_type;
+	u8 signature_type;
+} __packed;
+
+struct efi_device_path_cdrom_path {
+	struct efi_device_path dp;
+	u32 boot_entry;
+	u64 partition_start;
+	u64 partition_end;
+} __packed;
+
 struct efi_device_path_file_path {
 	struct efi_device_path dp;
-	u16 str[32];
-};
+	u16 str[];
+} __packed;
 
 #define BLOCK_IO_GUID \
 	EFI_GUID(0x964e5b21, 0x6459, 0x11d2, \
@@ -358,10 +429,10 @@
 	void *reset;
 	efi_status_t (EFIAPI *output_string)(
 			struct efi_simple_text_output_protocol *this,
-			const unsigned short *str);
+			const efi_string_t str);
 	efi_status_t (EFIAPI *test_string)(
 			struct efi_simple_text_output_protocol *this,
-			const unsigned short *str);
+			const efi_string_t str);
 	efi_status_t(EFIAPI *query_mode)(
 			struct efi_simple_text_output_protocol *this,
 			unsigned long mode_number, unsigned long *columns,
@@ -423,22 +494,14 @@
 	EFI_GUID(0x8b843e20, 0x8132, 0x4852, \
 		 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c)
 
-struct efi_device_path_protocol
-{
-	uint8_t type;
-	uint8_t sub_type;
-	uint16_t length;
-	uint8_t data[];
-};
-
 struct efi_device_path_to_text_protocol
 {
 	uint16_t *(EFIAPI *convert_device_node_to_text)(
-			struct efi_device_path_protocol *device_node,
+			struct efi_device_path *device_node,
 			bool display_only,
 			bool allow_shortcuts);
 	uint16_t *(EFIAPI *convert_device_path_to_text)(
-			struct efi_device_path_protocol *device_path,
+			struct efi_device_path *device_path,
 			bool display_only,
 			bool allow_shortcuts);
 };
@@ -609,4 +672,69 @@
 	struct efi_pxe_mode *mode;
 };
 
+#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \
+	EFI_GUID(0x964e5b22, 0x6459, 0x11d2, \
+		 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+#define EFI_FILE_PROTOCOL_REVISION 0x00010000
+
+struct efi_file_handle {
+	u64 rev;
+	efi_status_t (EFIAPI *open)(struct efi_file_handle *file,
+			struct efi_file_handle **new_handle,
+			s16 *file_name, u64 open_mode, u64 attributes);
+	efi_status_t (EFIAPI *close)(struct efi_file_handle *file);
+	efi_status_t (EFIAPI *delete)(struct efi_file_handle *file);
+	efi_status_t (EFIAPI *read)(struct efi_file_handle *file,
+			u64 *buffer_size, void *buffer);
+	efi_status_t (EFIAPI *write)(struct efi_file_handle *file,
+			u64 *buffer_size, void *buffer);
+	efi_status_t (EFIAPI *getpos)(struct efi_file_handle *file,
+			u64 *pos);
+	efi_status_t (EFIAPI *setpos)(struct efi_file_handle *file,
+			u64 pos);
+	efi_status_t (EFIAPI *getinfo)(struct efi_file_handle *file,
+			efi_guid_t *info_type, u64 *buffer_size, void *buffer);
+	efi_status_t (EFIAPI *setinfo)(struct efi_file_handle *file,
+			efi_guid_t *info_type, u64 buffer_size, void *buffer);
+	efi_status_t (EFIAPI *flush)(struct efi_file_handle *file);
+};
+
+#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \
+	EFI_GUID(0x964e5b22, 0x6459, 0x11d2, \
+		 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000
+
+struct efi_simple_file_system_protocol {
+	u64 rev;
+	efi_status_t (EFIAPI *open_volume)(struct efi_simple_file_system_protocol *this,
+			struct efi_file_handle **root);
+};
+
+#define EFI_FILE_INFO_GUID \
+	EFI_GUID(0x9576e92, 0x6d3f, 0x11d2, \
+		 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_FILE_MODE_READ	0x0000000000000001
+#define EFI_FILE_MODE_WRITE	0x0000000000000002
+#define EFI_FILE_MODE_CREATE	0x8000000000000000
+
+#define EFI_FILE_READ_ONLY	0x0000000000000001
+#define EFI_FILE_HIDDEN		0x0000000000000002
+#define EFI_FILE_SYSTEM		0x0000000000000004
+#define EFI_FILE_RESERVED	0x0000000000000008
+#define EFI_FILE_DIRECTORY	0x0000000000000010
+#define EFI_FILE_ARCHIVE	0x0000000000000020
+#define EFI_FILE_VALID_ATTR	0x0000000000000037
+
+struct efi_file_info {
+	u64 size;
+	u64 file_size;
+	u64 physical_size;
+	struct efi_time create_time;
+	struct efi_time last_access_time;
+	struct efi_time modification_time;
+	u64 attribute;
+	s16 file_name[0];
+};
+
 #endif
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 1179234..2f081f8 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -17,6 +17,7 @@
 
 int __efi_entry_check(void);
 int __efi_exit_check(void);
+const char *__efi_nesting(void);
 const char *__efi_nesting_inc(void);
 const char *__efi_nesting_dec(void);
 
@@ -41,9 +42,22 @@
 	})
 
 /*
- * Callback into UEFI world from u-boot:
+ * Call non-void UEFI function from u-boot and retrieve return value:
  */
-#define EFI_CALL(exp) do { \
+#define EFI_CALL(exp) ({ \
+	debug("%sEFI: Call: %s\n", __efi_nesting_inc(), #exp); \
+	assert(__efi_exit_check()); \
+	typeof(exp) _r = exp; \
+	assert(__efi_entry_check()); \
+	debug("%sEFI: %lu returned by %s\n", __efi_nesting_dec(), \
+	      (unsigned long)((uintptr_t)_r & ~EFI_ERROR_MASK), #exp); \
+	_r; \
+})
+
+/*
+ * Call void UEFI function from u-boot:
+ */
+#define EFI_CALL_VOID(exp) do { \
 	debug("%sEFI: Call: %s\n", __efi_nesting_inc(), #exp); \
 	assert(__efi_exit_check()); \
 	exp; \
@@ -51,6 +65,13 @@
 	debug("%sEFI: Return From: %s\n", __efi_nesting_dec(), #exp); \
 	} while(0)
 
+/*
+ * Write GUID
+ */
+#define EFI_PRINT_GUID(txt, guid) ({ \
+	debug("%sEFI: %s %pUl\n", __efi_nesting(), txt, guid); \
+	})
+
 extern struct efi_runtime_services efi_runtime_services;
 extern struct efi_system_table systab;
 
@@ -59,10 +80,15 @@
 extern const struct efi_console_control_protocol efi_console_control;
 extern const struct efi_device_path_to_text_protocol efi_device_path_to_text;
 
+uint16_t *efi_dp_str(struct efi_device_path *dp);
+
+extern const efi_guid_t efi_global_variable_guid;
 extern const efi_guid_t efi_guid_console_control;
 extern const efi_guid_t efi_guid_device_path;
 extern const efi_guid_t efi_guid_loaded_image;
 extern const efi_guid_t efi_guid_device_path_to_text_protocol;
+extern const efi_guid_t efi_simple_file_system_protocol_guid;
+extern const efi_guid_t efi_file_info_guid;
 
 extern unsigned int __efi_runtime_start, __efi_runtime_stop;
 extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop;
@@ -110,7 +136,8 @@
  * @nofify_function:	Function to call when the event is triggered
  * @notify_context:	Data to be passed to the notify function
  * @trigger_type:	Type of timer, see efi_set_timer
- * @signaled:		The notify function was already called
+ * @queued:		The notification functionis queued
+ * @signaled:		The event occured
  */
 struct efi_event {
 	uint32_t type;
@@ -120,6 +147,7 @@
 	u64 trigger_next;
 	u64 trigger_time;
 	enum efi_timer_delay trigger_type;
+	int queued;
 	int signaled;
 };
 
@@ -134,10 +162,13 @@
 /* Called by bootefi to make GOP (graphical) interface available */
 int efi_gop_register(void);
 /* Called by bootefi to make the network interface available */
-int efi_net_register(void **handle);
+int efi_net_register(void);
 /* Called by bootefi to make SMBIOS tables available */
 void efi_smbios_register(void);
 
+struct efi_simple_file_system_protocol *
+efi_fs_from_path(struct efi_device_path *fp);
+
 /* Called by networking code to memorize the dhcp ack package */
 void efi_net_set_dhcp_ack(void *pkt, int len);
 
@@ -166,6 +197,14 @@
 /* Call this to signal an event */
 void efi_signal_event(struct efi_event *event);
 
+/* open file system: */
+struct efi_simple_file_system_protocol *efi_simple_file_system(
+		struct blk_desc *desc, int part, struct efi_device_path *dp);
+
+/* open file from device-path: */
+struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp);
+
+
 /* Generic EFI memory allocator, call this to get memory */
 void *efi_alloc(uint64_t len, int memory_type);
 /* More specific EFI memory allocator, called by EFI payloads */
@@ -191,12 +230,43 @@
 int efi_memory_init(void);
 /* Adds new or overrides configuration table entry to the system table */
 efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table);
+void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj,
+			    struct efi_device_path *device_path,
+			    struct efi_device_path *file_path);
+efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
+				      void **buffer);
 
 #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
 extern void *efi_bounce_buffer;
 #define EFI_LOADER_BOUNCE_BUFFER_SIZE (64 * 1024 * 1024)
 #endif
 
+
+struct efi_device_path *efi_dp_next(const struct efi_device_path *dp);
+int efi_dp_match(struct efi_device_path *a, struct efi_device_path *b);
+struct efi_object *efi_dp_find_obj(struct efi_device_path *dp,
+				   struct efi_device_path **rem);
+unsigned efi_dp_size(const struct efi_device_path *dp);
+struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp);
+struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
+				      const struct efi_device_path *dp2);
+struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
+					   const struct efi_device_path *node);
+
+
+struct efi_device_path *efi_dp_from_dev(struct udevice *dev);
+struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part);
+struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
+					 const char *path);
+struct efi_device_path *efi_dp_from_eth(void);
+void efi_dp_split_file_path(struct efi_device_path *full_path,
+			    struct efi_device_path **device_path,
+			    struct efi_device_path **file_path);
+
+#define EFI_DP_TYPE(_dp, _type, _subtype) \
+	(((_dp)->type == DEVICE_PATH_TYPE_##_type) && \
+	 ((_dp)->sub_type == DEVICE_PATH_SUB_TYPE_##_subtype))
+
 /* Convert strings from normal C strings to uEFI strings */
 static inline void ascii2unicode(u16 *unicode, const char *ascii)
 {
@@ -233,6 +303,28 @@
 			struct efi_time_cap *capabilities);
 void efi_get_time_init(void);
 
+#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
+/*
+ * Entry point for the tests of the EFI API.
+ * It is called by 'bootefi selftest'
+ */
+efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
+				 struct efi_system_table *systab);
+#endif
+
+efi_status_t EFIAPI efi_get_variable(s16 *variable_name,
+		efi_guid_t *vendor, u32 *attributes,
+		unsigned long *data_size, void *data);
+efi_status_t EFIAPI efi_get_next_variable(
+		unsigned long *variable_name_size,
+		s16 *variable_name, efi_guid_t *vendor);
+efi_status_t EFIAPI efi_set_variable(s16 *variable_name,
+		efi_guid_t *vendor, u32 attributes,
+		unsigned long data_size, void *data);
+
+void *efi_bootmgr_load(struct efi_device_path **device_path,
+		       struct efi_device_path **file_path);
+
 #else /* defined(EFI_LOADER) && !defined(CONFIG_SPL_BUILD) */
 
 /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
diff --git a/include/efi_selftest.h b/include/efi_selftest.h
new file mode 100644
index 0000000..76304a2
--- /dev/null
+++ b/include/efi_selftest.h
@@ -0,0 +1,91 @@
+/*
+ *  EFI application loader
+ *
+ *  Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef _EFI_SELFTEST_H
+#define _EFI_SELFTEST_H
+
+#include <common.h>
+#include <efi.h>
+#include <efi_api.h>
+#include <linker_lists.h>
+
+/*
+ * Prints an error message.
+ *
+ * @...	format string followed by fields to print
+ */
+#define efi_st_error(...) \
+	efi_st_printf("%s(%u):\nERROR: ", __FILE__, __LINE__); \
+	efi_st_printf(__VA_ARGS__) \
+
+/*
+ * A test may be setup and executed at boottime,
+ * it may be setup at boottime and executed at runtime,
+ * or it may be setup and executed at runtime.
+ */
+enum efi_test_phase {
+	EFI_EXECUTE_BEFORE_BOOTTIME_EXIT = 1,
+	EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+	EFI_SETUP_AFTER_BOOTTIME_EXIT,
+};
+
+extern struct efi_simple_text_output_protocol *con_out;
+extern struct efi_simple_input_interface *con_in;
+
+/*
+ * Exit the boot services.
+ *
+ * The size of the memory map is determined.
+ * Pool memory is allocated to copy the memory map.
+ * The memory amp is copied and the map key is obtained.
+ * The map key is used to exit the boot services.
+ */
+void efi_st_exit_boot_services(void);
+
+/*
+ * Print a pointer to an u16 string
+ *
+ * @pointer: pointer
+ * @buf: pointer to buffer address
+ * on return position of terminating zero word
+ */
+void efi_st_printf(const char *fmt, ...)
+		 __attribute__ ((format (__printf__, 1, 2)));
+
+/*
+ * Reads an Unicode character from the input device.
+ *
+ * @return: Unicode character
+ */
+u16 efi_st_get_key(void);
+
+/**
+ * struct efi_unit_test - EFI unit test
+ *
+ * An efi_unit_test provides a interface to an EFI unit test.
+ *
+ * @name:	name of unit test
+ * @phase:	specifies when setup and execute are executed
+ * @setup:	set up the unit test
+ * @teardown:	tear down the unit test
+ * @execute:	execute the unit test
+ */
+struct efi_unit_test {
+	const char *name;
+	const enum efi_test_phase phase;
+	int (*setup)(const efi_handle_t handle,
+		     const struct efi_system_table *systable);
+	int (*execute)(void);
+	int (*teardown)(void);
+};
+
+/* Declare a new EFI unit test */
+#define EFI_UNIT_TEST(__name)						\
+	ll_entry_declare(struct efi_unit_test, __name, efi_unit_test)
+
+#endif /* _EFI_SELFTEST_H */
diff --git a/include/environment/ti/boot.h b/include/environment/ti/boot.h
index 5b1b97b..799d984 100644
--- a/include/environment/ti/boot.h
+++ b/include/environment/ti/boot.h
@@ -29,7 +29,14 @@
 	"partitions=" PARTS_DEFAULT "\0" \
 	"optargs=\0" \
 	"dofastboot=0\0" \
+	"emmc_linux_boot=" \
+		"echo Trying to boot Linux from eMMC ...; " \
+		"setenv mmcdev 1; " \
+		"setenv bootpart 1:2; " \
+		"setenv mmcroot /dev/mmcblk0p2 rw; " \
+		"run mmcboot;\0" \
 	"emmc_android_boot=" \
+		"echo Trying to boot Android from eMMC ...; " \
 		"setenv eval_bootargs setenv bootargs $bootargs; " \
 		"run eval_bootargs; " \
 		"setenv mmcdev 1; " \
@@ -44,7 +51,6 @@
 		"part size mmc ${mmcdev} ${boot_part} boot_size; " \
 		"mmc read ${fdtaddr} ${fdt_start} ${fdt_size}; " \
 		"mmc read ${loadaddr} ${boot_start} ${boot_size}; " \
-		"echo Booting from eMMC ...; " \
 		"bootm $loadaddr $loadaddr $fdtaddr;\0"
 
 #ifdef CONFIG_OMAP54XX
@@ -93,10 +99,7 @@
 	"run findfdt; " \
 	"run envboot; " \
 	"run mmcboot;" \
-	"setenv mmcdev 1; " \
-	"setenv bootpart 1:2; " \
-	"setenv mmcroot /dev/mmcblk0p2 rw; " \
-	"run mmcboot;" \
+	"run emmc_linux_boot; " \
 	"run emmc_android_boot; " \
 	""
 
diff --git a/include/fs.h b/include/fs.h
index 0869ad6..32fc480 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -13,6 +13,7 @@
 #define FS_TYPE_EXT	2
 #define FS_TYPE_SANDBOX	3
 #define FS_TYPE_UBIFS	4
+#define FS_TYPE_BTRFS	5
 
 /*
  * Tell the fs layer which block device an partition to use for future
diff --git a/include/fs_internal.h b/include/fs_internal.h
new file mode 100644
index 0000000..9d6dddd
--- /dev/null
+++ b/include/fs_internal.h
@@ -0,0 +1,17 @@
+/*
+ * 2017 by Marek Behun <marek.behun@nic.cz>
+ *
+ * Derived from code in ext4/dev.c, which was based on reiserfs/dev.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __U_BOOT_FS_INTERNAL_H__
+#define __U_BOOT_FS_INTERNAL_H__
+
+#include <part.h>
+
+int fs_devread(struct blk_desc *, disk_partition_t *, lbaint_t, int, int,
+	       char *);
+
+#endif /* __U_BOOT_FS_INTERNAL_H__ */
diff --git a/include/image.h b/include/image.h
index af98ed9..93451dd 100644
--- a/include/image.h
+++ b/include/image.h
@@ -1299,6 +1299,19 @@
 #define FDT_ERROR	((ulong)(-1))
 
 ulong fdt_getprop_u32(const void *fdt, int node, const char *prop);
+
+/**
+ * fit_find_config_node() - Find the node for the best DTB in a FIT image
+ *
+ * A FIT image contains one or more DTBs. This function parses the
+ * configurations described in the FIT images and returns the node of
+ * the first matching DTB. To check if a DTB matches a board, this function
+ * calls board_fit_config_name_match(). If no matching DTB is found, it returns
+ * the node described by the default configuration if it exists.
+ *
+ * @fdt: pointer to flat device tree
+ * @return the node if found, -ve otherwise
+ */
 int fit_find_config_node(const void *fdt);
 
 /**
diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
new file mode 100644
index 0000000..8b9d6ff
--- /dev/null
+++ b/include/linux/bitfield.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2014 Felix Fietkau <nbd@nbd.name>
+ * Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _LINUX_BITFIELD_H
+#define _LINUX_BITFIELD_H
+
+#include <linux/bug.h>
+
+/*
+ * Bitfield access macros
+ *
+ * FIELD_{GET,PREP} macros take as first parameter shifted mask
+ * from which they extract the base mask and shift amount.
+ * Mask must be a compilation time constant.
+ *
+ * Example:
+ *
+ *  #define REG_FIELD_A  GENMASK(6, 0)
+ *  #define REG_FIELD_B  BIT(7)
+ *  #define REG_FIELD_C  GENMASK(15, 8)
+ *  #define REG_FIELD_D  GENMASK(31, 16)
+ *
+ * Get:
+ *  a = FIELD_GET(REG_FIELD_A, reg);
+ *  b = FIELD_GET(REG_FIELD_B, reg);
+ *
+ * Set:
+ *  reg = FIELD_PREP(REG_FIELD_A, 1) |
+ *	  FIELD_PREP(REG_FIELD_B, 0) |
+ *	  FIELD_PREP(REG_FIELD_C, c) |
+ *	  FIELD_PREP(REG_FIELD_D, 0x40);
+ *
+ * Modify:
+ *  reg &= ~REG_FIELD_C;
+ *  reg |= FIELD_PREP(REG_FIELD_C, c);
+ */
+
+#define __bf_shf(x) (__builtin_ffsll(x) - 1)
+
+#define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx)			\
+	({								\
+		BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask),		\
+				 _pfx "mask is not constant");		\
+		BUILD_BUG_ON_MSG(!(_mask), _pfx "mask is zero");	\
+		BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ?		\
+				 ~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \
+				 _pfx "value too large for the field"); \
+		BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull,		\
+				 _pfx "type of reg too small for mask"); \
+		__BUILD_BUG_ON_NOT_POWER_OF_2((_mask) +			\
+					      (1ULL << __bf_shf(_mask))); \
+	})
+
+/**
+ * FIELD_FIT() - check if value fits in the field
+ * @_mask: shifted mask defining the field's length and position
+ * @_val:  value to test against the field
+ *
+ * Return: true if @_val can fit inside @_mask, false if @_val is too big.
+ */
+#define FIELD_FIT(_mask, _val)						\
+	({								\
+		__BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_FIT: ");	\
+		!((((typeof(_mask))_val) << __bf_shf(_mask)) & ~(_mask)); \
+	})
+
+/**
+ * FIELD_PREP() - prepare a bitfield element
+ * @_mask: shifted mask defining the field's length and position
+ * @_val:  value to put in the field
+ *
+ * FIELD_PREP() masks and shifts up the value.  The result should
+ * be combined with other fields of the bitfield using logical OR.
+ */
+#define FIELD_PREP(_mask, _val)						\
+	({								\
+		__BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: ");	\
+		((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask);	\
+	})
+
+/**
+ * FIELD_GET() - extract a bitfield element
+ * @_mask: shifted mask defining the field's length and position
+ * @_reg:  32bit value of entire bitfield
+ *
+ * FIELD_GET() extracts the field specified by @_mask from the
+ * bitfield passed in as @_reg by masking and shifting it down.
+ */
+#define FIELD_GET(_mask, _reg)						\
+	({								\
+		__BF_FIELD_CHECK(_mask, _reg, 0U, "FIELD_GET: ");	\
+		(typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask));	\
+	})
+
+#endif
diff --git a/include/linux/bug.h b/include/linux/bug.h
index 920e379..f07bb71 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -1,55 +1,34 @@
 #ifndef _LINUX_BUG_H
 #define _LINUX_BUG_H
 
+#include <vsprintf.h> /* for panic() */
+#include <linux/build_bug.h>
 #include <linux/compiler.h>
+#include <linux/printk.h>
 
-#ifdef __CHECKER__
-#define BUILD_BUG_ON_NOT_POWER_OF_2(n) (0)
-#define BUILD_BUG_ON_ZERO(e) (0)
-#define BUILD_BUG_ON_NULL(e) ((void*)0)
-#define BUILD_BUG_ON_INVALID(e) (0)
-#define BUILD_BUG_ON(condition) (0)
-#define BUILD_BUG() (0)
-#else /* __CHECKER__ */
+#define BUG() do { \
+	printk("BUG at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
+	panic("BUG!"); \
+} while (0)
 
-/* Force a compilation error if a constant expression is not a power of 2 */
-#define BUILD_BUG_ON_NOT_POWER_OF_2(n)			\
-	BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))
+#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
 
-/* Force a compilation error if condition is true, but also produce a
-   result (of value 0 and type size_t), so the expression can be used
-   e.g. in a structure initializer (or where-ever else comma expressions
-   aren't permitted). */
-#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
-#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
+#define WARN_ON(condition) ({						\
+	int __ret_warn_on = !!(condition);				\
+	if (unlikely(__ret_warn_on))					\
+		printk("WARNING at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
+	unlikely(__ret_warn_on);					\
+})
 
-/*
- * BUILD_BUG_ON_INVALID() permits the compiler to check the validity of the
- * expression but avoids the generation of any code, even if that expression
- * has side-effects.
- */
-#define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e))))
-
-/**
- * BUILD_BUG_ON - break compile if a condition is true.
- * @condition: the condition which the compiler should know is false.
- *
- * If you have some code which relies on certain constants being equal, or
- * some other compile-time-evaluated condition, you should use BUILD_BUG_ON to
- * detect if someone changes it.
- *
- * The implementation uses gcc's reluctance to create a negative array, but gcc
- * (as of 4.4) only emits that error for obvious cases (e.g. not arguments to
- * inline functions).  Luckily, in 4.3 they added the "error" function
- * attribute just for this type of case.  Thus, we use a negative sized array
- * (should always create an error on gcc versions older than 4.4) and then call
- * an undefined function with the error attribute (should always create an
- * error on gcc 4.3 and later).  If for some reason, neither creates a
- * compile-time error, we'll still have a link-time error, which is harder to
- * track down.
- */
-#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
-
-#endif	/* __CHECKER__ */
+#define WARN_ON_ONCE(condition)	({				\
+	static bool __warned;					\
+	int __ret_warn_once = !!(condition);			\
+								\
+	if (unlikely(__ret_warn_once && !__warned)) {		\
+		__warned = true;				\
+		WARN_ON(1);					\
+	}							\
+	unlikely(__ret_warn_once);				\
+})
 
 #endif	/* _LINUX_BUG_H */
diff --git a/include/linux/build_bug.h b/include/linux/build_bug.h
new file mode 100644
index 0000000..b7d22d6
--- /dev/null
+++ b/include/linux/build_bug.h
@@ -0,0 +1,84 @@
+#ifndef _LINUX_BUILD_BUG_H
+#define _LINUX_BUILD_BUG_H
+
+#include <linux/compiler.h>
+
+#ifdef __CHECKER__
+#define __BUILD_BUG_ON_NOT_POWER_OF_2(n) (0)
+#define BUILD_BUG_ON_NOT_POWER_OF_2(n) (0)
+#define BUILD_BUG_ON_ZERO(e) (0)
+#define BUILD_BUG_ON_NULL(e) ((void *)0)
+#define BUILD_BUG_ON_INVALID(e) (0)
+#define BUILD_BUG_ON_MSG(cond, msg) (0)
+#define BUILD_BUG_ON(condition) (0)
+#define BUILD_BUG() (0)
+#else /* __CHECKER__ */
+
+/* Force a compilation error if a constant expression is not a power of 2 */
+#define __BUILD_BUG_ON_NOT_POWER_OF_2(n)	\
+	BUILD_BUG_ON(((n) & ((n) - 1)) != 0)
+#define BUILD_BUG_ON_NOT_POWER_OF_2(n)			\
+	BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))
+
+/*
+ * Force a compilation error if condition is true, but also produce a
+ * result (of value 0 and type size_t), so the expression can be used
+ * e.g. in a structure initializer (or where-ever else comma expressions
+ * aren't permitted).
+ */
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
+#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:(-!!(e)); }))
+
+/*
+ * BUILD_BUG_ON_INVALID() permits the compiler to check the validity of the
+ * expression but avoids the generation of any code, even if that expression
+ * has side-effects.
+ */
+#define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e))))
+
+/**
+ * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied
+ *		      error message.
+ * @condition: the condition which the compiler should know is false.
+ *
+ * See BUILD_BUG_ON for description.
+ */
+#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
+
+/**
+ * BUILD_BUG_ON - break compile if a condition is true.
+ * @condition: the condition which the compiler should know is false.
+ *
+ * If you have some code which relies on certain constants being equal, or
+ * some other compile-time-evaluated condition, you should use BUILD_BUG_ON to
+ * detect if someone changes it.
+ *
+ * The implementation uses gcc's reluctance to create a negative array, but gcc
+ * (as of 4.4) only emits that error for obvious cases (e.g. not arguments to
+ * inline functions).  Luckily, in 4.3 they added the "error" function
+ * attribute just for this type of case.  Thus, we use a negative sized array
+ * (should always create an error on gcc versions older than 4.4) and then call
+ * an undefined function with the error attribute (should always create an
+ * error on gcc 4.3 and later).  If for some reason, neither creates a
+ * compile-time error, we'll still have a link-time error, which is harder to
+ * track down.
+ */
+#ifndef __OPTIMIZE__
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+#else
+#define BUILD_BUG_ON(condition) \
+	BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
+#endif
+
+/**
+ * BUILD_BUG - break compile if used.
+ *
+ * If you have some code that you expect the compiler to eliminate at
+ * build time, you should use BUILD_BUG to detect if it is
+ * unexpectedly used.
+ */
+#define BUILD_BUG() BUILD_BUG_ON_MSG(1, "BUILD_BUG failed")
+
+#endif	/* __CHECKER__ */
+
+#endif	/* _LINUX_BUILD_BUG_H */
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 2336b56..8711fe2 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -15,6 +15,23 @@
 
 extern struct p_current *current;
 
+/* avoid conflict with <dm/device.h> */
+#ifdef dev_dbg
+#undef dev_dbg
+#endif
+#ifdef dev_vdbg
+#undef dev_vdbg
+#endif
+#ifdef dev_info
+#undef dev_info
+#endif
+#ifdef dev_err
+#undef dev_err
+#endif
+#ifdef dev_warn
+#undef dev_warn
+#endif
+
 #define dev_dbg(dev, fmt, args...)		\
 	debug(fmt, ##args)
 #define dev_vdbg(dev, fmt, args...)		\
@@ -25,17 +42,6 @@
 	printf(fmt, ##args)
 #define dev_warn(dev, fmt, args...)		\
 	printf(fmt, ##args)
-#define printk	printf
-#define printk_once	printf
-
-#define KERN_EMERG
-#define KERN_ALERT
-#define KERN_CRIT
-#define KERN_ERR
-#define KERN_WARNING
-#define KERN_NOTICE
-#define KERN_INFO
-#define KERN_DEBUG
 
 #define GFP_ATOMIC ((gfp_t) 0)
 #define GFP_KERNEL ((gfp_t) 0)
@@ -98,21 +104,6 @@
 
 #define KERNEL_VERSION(a,b,c)	(((a) << 16) + ((b) << 8) + (c))
 
-#ifndef BUG
-#define BUG() do { \
-	printf("U-Boot BUG at %s:%d!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define BUG_ON(condition) do { if (condition) BUG(); } while(0)
-#endif /* BUG */
-
-#define WARN_ON(condition) ({						\
-	int __ret_warn_on = !!(condition);				\
-	if (unlikely(__ret_warn_on))					\
-		printf("WARNING in %s line %d\n", __FILE__, __LINE__);	\
-	unlikely(__ret_warn_on);					\
-})
-
 #define PAGE_SIZE	4096
 
 /* drivers/char/random.c */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 020ad16..0ea6c8f 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -476,7 +476,8 @@
 # define __compiletime_error_fallback(condition) do { } while (0)
 #endif
 
-#define __compiletime_assert(condition, msg, prefix, suffix)		\
+#ifdef __OPTIMIZE__
+# define __compiletime_assert(condition, msg, prefix, suffix)		\
 	do {								\
 		bool __cond = !(condition);				\
 		extern void prefix ## suffix(void) __compiletime_error(msg); \
@@ -484,6 +485,9 @@
 			prefix ## suffix();				\
 		__compiletime_error_fallback(__cond);			\
 	} while (0)
+#else
+# define __compiletime_assert(condition, msg, prefix, suffix) do { } while (0)
+#endif
 
 #define _compiletime_assert(condition, msg, prefix, suffix) \
 	__compiletime_assert(condition, msg, prefix, suffix)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 0b61671..87d2d95 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -57,6 +57,11 @@
 #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
+#define DIV_ROUND_DOWN_ULL(ll, d) \
+	({ unsigned long long _tmp = (ll); do_div(_tmp, d); _tmp; })
+
+#define DIV_ROUND_UP_ULL(ll, d)		DIV_ROUND_DOWN_ULL((ll) + (d) - 1, (d))
+
 #if BITS_PER_LONG == 32
 # define DIV_ROUND_UP_SECTOR_T(ll,d) DIV_ROUND_UP_ULL(ll, d)
 #else
diff --git a/include/linux/lzo.h b/include/linux/lzo.h
index 88687fa..8981d04 100644
--- a/include/linux/lzo.h
+++ b/include/linux/lzo.h
@@ -31,6 +31,9 @@
 int lzop_decompress(const unsigned char *src, size_t src_len,
 		    unsigned char *dst, size_t *dst_len);
 
+/* check if the header is valid (based on magic numbers) */
+bool lzop_is_valid_header(const unsigned char *src);
+
 /*
  * Return values (< 0 = Error)
  */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 1fd17c3..3e1694b 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -452,28 +452,20 @@
 #define MTD_DEBUG_LEVEL3	(3)	/* Noisy   */
 
 #ifdef CONFIG_MTD_DEBUG
-#define pr_debug(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
 #define MTDDEBUG(n, args...)				\
 	do {						\
 		if (n <= CONFIG_MTD_DEBUG_VERBOSE)	\
 			printk(KERN_INFO args);		\
 	} while(0)
 #else /* CONFIG_MTD_DEBUG */
-#define pr_debug(args...)
 #define MTDDEBUG(n, args...)				\
 	do {						\
 		if (0)					\
 			printk(KERN_INFO args);		\
 	} while(0)
 #endif /* CONFIG_MTD_DEBUG */
-#define pr_info(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
-#define pr_warn(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
-#define pr_err(args...)		MTDDEBUG(MTD_DEBUG_LEVEL0, args)
-#define pr_crit(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
-#define pr_cont(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
-#define pr_notice(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)
 #endif
- 
+
 static inline int mtd_is_bitflip(int err) {
 	return err == -EUCLEAN;
 }
diff --git a/include/linux/printk.h b/include/linux/printk.h
new file mode 100644
index 0000000..088513a
--- /dev/null
+++ b/include/linux/printk.h
@@ -0,0 +1,79 @@
+#ifndef __KERNEL_PRINTK__
+#define __KERNEL_PRINTK__
+
+#include <stdio.h>
+#include <linux/compiler.h>
+
+#define KERN_EMERG
+#define KERN_ALERT
+#define KERN_CRIT
+#define KERN_ERR
+#define KERN_WARNING
+#define KERN_NOTICE
+#define KERN_INFO
+#define KERN_DEBUG
+#define KERN_CONT
+
+#define printk(fmt, ...) \
+	printf(fmt, ##__VA_ARGS__)
+
+/*
+ * Dummy printk for disabled debugging statements to use whilst maintaining
+ * gcc's format checking.
+ */
+#define no_printk(fmt, ...)				\
+({							\
+	if (0)						\
+		printk(fmt, ##__VA_ARGS__);		\
+	0;						\
+})
+
+#define __printk(level, fmt, ...)					\
+({									\
+	level < CONFIG_LOGLEVEL ? printk(fmt, ##__VA_ARGS__) : 0;	\
+})
+
+#ifndef pr_fmt
+#define pr_fmt(fmt) fmt
+#endif
+
+#define pr_emerg(fmt, ...) \
+	__printk(0, pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_alert(fmt, ...) \
+	__printk(1, pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_crit(fmt, ...) \
+	__printk(2, pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_err(fmt, ...) \
+	__printk(3, pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_warning(fmt, ...) \
+	__printk(4, pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_warn pr_warning
+#define pr_notice(fmt, ...) \
+	__printk(5, pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_info(fmt, ...) \
+	__printk(6, pr_fmt(fmt), ##__VA_ARGS__)
+
+#define pr_cont(fmt, ...) \
+	printk(fmt, ##__VA_ARGS__)
+
+/* pr_devel() should produce zero code unless DEBUG is defined */
+#ifdef DEBUG
+#define pr_devel(fmt, ...) \
+	__printk(7, pr_fmt(fmt), ##__VA_ARGS__)
+#else
+#define pr_devel(fmt, ...) \
+	no_printk(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#ifdef DEBUG
+#define pr_debug(fmt, ...) \
+	__printk(7, pr_fmt(fmt), ##__VA_ARGS__)
+#else
+#define pr_debug(fmt, ...) \
+	no_printk(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#define printk_once(fmt, ...) \
+	printk(fmt, ##__VA_ARGS__)
+
+#endif
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index 0ad4782..264c971 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -418,6 +418,12 @@
 #define USB_ENDPOINT_XFER_INT		3
 #define USB_ENDPOINT_MAX_ADJUSTABLE	0x80
 
+#define USB_ENDPOINT_MAXP_MASK		0x07ff
+#define USB_EP_MAXP_MULT_SHIFT		11
+#define USB_EP_MAXP_MULT_MASK		(3 << USB_EP_MAXP_MULT_SHIFT)
+#define USB_EP_MAXP_MULT(m)		\
+	(((m) & USB_EP_MAXP_MULT_MASK) >> USB_EP_MAXP_MULT_SHIFT)
+
 /* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */
 #define USB_ENDPOINT_INTRTYPE		0x30
 #define USB_ENDPOINT_INTR_PERIODIC	(0 << 4)
@@ -625,6 +631,20 @@
 	return __le16_to_cpu(get_unaligned(&epd->wMaxPacketSize));
 }
 
+/**
+ * usb_endpoint_maxp_mult - get endpoint's transactional opportunities
+ * @epd: endpoint to be checked
+ *
+ * Return @epd's wMaxPacketSize[12:11] + 1
+ */
+static inline int
+usb_endpoint_maxp_mult(const struct usb_endpoint_descriptor *epd)
+{
+	int maxp = __le16_to_cpu(epd->wMaxPacketSize);
+
+	return USB_EP_MAXP_MULT(maxp) + 1;
+}
+
 static inline int usb_endpoint_interrupt_type(
 		const struct usb_endpoint_descriptor *epd)
 {
diff --git a/include/part.h b/include/part.h
index 86117a7..0caceaf 100644
--- a/include/part.h
+++ b/include/part.h
@@ -174,6 +174,21 @@
 			    disk_partition_t *info, int allow_whole_dev);
 
 /**
+ * part_get_info_by_name_type() - Search for a partition by name
+ *                                for only specified partition type
+ *
+ * @param dev_desc - block device descriptor
+ * @param gpt_name - the specified table entry name
+ * @param info - returns the disk partition info
+ * @param part_type - only search in partitions of this type
+ *
+ * @return - the partition number on match (starting on 1), -1 on no match,
+ * otherwise error
+ */
+int part_get_info_by_name_type(struct blk_desc *dev_desc, const char *name,
+			       disk_partition_t *info, int part_type);
+
+/**
  * part_get_info_by_name() - Search for a partition by name
  *                           among all available registered partitions
  *
@@ -280,8 +295,9 @@
 #define U_BOOT_PART_TYPE(__name)					\
 	ll_entry_declare(struct part_driver, __name, part_driver)
 
-#if CONFIG_IS_ENABLED(EFI_PARTITION)
 #include <part_efi.h>
+
+#if CONFIG_IS_ENABLED(EFI_PARTITION)
 /* disk/part_efi.c */
 /**
  * write_gpt_table() - Write the GUID Partition Table to disk
diff --git a/include/part_efi.h b/include/part_efi.h
index 317c044..31e6bc6 100644
--- a/include/part_efi.h
+++ b/include/part_efi.h
@@ -58,10 +58,6 @@
 /* linux/include/efi.h */
 typedef u16 efi_char16_t;
 
-typedef struct {
-	u8 b[16];
-} efi_guid_t;
-
 /* based on linux/include/genhd.h */
 struct partition {
 	u8 boot_ind;		/* 0x80 - active */
diff --git a/include/pci.h b/include/pci.h
index c8ef997..7adc043 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -1086,6 +1086,57 @@
 int pci_read_config16(pci_dev_t pcidev, int offset, u16 *valuep);
 int pci_read_config8(pci_dev_t pcidev, int offset, u8 *valuep);
 
+/**
+ * pci_generic_mmap_write_config() - Generic helper for writing to
+ * memory-mapped PCI configuration space.
+ * @bus: Pointer to the PCI bus
+ * @addr_f: Callback for calculating the config space address
+ * @bdf: Identifies the PCI device to access
+ * @offset: The offset into the device's configuration space
+ * @value: The value to write
+ * @size: Indicates the size of access to perform
+ *
+ * Write the value @value of size @size from offset @offset within the
+ * configuration space of the device identified by the bus, device & function
+ * numbers in @bdf on the PCI bus @bus. The callback function @addr_f is
+ * responsible for calculating the CPU address of the respective configuration
+ * space offset.
+ *
+ * Return: 0 on success, else -EINVAL
+ */
+int pci_generic_mmap_write_config(
+	struct udevice *bus,
+	int (*addr_f)(struct udevice *bus, pci_dev_t bdf, uint offset, void **addrp),
+	pci_dev_t bdf,
+	uint offset,
+	ulong value,
+	enum pci_size_t size);
+
+/**
+ * pci_generic_mmap_read_config() - Generic helper for reading from
+ * memory-mapped PCI configuration space.
+ * @bus: Pointer to the PCI bus
+ * @addr_f: Callback for calculating the config space address
+ * @bdf: Identifies the PCI device to access
+ * @offset: The offset into the device's configuration space
+ * @valuep: A pointer at which to store the read value
+ * @size: Indicates the size of access to perform
+ *
+ * Read a value of size @size from offset @offset within the configuration
+ * space of the device identified by the bus, device & function numbers in @bdf
+ * on the PCI bus @bus. The callback function @addr_f is responsible for
+ * calculating the CPU address of the respective configuration space offset.
+ *
+ * Return: 0 on success, else -EINVAL
+ */
+int pci_generic_mmap_read_config(
+	struct udevice *bus,
+	int (*addr_f)(struct udevice *bus, pci_dev_t bdf, uint offset, void **addrp),
+	pci_dev_t bdf,
+	uint offset,
+	ulong *valuep,
+	enum pci_size_t size);
+
 #ifdef CONFIG_DM_PCI_COMPAT
 /* Compatibility with old naming */
 static inline int pci_write_config_dword(pci_dev_t pcidev, int offset,
diff --git a/include/pe.h b/include/pe.h
index deb35a0..4ef3e92 100644
--- a/include/pe.h
+++ b/include/pe.h
@@ -62,6 +62,12 @@
 
 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
 
+/* PE32+ Subsystem type for EFI images */
+#define IMAGE_SUBSYSTEM_EFI_APPLICATION         10
+#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
+#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER      12
+#define IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER      13
+
 typedef struct _IMAGE_OPTIONAL_HEADER64 {
 	uint16_t Magic; /* 0x20b */
 	uint8_t  MajorLinkerVersion;
diff --git a/include/stdio.h b/include/stdio.h
new file mode 100644
index 0000000..aedf374
--- /dev/null
+++ b/include/stdio.h
@@ -0,0 +1,59 @@
+#ifndef __STDIO_H
+#define __STDIO_H
+
+#include <stdarg.h>
+#include <linux/compiler.h>
+
+/* stdin */
+int getc(void);
+int tstc(void);
+
+/* stdout */
+#if !defined(CONFIG_SPL_BUILD) || \
+	(defined(CONFIG_TPL_BUILD) && defined(CONFIG_TPL_SERIAL_SUPPORT)) || \
+	(defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD) && \
+		defined(CONFIG_SPL_SERIAL_SUPPORT))
+void putc(const char c);
+void puts(const char *s);
+int __printf(1, 2) printf(const char *fmt, ...);
+int vprintf(const char *fmt, va_list args);
+#else
+static inline void putc(const char c)
+{
+}
+
+static inline void puts(const char *s)
+{
+}
+
+static inline int __printf(1, 2) printf(const char *fmt, ...)
+{
+	return 0;
+}
+
+static inline int vprintf(const char *fmt, va_list args)
+{
+	return 0;
+}
+#endif
+
+/*
+ * FILE based functions (can only be used AFTER relocation!)
+ */
+#define stdin		0
+#define stdout		1
+#define stderr		2
+#define MAX_FILES	3
+
+/* stderr */
+#define eputc(c)		fputc(stderr, c)
+#define eputs(s)		fputs(stderr, s)
+#define eprintf(fmt, args...)	fprintf(stderr, fmt, ##args)
+
+int __printf(2, 3) fprintf(int file, const char *fmt, ...);
+void fputs(int file, const char *s);
+void fputc(int file, const char c);
+int ftstc(int file);
+int fgetc(int file);
+
+#endif /* __STDIO_H */
diff --git a/include/u-boot/crc.h b/include/u-boot/crc.h
index 6764d58..6d08f5d 100644
--- a/include/u-boot/crc.h
+++ b/include/u-boot/crc.h
@@ -28,4 +28,8 @@
 void crc32_wd_buf(const unsigned char *input, uint ilen,
 		    unsigned char *output, uint chunk_sz);
 
+/* lib/crc32c.c */
+void crc32c_init(uint32_t *, uint32_t);
+uint32_t crc32c_cal(uint32_t, const char *, int, uint32_t *);
+
 #endif /* _UBOOT_CRC_H */
diff --git a/include/u-boot/variadic-macro.h b/include/u-boot/variadic-macro.h
new file mode 100644
index 0000000..922beaf
--- /dev/null
+++ b/include/u-boot/variadic-macro.h
@@ -0,0 +1,59 @@
+/*
+ * Helper for work with variadic macros
+ *
+ * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __VARIADIC_MACRO_H__
+#define __VARIADIC_MACRO_H__
+
+#define _VM_GET_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, \
+	_14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, \
+	_28, _29, _30, _31, _32, N, ...) N
+
+#define _VM_HELP_0(_call, ...)
+#define _VM_HELP_1(_call, x, ...) _call(x)
+#define _VM_HELP_2(_call, x, ...) _call(x) _VM_HELP_1(_call, __VA_ARGS__)
+#define _VM_HELP_3(_call, x, ...) _call(x) _VM_HELP_2(_call, __VA_ARGS__)
+#define _VM_HELP_4(_call, x, ...) _call(x) _VM_HELP_3(_call, __VA_ARGS__)
+#define _VM_HELP_5(_call, x, ...) _call(x) _VM_HELP_4(_call, __VA_ARGS__)
+#define _VM_HELP_6(_call, x, ...) _call(x) _VM_HELP_5(_call, __VA_ARGS__)
+#define _VM_HELP_7(_call, x, ...) _call(x) _VM_HELP_6(_call, __VA_ARGS__)
+#define _VM_HELP_8(_call, x, ...) _call(x) _VM_HELP_7(_call, __VA_ARGS__)
+#define _VM_HELP_9(_call, x, ...) _call(x) _VM_HELP_8(_call, __VA_ARGS__)
+#define _VM_HELP_10(_call, x, ...) _call(x) _VM_HELP_9(_call, __VA_ARGS__)
+#define _VM_HELP_11(_call, x, ...) _call(x) _VM_HELP_10(_call, __VA_ARGS__)
+#define _VM_HELP_12(_call, x, ...) _call(x) _VM_HELP_11(_call, __VA_ARGS__)
+#define _VM_HELP_13(_call, x, ...) _call(x) _VM_HELP_12(_call, __VA_ARGS__)
+#define _VM_HELP_14(_call, x, ...) _call(x) _VM_HELP_13(_call, __VA_ARGS__)
+#define _VM_HELP_15(_call, x, ...) _call(x) _VM_HELP_14(_call, __VA_ARGS__)
+#define _VM_HELP_16(_call, x, ...) _call(x) _VM_HELP_15(_call, __VA_ARGS__)
+#define _VM_HELP_17(_call, x, ...) _call(x) _VM_HELP_16(_call, __VA_ARGS__)
+#define _VM_HELP_18(_call, x, ...) _call(x) _VM_HELP_17(_call, __VA_ARGS__)
+#define _VM_HELP_19(_call, x, ...) _call(x) _VM_HELP_18(_call, __VA_ARGS__)
+#define _VM_HELP_20(_call, x, ...) _call(x) _VM_HELP_19(_call, __VA_ARGS__)
+#define _VM_HELP_21(_call, x, ...) _call(x) _VM_HELP_20(_call, __VA_ARGS__)
+#define _VM_HELP_22(_call, x, ...) _call(x) _VM_HELP_21(_call, __VA_ARGS__)
+#define _VM_HELP_23(_call, x, ...) _call(x) _VM_HELP_22(_call, __VA_ARGS__)
+#define _VM_HELP_24(_call, x, ...) _call(x) _VM_HELP_23(_call, __VA_ARGS__)
+#define _VM_HELP_25(_call, x, ...) _call(x) _VM_HELP_24(_call, __VA_ARGS__)
+#define _VM_HELP_26(_call, x, ...) _call(x) _VM_HELP_25(_call, __VA_ARGS__)
+#define _VM_HELP_27(_call, x, ...) _call(x) _VM_HELP_26(_call, __VA_ARGS__)
+#define _VM_HELP_28(_call, x, ...) _call(x) _VM_HELP_27(_call, __VA_ARGS__)
+#define _VM_HELP_29(_call, x, ...) _call(x) _VM_HELP_28(_call, __VA_ARGS__)
+#define _VM_HELP_30(_call, x, ...) _call(x) _VM_HELP_29(_call, __VA_ARGS__)
+#define _VM_HELP_31(_call, x, ...) _call(x) _VM_HELP_30(_call, __VA_ARGS__)
+
+#define CALL_MACRO_FOR_EACH(x, ...)					 \
+	_VM_GET_NTH_ARG("", ##__VA_ARGS__, _VM_HELP_31, _VM_HELP_30,	 \
+	_VM_HELP_29, _VM_HELP_28, _VM_HELP_27, _VM_HELP_26, _VM_HELP_25, \
+	_VM_HELP_24, _VM_HELP_23, _VM_HELP_22, _VM_HELP_21, _VM_HELP_20, \
+	_VM_HELP_19, _VM_HELP_18, _VM_HELP_17, _VM_HELP_16, _VM_HELP_15, \
+	_VM_HELP_14, _VM_HELP_13, _VM_HELP_12, _VM_HELP_11, _VM_HELP_10, \
+	_VM_HELP_9, _VM_HELP_8, _VM_HELP_7, _VM_HELP_6, _VM_HELP_5,	 \
+	_VM_HELP_4, _VM_HELP_3, _VM_HELP_2, _VM_HELP_1,			 \
+	_VM_HELP_0)(x, __VA_ARGS__)
+
+#endif /* __VARIADIC_MACRO_H__ */
diff --git a/include/usb.h b/include/usb.h
index 0ddc082..57a7d8d 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -653,6 +653,18 @@
 };
 
 /**
+ * struct usb_emul_platdata - platform data about the USB emulator
+ *
+ * Given a USB emulator (UCLASS_USB_EMUL) 'dev', this is
+ * dev_get_uclass_platdata(dev).
+ *
+ * @port1:	USB emulator device port number on the parent hub
+ */
+struct usb_emul_platdata {
+	int port1;	/* Port number (numbered from 1) */
+};
+
+/**
  * struct dm_usb_ops - USB controller operations
  *
  * This defines the operations supoorted on a USB controller. Common
@@ -976,7 +988,6 @@
  * the USB emulation uclass about the features of the emulator.
  *
  * @dev:		Emulation device
- * @maxpacketsize:	Maximum packet size (e.g. PACKET_SIZE_64)
  * @strings:		List of USB string descriptors, terminated by a NULL
  *			entry
  * @desc_list:		List of points or USB descriptors, terminated by NULL.
@@ -984,8 +995,8 @@
  *			and others follow on after that.
  * @return 0 if OK, -ENOSYS if not implemented, other -ve on error
  */
-int usb_emul_setup_device(struct udevice *dev, int maxpacketsize,
-			  struct usb_string *strings, void **desc_list);
+int usb_emul_setup_device(struct udevice *dev, struct usb_string *strings,
+			  void **desc_list);
 
 /**
  * usb_emul_control() - Send a control packet to an emulator
@@ -1024,19 +1035,20 @@
 /**
  * usb_emul_find() - Find an emulator for a particular device
  *
- * Check @pipe to find a device number on bus @bus and return it.
+ * Check @pipe and @port1 to find a device number on bus @bus and return it.
  *
  * @bus:	USB bus (controller)
  * @pipe:	Describes pipe being used, and includes the device number
+ * @port1:	Describes port number on the parent hub
  * @emulp:	Returns pointer to emulator, or NULL if not found
  * @return 0 if found, -ve on error
  */
-int usb_emul_find(struct udevice *bus, ulong pipe, struct udevice **emulp);
+int usb_emul_find(struct udevice *bus, ulong pipe, int port1,
+		  struct udevice **emulp);
 
 /**
  * usb_emul_find_for_dev() - Find an emulator for a particular device
  *
- * @bus:	USB bus (controller)
  * @dev:	USB device to check
  * @emulp:	Returns pointer to emulator, or NULL if not found
  * @return 0 if found, -ve on error
@@ -1044,12 +1056,15 @@
 int usb_emul_find_for_dev(struct udevice *dev, struct udevice **emulp);
 
 /**
- * usb_emul_reset() - Reset all emulators ready for use
+ * usb_emul_find_descriptor() - Find a USB descriptor of a particular device
  *
- * Clear out any address information in the emulators and make then ready for
- * a new USB scan
+ * @ptr:	a pointer to a list of USB descriptor pointers
+ * @type:	type of USB descriptor to find
+ * @index:	if @type is USB_DT_CONFIG, this is the configuration value
+ * @return a pointer to the USB descriptor found, NULL if not found
  */
-void usb_emul_reset(struct udevice *dev);
+struct usb_generic_descriptor **usb_emul_find_descriptor(
+		struct usb_generic_descriptor **ptr, int type, int index);
 
 /**
  * usb_show_tree() - show the USB device tree
diff --git a/include/vsprintf.h b/include/vsprintf.h
index 490c96c..33d05aa 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -9,6 +9,7 @@
 #define __VSPRINTF_H
 
 #include <stdarg.h>
+#include <linux/types.h>
 
 ulong simple_strtoul(const char *cp, char **endp, unsigned int base);
 
diff --git a/lib/Kconfig b/lib/Kconfig
index 628ef8d..18663ba 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -146,6 +146,9 @@
 config MD5
 	bool
 
+config CRC32C
+	bool
+
 endmenu
 
 menu "Compression Support"
@@ -177,6 +180,11 @@
 	help
 	  This enables support for LZO compression algorithm.r
 
+config SPL_LZO
+	bool "Enable LZO decompression support in SPL"
+	help
+	  This enables support for LZO compression algorithm in the SPL.
+
 config SPL_GZIP
 	bool "Enable gzip decompression support for SPL build"
 	select SPL_ZLIB
diff --git a/lib/Makefile b/lib/Makefile
index faf4538..8cd779f 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -9,8 +9,8 @@
 
 obj-$(CONFIG_EFI) += efi/
 obj-$(CONFIG_EFI_LOADER) += efi_loader/
+obj-$(CONFIG_EFI_LOADER) += efi_selftest/
 obj-$(CONFIG_LZMA) += lzma/
-obj-$(CONFIG_LZO) += lzo/
 obj-$(CONFIG_BZIP2) += bzip2/
 obj-$(CONFIG_TIZEN) += tizen/
 obj-$(CONFIG_FIT) += libfdt/
@@ -51,6 +51,8 @@
 
 obj-$(CONFIG_$(SPL_)ZLIB) += zlib/
 obj-$(CONFIG_$(SPL_)GZIP) += gunzip.o
+obj-$(CONFIG_$(SPL_)LZO) += lzo/
+
 
 obj-$(CONFIG_$(SPL_TPL_)SAVEENV) += qsort.o
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/
@@ -70,6 +72,7 @@
 CFLAGS_display_options.o := $(if $(BUILD_TAG),-DBUILD_TAG='"$(BUILD_TAG)"')
 obj-$(CONFIG_BCH) += bch.o
 obj-y += crc32.o
+obj-$(CONFIG_CRC32C) += crc32c.o
 obj-y += ctype.o
 obj-y += div64.o
 obj-y += hang.o
diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c
index b04f7c6..f4f1bb8 100644
--- a/lib/asm-offsets.c
+++ b/lib/asm-offsets.c
@@ -38,5 +38,7 @@
 
 	DEFINE(GD_START_ADDR_SP, offsetof(struct global_data, start_addr_sp));
 
+	DEFINE(GD_NEW_GD, offsetof(struct global_data, new_gd));
+
 	return 0;
 }
diff --git a/lib/crc32c.c b/lib/crc32c.c
new file mode 100644
index 0000000..322c08f
--- /dev/null
+++ b/lib/crc32c.c
@@ -0,0 +1,38 @@
+/*
+ * Copied from Linux kernel crypto/crc32c.c
+ * Copyright (c) 2004 Cisco Systems, Inc.
+ * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <compiler.h>
+
+uint32_t crc32c_cal(uint32_t crc, const char *data, int length,
+		    uint32_t *crc32c_table)
+{
+	while (length--)
+		crc = crc32c_table[(u8)(crc ^ *data++)] ^ (crc >> 8);
+
+	return crc;
+}
+
+void crc32c_init(uint32_t *crc32c_table, uint32_t pol)
+{
+	int i, j;
+	uint32_t v;
+	const uint32_t poly = pol; /* Bit-reflected CRC32C polynomial */
+
+	for (i = 0; i < 256; i++) {
+		v = i;
+		for (j = 0; j < 8; j++)
+			v = (v >> 1) ^ ((v & 1) ? poly : 0);
+
+		crc32c_table[i] = v;
+	}
+}
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 30bf343..ddb978f 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -10,12 +10,14 @@
 CFLAGS_helloworld.o := $(CFLAGS_EFI)
 CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI)
 
-efiprogs-$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE) += helloworld.efi
-always := $(efiprogs-y)
+ifneq ($(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),)
+always += helloworld.efi
+endif
 
 obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o
 obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o
-obj-y += efi_memory.o efi_device_path_to_text.o
+obj-y += efi_memory.o efi_device_path_to_text.o efi_device_path.o
+obj-y += efi_file.o efi_variable.o efi_bootmgr.o
 obj-$(CONFIG_LCD) += efi_gop.o
 obj-$(CONFIG_DM_VIDEO) += efi_gop.o
 obj-$(CONFIG_PARTITIONS) += efi_disk.o
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
new file mode 100644
index 0000000..857d88a
--- /dev/null
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -0,0 +1,180 @@
+/*
+ *  EFI utils
+ *
+ *  Copyright (c) 2017 Rob Clark
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <malloc.h>
+#include <efi_loader.h>
+
+static const struct efi_boot_services *bs;
+static const struct efi_runtime_services *rs;
+
+#define LOAD_OPTION_ACTIVE		0x00000001
+#define LOAD_OPTION_FORCE_RECONNECT	0x00000002
+#define LOAD_OPTION_HIDDEN		0x00000008
+
+/*
+ * bootmgr implements the logic of trying to find a payload to boot
+ * based on the BootOrder + BootXXXX variables, and then loading it.
+ *
+ * TODO detecting a special key held (f9?) and displaying a boot menu
+ * like you would get on a PC would be clever.
+ *
+ * TODO if we had a way to write and persist variables after the OS
+ * has started, we'd also want to check OsIndications to see if we
+ * should do normal or recovery boot.
+ */
+
+
+/*
+ * See section 3.1.3 in the v2.7 UEFI spec for more details on
+ * the layout of EFI_LOAD_OPTION.  In short it is:
+ *
+ *    typedef struct _EFI_LOAD_OPTION {
+ *        UINT32 Attributes;
+ *        UINT16 FilePathListLength;
+ *        // CHAR16 Description[];   <-- variable length, NULL terminated
+ *        // EFI_DEVICE_PATH_PROTOCOL FilePathList[];  <-- FilePathListLength bytes
+ *        // UINT8 OptionalData[];
+ *    } EFI_LOAD_OPTION;
+ */
+struct load_option {
+	u32 attributes;
+	u16 file_path_length;
+	u16 *label;
+	struct efi_device_path *file_path;
+	u8 *optional_data;
+};
+
+/* parse an EFI_LOAD_OPTION, as described above */
+static void parse_load_option(struct load_option *lo, void *ptr)
+{
+	lo->attributes = *(u32 *)ptr;
+	ptr += sizeof(u32);
+
+	lo->file_path_length = *(u16 *)ptr;
+	ptr += sizeof(u16);
+
+	lo->label = ptr;
+	ptr += (utf16_strlen(lo->label) + 1) * 2;
+
+	lo->file_path = ptr;
+	ptr += lo->file_path_length;
+
+	lo->optional_data = ptr;
+}
+
+/* free() the result */
+static void *get_var(u16 *name, const efi_guid_t *vendor,
+		     unsigned long *size)
+{
+	efi_guid_t *v = (efi_guid_t *)vendor;
+	efi_status_t ret;
+	void *buf = NULL;
+
+	*size = 0;
+	EFI_CALL(ret = rs->get_variable((s16 *)name, v, NULL, size, buf));
+	if (ret == EFI_BUFFER_TOO_SMALL) {
+		buf = malloc(*size);
+		EFI_CALL(ret = rs->get_variable((s16 *)name, v, NULL, size, buf));
+	}
+
+	if (ret != EFI_SUCCESS) {
+		free(buf);
+		*size = 0;
+		return NULL;
+	}
+
+	return buf;
+}
+
+/*
+ * Attempt to load load-option number 'n', returning device_path and file_path
+ * if successful.  This checks that the EFI_LOAD_OPTION is active (enabled)
+ * and that the specified file to boot exists.
+ */
+static void *try_load_entry(uint16_t n, struct efi_device_path **device_path,
+			    struct efi_device_path **file_path)
+{
+	struct load_option lo;
+	u16 varname[] = L"Boot0000";
+	u16 hexmap[] = L"0123456789ABCDEF";
+	void *load_option, *image = NULL;
+	unsigned long size;
+
+	varname[4] = hexmap[(n & 0xf000) >> 12];
+	varname[5] = hexmap[(n & 0x0f00) >> 8];
+	varname[6] = hexmap[(n & 0x00f0) >> 4];
+	varname[7] = hexmap[(n & 0x000f) >> 0];
+
+	load_option = get_var(varname, &efi_global_variable_guid, &size);
+	if (!load_option)
+		return NULL;
+
+	parse_load_option(&lo, load_option);
+
+	if (lo.attributes & LOAD_OPTION_ACTIVE) {
+		efi_status_t ret;
+		u16 *str = NULL;
+
+		debug("%s: trying to load \"%ls\" from: %ls\n", __func__,
+		      lo.label, (str = efi_dp_str(lo.file_path)));
+		efi_free_pool(str);
+
+		ret = efi_load_image_from_path(lo.file_path, &image);
+
+		if (ret != EFI_SUCCESS)
+			goto error;
+
+		printf("Booting: %ls\n", lo.label);
+		efi_dp_split_file_path(lo.file_path, device_path, file_path);
+	}
+
+error:
+	free(load_option);
+
+	return image;
+}
+
+/*
+ * Attempt to load, in the order specified by BootOrder EFI variable, the
+ * available load-options, finding and returning the first one that can
+ * be loaded successfully.
+ */
+void *efi_bootmgr_load(struct efi_device_path **device_path,
+		       struct efi_device_path **file_path)
+{
+	uint16_t *bootorder;
+	unsigned long size;
+	void *image = NULL;
+	int i, num;
+
+	__efi_entry_check();
+
+	bs = systab.boottime;
+	rs = systab.runtime;
+
+	bootorder = get_var(L"BootOrder", &efi_global_variable_guid, &size);
+	if (!bootorder)
+		goto error;
+
+	num = size / sizeof(uint16_t);
+	for (i = 0; i < num; i++) {
+		debug("%s: trying to load Boot%04X\n", __func__, bootorder[i]);
+		image = try_load_entry(bootorder[i], device_path, file_path);
+		if (image)
+			break;
+	}
+
+	free(bootorder);
+
+error:
+	__efi_exit_check();
+
+	return image;
+}
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 43f3238..9e741c3 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <efi_loader.h>
+#include <environment.h>
 #include <malloc.h>
 #include <asm/global_data.h>
 #include <libfdt_env.h>
@@ -18,6 +19,9 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/* Task priority level */
+static UINTN efi_tpl = TPL_APPLICATION;
+
 /* This list contains all the EFI objects our payload has access to */
 LIST_HEAD(efi_obj_list);
 
@@ -109,6 +113,11 @@
 	return &indent[max - level];
 }
 
+const char *__efi_nesting(void)
+{
+	return indent_string(nesting_level);
+}
+
 const char *__efi_nesting_inc(void)
 {
 	return indent_string(nesting_level++);
@@ -154,12 +163,15 @@
 
 void efi_signal_event(struct efi_event *event)
 {
-	if (event->signaled)
-		return;
-	event->signaled = 1;
-	if (event->type & EVT_NOTIFY_SIGNAL) {
-		EFI_CALL(event->notify_function(event, event->notify_context));
+	if (event->notify_function) {
+		event->queued = 1;
+		/* Check TPL */
+		if (efi_tpl >= event->notify_tpl)
+			return;
+		EFI_CALL_VOID(event->notify_function(event,
+						     event->notify_context));
 	}
+	event->queued = 0;
 }
 
 static efi_status_t efi_unsupported(const char *funcname)
@@ -170,14 +182,31 @@
 
 static unsigned long EFIAPI efi_raise_tpl(UINTN new_tpl)
 {
+	UINTN old_tpl = efi_tpl;
+
 	EFI_ENTRY("0x%zx", new_tpl);
-	return EFI_EXIT(0);
+
+	if (new_tpl < efi_tpl)
+		debug("WARNING: new_tpl < current_tpl in %s\n", __func__);
+	efi_tpl = new_tpl;
+	if (efi_tpl > TPL_HIGH_LEVEL)
+		efi_tpl = TPL_HIGH_LEVEL;
+
+	EFI_EXIT(EFI_SUCCESS);
+	return old_tpl;
 }
 
 static void EFIAPI efi_restore_tpl(UINTN old_tpl)
 {
 	EFI_ENTRY("0x%zx", old_tpl);
-	efi_unsupported(__func__);
+
+	if (old_tpl > efi_tpl)
+		debug("WARNING: old_tpl > current_tpl in %s\n", __func__);
+	efi_tpl = old_tpl;
+	if (efi_tpl > TPL_HIGH_LEVEL)
+		efi_tpl = TPL_HIGH_LEVEL;
+
+	EFI_EXIT(EFI_SUCCESS);
 }
 
 static efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type,
@@ -270,6 +299,7 @@
 		efi_events[i].notify_context = notify_context;
 		/* Disable timers on bootup */
 		efi_events[i].trigger_next = -1ULL;
+		efi_events[i].queued = 0;
 		efi_events[i].signaled = 0;
 		*event = &efi_events[i];
 		return EFI_SUCCESS;
@@ -301,16 +331,25 @@
 	u64 now = timer_get_us();
 
 	for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
-		if (!efi_events[i].type ||
-		    !(efi_events[i].type & EVT_TIMER) ||
-		    efi_events[i].trigger_type == EFI_TIMER_STOP ||
+		if (!efi_events[i].type)
+			continue;
+		if (efi_events[i].queued)
+			efi_signal_event(&efi_events[i]);
+		if (!(efi_events[i].type & EVT_TIMER) ||
 		    now < efi_events[i].trigger_next)
 			continue;
-		if (efi_events[i].trigger_type == EFI_TIMER_PERIODIC) {
+		switch (efi_events[i].trigger_type) {
+		case EFI_TIMER_RELATIVE:
+			efi_events[i].trigger_type = EFI_TIMER_STOP;
+			break;
+		case EFI_TIMER_PERIODIC:
 			efi_events[i].trigger_next +=
 				efi_events[i].trigger_time;
-			efi_events[i].signaled = 0;
+			break;
+		default:
+			continue;
 		}
+		efi_events[i].signaled = 1;
 		efi_signal_event(&efi_events[i]);
 	}
 	WATCHDOG_RESET();
@@ -347,6 +386,7 @@
 		}
 		event->trigger_type = type;
 		event->trigger_time = trigger_time;
+		event->signaled = 0;
 		return EFI_SUCCESS;
 	}
 	return EFI_INVALID_PARAMETER;
@@ -371,6 +411,9 @@
 	/* Check parameters */
 	if (!num_events || !event)
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
+	/* Check TPL */
+	if (efi_tpl != TPL_APPLICATION)
+		return EFI_EXIT(EFI_UNSUPPORTED);
 	for (i = 0; i < num_events; ++i) {
 		for (j = 0; j < ARRAY_SIZE(efi_events); ++j) {
 			if (event[i] == &efi_events[j])
@@ -380,6 +423,8 @@
 known_event:
 		if (!event[i]->type || event[i]->type & EVT_NOTIFY_SIGNAL)
 			return EFI_EXIT(EFI_INVALID_PARAMETER);
+		if (!event[i]->signaled)
+			efi_signal_event(event[i]);
 	}
 
 	/* Wait for signal */
@@ -412,7 +457,11 @@
 	for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
 		if (event != &efi_events[i])
 			continue;
-		efi_signal_event(event);
+		if (event->signaled)
+			break;
+		event->signaled = 1;
+		if (event->type & EVT_NOTIFY_SIGNAL)
+			efi_signal_event(event);
 		break;
 	}
 	return EFI_EXIT(EFI_SUCCESS);
@@ -427,6 +476,7 @@
 		if (event == &efi_events[i]) {
 			event->type = 0;
 			event->trigger_next = -1ULL;
+			event->queued = 0;
 			event->signaled = 0;
 			return EFI_EXIT(EFI_SUCCESS);
 		}
@@ -445,6 +495,8 @@
 			continue;
 		if (!event->type || event->type & EVT_NOTIFY_SIGNAL)
 			break;
+		if (!event->signaled)
+			efi_signal_event(event);
 		if (event->signaled)
 			return EFI_EXIT(EFI_SUCCESS);
 		return EFI_EXIT(EFI_NOT_READY);
@@ -513,7 +565,7 @@
 			efi_guid_t *protocol, int protocol_interface_type,
 			void *protocol_interface)
 {
-	EFI_ENTRY("%p, %p, %d, %p", handle, protocol, protocol_interface_type,
+	EFI_ENTRY("%p, %pUl, %d, %p", handle, protocol, protocol_interface_type,
 		  protocol_interface);
 
 	return EFI_EXIT(efi_install_protocol_interface(handle, protocol,
@@ -525,7 +577,7 @@
 			efi_guid_t *protocol, void *old_interface,
 			void *new_interface)
 {
-	EFI_ENTRY("%p, %p, %p, %p", handle, protocol, old_interface,
+	EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface,
 		  new_interface);
 	return EFI_EXIT(EFI_ACCESS_DENIED);
 }
@@ -574,7 +626,7 @@
 static efi_status_t EFIAPI efi_uninstall_protocol_interface_ext(void *handle,
 			efi_guid_t *protocol, void *protocol_interface)
 {
-	EFI_ENTRY("%p, %p, %p", handle, protocol, protocol_interface);
+	EFI_ENTRY("%p, %pUl, %p", handle, protocol, protocol_interface);
 
 	return EFI_EXIT(efi_uninstall_protocol_interface(handle, protocol,
 							 protocol_interface));
@@ -584,7 +636,7 @@
 							struct efi_event *event,
 							void **registration)
 {
-	EFI_ENTRY("%p, %p, %p", protocol, event, registration);
+	EFI_ENTRY("%pUl, %p, %p", protocol, event, registration);
 	return EFI_EXIT(EFI_OUT_OF_RESOURCES);
 }
 
@@ -654,7 +706,7 @@
 			efi_guid_t *protocol, void *search_key,
 			unsigned long *buffer_size, efi_handle_t *buffer)
 {
-	EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key,
+	EFI_ENTRY("%d, %pUl, %p, %p, %p", search_type, protocol, search_key,
 		  buffer_size, buffer);
 
 	return EFI_EXIT(efi_locate_handle(search_type, protocol, search_key,
@@ -665,8 +717,17 @@
 			struct efi_device_path **device_path,
 			efi_handle_t *device)
 {
-	EFI_ENTRY("%p, %p, %p", protocol, device_path, device);
-	return EFI_EXIT(EFI_NOT_FOUND);
+	struct efi_object *efiobj;
+
+	EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device);
+
+	efiobj = efi_dp_find_obj(*device_path, device_path);
+	if (!efiobj)
+		return EFI_EXIT(EFI_NOT_FOUND);
+
+	*device = efiobj->handle;
+
+	return EFI_EXIT(EFI_SUCCESS);
 }
 
 /* Collapses configuration table entries, removing index i */
@@ -713,10 +774,87 @@
 static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
 							       void *table)
 {
-	EFI_ENTRY("%p, %p", guid, table);
+	EFI_ENTRY("%pUl, %p", guid, table);
 	return EFI_EXIT(efi_install_configuration_table(guid, table));
 }
 
+/* Initialize a loaded_image_info + loaded_image_info object with correct
+ * protocols, boot-device, etc.
+ */
+void efi_setup_loaded_image(struct efi_loaded_image *info, struct efi_object *obj,
+			    struct efi_device_path *device_path,
+			    struct efi_device_path *file_path)
+{
+	obj->handle = info;
+
+	/*
+	 * When asking for the device path interface, return
+	 * bootefi_device_path
+	 */
+	obj->protocols[0].guid = &efi_guid_device_path;
+	obj->protocols[0].protocol_interface = device_path;
+
+	/*
+	 * When asking for the loaded_image interface, just
+	 * return handle which points to loaded_image_info
+	 */
+	obj->protocols[1].guid = &efi_guid_loaded_image;
+	obj->protocols[1].protocol_interface = info;
+
+	obj->protocols[2].guid = &efi_guid_console_control;
+	obj->protocols[2].protocol_interface = (void *)&efi_console_control;
+
+	obj->protocols[3].guid = &efi_guid_device_path_to_text_protocol;
+	obj->protocols[3].protocol_interface =
+		(void *)&efi_device_path_to_text;
+
+	info->file_path = file_path;
+	info->device_handle = efi_dp_find_obj(device_path, NULL);
+
+	list_add_tail(&obj->link, &efi_obj_list);
+}
+
+efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
+				      void **buffer)
+{
+	struct efi_file_info *info = NULL;
+	struct efi_file_handle *f;
+	static efi_status_t ret;
+	uint64_t bs;
+
+	f = efi_file_from_path(file_path);
+	if (!f)
+		return EFI_DEVICE_ERROR;
+
+	bs = 0;
+	EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
+				  &bs, info));
+	if (ret == EFI_BUFFER_TOO_SMALL) {
+		info = malloc(bs);
+		EFI_CALL(ret = f->getinfo(f, (efi_guid_t *)&efi_file_info_guid,
+					  &bs, info));
+	}
+	if (ret != EFI_SUCCESS)
+		goto error;
+
+	ret = efi_allocate_pool(EFI_LOADER_DATA, info->file_size, buffer);
+	if (ret)
+		goto error;
+
+	EFI_CALL(ret = f->read(f, &info->file_size, *buffer));
+
+error:
+	free(info);
+	EFI_CALL(f->close(f));
+
+	if (ret != EFI_SUCCESS) {
+		efi_free_pool(*buffer);
+		*buffer = NULL;
+	}
+
+	return ret;
+}
+
 static efi_status_t EFIAPI efi_load_image(bool boot_policy,
 					  efi_handle_t parent_image,
 					  struct efi_device_path *file_path,
@@ -724,25 +862,40 @@
 					  unsigned long source_size,
 					  efi_handle_t *image_handle)
 {
-	static struct efi_object loaded_image_info_obj = {
-		.protocols = {
-			{
-				.guid = &efi_guid_loaded_image,
-			},
-		},
-	};
 	struct efi_loaded_image *info;
 	struct efi_object *obj;
 
 	EFI_ENTRY("%d, %p, %p, %p, %ld, %p", boot_policy, parent_image,
 		  file_path, source_buffer, source_size, image_handle);
-	info = malloc(sizeof(*info));
-	loaded_image_info_obj.protocols[0].protocol_interface = info;
-	obj = malloc(sizeof(loaded_image_info_obj));
-	memset(info, 0, sizeof(*info));
-	memcpy(obj, &loaded_image_info_obj, sizeof(loaded_image_info_obj));
-	obj->handle = info;
-	info->file_path = file_path;
+
+	info = calloc(1, sizeof(*info));
+	obj = calloc(1, sizeof(*obj));
+
+	if (!source_buffer) {
+		struct efi_device_path *dp, *fp;
+		efi_status_t ret;
+
+		ret = efi_load_image_from_path(file_path, &source_buffer);
+		if (ret != EFI_SUCCESS) {
+			free(info);
+			free(obj);
+			return EFI_EXIT(ret);
+		}
+
+		/*
+		 * split file_path which contains both the device and
+		 * file parts:
+		 */
+		efi_dp_split_file_path(file_path, &dp, &fp);
+
+		efi_setup_loaded_image(info, obj, dp, fp);
+	} else {
+		/* In this case, file_path is the "device" path, ie.
+		 * something like a HARDWARE_DEVICE:MEMORY_MAPPED
+		 */
+		efi_setup_loaded_image(info, obj, file_path, NULL);
+	}
+
 	info->reserved = efi_load_pe(source_buffer, info);
 	if (!info->reserved) {
 		free(info);
@@ -751,7 +904,6 @@
 	}
 
 	*image_handle = info;
-	list_add_tail(&obj->link, &efi_obj_list);
 
 	return EFI_EXIT(EFI_SUCCESS);
 }
@@ -793,6 +945,15 @@
 	EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status,
 		  exit_data_size, exit_data);
 
+	/* Make sure entry/exit counts for EFI world cross-overs match */
+	__efi_exit_check();
+
+	/*
+	 * But longjmp out with the U-Boot gd, not the application's, as
+	 * the other end is a setjmp call inside EFI context.
+	 */
+	efi_restore_gd();
+
 	loaded_image_info->exit_status = exit_status;
 	longjmp(&loaded_image_info->exit_jmp, 1);
 
@@ -840,8 +1001,24 @@
 static efi_status_t EFIAPI efi_exit_boot_services(void *image_handle,
 						  unsigned long map_key)
 {
+	int i;
+
 	EFI_ENTRY("%p, %ld", image_handle, map_key);
 
+	/* Notify that ExitBootServices is invoked. */
+	for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
+		if (efi_events[i].type != EVT_SIGNAL_EXIT_BOOT_SERVICES)
+			continue;
+		efi_signal_event(&efi_events[i]);
+	}
+	/* Make sure that notification functions are not called anymore */
+	efi_tpl = TPL_HIGH_LEVEL;
+
+#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
+	/* save any EFI variables that have been written: */
+	env_save();
+#endif
+
 	board_quiesce_devices();
 
 	/* Fix up caches for EFI payloads if necessary */
@@ -906,7 +1083,7 @@
 					      void *agent_handle,
 					      void *controller_handle)
 {
-	EFI_ENTRY("%p, %p, %p, %p", handle, protocol, agent_handle,
+	EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, agent_handle,
 		  controller_handle);
 	return EFI_EXIT(EFI_NOT_FOUND);
 }
@@ -916,7 +1093,7 @@
 			struct efi_open_protocol_info_entry **entry_buffer,
 			unsigned long *entry_count)
 {
-	EFI_ENTRY("%p, %p, %p, %p", handle, protocol, entry_buffer,
+	EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, entry_buffer,
 		  entry_count);
 	return EFI_EXIT(EFI_NOT_FOUND);
 }
@@ -982,7 +1159,7 @@
 	efi_status_t r;
 	unsigned long buffer_size = 0;
 
-	EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key,
+	EFI_ENTRY("%d, %pUl, %p, %p, %p", search_type, protocol, search_key,
 		  no_handles, buffer);
 
 	if (!no_handles || !buffer) {
@@ -1014,11 +1191,13 @@
 	struct list_head *lhandle;
 	int i;
 
-	EFI_ENTRY("%p, %p, %p", protocol, registration, protocol_interface);
+	EFI_ENTRY("%pUl, %p, %p", protocol, registration, protocol_interface);
 
 	if (!protocol || !protocol_interface)
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
 
+	EFI_PRINT_GUID("protocol", protocol);
+
 	list_for_each(lhandle, &efi_obj_list) {
 		struct efi_object *efiobj;
 
@@ -1122,7 +1301,7 @@
 	int i;
 	efi_status_t r = EFI_INVALID_PARAMETER;
 
-	EFI_ENTRY("%p, %p, %p, %p, %p, 0x%x", handle, protocol,
+	EFI_ENTRY("%p, %pUl, %p, %p, %p, 0x%x", handle, protocol,
 		  protocol_interface, agent_handle, controller_handle,
 		  attributes);
 
@@ -1132,6 +1311,8 @@
 		goto out;
 	}
 
+	EFI_PRINT_GUID("protocol", protocol);
+
 	switch (attributes) {
 	case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
 	case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 3fc82b8..fd5398d 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -8,7 +8,10 @@
 
 #include <common.h>
 #include <charset.h>
+#include <dm/device.h>
 #include <efi_loader.h>
+#include <stdio_dev.h>
+#include <video_console.h>
 
 static bool console_size_queried;
 
@@ -137,34 +140,46 @@
 	return EFI_EXIT(EFI_UNSUPPORTED);
 }
 
-static void print_unicode_in_utf8(u16 c)
-{
-	char utf8[MAX_UTF8_PER_UTF16] = { 0 };
-	utf16_to_utf8((u8 *)utf8, &c, 1);
-	puts(utf8);
-}
-
 static efi_status_t EFIAPI efi_cout_output_string(
 			struct efi_simple_text_output_protocol *this,
-			const unsigned short *string)
+			const efi_string_t string)
 {
-	struct cout_mode *mode;
-	u16 ch;
+	struct simple_text_output_mode *con = &efi_con_mode;
+	struct cout_mode *mode = &efi_cout_modes[con->mode];
 
-	mode = &efi_cout_modes[efi_con_mode.mode];
 	EFI_ENTRY("%p, %p", this, string);
-	for (;(ch = *string); string++) {
-		print_unicode_in_utf8(ch);
-		efi_con_mode.cursor_column++;
-		if (ch == '\n') {
-			efi_con_mode.cursor_column = 1;
-			efi_con_mode.cursor_row++;
-		} else if (efi_con_mode.cursor_column > mode->columns) {
-			efi_con_mode.cursor_column = 1;
-			efi_con_mode.cursor_row++;
+
+	unsigned int n16 = utf16_strlen(string);
+	char buf[MAX_UTF8_PER_UTF16 * n16 + 1];
+	char *p;
+
+	*utf16_to_utf8((u8 *)buf, string, n16) = '\0';
+
+	fputs(stdout, buf);
+
+	for (p = buf; *p; p++) {
+		switch (*p) {
+		case '\r':   /* carriage-return */
+			con->cursor_column = 0;
+			break;
+		case '\n':   /* newline */
+			con->cursor_column = 0;
+			con->cursor_row++;
+			break;
+		case '\t':   /* tab, assume 8 char align */
+			break;
+		case '\b':   /* backspace */
+			con->cursor_column = max(0, con->cursor_column - 1);
+			break;
+		default:
+			con->cursor_column++;
+			break;
 		}
-		if (efi_con_mode.cursor_row > mode->rows)
-			efi_con_mode.cursor_row = mode->rows;
+		if (con->cursor_column >= mode->columns) {
+			con->cursor_column = 0;
+			con->cursor_row++;
+		}
+		con->cursor_row = min(con->cursor_row, (s32)mode->rows - 1);
 	}
 
 	return EFI_EXIT(EFI_SUCCESS);
@@ -172,7 +187,7 @@
 
 static efi_status_t EFIAPI efi_cout_test_string(
 			struct efi_simple_text_output_protocol *this,
-			const unsigned short *string)
+			const efi_string_t string)
 {
 	EFI_ENTRY("%p, %p", this, string);
 	return EFI_EXIT(EFI_SUCCESS);
@@ -186,6 +201,34 @@
 	return (mode->rows == rows) && (mode->columns == cols);
 }
 
+static int query_console_serial(int *rows, int *cols)
+{
+	/* Ask the terminal about its size */
+	int n[3];
+	u64 timeout;
+
+	/* Empty input buffer */
+	while (tstc())
+		getc();
+
+	printf(ESC"[18t");
+
+	/* Check if we have a terminal that understands */
+	timeout = timer_get_us() + 1000000;
+	while (!tstc())
+		if (timer_get_us() > timeout)
+			return -1;
+
+	/* Read {depth,rows,cols} */
+	if (term_read_reply(n, 3, 't'))
+		return -1;
+
+	*cols = n[2];
+	*rows = n[1];
+
+	return 0;
+}
+
 static efi_status_t EFIAPI efi_cout_query_mode(
 			struct efi_simple_text_output_protocol *this,
 			unsigned long mode_number, unsigned long *columns,
@@ -194,34 +237,24 @@
 	EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows);
 
 	if (!console_size_queried) {
-		/* Ask the terminal about its size */
-		int n[3];
-		int cols;
-		int rows;
-		u64 timeout;
+		const char *stdout_name = env_get("stdout");
+		int rows, cols;
 
 		console_size_queried = true;
 
-		/* Empty input buffer */
-		while (tstc())
-			getc();
-
-		printf(ESC"[18t");
-
-		/* Check if we have a terminal that understands */
-		timeout = timer_get_us() + 1000000;
-		while (!tstc())
-			if (timer_get_us() > timeout)
-				goto out;
-
-		/* Read {depth,rows,cols} */
-		if (term_read_reply(n, 3, 't')) {
+		if (stdout_name && !strcmp(stdout_name, "vidconsole") &&
+		    IS_ENABLED(CONFIG_DM_VIDEO)) {
+			struct stdio_dev *stdout_dev =
+				stdio_get_by_name("vidconsole");
+			struct udevice *dev = stdout_dev->priv;
+			struct vidconsole_priv *priv =
+				dev_get_uclass_priv(dev);
+			rows = priv->rows;
+			cols = priv->cols;
+		} else if (query_console_serial(&rows, &cols)) {
 			goto out;
 		}
 
-		cols = n[2];
-		rows = n[1];
-
 		/* Test if we can have Mode 1 */
 		if (cols >= 80 && rows >= 50) {
 			efi_cout_modes[1].present = 1;
@@ -426,8 +459,10 @@
 					    void *context)
 {
 	EFI_ENTRY("%p, %p", event, context);
-	if (tstc())
+	if (tstc()) {
+		efi_con_in.wait_for_key->signaled = 1;
 		efi_signal_event(efi_con_in.wait_for_key);
+		}
 	EFI_EXIT(EFI_SUCCESS);
 }
 
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
new file mode 100644
index 0000000..5d5c3b3
--- /dev/null
+++ b/lib/efi_loader/efi_device_path.c
@@ -0,0 +1,563 @@
+/*
+ * EFI device path from u-boot device-model mapping
+ *
+ * (C) Copyright 2017 Rob Clark
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <dm.h>
+#include <usb.h>
+#include <mmc.h>
+#include <efi_loader.h>
+#include <inttypes.h>
+#include <part.h>
+
+/* template END node: */
+static const struct efi_device_path END = {
+	.type     = DEVICE_PATH_TYPE_END,
+	.sub_type = DEVICE_PATH_SUB_TYPE_END,
+	.length   = sizeof(END),
+};
+
+#define U_BOOT_GUID \
+	EFI_GUID(0xe61d73b9, 0xa384, 0x4acc, \
+		 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3, 0x62, 0x8b)
+
+/* template ROOT node: */
+static const struct efi_device_path_vendor ROOT = {
+	.dp = {
+		.type     = DEVICE_PATH_TYPE_HARDWARE_DEVICE,
+		.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR,
+		.length   = sizeof(ROOT),
+	},
+	.guid = U_BOOT_GUID,
+};
+
+static void *dp_alloc(size_t sz)
+{
+	void *buf;
+
+	if (efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, sz, &buf) != EFI_SUCCESS)
+		return NULL;
+
+	return buf;
+}
+
+/*
+ * Iterate to next block in device-path, terminating (returning NULL)
+ * at /End* node.
+ */
+struct efi_device_path *efi_dp_next(const struct efi_device_path *dp)
+{
+	if (dp == NULL)
+		return NULL;
+	if (dp->type == DEVICE_PATH_TYPE_END)
+		return NULL;
+	dp = ((void *)dp) + dp->length;
+	if (dp->type == DEVICE_PATH_TYPE_END)
+		return NULL;
+	return (struct efi_device_path *)dp;
+}
+
+/*
+ * Compare two device-paths, stopping when the shorter of the two hits
+ * an End* node.  This is useful to, for example, compare a device-path
+ * representing a device with one representing a file on the device, or
+ * a device with a parent device.
+ */
+int efi_dp_match(struct efi_device_path *a, struct efi_device_path *b)
+{
+	while (1) {
+		int ret;
+
+		ret = memcmp(&a->length, &b->length, sizeof(a->length));
+		if (ret)
+			return ret;
+
+		ret = memcmp(a, b, a->length);
+		if (ret)
+			return ret;
+
+		a = efi_dp_next(a);
+		b = efi_dp_next(b);
+
+		if (!a || !b)
+			return 0;
+	}
+}
+
+
+/*
+ * See UEFI spec (section 3.1.2, about short-form device-paths..
+ * tl;dr: we can have a device-path that starts with a USB WWID
+ * or USB Class node, and a few other cases which don't encode
+ * the full device path with bus hierarchy:
+ *
+ *   - MESSAGING:USB_WWID
+ *   - MESSAGING:USB_CLASS
+ *   - MEDIA:FILE_PATH
+ *   - MEDIA:HARD_DRIVE
+ *   - MESSAGING:URI
+ */
+static struct efi_device_path *shorten_path(struct efi_device_path *dp)
+{
+	while (dp) {
+		/*
+		 * TODO: Add MESSAGING:USB_WWID and MESSAGING:URI..
+		 * in practice fallback.efi just uses MEDIA:HARD_DRIVE
+		 * so not sure when we would see these other cases.
+		 */
+		if (EFI_DP_TYPE(dp, MESSAGING_DEVICE, MSG_USB_CLASS) ||
+		    EFI_DP_TYPE(dp, MEDIA_DEVICE, HARD_DRIVE_PATH) ||
+		    EFI_DP_TYPE(dp, MEDIA_DEVICE, FILE_PATH))
+			return dp;
+
+		dp = efi_dp_next(dp);
+	}
+
+	return dp;
+}
+
+static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path,
+				   struct efi_device_path **rem)
+{
+	struct efi_object *efiobj;
+
+	list_for_each_entry(efiobj, &efi_obj_list, link) {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
+			struct efi_handler *handler = &efiobj->protocols[i];
+			struct efi_device_path *obj_dp;
+
+			if (!handler->guid)
+				break;
+
+			if (guidcmp(handler->guid, &efi_guid_device_path))
+				continue;
+
+			obj_dp = handler->protocol_interface;
+
+			do {
+				if (efi_dp_match(dp, obj_dp) == 0) {
+					if (rem) {
+						*rem = ((void *)dp) +
+							efi_dp_size(obj_dp);
+					}
+					return efiobj;
+				}
+
+				obj_dp = shorten_path(efi_dp_next(obj_dp));
+			} while (short_path && obj_dp);
+		}
+	}
+
+	return NULL;
+}
+
+
+/*
+ * Find an efiobj from device-path, if 'rem' is not NULL, returns the
+ * remaining part of the device path after the matched object.
+ */
+struct efi_object *efi_dp_find_obj(struct efi_device_path *dp,
+				   struct efi_device_path **rem)
+{
+	struct efi_object *efiobj;
+
+	efiobj = find_obj(dp, false, rem);
+
+	if (!efiobj)
+		efiobj = find_obj(dp, true, rem);
+
+	return efiobj;
+}
+
+/* return size not including End node: */
+unsigned efi_dp_size(const struct efi_device_path *dp)
+{
+	unsigned sz = 0;
+
+	while (dp) {
+		sz += dp->length;
+		dp = efi_dp_next(dp);
+	}
+
+	return sz;
+}
+
+struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
+{
+	struct efi_device_path *ndp;
+	unsigned sz = efi_dp_size(dp) + sizeof(END);
+
+	if (!dp)
+		return NULL;
+
+	ndp = dp_alloc(sz);
+	memcpy(ndp, dp, sz);
+
+	return ndp;
+}
+
+struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
+				      const struct efi_device_path *dp2)
+{
+	struct efi_device_path *ret;
+
+	if (!dp1) {
+		ret = efi_dp_dup(dp2);
+	} else if (!dp2) {
+		ret = efi_dp_dup(dp1);
+	} else {
+		/* both dp1 and dp2 are non-null */
+		unsigned sz1 = efi_dp_size(dp1);
+		unsigned sz2 = efi_dp_size(dp2);
+		void *p = dp_alloc(sz1 + sz2 + sizeof(END));
+		memcpy(p, dp1, sz1);
+		memcpy(p + sz1, dp2, sz2);
+		memcpy(p + sz1 + sz2, &END, sizeof(END));
+		ret = p;
+	}
+
+	return ret;
+}
+
+struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
+					   const struct efi_device_path *node)
+{
+	struct efi_device_path *ret;
+
+	if (!node && !dp) {
+		ret = efi_dp_dup(&END);
+	} else if (!node) {
+		ret = efi_dp_dup(dp);
+	} else if (!dp) {
+		unsigned sz = node->length;
+		void *p = dp_alloc(sz + sizeof(END));
+		memcpy(p, node, sz);
+		memcpy(p + sz, &END, sizeof(END));
+		ret = p;
+	} else {
+		/* both dp and node are non-null */
+		unsigned sz = efi_dp_size(dp);
+		void *p = dp_alloc(sz + node->length + sizeof(END));
+		memcpy(p, dp, sz);
+		memcpy(p + sz, node, node->length);
+		memcpy(p + sz + node->length, &END, sizeof(END));
+		ret = p;
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_DM
+/* size of device-path not including END node for device and all parents
+ * up to the root device.
+ */
+static unsigned dp_size(struct udevice *dev)
+{
+	if (!dev || !dev->driver)
+		return sizeof(ROOT);
+
+	switch (dev->driver->id) {
+	case UCLASS_ROOT:
+	case UCLASS_SIMPLE_BUS:
+		/* stop traversing parents at this point: */
+		return sizeof(ROOT);
+	case UCLASS_MMC:
+		return dp_size(dev->parent) +
+			sizeof(struct efi_device_path_sd_mmc_path);
+	case UCLASS_MASS_STORAGE:
+	case UCLASS_USB_HUB:
+		return dp_size(dev->parent) +
+			sizeof(struct efi_device_path_usb_class);
+	default:
+		/* just skip over unknown classes: */
+		return dp_size(dev->parent);
+	}
+}
+
+static void *dp_fill(void *buf, struct udevice *dev)
+{
+	if (!dev || !dev->driver)
+		return buf;
+
+	switch (dev->driver->id) {
+	case UCLASS_ROOT:
+	case UCLASS_SIMPLE_BUS: {
+		/* stop traversing parents at this point: */
+		struct efi_device_path_vendor *vdp = buf;
+		*vdp = ROOT;
+		return &vdp[1];
+	}
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
+	case UCLASS_MMC: {
+		struct efi_device_path_sd_mmc_path *sddp =
+			dp_fill(buf, dev->parent);
+		struct mmc *mmc = mmc_get_mmc_dev(dev);
+		struct blk_desc *desc = mmc_get_blk_desc(mmc);
+
+		sddp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+		sddp->dp.sub_type = (desc->if_type == IF_TYPE_MMC) ?
+			DEVICE_PATH_SUB_TYPE_MSG_MMC :
+			DEVICE_PATH_SUB_TYPE_MSG_SD;
+		sddp->dp.length   = sizeof(*sddp);
+		sddp->slot_number = dev->seq;
+
+		return &sddp[1];
+	}
+#endif
+	case UCLASS_MASS_STORAGE:
+	case UCLASS_USB_HUB: {
+		struct efi_device_path_usb_class *udp =
+			dp_fill(buf, dev->parent);
+		struct usb_device *udev = dev_get_parent_priv(dev);
+		struct usb_device_descriptor *desc = &udev->descriptor;
+
+		udp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+		udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS;
+		udp->dp.length   = sizeof(*udp);
+		udp->vendor_id   = desc->idVendor;
+		udp->product_id  = desc->idProduct;
+		udp->device_class    = desc->bDeviceClass;
+		udp->device_subclass = desc->bDeviceSubClass;
+		udp->device_protocol = desc->bDeviceProtocol;
+
+		return &udp[1];
+	}
+	default:
+		debug("unhandled device class: %s (%u)\n",
+		      dev->name, dev->driver->id);
+		return dp_fill(buf, dev->parent);
+	}
+}
+
+/* Construct a device-path from a device: */
+struct efi_device_path *efi_dp_from_dev(struct udevice *dev)
+{
+	void *buf, *start;
+
+	start = buf = dp_alloc(dp_size(dev) + sizeof(END));
+	buf = dp_fill(buf, dev);
+	*((struct efi_device_path *)buf) = END;
+
+	return start;
+}
+#endif
+
+static unsigned dp_part_size(struct blk_desc *desc, int part)
+{
+	unsigned dpsize;
+
+#ifdef CONFIG_BLK
+	dpsize = dp_size(desc->bdev->parent);
+#else
+	dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb);
+#endif
+
+	if (part == 0) /* the actual disk, not a partition */
+		return dpsize;
+
+	if (desc->part_type == PART_TYPE_ISO)
+		dpsize += sizeof(struct efi_device_path_cdrom_path);
+	else
+		dpsize += sizeof(struct efi_device_path_hard_drive_path);
+
+	return dpsize;
+}
+
+static void *dp_part_fill(void *buf, struct blk_desc *desc, int part)
+{
+	disk_partition_t info;
+
+#ifdef CONFIG_BLK
+	buf = dp_fill(buf, desc->bdev->parent);
+#else
+	/*
+	 * We *could* make a more accurate path, by looking at if_type
+	 * and handling all the different cases like we do for non-
+	 * legacy (ie CONFIG_BLK=y) case.  But most important thing
+	 * is just to have a unique device-path for if_type+devnum.
+	 * So map things to a fictional USB device:
+	 */
+	struct efi_device_path_usb *udp;
+
+	memcpy(buf, &ROOT, sizeof(ROOT));
+	buf += sizeof(ROOT);
+
+	udp = buf;
+	udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+	udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
+	udp->dp.length = sizeof(*udp);
+	udp->parent_port_number = desc->if_type;
+	udp->usb_interface = desc->devnum;
+	buf = &udp[1];
+#endif
+
+	if (part == 0) /* the actual disk, not a partition */
+		return buf;
+
+	part_get_info(desc, part, &info);
+
+	if (desc->part_type == PART_TYPE_ISO) {
+		struct efi_device_path_cdrom_path *cddp = buf;
+
+		cddp->boot_entry = part - 1;
+		cddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
+		cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH;
+		cddp->dp.length = sizeof(*cddp);
+		cddp->partition_start = info.start;
+		cddp->partition_end = info.size;
+
+		buf = &cddp[1];
+	} else {
+		struct efi_device_path_hard_drive_path *hddp = buf;
+
+		hddp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
+		hddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH;
+		hddp->dp.length = sizeof(*hddp);
+		hddp->partition_number = part - 1;
+		hddp->partition_start = info.start;
+		hddp->partition_end = info.size;
+		if (desc->part_type == PART_TYPE_EFI)
+			hddp->partmap_type = 2;
+		else
+			hddp->partmap_type = 1;
+		hddp->signature_type = desc->sig_type;
+		if (hddp->signature_type != 0)
+			memcpy(hddp->partition_signature, &desc->guid_sig,
+			       sizeof(hddp->partition_signature));
+
+		buf = &hddp[1];
+	}
+
+	return buf;
+}
+
+
+/* Construct a device-path from a partition on a blk device: */
+struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
+{
+	void *buf, *start;
+
+	start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END));
+
+	buf = dp_part_fill(buf, desc, part);
+
+	*((struct efi_device_path *)buf) = END;
+
+	return start;
+}
+
+/* convert path to an UEFI style path (ie. DOS style backslashes and utf16) */
+static void path_to_uefi(u16 *uefi, const char *path)
+{
+	while (*path) {
+		char c = *(path++);
+		if (c == '/')
+			c = '\\';
+		*(uefi++) = c;
+	}
+	*uefi = '\0';
+}
+
+/*
+ * If desc is NULL, this creates a path with only the file component,
+ * otherwise it creates a full path with both device and file components
+ */
+struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
+		const char *path)
+{
+	struct efi_device_path_file_path *fp;
+	void *buf, *start;
+	unsigned dpsize = 0, fpsize;
+
+	if (desc)
+		dpsize = dp_part_size(desc, part);
+
+	fpsize = sizeof(struct efi_device_path) + 2 * (strlen(path) + 1);
+	dpsize += fpsize;
+
+	start = buf = dp_alloc(dpsize + sizeof(END));
+
+	if (desc)
+		buf = dp_part_fill(buf, desc, part);
+
+	/* add file-path: */
+	fp = buf;
+	fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
+	fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
+	fp->dp.length = fpsize;
+	path_to_uefi(fp->str, path);
+	buf += fpsize;
+
+	*((struct efi_device_path *)buf) = END;
+
+	return start;
+}
+
+#ifdef CONFIG_NET
+struct efi_device_path *efi_dp_from_eth(void)
+{
+	struct efi_device_path_mac_addr *ndp;
+	void *buf, *start;
+	unsigned dpsize = 0;
+
+	assert(eth_get_dev());
+
+#ifdef CONFIG_DM_ETH
+	dpsize += dp_size(eth_get_dev());
+#else
+	dpsize += sizeof(ROOT);
+#endif
+	dpsize += sizeof(*ndp);
+
+	start = buf = dp_alloc(dpsize + sizeof(END));
+
+#ifdef CONFIG_DM_ETH
+	buf = dp_fill(buf, eth_get_dev());
+#else
+	memcpy(buf, &ROOT, sizeof(ROOT));
+	buf += sizeof(ROOT);
+#endif
+
+	ndp = buf;
+	ndp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+	ndp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
+	ndp->dp.length = sizeof(*ndp);
+	memcpy(ndp->mac.addr, eth_get_ethaddr(), ARP_HLEN);
+	buf = &ndp[1];
+
+	*((struct efi_device_path *)buf) = END;
+
+	return start;
+}
+#endif
+
+/*
+ * Helper to split a full device path (containing both device and file
+ * parts) into it's constituent parts.
+ */
+void efi_dp_split_file_path(struct efi_device_path *full_path,
+			    struct efi_device_path **device_path,
+			    struct efi_device_path **file_path)
+{
+	struct efi_device_path *p, *dp, *fp;
+
+	dp = efi_dp_dup(full_path);
+	p = dp;
+	while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH))
+		p = efi_dp_next(p);
+	fp = efi_dp_dup(p);
+
+	p->type = DEVICE_PATH_TYPE_END;
+	p->sub_type = DEVICE_PATH_SUB_TYPE_END;
+	p->length = sizeof(*p);
+
+	*device_path = dp;
+	*file_path = fp;
+}
diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c
index 4b2f43f..1a5ef39 100644
--- a/lib/efi_loader/efi_device_path_to_text.c
+++ b/lib/efi_loader/efi_device_path_to_text.c
@@ -15,81 +15,199 @@
 const efi_guid_t efi_guid_device_path_to_text_protocol =
 		EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
 
+static char *dp_unknown(char *s, struct efi_device_path *dp)
+{
+	s += sprintf(s, "/UNKNOWN(%04x,%04x)", dp->type, dp->sub_type);
+	return s;
+}
+
+static char *dp_hardware(char *s, struct efi_device_path *dp)
+{
+	switch (dp->sub_type) {
+	case DEVICE_PATH_SUB_TYPE_VENDOR: {
+		struct efi_device_path_vendor *vdp =
+			(struct efi_device_path_vendor *)dp;
+		s += sprintf(s, "/VenHw(%pUl)", &vdp->guid);
+		break;
+	}
+	default:
+		s = dp_unknown(s, dp);
+		break;
+	}
+	return s;
+}
+
+static char *dp_acpi(char *s, struct efi_device_path *dp)
+{
+	switch (dp->sub_type) {
+	case DEVICE_PATH_SUB_TYPE_ACPI_DEVICE: {
+		struct efi_device_path_acpi_path *adp =
+			(struct efi_device_path_acpi_path *)dp;
+		s += sprintf(s, "/Acpi(PNP%04x", EISA_PNP_NUM(adp->hid));
+		if (adp->uid)
+			s += sprintf(s, ",%d", adp->uid);
+		s += sprintf(s, ")");
+		break;
+	}
+	default:
+		s = dp_unknown(s, dp);
+		break;
+	}
+	return s;
+}
+
+static char *dp_msging(char *s, struct efi_device_path *dp)
+{
+	switch (dp->sub_type) {
+	case DEVICE_PATH_SUB_TYPE_MSG_USB: {
+		struct efi_device_path_usb *udp =
+			(struct efi_device_path_usb *)dp;
+		s += sprintf(s, "/Usb(0x%x,0x%x)", udp->parent_port_number,
+			     udp->usb_interface);
+		break;
+	}
+	case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: {
+		struct efi_device_path_mac_addr *mdp =
+			(struct efi_device_path_mac_addr *)dp;
+
+		if (mdp->if_type != 0 && mdp->if_type != 1)
+			break;
+
+		s += sprintf(s, "/MAC(%02x%02x%02x%02x%02x%02x,0x%1x)",
+			mdp->mac.addr[0], mdp->mac.addr[1],
+			mdp->mac.addr[2], mdp->mac.addr[3],
+			mdp->mac.addr[4], mdp->mac.addr[5],
+			mdp->if_type);
+
+		break;
+	}
+	case DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS: {
+		struct efi_device_path_usb_class *ucdp =
+			(struct efi_device_path_usb_class *)dp;
+
+		s += sprintf(s, "/USBClass(%x,%x,%x,%x,%x)",
+			ucdp->vendor_id, ucdp->product_id,
+			ucdp->device_class, ucdp->device_subclass,
+			ucdp->device_protocol);
+
+		break;
+	}
+	case DEVICE_PATH_SUB_TYPE_MSG_SD:
+	case DEVICE_PATH_SUB_TYPE_MSG_MMC: {
+		const char *typename =
+			(dp->sub_type == DEVICE_PATH_SUB_TYPE_MSG_SD) ?
+					"SDCard" : "MMC";
+		struct efi_device_path_sd_mmc_path *sddp =
+			(struct efi_device_path_sd_mmc_path *)dp;
+		s += sprintf(s, "/%s(Slot%u)", typename, sddp->slot_number);
+		break;
+	}
+	default:
+		s = dp_unknown(s, dp);
+		break;
+	}
+	return s;
+}
+
+static char *dp_media(char *s, struct efi_device_path *dp)
+{
+	switch (dp->sub_type) {
+	case DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH: {
+		struct efi_device_path_hard_drive_path *hddp =
+			(struct efi_device_path_hard_drive_path *)dp;
+		void *sig = hddp->partition_signature;
+
+		switch (hddp->signature_type) {
+		case SIG_TYPE_MBR:
+			s += sprintf(s, "/HD(Part%d,Sig%08x)",
+				     hddp->partition_number,
+				     *(uint32_t *)sig);
+			break;
+		case SIG_TYPE_GUID:
+			s += sprintf(s, "/HD(Part%d,Sig%pUl)",
+				     hddp->partition_number, sig);
+		default:
+			s += sprintf(s, "/HD(Part%d,MBRType=%02x,SigType=%02x)",
+				     hddp->partition_number, hddp->partmap_type,
+				     hddp->signature_type);
+		}
+
+		break;
+	}
+	case DEVICE_PATH_SUB_TYPE_CDROM_PATH: {
+		struct efi_device_path_cdrom_path *cddp =
+			(struct efi_device_path_cdrom_path *)dp;
+		s += sprintf(s, "/CDROM(0x%x)", cddp->boot_entry);
+		break;
+	}
+	case DEVICE_PATH_SUB_TYPE_FILE_PATH: {
+		struct efi_device_path_file_path *fp =
+			(struct efi_device_path_file_path *)dp;
+		int slen = (dp->length - sizeof(*dp)) / 2;
+		s += sprintf(s, "/%-*ls", slen, fp->str);
+		break;
+	}
+	default:
+		s = dp_unknown(s, dp);
+		break;
+	}
+	return s;
+}
+
 static uint16_t *efi_convert_device_node_to_text(
-		struct efi_device_path_protocol *device_node,
+		struct efi_device_path *dp,
 		bool display_only,
 		bool allow_shortcuts)
 {
-	unsigned long buffer_size;
+	unsigned long len;
 	efi_status_t r;
-	uint16_t *buffer = NULL;
-	int i;
+	char buf[512];  /* this ought be be big enough for worst case */
+	char *str = buf;
+	uint16_t *out;
 
-	switch (device_node->type) {
-	case DEVICE_PATH_TYPE_END:
+	while (dp) {
+		switch (dp->type) {
+		case DEVICE_PATH_TYPE_HARDWARE_DEVICE:
+			str = dp_hardware(str, dp);
+			break;
+		case DEVICE_PATH_TYPE_ACPI_DEVICE:
+			str = dp_acpi(str, dp);
+			break;
+		case DEVICE_PATH_TYPE_MESSAGING_DEVICE:
+			str = dp_msging(str, dp);
+			break;
+		case DEVICE_PATH_TYPE_MEDIA_DEVICE:
+			str = dp_media(str, dp);
+			break;
+		default:
+			str = dp_unknown(str, dp);
+		}
+
+		dp = efi_dp_next(dp);
+	}
+
+	*str++ = '\0';
+
+	len = str - buf;
+	r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, 2 * len, (void **)&out);
+	if (r != EFI_SUCCESS)
 		return NULL;
-	case DEVICE_PATH_TYPE_MESSAGING_DEVICE:
-		switch (device_node->sub_type) {
-		case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: {
-			struct efi_device_path_mac_addr *dp =
-				(struct efi_device_path_mac_addr *)device_node;
 
-			if (dp->if_type != 0 && dp->if_type != 1)
-				break;
-			r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
-					      2 * MAC_OUTPUT_LEN,
-					      (void **)&buffer);
-			if (r != EFI_SUCCESS)
-				return NULL;
-			sprintf((char *)buffer,
-				"MAC(%02x%02x%02x%02x%02x%02x,0x%1x)",
-				dp->mac.addr[0], dp->mac.addr[1],
-				dp->mac.addr[2], dp->mac.addr[3],
-				dp->mac.addr[4], dp->mac.addr[5],
-				dp->if_type);
-			for (i = MAC_OUTPUT_LEN - 1; i >= 0; --i)
-				buffer[i] = ((uint8_t *)buffer)[i];
-			break;
-			}
-		}
-		break;
-	case DEVICE_PATH_TYPE_MEDIA_DEVICE:
-		switch (device_node->sub_type) {
-		case DEVICE_PATH_SUB_TYPE_FILE_PATH:
-			buffer_size = device_node->length - 4;
-			r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
-					      buffer_size, (void **) &buffer);
-			if (r != EFI_SUCCESS)
-				return NULL;
-			memcpy(buffer, device_node->data, buffer_size);
-			break;
-		}
-		break;
-	}
+	ascii2unicode(out, buf);
+	out[len - 1] = 0;
 
-	/*
-	 * For all node types that we do not yet support return
-	 * 'UNKNOWN(type,subtype)'.
-	 */
-	if (!buffer) {
-		r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
-				      2 * UNKNOWN_OUTPUT_LEN,
-				      (void **)&buffer);
-		if (r != EFI_SUCCESS)
-			return NULL;
-		sprintf((char *)buffer,
-			"UNKNOWN(%04x,%04x)",
-			device_node->type,
-			device_node->sub_type);
-		for (i = UNKNOWN_OUTPUT_LEN - 1; i >= 0; --i)
-			buffer[i] = ((uint8_t *)buffer)[i];
-	}
-
-	return buffer;
+	return out;
 }
 
+/* helper for debug prints.. efi_free_pool() the result. */
+uint16_t *efi_dp_str(struct efi_device_path *dp)
+{
+	return efi_convert_device_node_to_text(dp, true, true);
+}
+
+
 static uint16_t EFIAPI *efi_convert_device_node_to_text_ext(
-		struct efi_device_path_protocol *device_node,
+		struct efi_device_path *device_node,
 		bool display_only,
 		bool allow_shortcuts)
 {
@@ -105,7 +223,7 @@
 }
 
 static uint16_t EFIAPI *efi_convert_device_path_to_text(
-		struct efi_device_path_protocol *device_path,
+		struct efi_device_path *device_path,
 		bool display_only,
 		bool allow_shortcuts)
 {
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index ed06485..eb9ce77 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -28,11 +28,15 @@
 	/* EFI Interface Media descriptor struct, referenced by ops */
 	struct efi_block_io_media media;
 	/* EFI device path to this block device */
-	struct efi_device_path_file_path *dp;
+	struct efi_device_path *dp;
+	/* partition # */
+	unsigned int part;
+	/* handle to filesys proto (for partition objects) */
+	struct efi_simple_file_system_protocol *volume;
 	/* Offset into disk for simple partitions */
 	lbaint_t offset;
 	/* Internal block device */
-	const struct blk_desc *desc;
+	struct blk_desc *desc;
 };
 
 static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this,
@@ -47,7 +51,7 @@
 	EFI_DISK_WRITE,
 };
 
-static efi_status_t EFIAPI efi_disk_rw_blocks(struct efi_block_io *this,
+static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this,
 			u32 media_id, u64 lba, unsigned long buffer_size,
 			void *buffer, enum efi_disk_direction direction)
 {
@@ -170,28 +174,58 @@
 	.flush_blocks = &efi_disk_flush_blocks,
 };
 
+/*
+ * Find filesystem from a device-path.  The passed in path 'p' probably
+ * contains one or more /File(name) nodes, so the comparison stops at
+ * the first /File() node, and returns the pointer to that via 'rp'.
+ * This is mostly intended to be a helper to map a device-path to an
+ * efi_file_handle object.
+ */
+struct efi_simple_file_system_protocol *
+efi_fs_from_path(struct efi_device_path *fp)
+{
+	struct efi_object *efiobj;
+	struct efi_disk_obj *diskobj;
+
+	efiobj = efi_dp_find_obj(fp, NULL);
+	if (!efiobj)
+		return NULL;
+
+	diskobj = container_of(efiobj, struct efi_disk_obj, parent);
+
+	return diskobj->volume;
+}
+
 static void efi_disk_add_dev(const char *name,
 			     const char *if_typename,
-			     const struct blk_desc *desc,
+			     struct blk_desc *desc,
 			     int dev_index,
-			     lbaint_t offset)
+			     lbaint_t offset,
+			     unsigned int part)
 {
 	struct efi_disk_obj *diskobj;
-	struct efi_device_path_file_path *dp;
-	int objlen = sizeof(*diskobj) + (sizeof(*dp) * 2);
 
 	/* Don't add empty devices */
 	if (!desc->lba)
 		return;
 
-	diskobj = calloc(1, objlen);
+	diskobj = calloc(1, sizeof(*diskobj));
 
 	/* Fill in object data */
-	dp = (void *)&diskobj[1];
+	diskobj->dp = efi_dp_from_part(desc, part);
+	diskobj->part = part;
 	diskobj->parent.protocols[0].guid = &efi_block_io_guid;
 	diskobj->parent.protocols[0].protocol_interface = &diskobj->ops;
 	diskobj->parent.protocols[1].guid = &efi_guid_device_path;
-	diskobj->parent.protocols[1].protocol_interface = dp;
+	diskobj->parent.protocols[1].protocol_interface = diskobj->dp;
+	if (part >= 1) {
+		diskobj->volume = efi_simple_file_system(desc, part,
+							 diskobj->dp);
+		diskobj->parent.protocols[2].guid =
+			&efi_simple_file_system_protocol_guid;
+		diskobj->parent.protocols[2].protocol_interface =
+			diskobj->volume;
+	}
 	diskobj->parent.handle = diskobj;
 	diskobj->ops = block_io_disk_template;
 	diskobj->ifname = if_typename;
@@ -207,17 +241,6 @@
 	diskobj->media.last_block = desc->lba - offset;
 	diskobj->ops.media = &diskobj->media;
 
-	/* Fill in device path */
-	diskobj->dp = dp;
-	dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
-	dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
-	dp[0].dp.length = sizeof(*dp);
-	ascii2unicode(dp[0].str, name);
-
-	dp[1].dp.type = DEVICE_PATH_TYPE_END;
-	dp[1].dp.sub_type = DEVICE_PATH_SUB_TYPE_END;
-	dp[1].dp.length = sizeof(*dp);
-
 	/* Hook up to the device list */
 	list_add_tail(&diskobj->parent.link, &efi_obj_list);
 }
@@ -236,14 +259,18 @@
 	if (desc->part_type != PART_TYPE_ISO)
 		return 0;
 
+	/* and devices for each partition: */
 	while (!part_get_info(desc, part, &info)) {
 		snprintf(devname, sizeof(devname), "%s:%d", pdevname,
 			 part);
 		efi_disk_add_dev(devname, if_typename, desc, diskid,
-				 info.start);
+				 info.start, part);
 		part++;
 		disks++;
 	}
+
+	/* ... and add block device: */
+	efi_disk_add_dev(devname, if_typename, desc, diskid, 0, 0);
 #endif
 
 	return disks;
@@ -271,9 +298,22 @@
 	     uclass_next_device_check(&dev)) {
 		struct blk_desc *desc = dev_get_uclass_platdata(dev);
 		const char *if_typename = dev->driver->name;
+		disk_partition_t info;
+		int part = 1;
 
 		printf("Scanning disk %s...\n", dev->name);
-		efi_disk_add_dev(dev->name, if_typename, desc, desc->devnum, 0);
+
+		/* add devices for each partition: */
+		while (!part_get_info(desc, part, &info)) {
+			efi_disk_add_dev(dev->name, if_typename, desc,
+					 desc->devnum, 0, part);
+			part++;
+		}
+
+		/* ... and add block device: */
+		efi_disk_add_dev(dev->name, if_typename, desc,
+				 desc->devnum, 0, 0);
+
 		disks++;
 
 		/*
@@ -309,7 +349,7 @@
 
 			snprintf(devname, sizeof(devname), "%s%d",
 				 if_typename, i);
-			efi_disk_add_dev(devname, if_typename, desc, i, 0);
+			efi_disk_add_dev(devname, if_typename, desc, i, 0, 0);
 			disks++;
 
 			/*
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
new file mode 100644
index 0000000..52a4e74
--- /dev/null
+++ b/lib/efi_loader/efi_file.c
@@ -0,0 +1,560 @@
+/*
+ *  EFI utils
+ *
+ *  Copyright (c) 2017 Rob Clark
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <efi_loader.h>
+#include <malloc.h>
+#include <fs.h>
+
+struct file_system {
+	struct efi_simple_file_system_protocol base;
+	struct efi_device_path *dp;
+	struct blk_desc *desc;
+	int part;
+};
+#define to_fs(x) container_of(x, struct file_system, base)
+
+struct file_handle {
+	struct efi_file_handle base;
+	struct file_system *fs;
+	loff_t offset;       /* current file position/cursor */
+	int isdir;
+
+	/* for reading a directory: */
+	struct fs_dir_stream *dirs;
+	struct fs_dirent *dent;
+
+	char path[0];
+};
+#define to_fh(x) container_of(x, struct file_handle, base)
+
+static const struct efi_file_handle efi_file_handle_protocol;
+
+static char *basename(struct file_handle *fh)
+{
+	char *s = strrchr(fh->path, '/');
+	if (s)
+		return s + 1;
+	return fh->path;
+}
+
+static int set_blk_dev(struct file_handle *fh)
+{
+	return fs_set_blk_dev_with_part(fh->fs->desc, fh->fs->part);
+}
+
+static int is_dir(struct file_handle *fh)
+{
+	struct fs_dir_stream *dirs;
+
+	set_blk_dev(fh);
+	dirs = fs_opendir(fh->path);
+	if (!dirs)
+		return 0;
+
+	fs_closedir(dirs);
+
+	return 1;
+}
+
+/*
+ * Normalize a path which may include either back or fwd slashes,
+ * double slashes, . or .. entries in the path, etc.
+ */
+static int sanitize_path(char *path)
+{
+	char *p;
+
+	/* backslash to slash: */
+	p = path;
+	while ((p = strchr(p, '\\')))
+		*p++ = '/';
+
+	/* handle double-slashes: */
+	p = path;
+	while ((p = strstr(p, "//"))) {
+		char *src = p + 1;
+		memmove(p, src, strlen(src) + 1);
+	}
+
+	/* handle extra /.'s */
+	p = path;
+	while ((p = strstr(p, "/."))) {
+		/*
+		 * You'd be tempted to do this *after* handling ".."s
+		 * below to avoid having to check if "/." is start of
+		 * a "/..", but that won't have the correct results..
+		 * for example, "/foo/./../bar" would get resolved to
+		 * "/foo/bar" if you did these two passes in the other
+		 * order
+		 */
+		if (p[2] == '.') {
+			p += 2;
+			continue;
+		}
+		char *src = p + 2;
+		memmove(p, src, strlen(src) + 1);
+	}
+
+	/* handle extra /..'s: */
+	p = path;
+	while ((p = strstr(p, "/.."))) {
+		char *src = p + 3;
+
+		p--;
+
+		/* find beginning of previous path entry: */
+		while (true) {
+			if (p < path)
+				return -1;
+			if (*p == '/')
+				break;
+			p--;
+		}
+
+		memmove(p, src, strlen(src) + 1);
+	}
+
+	return 0;
+}
+
+/* NOTE: despite what you would expect, 'file_name' is actually a path.
+ * With windoze style backlashes, ofc.
+ */
+static struct efi_file_handle *file_open(struct file_system *fs,
+		struct file_handle *parent, s16 *file_name, u64 mode)
+{
+	struct file_handle *fh;
+	char f0[MAX_UTF8_PER_UTF16] = {0};
+	int plen = 0;
+	int flen = 0;
+
+	if (file_name) {
+		utf16_to_utf8((u8 *)f0, (u16 *)file_name, 1);
+		flen = utf16_strlen((u16 *)file_name);
+	}
+
+	/* we could have a parent, but also an absolute path: */
+	if (f0[0] == '\\') {
+		plen = 0;
+	} else if (parent) {
+		plen = strlen(parent->path) + 1;
+	}
+
+	/* +2 is for null and '/' */
+	fh = calloc(1, sizeof(*fh) + plen + (flen * MAX_UTF8_PER_UTF16) + 2);
+
+	fh->base = efi_file_handle_protocol;
+	fh->fs = fs;
+
+	if (parent) {
+		char *p = fh->path;
+
+		if (plen > 0) {
+			strcpy(p, parent->path);
+			p += plen - 1;
+			*p++ = '/';
+		}
+
+		utf16_to_utf8((u8 *)p, (u16 *)file_name, flen);
+
+		if (sanitize_path(fh->path))
+			goto error;
+
+		/* check if file exists: */
+		if (set_blk_dev(fh))
+			goto error;
+
+		if (!((mode & EFI_FILE_MODE_CREATE) || fs_exists(fh->path)))
+			goto error;
+
+		/* figure out if file is a directory: */
+		fh->isdir = is_dir(fh);
+	} else {
+		fh->isdir = 1;
+		strcpy(fh->path, "");
+	}
+
+	return &fh->base;
+
+error:
+	free(fh);
+	return NULL;
+}
+
+static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file,
+		struct efi_file_handle **new_handle,
+		s16 *file_name, u64 open_mode, u64 attributes)
+{
+	struct file_handle *fh = to_fh(file);
+
+	EFI_ENTRY("%p, %p, \"%ls\", %llx, %llu", file, new_handle, file_name,
+		  open_mode, attributes);
+
+	*new_handle = file_open(fh->fs, fh, file_name, open_mode);
+	if (!*new_handle)
+		return EFI_EXIT(EFI_NOT_FOUND);
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t file_close(struct file_handle *fh)
+{
+	fs_closedir(fh->dirs);
+	free(fh);
+	return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI efi_file_close(struct efi_file_handle *file)
+{
+	struct file_handle *fh = to_fh(file);
+	EFI_ENTRY("%p", file);
+	return EFI_EXIT(file_close(fh));
+}
+
+static efi_status_t EFIAPI efi_file_delete(struct efi_file_handle *file)
+{
+	struct file_handle *fh = to_fh(file);
+	EFI_ENTRY("%p", file);
+	file_close(fh);
+	return EFI_EXIT(EFI_WARN_DELETE_FAILURE);
+}
+
+static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size,
+		void *buffer)
+{
+	loff_t actread;
+
+	if (fs_read(fh->path, (ulong)buffer, fh->offset,
+		    *buffer_size, &actread))
+		return EFI_DEVICE_ERROR;
+
+	*buffer_size = actread;
+	fh->offset += actread;
+
+	return EFI_SUCCESS;
+}
+
+static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
+		void *buffer)
+{
+	struct efi_file_info *info = buffer;
+	struct fs_dirent *dent;
+	unsigned int required_size;
+
+	if (!fh->dirs) {
+		assert(fh->offset == 0);
+		fh->dirs = fs_opendir(fh->path);
+		if (!fh->dirs)
+			return EFI_DEVICE_ERROR;
+	}
+
+	/*
+	 * So this is a bit awkward.  Since fs layer is stateful and we
+	 * can't rewind an entry, in the EFI_BUFFER_TOO_SMALL case below
+	 * we might have to return without consuming the dent.. so we
+	 * have to stash it for next call.
+	 */
+	if (fh->dent) {
+		dent = fh->dent;
+		fh->dent = NULL;
+	} else {
+		dent = fs_readdir(fh->dirs);
+	}
+
+
+	if (!dent) {
+		/* no more files in directory: */
+		/* workaround shim.efi bug/quirk.. as find_boot_csv()
+		 * loops through directory contents, it initially calls
+		 * read w/ zero length buffer to find out how much mem
+		 * to allocate for the EFI_FILE_INFO, then allocates,
+		 * and then calls a 2nd time.  If we return size of
+		 * zero the first time, it happily passes that to
+		 * AllocateZeroPool(), and when that returns NULL it
+		 * thinks it is EFI_OUT_OF_RESOURCES.  So on first
+		 * call return a non-zero size:
+		 */
+		if (*buffer_size == 0)
+			*buffer_size = sizeof(*info);
+		else
+			*buffer_size = 0;
+		return EFI_SUCCESS;
+	}
+
+	/* check buffer size: */
+	required_size = sizeof(*info) + 2 * (strlen(dent->name) + 1);
+	if (*buffer_size < required_size) {
+		*buffer_size = required_size;
+		fh->dent = dent;
+		return EFI_BUFFER_TOO_SMALL;
+	}
+
+	*buffer_size = required_size;
+	memset(info, 0, required_size);
+
+	info->size = required_size;
+	info->file_size = dent->size;
+	info->physical_size = dent->size;
+
+	if (dent->type == FS_DT_DIR)
+		info->attribute |= EFI_FILE_DIRECTORY;
+
+	ascii2unicode((u16 *)info->file_name, dent->name);
+
+	fh->offset++;
+
+	return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file,
+		u64 *buffer_size, void *buffer)
+{
+	struct file_handle *fh = to_fh(file);
+	efi_status_t ret = EFI_SUCCESS;
+
+	EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
+
+	if (set_blk_dev(fh)) {
+		ret = EFI_DEVICE_ERROR;
+		goto error;
+	}
+
+	if (fh->isdir)
+		ret = dir_read(fh, buffer_size, buffer);
+	else
+		ret = file_read(fh, buffer_size, buffer);
+
+error:
+	return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
+		u64 *buffer_size, void *buffer)
+{
+	struct file_handle *fh = to_fh(file);
+	efi_status_t ret = EFI_SUCCESS;
+	loff_t actwrite;
+
+	EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
+
+	if (set_blk_dev(fh)) {
+		ret = EFI_DEVICE_ERROR;
+		goto error;
+	}
+
+	if (fs_write(fh->path, (ulong)buffer, fh->offset, *buffer_size,
+		     &actwrite)) {
+		ret = EFI_DEVICE_ERROR;
+		goto error;
+	}
+
+	*buffer_size = actwrite;
+	fh->offset += actwrite;
+
+error:
+	return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI efi_file_getpos(struct efi_file_handle *file,
+		u64 *pos)
+{
+	struct file_handle *fh = to_fh(file);
+	EFI_ENTRY("%p, %p", file, pos);
+	*pos = fh->offset;
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file,
+		u64 pos)
+{
+	struct file_handle *fh = to_fh(file);
+	efi_status_t ret = EFI_SUCCESS;
+
+	EFI_ENTRY("%p, %llu", file, pos);
+
+	if (fh->isdir) {
+		if (pos != 0) {
+			ret = EFI_UNSUPPORTED;
+			goto error;
+		}
+		fs_closedir(fh->dirs);
+		fh->dirs = NULL;
+	}
+
+	if (pos == ~0ULL) {
+		loff_t file_size;
+
+		if (set_blk_dev(fh)) {
+			ret = EFI_DEVICE_ERROR;
+			goto error;
+		}
+
+		if (fs_size(fh->path, &file_size)) {
+			ret = EFI_DEVICE_ERROR;
+			goto error;
+		}
+
+		pos = file_size;
+	}
+
+	fh->offset = pos;
+
+error:
+	return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file,
+		efi_guid_t *info_type, u64 *buffer_size, void *buffer)
+{
+	struct file_handle *fh = to_fh(file);
+	efi_status_t ret = EFI_SUCCESS;
+
+	EFI_ENTRY("%p, %p, %p, %p", file, info_type, buffer_size, buffer);
+
+	if (!guidcmp(info_type, &efi_file_info_guid)) {
+		struct efi_file_info *info = buffer;
+		char *filename = basename(fh);
+		unsigned int required_size;
+		loff_t file_size;
+
+		/* check buffer size: */
+		required_size = sizeof(*info) + 2 * (strlen(filename) + 1);
+		if (*buffer_size < required_size) {
+			*buffer_size = required_size;
+			ret = EFI_BUFFER_TOO_SMALL;
+			goto error;
+		}
+
+		if (set_blk_dev(fh)) {
+			ret = EFI_DEVICE_ERROR;
+			goto error;
+		}
+
+		if (fs_size(fh->path, &file_size)) {
+			ret = EFI_DEVICE_ERROR;
+			goto error;
+		}
+
+		memset(info, 0, required_size);
+
+		info->size = required_size;
+		info->file_size = file_size;
+		info->physical_size = file_size;
+
+		if (fh->isdir)
+			info->attribute |= EFI_FILE_DIRECTORY;
+
+		ascii2unicode((u16 *)info->file_name, filename);
+	} else {
+		ret = EFI_UNSUPPORTED;
+	}
+
+error:
+	return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file,
+		efi_guid_t *info_type, u64 buffer_size, void *buffer)
+{
+	EFI_ENTRY("%p, %p, %llu, %p", file, info_type, buffer_size, buffer);
+	return EFI_EXIT(EFI_UNSUPPORTED);
+}
+
+static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *file)
+{
+	EFI_ENTRY("%p", file);
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static const struct efi_file_handle efi_file_handle_protocol = {
+	.rev = EFI_FILE_PROTOCOL_REVISION,
+	.open = efi_file_open,
+	.close = efi_file_close,
+	.delete = efi_file_delete,
+	.read = efi_file_read,
+	.write = efi_file_write,
+	.getpos = efi_file_getpos,
+	.setpos = efi_file_setpos,
+	.getinfo = efi_file_getinfo,
+	.setinfo = efi_file_setinfo,
+	.flush = efi_file_flush,
+};
+
+struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
+{
+	struct efi_simple_file_system_protocol *v;
+	struct efi_file_handle *f;
+	efi_status_t ret;
+
+	v = efi_fs_from_path(fp);
+	if (!v)
+		return NULL;
+
+	EFI_CALL(ret = v->open_volume(v, &f));
+	if (ret != EFI_SUCCESS)
+		return NULL;
+
+	/* skip over device-path nodes before the file path: */
+	while (fp && !EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH))
+		fp = efi_dp_next(fp);
+
+	while (fp) {
+		struct efi_device_path_file_path *fdp =
+			container_of(fp, struct efi_device_path_file_path, dp);
+		struct efi_file_handle *f2;
+
+		if (!EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH)) {
+			printf("bad file path!\n");
+			f->close(f);
+			return NULL;
+		}
+
+		EFI_CALL(ret = f->open(f, &f2, (s16 *)fdp->str,
+				       EFI_FILE_MODE_READ, 0));
+		if (ret != EFI_SUCCESS)
+			return NULL;
+
+		fp = efi_dp_next(fp);
+
+		EFI_CALL(f->close(f));
+		f = f2;
+	}
+
+	return f;
+}
+
+static efi_status_t EFIAPI
+efi_open_volume(struct efi_simple_file_system_protocol *this,
+		struct efi_file_handle **root)
+{
+	struct file_system *fs = to_fs(this);
+
+	EFI_ENTRY("%p, %p", this, root);
+
+	*root = file_open(fs, NULL, NULL, 0);
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+struct efi_simple_file_system_protocol *
+efi_simple_file_system(struct blk_desc *desc, int part,
+		       struct efi_device_path *dp)
+{
+	struct file_system *fs;
+
+	fs = calloc(1, sizeof(*fs));
+	fs->base.rev = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
+	fs->base.open_volume = efi_open_volume;
+	fs->desc = desc;
+	fs->part = part;
+	fs->dp = dp;
+
+	return &fs->base;
+}
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index f961407..af29cc4 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -15,8 +15,12 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
 const efi_guid_t efi_guid_device_path = DEVICE_PATH_GUID;
 const efi_guid_t efi_guid_loaded_image = LOADED_IMAGE_GUID;
+const efi_guid_t efi_simple_file_system_protocol_guid =
+		EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
+const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
 
 static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
 			unsigned long rel_size, void *efi_reloc)
@@ -90,6 +94,7 @@
 	unsigned long virt_size = 0;
 	bool can_run_nt64 = true;
 	bool can_run_nt32 = true;
+	uint16_t image_type;
 
 #if defined(CONFIG_ARM64)
 	can_run_nt32 = false;
@@ -135,6 +140,7 @@
 		entry = efi_reloc + opt->AddressOfEntryPoint;
 		rel_size = opt->DataDirectory[rel_idx].Size;
 		rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
+		image_type = opt->Subsystem;
 	} else if (can_run_nt32 &&
 		   (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)) {
 		IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
@@ -148,12 +154,32 @@
 		entry = efi_reloc + opt->AddressOfEntryPoint;
 		rel_size = opt->DataDirectory[rel_idx].Size;
 		rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
+		image_type = opt->Subsystem;
 	} else {
 		printf("%s: Invalid optional header magic %x\n", __func__,
 		       nt->OptionalHeader.Magic);
 		return NULL;
 	}
 
+	switch (image_type) {
+	case IMAGE_SUBSYSTEM_EFI_APPLICATION:
+		loaded_image_info->image_code_type = EFI_LOADER_CODE;
+		loaded_image_info->image_data_type = EFI_LOADER_DATA;
+		break;
+	case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
+		loaded_image_info->image_code_type = EFI_BOOT_SERVICES_CODE;
+		loaded_image_info->image_data_type = EFI_BOOT_SERVICES_DATA;
+		break;
+	case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
+	case IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
+		loaded_image_info->image_code_type = EFI_RUNTIME_SERVICES_CODE;
+		loaded_image_info->image_data_type = EFI_RUNTIME_SERVICES_DATA;
+		break;
+	default:
+		printf("%s: invalid image type: %u\n", __func__, image_type);
+		break;
+	}
+
 	/* Load sections into RAM */
 	for (i = num_sections - 1; i >= 0; i--) {
 		IMAGE_SECTION_HEADER *sec = &sections[i];
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 9e079f1..d47759e 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -43,7 +43,7 @@
  */
 struct efi_pool_allocation {
 	u64 num_pages;
-	char data[];
+	char data[] __aligned(ARCH_DMA_MINALIGN);
 };
 
 /*
@@ -356,7 +356,8 @@
 {
 	efi_status_t r;
 	efi_physical_addr_t t;
-	u64 num_pages = (size + sizeof(u64) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+	u64 num_pages = (size + sizeof(struct efi_pool_allocation) +
+			 EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
 
 	if (size == 0) {
 		*buffer = NULL;
diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
index 0b949d8..91f1e4a 100644
--- a/lib/efi_loader/efi_net.c
+++ b/lib/efi_loader/efi_net.c
@@ -26,9 +26,6 @@
 	/* EFI Interface callback struct for network */
 	struct efi_simple_network net;
 	struct efi_simple_network_mode net_mode;
-	/* Device path to the network adapter */
-	struct efi_device_path_mac_addr dp_mac;
-	struct efi_device_path_file_path dp_end;
 	/* PXE struct to transmit dhcp data */
 	struct efi_pxe pxe;
 	struct efi_pxe_mode pxe_mode;
@@ -210,19 +207,9 @@
 }
 
 /* This gets called from do_bootefi_exec(). */
-int efi_net_register(void **handle)
+int efi_net_register(void)
 {
 	struct efi_net_obj *netobj;
-	struct efi_device_path_mac_addr dp_net = {
-		.dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE,
-		.dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR,
-		.dp.length = sizeof(dp_net),
-	};
-	struct efi_device_path_file_path dp_end = {
-		.dp.type = DEVICE_PATH_TYPE_END,
-		.dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
-		.dp.length = sizeof(dp_end),
-	};
 
 	if (!eth_get_dev()) {
 		/* No eth device active, don't expose any */
@@ -236,7 +223,8 @@
 	netobj->parent.protocols[0].guid = &efi_net_guid;
 	netobj->parent.protocols[0].protocol_interface = &netobj->net;
 	netobj->parent.protocols[1].guid = &efi_guid_device_path;
-	netobj->parent.protocols[1].protocol_interface = &netobj->dp_mac;
+	netobj->parent.protocols[1].protocol_interface =
+		efi_dp_from_eth();
 	netobj->parent.protocols[2].guid = &efi_pxe_guid;
 	netobj->parent.protocols[2].protocol_interface = &netobj->pxe;
 	netobj->parent.handle = &netobj->net;
@@ -255,9 +243,6 @@
 	netobj->net.receive = efi_net_receive;
 	netobj->net.mode = &netobj->net_mode;
 	netobj->net_mode.state = EFI_NETWORK_STARTED;
-	netobj->dp_mac = dp_net;
-	netobj->dp_end = dp_end;
-	memcpy(netobj->dp_mac.mac.addr, eth_get_ethaddr(), 6);
 	memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6);
 	netobj->net_mode.max_packet_size = PKTSIZE;
 
@@ -268,8 +253,5 @@
 	/* Hook net up to the device list */
 	list_add_tail(&netobj->parent.link, &efi_obj_list);
 
-	if (handle)
-		*handle = &netobj->net;
-
 	return 0;
 }
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index ad7f375..8104e08 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -184,7 +184,16 @@
 		/* Clean up system table */
 		.ptr = &systab.boottime,
 		.patchto = NULL,
-	},
+	}, {
+		.ptr = &efi_runtime_services.get_variable,
+		.patchto = &efi_device_error,
+	}, {
+		.ptr = &efi_runtime_services.get_next_variable,
+		.patchto = &efi_device_error,
+	}, {
+		.ptr = &efi_runtime_services.set_variable,
+		.patchto = &efi_device_error,
+	}
 };
 
 static bool efi_runtime_tobedetached(void *p)
@@ -243,7 +252,8 @@
 
 		/* Check if the relocation is inside bounds */
 		if (map && ((newaddr < map->virtual_start) ||
-		    newaddr > (map->virtual_start + (map->num_pages << 12)))) {
+		    newaddr > (map->virtual_start +
+			      (map->num_pages << EFI_PAGE_SHIFT)))) {
 			if (!efi_runtime_tobedetached(p))
 				printf("U-Boot EFI: Relocation at %p is out of "
 				       "range (%lx)\n", p, newaddr);
@@ -269,7 +279,8 @@
 			uint32_t descriptor_version,
 			struct efi_mem_desc *virtmap)
 {
-	ulong runtime_start = (ulong)&__efi_runtime_start & ~0xfffULL;
+	ulong runtime_start = (ulong)&__efi_runtime_start &
+			      ~(ulong)EFI_PAGE_MASK;
 	int n = memory_map_size / descriptor_size;
 	int i;
 
@@ -382,9 +393,9 @@
 	.set_wakeup_time = (void *)&efi_unimplemented,
 	.set_virtual_address_map = &efi_set_virtual_address_map,
 	.convert_pointer = (void *)&efi_invalid_parameter,
-	.get_variable = (void *)&efi_device_error,
-	.get_next_variable = (void *)&efi_device_error,
-	.set_variable = (void *)&efi_device_error,
+	.get_variable = efi_get_variable,
+	.get_next_variable = efi_get_next_variable,
+	.set_variable = efi_set_variable,
 	.get_next_high_mono_count = (void *)&efi_device_error,
 	.reset_system = &efi_reset_system_boottime,
 };
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
new file mode 100644
index 0000000..6c177da
--- /dev/null
+++ b/lib/efi_loader/efi_variable.c
@@ -0,0 +1,335 @@
+/*
+ *  EFI utils
+ *
+ *  Copyright (c) 2017 Rob Clark
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <malloc.h>
+#include <charset.h>
+#include <efi_loader.h>
+
+#define READ_ONLY BIT(31)
+
+/*
+ * Mapping between EFI variables and u-boot variables:
+ *
+ *   efi_$guid_$varname = {attributes}(type)value
+ *
+ * For example:
+ *
+ *   efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported=
+ *      "{ro,boot,run}(blob)0000000000000000"
+ *   efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder=
+ *      "(blob)00010000"
+ *
+ * The attributes are a comma separated list of these possible
+ * attributes:
+ *
+ *   + ro   - read-only
+ *   + boot - boot-services access
+ *   + run  - runtime access
+ *
+ * NOTE: with current implementation, no variables are available after
+ * ExitBootServices, and all are persisted (if possible).
+ *
+ * If not specified, the attributes default to "{boot}".
+ *
+ * The required type is one of:
+ *
+ *   + utf8 - raw utf8 string
+ *   + blob - arbitrary length hex string
+ *
+ * Maybe a utf16 type would be useful to for a string value to be auto
+ * converted to utf16?
+ */
+
+#define MAX_VAR_NAME 31
+#define MAX_NATIVE_VAR_NAME \
+	(strlen("efi_xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx_") + \
+		(MAX_VAR_NAME * MAX_UTF8_PER_UTF16))
+
+static int hex(unsigned char ch)
+{
+	if (ch >= 'a' && ch <= 'f')
+		return ch-'a'+10;
+	if (ch >= '0' && ch <= '9')
+		return ch-'0';
+	if (ch >= 'A' && ch <= 'F')
+		return ch-'A'+10;
+	return -1;
+}
+
+static const char *hex2mem(u8 *mem, const char *hexstr, int count)
+{
+	memset(mem, 0, count/2);
+
+	do {
+		int nibble;
+
+		*mem = 0;
+
+		if (!count || !*hexstr)
+			break;
+
+		nibble = hex(*hexstr);
+		if (nibble < 0)
+			break;
+
+		*mem = nibble;
+		count--;
+		hexstr++;
+
+		if (!count || !*hexstr)
+			break;
+
+		nibble = hex(*hexstr);
+		if (nibble < 0)
+			break;
+
+		*mem = (*mem << 4) | nibble;
+		count--;
+		hexstr++;
+		mem++;
+
+	} while (1);
+
+	if (*hexstr)
+		return hexstr;
+
+	return NULL;
+}
+
+static char *mem2hex(char *hexstr, const u8 *mem, int count)
+{
+	static const char hexchars[] = "0123456789abcdef";
+
+	while (count-- > 0) {
+		u8 ch = *mem++;
+		*hexstr++ = hexchars[ch >> 4];
+		*hexstr++ = hexchars[ch & 0xf];
+	}
+
+	return hexstr;
+}
+
+static efi_status_t efi_to_native(char *native, s16 *variable_name,
+		efi_guid_t *vendor)
+{
+	size_t len;
+
+	len = utf16_strlen((u16 *)variable_name);
+	if (len >= MAX_VAR_NAME)
+		return EFI_DEVICE_ERROR;
+
+	native += sprintf(native, "efi_%pUl_", vendor);
+	native  = (char *)utf16_to_utf8((u8 *)native, (u16 *)variable_name, len);
+	*native = '\0';
+
+	return EFI_SUCCESS;
+}
+
+static const char *prefix(const char *str, const char *prefix)
+{
+	size_t n = strlen(prefix);
+	if (!strncmp(prefix, str, n))
+		return str + n;
+	return NULL;
+}
+
+/* parse attributes part of variable value, if present: */
+static const char *parse_attr(const char *str, u32 *attrp)
+{
+	u32 attr = 0;
+	char sep = '{';
+
+	if (*str != '{') {
+		*attrp = EFI_VARIABLE_BOOTSERVICE_ACCESS;
+		return str;
+	}
+
+	while (*str == sep) {
+		const char *s;
+
+		str++;
+
+		if ((s = prefix(str, "ro"))) {
+			attr |= READ_ONLY;
+		} else if ((s = prefix(str, "boot"))) {
+			attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
+		} else if ((s = prefix(str, "run"))) {
+			attr |= EFI_VARIABLE_RUNTIME_ACCESS;
+		} else {
+			printf("invalid attribute: %s\n", str);
+			break;
+		}
+
+		str = s;
+		sep = ',';
+	}
+
+	str++;
+
+	*attrp = attr;
+
+	return str;
+}
+
+/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetVariable.28.29 */
+efi_status_t EFIAPI efi_get_variable(s16 *variable_name,
+		efi_guid_t *vendor, u32 *attributes,
+		unsigned long *data_size, void *data)
+{
+	char native_name[MAX_NATIVE_VAR_NAME + 1];
+	efi_status_t ret;
+	unsigned long in_size;
+	const char *val, *s;
+	u32 attr;
+
+	EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes,
+		  data_size, data);
+
+	if (!variable_name || !vendor || !data_size)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	ret = efi_to_native(native_name, variable_name, vendor);
+	if (ret)
+		return EFI_EXIT(ret);
+
+	debug("%s: get '%s'\n", __func__, native_name);
+
+	val = env_get(native_name);
+	if (!val)
+		return EFI_EXIT(EFI_NOT_FOUND);
+
+	val = parse_attr(val, &attr);
+
+	in_size = *data_size;
+
+	if ((s = prefix(val, "(blob)"))) {
+		unsigned len = strlen(s);
+
+		/* two characters per byte: */
+		len = DIV_ROUND_UP(len, 2);
+		*data_size = len;
+
+		if (in_size < len)
+			return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+
+		if (!data)
+			return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+		if (hex2mem(data, s, len * 2))
+			return EFI_EXIT(EFI_DEVICE_ERROR);
+
+		debug("%s: got value: \"%s\"\n", __func__, s);
+	} else if ((s = prefix(val, "(utf8)"))) {
+		unsigned len = strlen(s) + 1;
+
+		*data_size = len;
+
+		if (in_size < len)
+			return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+
+		if (!data)
+			return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+		memcpy(data, s, len);
+		((char *)data)[len] = '\0';
+
+		debug("%s: got value: \"%s\"\n", __func__, (char *)data);
+	} else {
+		debug("%s: invalid value: '%s'\n", __func__, val);
+		return EFI_EXIT(EFI_DEVICE_ERROR);
+	}
+
+	if (attributes)
+		*attributes = attr & EFI_VARIABLE_MASK;
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetNextVariableName.28.29 */
+efi_status_t EFIAPI efi_get_next_variable(
+		unsigned long *variable_name_size,
+		s16 *variable_name, efi_guid_t *vendor)
+{
+	EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor);
+
+	return EFI_EXIT(EFI_DEVICE_ERROR);
+}
+
+/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#SetVariable.28.29 */
+efi_status_t EFIAPI efi_set_variable(s16 *variable_name,
+		efi_guid_t *vendor, u32 attributes,
+		unsigned long data_size, void *data)
+{
+	char native_name[MAX_NATIVE_VAR_NAME + 1];
+	efi_status_t ret = EFI_SUCCESS;
+	char *val, *s;
+	u32 attr;
+
+	EFI_ENTRY("\"%ls\" %pUl %x %lu %p", variable_name, vendor, attributes,
+		  data_size, data);
+
+	if (!variable_name || !vendor)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	ret = efi_to_native(native_name, variable_name, vendor);
+	if (ret)
+		return EFI_EXIT(ret);
+
+#define ACCESS_ATTR (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)
+
+	if ((data_size == 0) || !(attributes & ACCESS_ATTR)) {
+		/* delete the variable: */
+		env_set(native_name, NULL);
+		return EFI_EXIT(EFI_SUCCESS);
+	}
+
+	val = env_get(native_name);
+	if (val) {
+		parse_attr(val, &attr);
+
+		if (attr & READ_ONLY)
+			return EFI_EXIT(EFI_WRITE_PROTECTED);
+	}
+
+	val = malloc(2 * data_size + strlen("{ro,run,boot}(blob)") + 1);
+	if (!val)
+		return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+	s = val;
+
+	/* store attributes: */
+	attributes &= (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS);
+	s += sprintf(s, "{");
+	while (attributes) {
+		u32 attr = 1 << (ffs(attributes) - 1);
+
+		if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS)
+			s += sprintf(s, "boot");
+		else if (attr == EFI_VARIABLE_RUNTIME_ACCESS)
+			s += sprintf(s, "run");
+
+		attributes &= ~attr;
+		if (attributes)
+			s += sprintf(s, ",");
+	}
+	s += sprintf(s, "}");
+
+	/* store payload: */
+	s += sprintf(s, "(blob)");
+	s = mem2hex(s, data, data_size);
+	*s = '\0';
+
+	debug("%s: setting: %s=%s\n", __func__, native_name, val);
+
+	if (env_set(native_name, val))
+		ret = EFI_DEVICE_ERROR;
+
+	free(val);
+
+	return EFI_EXIT(ret);
+}
diff --git a/lib/efi_selftest/Kconfig b/lib/efi_selftest/Kconfig
new file mode 100644
index 0000000..3b5f3a1
--- /dev/null
+++ b/lib/efi_selftest/Kconfig
@@ -0,0 +1,7 @@
+config CMD_BOOTEFI_SELFTEST
+	bool "Allow booting an EFI efi_selftest"
+	depends on CMD_BOOTEFI
+	help
+	  This adds an EFI test application to U-Boot that can be executed
+	  with the 'bootefi selftest' command. It provides extended tests of
+	  the EFI API implementation.
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
new file mode 100644
index 0000000..30f1960
--- /dev/null
+++ b/lib/efi_selftest/Makefile
@@ -0,0 +1,26 @@
+:
+# (C) Copyright 2017, Heinrich Schuchardt <xypron.glpk@gmx.de>
+#
+#  SPDX-License-Identifier:     GPL-2.0+
+#
+
+# This file only gets included with CONFIG_EFI_LOADER set, so all
+# object inclusion implicitly depends on it
+
+CFLAGS_efi_selftest.o := $(CFLAGS_EFI)
+CFLAGS_REMOVE_efi_selftest.o := $(CFLAGS_NON_EFI)
+CFLAGS_efi_selftest_console.o := $(CFLAGS_EFI)
+CFLAGS_REMOVE_efi_selftest_console.o := $(CFLAGS_NON_EFI)
+CFLAGS_efi_selftest_events.o := $(CFLAGS_EFI)
+CFLAGS_REMOVE_efi_selftest_events.o := $(CFLAGS_NON_EFI)
+CFLAGS_efi_selftest_exitbootservices.o := $(CFLAGS_EFI)
+CFLAGS_REMOVE_efi_selftest_exitbootservices.o := $(CFLAGS_NON_EFI)
+CFLAGS_efi_selftest_tpl.o := $(CFLAGS_EFI)
+CFLAGS_REMOVE_efi_selftest_tpl.o := $(CFLAGS_NON_EFI)
+
+obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += \
+efi_selftest.o \
+efi_selftest_console.o \
+efi_selftest_events.o \
+efi_selftest_exitbootservices.o \
+efi_selftest_tpl.o
diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c
new file mode 100644
index 0000000..efec832
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest.c
@@ -0,0 +1,219 @@
+/*
+ * EFI efi_selftest
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <efi_selftest.h>
+#include <vsprintf.h>
+
+static const struct efi_system_table *systable;
+static const struct efi_boot_services *boottime;
+static const struct efi_runtime_services *runtime;
+static efi_handle_t handle;
+static u16 reset_message[] = L"Selftest completed";
+
+/*
+ * Exit the boot services.
+ *
+ * The size of the memory map is determined.
+ * Pool memory is allocated to copy the memory map.
+ * The memory amp is copied and the map key is obtained.
+ * The map key is used to exit the boot services.
+ */
+void efi_st_exit_boot_services(void)
+{
+	unsigned long  map_size = 0;
+	unsigned long  map_key;
+	unsigned long desc_size;
+	u32 desc_version;
+	efi_status_t ret;
+	struct efi_mem_desc *memory_map;
+
+	ret = boottime->get_memory_map(&map_size, NULL, &map_key, &desc_size,
+				       &desc_version);
+	if (ret != EFI_BUFFER_TOO_SMALL) {
+		efi_st_printf("ERROR: GetMemoryMap did not return "
+			      "EFI_BUFFER_TOO_SMALL\n");
+		return;
+	}
+	/* Allocate extra space for newly allocated memory */
+	map_size += sizeof(struct efi_mem_desc);
+	ret = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, map_size,
+				      (void **)&memory_map);
+	if (ret != EFI_SUCCESS) {
+		efi_st_printf("ERROR: AllocatePool did not return "
+			      "EFI_SUCCESS\n");
+		return;
+	}
+	ret = boottime->get_memory_map(&map_size, memory_map, &map_key,
+				       &desc_size, &desc_version);
+	if (ret != EFI_SUCCESS) {
+		efi_st_printf("ERROR: GetMemoryMap did not return "
+			      "EFI_SUCCESS\n");
+		return;
+	}
+	ret = boottime->exit_boot_services(handle, map_key);
+	if (ret != EFI_SUCCESS) {
+		efi_st_printf("ERROR: ExitBootServices did not return "
+			      "EFI_SUCCESS\n");
+		return;
+	}
+	efi_st_printf("\nBoot services terminated\n");
+}
+
+/*
+ * Set up a test.
+ *
+ * @test	the test to be executed
+ * @failures	counter that will be incremented if a failure occurs
+ */
+static int setup(struct efi_unit_test *test, unsigned int *failures)
+{
+	int ret;
+
+	if (!test->setup)
+		return 0;
+	efi_st_printf("\nSetting up '%s'\n", test->name);
+	ret = test->setup(handle, systable);
+	if (ret) {
+		efi_st_printf("ERROR: Setting up '%s' failed\n", test->name);
+		++*failures;
+	} else {
+		efi_st_printf("Setting up '%s' succeeded\n", test->name);
+	}
+	return ret;
+}
+
+/*
+ * Execute a test.
+ *
+ * @test	the test to be executed
+ * @failures	counter that will be incremented if a failure occurs
+ */
+static int execute(struct efi_unit_test *test, unsigned int *failures)
+{
+	int ret;
+
+	if (!test->execute)
+		return 0;
+	efi_st_printf("\nExecuting '%s'\n", test->name);
+	ret = test->execute();
+	if (ret) {
+		efi_st_printf("ERROR: Executing '%s' failed\n", test->name);
+		++*failures;
+	} else {
+		efi_st_printf("Executing '%s' succeeded\n", test->name);
+	}
+	return ret;
+}
+
+/*
+ * Tear down a test.
+ *
+ * @test	the test to be torn down
+ * @failures	counter that will be incremented if a failure occurs
+ */
+static int teardown(struct efi_unit_test *test, unsigned int *failures)
+{
+	int ret;
+
+	if (!test->teardown)
+		return 0;
+	efi_st_printf("\nTearing down '%s'\n", test->name);
+	ret = test->teardown();
+	if (ret) {
+		efi_st_printf("ERROR: Tearing down '%s' failed\n", test->name);
+		++*failures;
+	} else {
+		efi_st_printf("Tearing down '%s' succeeded\n", test->name);
+	}
+	return ret;
+}
+
+/*
+ * Execute selftest of the EFI API
+ *
+ * This is the main entry point of the EFI selftest application.
+ *
+ * All tests use a driver model and are run in three phases:
+ * setup, execute, teardown.
+ *
+ * A test may be setup and executed at boottime,
+ * it may be setup at boottime and executed at runtime,
+ * or it may be setup and executed at runtime.
+ *
+ * After executing all tests the system is reset.
+ *
+ * @image_handle:	handle of the loaded EFI image
+ * @systab:		EFI system table
+ */
+efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
+				 struct efi_system_table *systab)
+{
+	struct efi_unit_test *test;
+	unsigned int failures = 0;
+
+	systable = systab;
+	boottime = systable->boottime;
+	runtime = systable->runtime;
+	handle = image_handle;
+	con_out = systable->con_out;
+	con_in = systable->con_in;
+
+	efi_st_printf("\nTesting EFI API implementation\n");
+
+	efi_st_printf("\nNumber of tests to execute: %u\n",
+		      ll_entry_count(struct efi_unit_test, efi_unit_test));
+
+	/* Execute boottime tests */
+	for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
+	     test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) {
+		if (test->phase == EFI_EXECUTE_BEFORE_BOOTTIME_EXIT) {
+			setup(test, &failures);
+			execute(test, &failures);
+			teardown(test, &failures);
+		}
+	}
+
+	/* Execute mixed tests */
+	for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
+	     test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) {
+		if (test->phase == EFI_SETUP_BEFORE_BOOTTIME_EXIT)
+			setup(test, &failures);
+	}
+
+	efi_st_exit_boot_services();
+
+	for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
+	     test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) {
+		if (test->phase == EFI_SETUP_BEFORE_BOOTTIME_EXIT) {
+			execute(test, &failures);
+			teardown(test, &failures);
+		}
+	}
+
+	/* Execute runtime tests */
+	for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
+	     test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) {
+		if (test->phase == EFI_SETUP_AFTER_BOOTTIME_EXIT) {
+			setup(test, &failures);
+			execute(test, &failures);
+			teardown(test, &failures);
+		}
+	}
+
+	/* Give feedback */
+	efi_st_printf("\nSummary: %u failures\n\n", failures);
+
+	/* Reset system */
+	efi_st_printf("Preparing for reset. Press any key.\n");
+	efi_st_get_key();
+	runtime->reset_system(EFI_RESET_WARM, EFI_NOT_READY,
+			      sizeof(reset_message), reset_message);
+	efi_st_printf("\nERROR: reset failed.\n");
+
+	return EFI_UNSUPPORTED;
+}
diff --git a/lib/efi_selftest/efi_selftest_console.c b/lib/efi_selftest/efi_selftest_console.c
new file mode 100644
index 0000000..7b5b724
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_console.c
@@ -0,0 +1,187 @@
+/*
+ * EFI efi_selftest
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <efi_selftest.h>
+#include <vsprintf.h>
+
+struct efi_simple_text_output_protocol *con_out;
+struct efi_simple_input_interface *con_in;
+
+/*
+ * Print a pointer to an u16 string
+ *
+ * @pointer: pointer
+ * @buf: pointer to buffer address
+ * on return position of terminating zero word
+ */
+static void pointer(void *pointer, u16 **buf)
+{
+	int i;
+	u16 c;
+	uintptr_t p = (uintptr_t)pointer;
+	u16 *pos = *buf;
+
+	for (i = 8 * sizeof(p) - 4; i >= 0; i -= 4) {
+		c = (p >> i) & 0x0f;
+		c += '0';
+		if (c > '9')
+			c += 'a' - '9' - 1;
+		*pos++ = c;
+	}
+	*pos = 0;
+	*buf = pos;
+}
+
+/*
+ * Print an unsigned 32bit value as decimal number to an u16 string
+ *
+ * @value: value to be printed
+ * @buf: pointer to buffer address
+ * on return position of terminating zero word
+ */
+static void uint2dec(u32 value, u16 **buf)
+{
+	u16 *pos = *buf;
+	int i;
+	u16 c;
+	u64 f;
+
+	/*
+	 * Increment by .5 and multiply with
+	 * (2 << 60) / 1,000,000,000 = 0x44B82FA0.9B5A52CC
+	 * to move the first digit to bit 60-63.
+	 */
+	f = 0x225C17D0;
+	f += (0x9B5A52DULL * value) >> 28;
+	f += 0x44B82FA0ULL * value;
+
+	for (i = 0; i < 10; ++i) {
+		/* Write current digit */
+		c = f >> 60;
+		if (c || pos != *buf)
+			*pos++ = c + '0';
+		/* Eliminate current digit */
+		f &= 0xfffffffffffffff;
+		/* Get next digit */
+		f *= 0xaULL;
+	}
+	if (pos == *buf)
+		*pos++ = '0';
+	*pos = 0;
+	*buf = pos;
+}
+
+/*
+ * Print a signed 32bit value as decimal number to an u16 string
+ *
+ * @value: value to be printed
+ * @buf: pointer to buffer address
+ * on return position of terminating zero word
+ */
+static void int2dec(s32 value, u16 **buf)
+{
+	u32 u;
+	u16 *pos = *buf;
+
+	if (value < 0) {
+		*pos++ = '-';
+		u = -value;
+	} else {
+		u = value;
+	}
+	uint2dec(u, &pos);
+	*buf = pos;
+}
+
+/*
+ * Print a formatted string to the EFI console
+ *
+ * @fmt: format string
+ * @...: optional arguments
+ */
+void efi_st_printf(const char *fmt, ...)
+{
+	va_list args;
+	u16 buf[160];
+	const char *c;
+	u16 *pos = buf;
+	const char *s;
+
+	va_start(args, fmt);
+
+	c = fmt;
+	for (; *c; ++c) {
+		switch (*c) {
+		case '\\':
+			++c;
+			switch (*c) {
+			case '\0':
+				--c;
+				break;
+			case 'n':
+				*pos++ = '\n';
+				break;
+			case 'r':
+				*pos++ = '\r';
+				break;
+			case 't':
+				*pos++ = '\t';
+				break;
+			default:
+				*pos++ = *c;
+			}
+			break;
+		case '%':
+			++c;
+			switch (*c) {
+			case '\0':
+				--c;
+				break;
+			case 'd':
+				int2dec(va_arg(args, s32), &pos);
+				break;
+			case 'p':
+				pointer(va_arg(args, void*), &pos);
+				break;
+			case 's':
+				s = va_arg(args, const char *);
+				for (; *s; ++s)
+					*pos++ = *s;
+				break;
+			case 'u':
+				uint2dec(va_arg(args, u32), &pos);
+				break;
+			default:
+				break;
+			}
+			break;
+		default:
+			*pos++ = *c;
+		}
+	}
+	va_end(args);
+	*pos = 0;
+	con_out->output_string(con_out, buf);
+}
+
+/*
+ * Reads an Unicode character from the input device.
+ *
+ * @return: Unicode character
+ */
+u16 efi_st_get_key(void)
+{
+	struct efi_input_key input_key;
+	efi_status_t ret;
+
+	/* Wait for next key */
+	do {
+		ret = con_in->read_key_stroke(con_in, &input_key);
+	} while (ret == EFI_NOT_READY);
+	return input_key.unicode_char;
+}
diff --git a/lib/efi_selftest/efi_selftest_events.c b/lib/efi_selftest/efi_selftest_events.c
new file mode 100644
index 0000000..c4f6695
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_events.c
@@ -0,0 +1,195 @@
+/*
+ * efi_selftest_events
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This unit test uses timer events to check the implementation
+ * of the following boottime services:
+ * CreateEvent, CloseEvent, WaitForEvent, CheckEvent, SetTimer.
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_event *event_notify;
+static struct efi_event *event_wait;
+static unsigned int counter;
+static struct efi_boot_services *boottime;
+
+/*
+ * Notification function, increments a counter.
+ *
+ * @event	notified event
+ * @context	pointer to the counter
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+	if (!context)
+		return;
+	++*(unsigned int *)context;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Create two timer events.
+ * One with EVT_NOTIFY_SIGNAL, the other with EVT_NOTIFY_WAIT.
+ *
+ * @handle:	handle of the loaded image
+ * @systable:	system table
+ */
+static int setup(const efi_handle_t handle,
+		 const struct efi_system_table *systable)
+{
+	efi_status_t ret;
+
+	boottime = systable->boottime;
+
+	ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL,
+				     TPL_CALLBACK, notify, (void *)&counter,
+				     &event_notify);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("could not create event\n");
+		return 1;
+	}
+	ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_WAIT,
+				     TPL_CALLBACK, notify, NULL, &event_wait);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("could not create event\n");
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Close the events created in setup.
+ */
+static int teardown(void)
+{
+	efi_status_t ret;
+
+	if (event_notify) {
+		ret = boottime->close_event(event_notify);
+		event_notify = NULL;
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("could not close event\n");
+			return 1;
+		}
+	}
+	if (event_wait) {
+		ret = boottime->close_event(event_wait);
+		event_wait = NULL;
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("could not close event\n");
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Run a 10 ms periodic timer and check that it is called 10 times
+ * while waiting for 100 ms single shot timer.
+ *
+ * Run a 100 ms single shot timer and check that it is called once
+ * while waiting for 100 ms periodic timer for two periods.
+ */
+static int execute(void)
+{
+	unsigned long index;
+	efi_status_t ret;
+
+	/* Set 10 ms timer */
+	counter = 0;
+	ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Could not set timer\n");
+		return 1;
+	}
+	/* Set 100 ms timer */
+	ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000000);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Could not set timer\n");
+		return 1;
+	}
+
+	index = 5;
+	ret = boottime->wait_for_event(1, &event_wait, &index);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Could not wait for event\n");
+		return 1;
+	}
+	ret = boottime->check_event(event_wait);
+	if (ret != EFI_NOT_READY) {
+		efi_st_error("Signaled state was not cleared.\n");
+		efi_st_printf("ret = %u\n", (unsigned int)ret);
+		return 1;
+	}
+	if (index != 0) {
+		efi_st_error("WaitForEvent returned wrong index\n");
+		return 1;
+	}
+	efi_st_printf("Counter periodic: %u\n", counter);
+	if (counter < 8 || counter > 12) {
+		efi_st_error("Incorrect timing of events\n");
+		return 1;
+	}
+	ret = boottime->set_timer(event_notify, EFI_TIMER_STOP, 0);
+	if (index != 0) {
+		efi_st_error("Could not cancel timer\n");
+		return 1;
+	}
+	/* Set 10 ms timer */
+	counter = 0;
+	ret = boottime->set_timer(event_notify, EFI_TIMER_RELATIVE, 100000);
+	if (index != 0) {
+		efi_st_error("Could not set timer\n");
+		return 1;
+	}
+	/* Set 100 ms timer */
+	ret = boottime->set_timer(event_wait, EFI_TIMER_PERIODIC, 1000000);
+	if (index != 0) {
+		efi_st_error("Could not set timer\n");
+		return 1;
+	}
+	ret = boottime->wait_for_event(1, &event_wait, &index);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Could not wait for event\n");
+		return 1;
+	}
+	efi_st_printf("Counter single shot: %u\n", counter);
+	if (counter != 1) {
+		efi_st_error("Single shot timer failed\n");
+		return 1;
+	}
+	ret = boottime->wait_for_event(1, &event_wait, &index);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Could not wait for event\n");
+		return 1;
+	}
+	efi_st_printf("Stopped counter: %u\n", counter);
+	if (counter != 1) {
+		efi_st_error("Stopped timer fired\n");
+		return 1;
+	}
+	ret = boottime->set_timer(event_wait, EFI_TIMER_STOP, 0);
+	if (index != 0) {
+		efi_st_error("Could not cancel timer\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+EFI_UNIT_TEST(events) = {
+	.name = "event services",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+	.teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_exitbootservices.c b/lib/efi_selftest/efi_selftest_exitbootservices.c
new file mode 100644
index 0000000..60271e6
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_exitbootservices.c
@@ -0,0 +1,106 @@
+/*
+ * efi_selftest_events
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This unit test checks that the notification function of an
+ * EVT_SIGNAL_EXIT_BOOT_SERVICES event is called exactly once.
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_boot_services *boottime;
+static struct efi_event *event_notify;
+static unsigned int counter;
+
+/*
+ * Notification function, increments a counter.
+ *
+ * @event	notified event
+ * @context	pointer to the counter
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+	if (!context)
+		return;
+	++*(unsigned int *)context;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Create an EVT_SIGNAL_EXIT_BOOT_SERVICES event.
+ *
+ * @handle:	handle of the loaded image
+ * @systable:	system table
+ */
+static int setup(const efi_handle_t handle,
+		 const struct efi_system_table *systable)
+{
+	efi_status_t ret;
+
+	boottime = systable->boottime;
+
+	counter = 0;
+	ret = boottime->create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES,
+				     TPL_CALLBACK, notify, (void *)&counter,
+				     &event_notify);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("could not create event\n");
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Close the event created in setup.
+ */
+static int teardown(void)
+{
+	efi_status_t ret;
+
+	if (event_notify) {
+		ret = boottime->close_event(event_notify);
+		event_notify = NULL;
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("could not close event\n");
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Check that the notification function of the EVT_SIGNAL_EXIT_BOOT_SERVICES
+ * event has been called.
+ *
+ * Call ExitBootServices again and check that the notification function is
+ * not called again.
+ */
+static int execute(void)
+{
+	if (counter != 1) {
+		efi_st_error("ExitBootServices was not notified");
+		return 1;
+	}
+	efi_st_exit_boot_services();
+	if (counter != 1) {
+		efi_st_error("ExitBootServices was notified twice");
+		return 1;
+	}
+	return 0;
+}
+
+EFI_UNIT_TEST(exitbootservices) = {
+	.name = "ExitBootServices",
+	.phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+	.teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_tpl.c b/lib/efi_selftest/efi_selftest_tpl.c
new file mode 100644
index 0000000..90ace0f
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_tpl.c
@@ -0,0 +1,214 @@
+/*
+ * efi_selftest_events
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This unit test uses timer events to check the handling of
+ * task priority levels.
+ */
+
+#include <efi_selftest.h>
+
+static struct efi_event *event_notify;
+static struct efi_event *event_wait;
+static unsigned int counter;
+static struct efi_boot_services *boottime;
+
+/*
+ * Notification function, increments a counter.
+ *
+ * @event	notified event
+ * @context	pointer to the counter
+ */
+static void EFIAPI notify(struct efi_event *event, void *context)
+{
+	if (!context)
+		return;
+	++*(unsigned int *)context;
+}
+
+/*
+ * Setup unit test.
+ *
+ * Create two timer events.
+ * One with EVT_NOTIFY_SIGNAL, the other with EVT_NOTIFY_WAIT.
+ *
+ * @handle:	handle of the loaded image
+ * @systable:	system table
+ */
+static int setup(const efi_handle_t handle,
+		 const struct efi_system_table *systable)
+{
+	efi_status_t ret;
+
+	boottime = systable->boottime;
+
+	ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL,
+				     TPL_CALLBACK, notify, (void *)&counter,
+				     &event_notify);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("could not create event\n");
+		return 1;
+	}
+	ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_WAIT,
+				     TPL_HIGH_LEVEL, notify, NULL, &event_wait);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("could not create event\n");
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Close the events created in setup.
+ */
+static int teardown(void)
+{
+	efi_status_t ret;
+
+	if (event_notify) {
+		ret = boottime->close_event(event_notify);
+		event_notify = NULL;
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("could not close event\n");
+			return 1;
+		}
+	}
+	if (event_wait) {
+		ret = boottime->close_event(event_wait);
+		event_wait = NULL;
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("could not close event\n");
+			return 1;
+		}
+	}
+	boottime->restore_tpl(TPL_APPLICATION);
+	return 0;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Run a 10 ms periodic timer and check that it is called 10 times
+ * while waiting for 100 ms single shot timer.
+ *
+ * Raise the TPL level to the level of the 10 ms timer and observe
+ * that the notification function is not called again.
+ *
+ * Lower the TPL level and check that the queued notification
+ * function is called.
+ */
+static int execute(void)
+{
+	unsigned long index;
+	efi_status_t ret;
+	UINTN old_tpl;
+
+	/* Set 10 ms timer */
+	counter = 0;
+	ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Could not set timer\n");
+		return 1;
+	}
+	/* Set 100 ms timer */
+	ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000000);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Could not set timer\n");
+		return 1;
+	}
+	index = 5;
+	ret = boottime->wait_for_event(1, &event_wait, &index);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Could not wait for event\n");
+		return 1;
+	}
+	ret = boottime->check_event(event_wait);
+	if (ret != EFI_NOT_READY) {
+		efi_st_error("Signaled state was not cleared.\n");
+		efi_st_printf("ret = %u\n", (unsigned int)ret);
+		return 1;
+	}
+	if (index != 0) {
+		efi_st_error("WaitForEvent returned wrong index\n");
+		return 1;
+	}
+	efi_st_printf("Counter with TPL level TPL_APPLICATION: %u\n", counter);
+	if (counter < 8 || counter > 12) {
+		efi_st_error("Incorrect timing of events\n");
+		return 1;
+	}
+	ret = boottime->set_timer(event_notify, EFI_TIMER_STOP, 0);
+	if (index != 0) {
+		efi_st_error("Could not cancel timer\n");
+		return 1;
+	}
+	/* Raise TPL level */
+	old_tpl = boottime->raise_tpl(TPL_CALLBACK);
+	if (old_tpl != TPL_APPLICATION) {
+		efi_st_error("Initial TPL level was not TPL_APPLICATION");
+		return 1;
+	}
+	/* Set 10 ms timer */
+	counter = 0;
+	ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000);
+	if (index != 0) {
+		efi_st_error("Could not set timer\n");
+		return 1;
+	}
+	/* Set 100 ms timer */
+	ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000000);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Could not set timer\n");
+		return 1;
+	}
+	do {
+		ret = boottime->check_event(event_wait);
+	} while (ret == EFI_NOT_READY);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Could not check event\n");
+		return 1;
+	}
+	efi_st_printf("Counter with TPL level TPL_CALLBACK: %u\n", counter);
+	if (counter != 0) {
+		efi_st_error("Suppressed timer fired\n");
+		return 1;
+	}
+	/* Set 1 ms timer */
+	ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Could not set timer\n");
+		return 1;
+	}
+	/* Restore the old TPL level */
+	boottime->restore_tpl(TPL_APPLICATION);
+	ret = boottime->wait_for_event(1, &event_wait, &index);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Could not wait for event\n");
+		return 1;
+	}
+	efi_st_printf("Counter with TPL level TPL_APPLICATION: %u\n", counter);
+	if (counter < 1) {
+		efi_st_error("Queued timer event did not fire\n");
+		return 1;
+	}
+	ret = boottime->set_timer(event_wait, EFI_TIMER_STOP, 0);
+	if (index != 0) {
+		efi_st_error("Could not cancel timer\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+EFI_UNIT_TEST(tpl) = {
+	.name = "task priority levels",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+	.teardown = teardown,
+};
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 107a892..45f3fe7 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -4,17 +4,18 @@
  */
 
 #ifndef USE_HOSTCC
-#include <boot_fit.h>
 #include <common.h>
+#include <boot_fit.h>
 #include <dm.h>
-#include <errno.h>
-#include <serial.h>
-#include <libfdt.h>
-#include <fdt_support.h>
-#include <fdtdec.h>
-#include <asm/sections.h>
 #include <dm/of_extra.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <fdt_support.h>
+#include <libfdt.h>
+#include <serial.h>
+#include <asm/sections.h>
 #include <linux/ctype.h>
+#include <linux/lzo.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -1203,9 +1204,66 @@
 }
 #endif
 
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT_GZIP) ||\
+	CONFIG_IS_ENABLED(MULTI_DTB_FIT_LZO)
+static int uncompress_blob(const void *src, ulong sz_src, void **dstp)
+{
+	size_t sz_out = CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ;
+	ulong sz_in = sz_src;
+	void *dst;
+	int rc;
+
+	if (CONFIG_IS_ENABLED(GZIP))
+		if (gzip_parse_header(src, sz_in) < 0)
+			return -1;
+	if (CONFIG_IS_ENABLED(LZO))
+		if (!lzop_is_valid_header(src))
+			return -EBADMSG;
+
+	if (CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC)) {
+		dst = malloc(sz_out);
+		if (!dst) {
+			puts("uncompress_blob: Unable to allocate memory\n");
+			return -ENOMEM;
+		}
+	} else  {
+#  if CONFIG_IS_ENABLED(MULTI_DTB_FIT_USER_DEFINED_AREA)
+		dst = (void *)CONFIG_VAL(MULTI_DTB_FIT_USER_DEF_ADDR);
+#  else
+		return -ENOTSUPP;
+#  endif
+	}
+
+	if (CONFIG_IS_ENABLED(GZIP))
+		rc = gunzip(dst, sz_out, (u8 *)src, &sz_in);
+	else if (CONFIG_IS_ENABLED(LZO))
+		rc = lzop_decompress(src, sz_in, dst, &sz_out);
+
+	if (rc < 0) {
+		/* not a valid compressed blob */
+		puts("uncompress_blob: Unable to uncompress\n");
+		if (CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC))
+			free(dst);
+		return -EBADMSG;
+	}
+	*dstp = dst;
+	return 0;
+}
+# else
+static int uncompress_blob(const void *src, ulong sz_src, void **dstp)
+{
+	return -ENOTSUPP;
+}
+# endif
+#endif
+
 int fdtdec_setup(void)
 {
 #if CONFIG_IS_ENABLED(OF_CONTROL)
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+	void *fdt_blob;
+# endif
 # ifdef CONFIG_OF_EMBED
 	/* Get a pointer to the FDT */
 	gd->fdt_blob = __dtb_dt_begin;
@@ -1216,15 +1274,6 @@
 		gd->fdt_blob = (ulong *)&_image_binary_end;
 	else
 		gd->fdt_blob = (ulong *)&__bss_end;
-
-#  elif defined CONFIG_FIT_EMBED
-	gd->fdt_blob = locate_dtb_in_fit(&_end);
-
-	if (gd->fdt_blob == NULL || gd->fdt_blob <= ((void *)&_end)) {
-		puts("Failed to find proper dtb in embedded FIT Image\n");
-		return -1;
-	}
-
 #  else
 	/* FDT is at end of image */
 	gd->fdt_blob = (ulong *)&_end;
@@ -1243,7 +1292,27 @@
 	gd->fdt_blob = (void *)env_get_ulong("fdtcontroladdr", 16,
 						(uintptr_t)gd->fdt_blob);
 # endif
+
+# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+	/*
+	 * Try and uncompress the blob.
+	 * Unfortunately there is no way to know how big the input blob really
+	 * is. So let us set the maximum input size arbitrarily high. 16MB
+	 * ought to be more than enough for packed DTBs.
+	 */
+	if (uncompress_blob(gd->fdt_blob, 0x1000000, &fdt_blob) == 0)
+		gd->fdt_blob = fdt_blob;
+
+	/*
+	 * Check if blob is a FIT images containings DTBs.
+	 * If so, pick the most relevant
+	 */
+	fdt_blob = locate_dtb_in_fit(gd->fdt_blob);
+	if (fdt_blob)
+		gd->fdt_blob = fdt_blob;
+# endif
 #endif
+
 	return fdtdec_prepare_fdt();
 }
 
diff --git a/lib/gunzip.c b/lib/gunzip.c
index 832b306..adb86c7 100644
--- a/lib/gunzip.c
+++ b/lib/gunzip.c
@@ -42,7 +42,7 @@
 	free (addr);
 }
 
-int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp)
+int gzip_parse_header(const unsigned char *src, unsigned long len)
 {
 	int i, flags;
 
@@ -63,12 +63,21 @@
 			;
 	if ((flags & HEAD_CRC) != 0)
 		i += 2;
-	if (i >= *lenp) {
+	if (i >= len) {
 		puts ("Error: gunzip out of data in header\n");
 		return (-1);
 	}
+	return i;
+}
 
-	return zunzip(dst, dstlen, src, lenp, 1, i);
+int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp)
+{
+	int offset = gzip_parse_header(src, *lenp);
+
+	if (offset < 0)
+		return offset;
+
+	return zunzip(dst, dstlen, src, lenp, 1, offset);
 }
 
 #ifdef CONFIG_CMD_UNZIP
diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c
index ccc90b8..65fef0b 100644
--- a/lib/lzo/lzo1x_decompress.c
+++ b/lib/lzo/lzo1x_decompress.c
@@ -30,16 +30,29 @@
 
 #define HEADER_HAS_FILTER	0x00000800L
 
+
+bool lzop_is_valid_header(const unsigned char *src)
+{
+	int i;
+	/* read magic: 9 first bytes */
+	for (i = 0; i < ARRAY_SIZE(lzop_magic); i++) {
+		if (*src++ != lzop_magic[i])
+			return false;
+	}
+	return true;
+}
+
 static inline const unsigned char *parse_header(const unsigned char *src)
 {
 	u16 version;
 	int i;
 
-	/* read magic: 9 first bytes */
-	for (i = 0; i < ARRAY_SIZE(lzop_magic); i++) {
-		if (*src++ != lzop_magic[i])
-			return NULL;
-	}
+	if (!lzop_is_valid_header(src))
+		return NULL;
+
+	/* skip header */
+	src += 9;
+
 	/* get version (2bytes), skip library version (2),
 	 * 'need to be extracted' version (2) and
 	 * method (1) */
diff --git a/scripts/Kconfig b/scripts/Kconfig
deleted file mode 100644
index 2a2c18e..0000000
--- a/scripts/Kconfig
+++ /dev/null
@@ -1,2 +0,0 @@
-config BUILD_BIN2C
-	bool
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 2a7ed70..861a3dc 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -359,20 +359,22 @@
 $(obj)/%.S: $(src)/%.ttf
 	$(call cmd,S_ttf)
 
-# EFI Hello World application
+# EFI applications
+# A Makefile target *.efi is built as EFI application.
+# A Makefile target *_efi.S wraps *.efi as built-in EFI application.
 # ---------------------------------------------------------------------------
 
 # Generate an assembly file to wrap the EFI app
-cmd_S_efi=						\
-(							\
-	echo '.section .rodata.efi.init,"a"';		\
-	echo '.balign 16';				\
-	echo '.global __efi_hello_world_begin';		\
-	echo '__efi_hello_world_begin:';		\
-	echo '.incbin "$<" ';				\
-	echo '__efi_hello_world_end:';			\
-	echo '.global __efi_hello_world_end';		\
-	echo '.balign 16';				\
+cmd_S_efi=					\
+(						\
+	echo '.section .rodata.$*.init,"a"';	\
+	echo '.balign 16';			\
+	echo '.global __efi_$*_begin';		\
+	echo '__efi_$*_begin:';			\
+	echo '.incbin "$<" ';			\
+	echo '__efi_$*_end:';			\
+	echo '.global __efi_$*_end';		\
+	echo '.balign 16';			\
 ) > $@
 
 $(obj)/%_efi.S: $(obj)/%.efi
@@ -383,7 +385,7 @@
 		.dynamic -j .dynsym  -j .rel* -j .rela* -j .reloc \
 		$(if $(EFI_TARGET),$(EFI_TARGET),-O binary) $^ $@
 
-$(obj)/%.efi: $(obj)/%.so
+$(obj)/%.efi: $(obj)/%_efi.so
 	$(call cmd,efi_objcopy)
 
 quiet_cmd_efi_ld = LD      $@
@@ -392,9 +394,7 @@
 
 EFI_LDS_PATH = $(srctree)/arch/$(ARCH)/lib/$(EFI_LDS)
 
-$(obj)/helloworld.so: $(EFI_LDS_PATH)
-
-$(obj)/helloworld.so: $(obj)/helloworld.o arch/$(ARCH)/lib/$(EFI_CRT0) \
+$(obj)/%_efi.so: $(obj)/%.o arch/$(ARCH)/lib/$(EFI_CRT0) \
 		arch/$(ARCH)/lib/$(EFI_RELOC)
 	$(call cmd,efi_ld)
 
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index b86ea76..49b27ac 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -209,10 +209,21 @@
 quiet_cmd_copy = COPY    $@
       cmd_copy = cp $< $@
 
+ifneq ($(CONFIG_SPL_MULTI_DTB_FIT),y)
+FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).dtb
+else ifeq ($(CONFIG_SPL_MULTI_DTB_FIT_LZO),y)
+FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit.lzo
+else ifeq ($(CONFIG_SPL_MULTI_DTB_FIT_GZIP),y)
+FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit.gz
+else
+FINAL_DTB_CONTAINER = $(obj)/$(SPL_BIN).multidtb.fit
+endif
+
+
 ifeq ($(CONFIG_$(SPL_TPL_)OF_CONTROL)$(CONFIG_OF_SEPARATE)$(CONFIG_$(SPL_TPL_)OF_PLATDATA),yy)
 $(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN)-nodtb.bin \
 		$(if $(CONFIG_SPL_SEPARATE_BSS),,$(obj)/$(SPL_BIN)-pad.bin) \
-		$(obj)/$(SPL_BIN).dtb FORCE
+		$(FINAL_DTB_CONTAINER)  FORCE
 	$(call if_changed,cat)
 
 $(obj)/$(SPL_BIN).bin: $(obj)/$(SPL_BIN)-dtb.bin FORCE
@@ -383,6 +394,28 @@
 PHONY += FORCE
 FORCE:
 
+PHONY += dtbs
+dtbs:
+	$(Q)$(MAKE) $(build)=dts dtbs
+
 # Declare the contents of the .PHONY variable as phony.  We keep that
 # information in a variable so we can use it in if_changed and friends.
 .PHONY: $(PHONY)
+
+SHRUNK_ARCH_DTB = $(patsubst %,$(obj)/dts/%.dtb,$(subst ",,$(CONFIG_SPL_OF_LIST)))
+.SECONDEXPANSION:
+$(SHRUNK_ARCH_DTB): $$(patsubst $(obj)/dts/%, arch/$(ARCH)/dts/%, $$@)
+	$(call if_changed,fdtgrep)
+
+MKIMAGEFLAGS_$(SPL_BIN).multidtb.fit = -f auto -A $(ARCH) -T firmware -C none -O u-boot \
+	-n "Multi DTB fit image for $(SPL_BIN)" -E \
+	$(patsubst %,-b %,$(SHRUNK_ARCH_DTB))
+
+$(obj)/$(SPL_BIN).multidtb.fit: /dev/null $(SHRUNK_ARCH_DTB) FORCE
+	$(call if_changed,mkimage)
+
+$(obj)/$(SPL_BIN).multidtb.fit.gz: $(obj)/$(SPL_BIN).multidtb.fit
+	@gzip -kf9 $< > $@
+
+$(obj)/$(SPL_BIN).multidtb.fit.lzo: $(obj)/$(SPL_BIN).multidtb.fit
+	@lzop -f9 $< > $@
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index db5d88b..78bcf06 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -1847,7 +1847,6 @@
 CONFIG_RAMDISK_BOOT
 CONFIG_RAM_BOOT
 CONFIG_RAM_BOOT_PHYS
-CONFIG_RANDOM_UUID
 CONFIG_RCAR_BOARD_STRING
 CONFIG_RD_LVL
 CONFIG_REALMODE_DEBUG
@@ -4973,8 +4972,6 @@
 CONFIG_USBD_VENDORID
 CONFIG_USBID_ADDR
 CONFIG_USBNET_DEV_ADDR
-CONFIG_USBNET_HOST_ADDR
-CONFIG_USBNET_MANUFACTURER
 CONFIG_USBTTY
 CONFIG_USB_AM35X
 CONFIG_USB_ATMEL
@@ -5004,10 +5001,7 @@
 CONFIG_USB_EHCI_TXFIFO_THRESH
 CONFIG_USB_EHCI_VCT
 CONFIG_USB_EHCI_VF
-CONFIG_USB_ETHER
-CONFIG_USB_ETH_CDC
 CONFIG_USB_ETH_QMULT
-CONFIG_USB_ETH_RNDIS
 CONFIG_USB_ETH_SUBSET
 CONFIG_USB_EXT2_BOOT
 CONFIG_USB_FAT_BOOT
diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore
new file mode 100644
index 0000000..d807c08
--- /dev/null
+++ b/scripts/dtc/.gitignore
@@ -0,0 +1,4 @@
+/dtc
+/dtc-lexer.lex.c
+/dtc-parser.tab.c
+/dtc-parser.tab.h
diff --git a/scripts/spelling.txt b/scripts/spelling.txt
new file mode 100644
index 0000000..400ef35
--- /dev/null
+++ b/scripts/spelling.txt
@@ -0,0 +1,1217 @@
+# Originally from Debian's Lintian tool. Various false positives have been
+# removed, and various additions have been made as they've been discovered
+# in the kernel source.
+#
+# License: GPLv2
+#
+# The format of each line is:
+# mistake||correction
+#
+abandonning||abandoning
+abigious||ambiguous
+abitrate||arbitrate
+abov||above
+abreviated||abbreviated
+absense||absence
+absolut||absolute
+absoulte||absolute
+acccess||access
+acceess||access
+acceleratoin||acceleration
+accelleration||acceleration
+accesing||accessing
+accesnt||accent
+accessable||accessible
+accesss||access
+accidentaly||accidentally
+accidentually||accidentally
+accoding||according
+accomodate||accommodate
+accomodates||accommodates
+accordign||according
+accoring||according
+accout||account
+accquire||acquire
+accquired||acquired
+accross||across
+acessable||accessible
+acess||access
+achitecture||architecture
+acient||ancient
+acitions||actions
+acitve||active
+acknowldegement||acknowledgment
+acknowledgement||acknowledgment
+ackowledge||acknowledge
+ackowledged||acknowledged
+acording||according
+activete||activate
+actived||activated
+actualy||actually
+acumulating||accumulating
+acumulator||accumulator
+adapater||adapter
+addional||additional
+additionaly||additionally
+addres||address
+adddress||address
+addreses||addresses
+addresss||address
+aditional||additional
+aditionally||additionally
+aditionaly||additionally
+adminstrative||administrative
+adress||address
+adresses||addresses
+adviced||advised
+afecting||affecting
+againt||against
+agaist||against
+albumns||albums
+alegorical||allegorical
+algined||aligned
+algorith||algorithm
+algorithmical||algorithmically
+algoritm||algorithm
+algoritms||algorithms
+algorrithm||algorithm
+algorritm||algorithm
+aligment||alignment
+alignement||alignment
+allign||align
+alligned||aligned
+allocatote||allocate
+allocatrd||allocated
+allocte||allocate
+allpication||application
+alocate||allocate
+alogirhtms||algorithms
+alogrithm||algorithm
+alot||a lot
+alow||allow
+alows||allows
+altough||although
+alue||value
+ambigious||ambiguous
+amoung||among
+amout||amount
+an union||a union
+an user||a user
+an userspace||a userspace
+an one||a one
+analysator||analyzer
+ang||and
+anniversery||anniversary
+annoucement||announcement
+anomolies||anomalies
+anomoly||anomaly
+anway||anyway
+aplication||application
+appearence||appearance
+applicaion||application
+appliction||application
+applictions||applications
+applys||applies
+appplications||applications
+appropiate||appropriate
+appropriatly||appropriately
+approriate||appropriate
+approriately||appropriately
+apropriate||appropriate
+aquainted||acquainted
+aquired||acquired
+aquisition||acquisition
+arbitary||arbitrary
+architechture||architecture
+arguement||argument
+arguements||arguments
+aritmetic||arithmetic
+arne't||aren't
+arraival||arrival
+artifical||artificial
+artillary||artillery
+asign||assign
+asser||assert
+assertation||assertion
+assiged||assigned
+assigment||assignment
+assigments||assignments
+assistent||assistant
+assocation||association
+associcated||associated
+assotiated||associated
+assum||assume
+assumtpion||assumption
+asuming||assuming
+asycronous||asynchronous
+asynchnous||asynchronous
+atomatically||automatically
+atomicly||atomically
+atempt||attempt
+attachement||attachment
+attched||attached
+attemps||attempts
+attemping||attempting
+attruibutes||attributes
+authentification||authentication
+automaticaly||automatically
+automaticly||automatically
+automatize||automate
+automatized||automated
+automatizes||automates
+autonymous||autonomous
+auxillary||auxiliary
+auxilliary||auxiliary
+avaiable||available
+avaible||available
+availabe||available
+availabled||available
+availablity||availability
+availale||available
+availavility||availability
+availble||available
+availiable||available
+avalable||available
+avaliable||available
+aysnc||async
+backgroud||background
+backword||backward
+backwords||backwards
+bahavior||behavior
+bakup||backup
+baloon||balloon
+baloons||balloons
+bandwith||bandwidth
+banlance||balance
+batery||battery
+beacuse||because
+becasue||because
+becomming||becoming
+becuase||because
+beeing||being
+befor||before
+begining||beginning
+beter||better
+betweeen||between
+bianries||binaries
+bitmast||bitmask
+boardcast||broadcast
+borad||board
+boundry||boundary
+brievely||briefly
+broadcat||broadcast
+cacluated||calculated
+caculation||calculation
+calender||calendar
+calle||called
+callibration||calibration
+calucate||calculate
+calulate||calculate
+cancelation||cancellation
+cancle||cancel
+capabilites||capabilities
+capabitilies||capabilities
+capatibilities||capabilities
+capapbilities||capabilities
+carefuly||carefully
+cariage||carriage
+catagory||category
+cehck||check
+challange||challenge
+challanges||challenges
+chanell||channel
+changable||changeable
+chanined||chained
+channle||channel
+channnel||channel
+charachter||character
+charachters||characters
+charactor||character
+charater||character
+charaters||characters
+charcter||character
+chcek||check
+chck||check
+checksuming||checksumming
+childern||children
+childs||children
+chiled||child
+chked||checked
+chnage||change
+chnages||changes
+chnnel||channel
+choosen||chosen
+chouse||chose
+circumvernt||circumvent
+claread||cleared
+clared||cleared
+closeing||closing
+clustred||clustered
+coexistance||coexistence
+collapsable||collapsible
+colorfull||colorful
+comand||command
+comit||commit
+commerical||commercial
+comming||coming
+comminucation||communication
+commited||committed
+commiting||committing
+committ||commit
+commoditiy||commodity
+comsume||consume
+comsumer||consumer
+comsuming||consuming
+compability||compatibility
+compaibility||compatibility
+compatability||compatibility
+compatable||compatible
+compatibiliy||compatibility
+compatibilty||compatibility
+compatiblity||compatibility
+competion||completion
+compilant||compliant
+compleatly||completely
+completition||completion
+completly||completely
+complient||compliant
+componnents||components
+compoment||component
+compres||compress
+compresion||compression
+comression||compression
+comunication||communication
+conbination||combination
+conditionaly||conditionally
+conected||connected
+connecetd||connected
+configuartion||configuration
+configuratoin||configuration
+configuraton||configuration
+configuretion||configuration
+configutation||configuration
+conider||consider
+conjuction||conjunction
+connectinos||connections
+connnection||connection
+connnections||connections
+consistancy||consistency
+consistant||consistent
+containes||contains
+containts||contains
+contaisn||contains
+contant||contact
+contence||contents
+continous||continuous
+continously||continuously
+continueing||continuing
+contraints||constraints
+contol||control
+contoller||controller
+controled||controlled
+controler||controller
+controll||control
+contruction||construction
+contry||country
+conuntry||country
+convertion||conversion
+convertor||converter
+convienient||convenient
+convinient||convenient
+corected||corrected
+correponding||corresponding
+correponds||corresponds
+correspoding||corresponding
+cotrol||control
+cound||could
+couter||counter
+coutner||counter
+cryptocraphic||cryptographic
+cunter||counter
+curently||currently
+cylic||cyclic
+dafault||default
+deafult||default
+deamon||daemon
+decompres||decompress
+decription||description
+dectected||detected
+defailt||default
+defferred||deferred
+definate||definite
+definately||definitely
+defintion||definition
+defintions||definitions
+defualt||default
+defult||default
+deintializing||deinitializing
+deintialize||deinitialize
+deintialized||deinitialized
+deivce||device
+delared||declared
+delare||declare
+delares||declares
+delaring||declaring
+delemiter||delimiter
+demodualtor||demodulator
+demension||dimension
+dependancies||dependencies
+dependancy||dependency
+dependant||dependent
+depreacted||deprecated
+depreacte||deprecate
+desactivate||deactivate
+desciptor||descriptor
+desciptors||descriptors
+descripton||description
+descrition||description
+descritptor||descriptor
+desctiptor||descriptor
+desriptor||descriptor
+desriptors||descriptors
+destionation||destination
+destory||destroy
+destoryed||destroyed
+destorys||destroys
+destroied||destroyed
+detabase||database
+deteced||detected
+develope||develop
+developement||development
+developped||developed
+developpement||development
+developper||developer
+developpment||development
+deveolpment||development
+devided||divided
+deviece||device
+diable||disable
+dictionnary||dictionary
+didnt||didn't
+diferent||different
+differrence||difference
+diffrent||different
+diffrentiate||differentiate
+difinition||definition
+diplay||display
+direectly||directly
+disassocation||disassociation
+disapear||disappear
+disapeared||disappeared
+disappared||disappeared
+disble||disable
+disbled||disabled
+disconnet||disconnect
+discontinous||discontinuous
+dispertion||dispersion
+dissapears||disappears
+distiction||distinction
+docuentation||documentation
+documantation||documentation
+documentaion||documentation
+documment||document
+doesnt||doesn't
+dorp||drop
+dosen||doesn
+downlad||download
+downlads||downloads
+druing||during
+dynmaic||dynamic
+easilly||easily
+ecspecially||especially
+edditable||editable
+editting||editing
+efective||effective
+efficently||efficiently
+ehther||ether
+eigth||eight
+elementry||elementary
+eletronic||electronic
+embeded||embedded
+enabledi||enabled
+enchanced||enhanced
+encorporating||incorporating
+encrupted||encrypted
+encrypiton||encryption
+encryptio||encryption
+endianess||endianness
+enhaced||enhanced
+enlightnment||enlightenment
+entrys||entries
+enocded||encoded
+enterily||entirely
+enviroiment||environment
+enviroment||environment
+environement||environment
+environent||environment
+eqivalent||equivalent
+equiped||equipped
+equivelant||equivalent
+equivilant||equivalent
+eror||error
+estbalishment||establishment
+etsablishment||establishment
+etsbalishment||establishment
+excecutable||executable
+exceded||exceeded
+excellant||excellent
+exeed||exceed
+existance||existence
+existant||existent
+exixt||exist
+exlcude||exclude
+exlcusive||exclusive
+exmaple||example
+expecially||especially
+explicite||explicit
+explicitely||explicitly
+explict||explicit
+explictely||explicitly
+explictly||explicitly
+expresion||expression
+exprimental||experimental
+extened||extended
+extensability||extensibility
+extention||extension
+extracter||extractor
+falied||failed
+faild||failed
+faill||fail
+failied||failed
+faillure||failure
+failue||failure
+failuer||failure
+faireness||fairness
+falied||failed
+faliure||failure
+fallbck||fallback
+familar||familiar
+fatser||faster
+feauture||feature
+feautures||features
+fetaure||feature
+fetaures||features
+fileystem||filesystem
+fimware||firmware
+finanize||finalize
+findn||find
+finilizes||finalizes
+finsih||finish
+flusing||flushing
+folloing||following
+followign||following
+followings||following
+follwing||following
+forseeable||foreseeable
+forse||force
+fortan||fortran
+forwardig||forwarding
+framming||framing
+framwork||framework
+frequncy||frequency
+frome||from
+fucntion||function
+fuction||function
+fuctions||functions
+funcion||function
+functionallity||functionality
+functionaly||functionally
+functionnality||functionality
+functonality||functionality
+funtion||function
+funtions||functions
+furthur||further
+futhermore||furthermore
+futrue||future
+gaurenteed||guaranteed
+generiously||generously
+genereate||generate
+genric||generic
+globel||global
+grabing||grabbing
+grahical||graphical
+grahpical||graphical
+grapic||graphic
+guage||gauge
+guarenteed||guaranteed
+guarentee||guarantee
+halfs||halves
+hander||handler
+handfull||handful
+hanled||handled
+happend||happened
+harware||hardware
+heirarchically||hierarchically
+helpfull||helpful
+hierachy||hierarchy
+hierarchie||hierarchy
+howver||however
+hsould||should
+hypervior||hypervisor
+hypter||hyper
+identidier||identifier
+iligal||illegal
+illigal||illegal
+imblance||imbalance
+immeadiately||immediately
+immedaite||immediate
+immediatelly||immediately
+immediatly||immediately
+immidiate||immediate
+impelentation||implementation
+impementated||implemented
+implemantation||implementation
+implemenation||implementation
+implementaiton||implementation
+implementated||implemented
+implemention||implementation
+implemetation||implementation
+implemntation||implementation
+implentation||implementation
+implmentation||implementation
+implmenting||implementing
+incomming||incoming
+incompatabilities||incompatibilities
+incompatable||incompatible
+inconsistant||inconsistent
+increas||increase
+incrment||increment
+indendation||indentation
+indended||intended
+independant||independent
+independantly||independently
+independed||independent
+indiate||indicate
+indicat||indicate
+inexpect||inexpected
+infomation||information
+informatiom||information
+informations||information
+informtion||information
+infromation||information
+ingore||ignore
+inital||initial
+initalized||initialized
+initalised||initialized
+initalise||initialize
+initalize||initialize
+initation||initiation
+initators||initiators
+initialiazation||initialization
+initializiation||initialization
+initialzed||initialized
+initilization||initialization
+initilize||initialize
+inofficial||unofficial
+insititute||institute
+instal||install
+instanciated||instantiated
+inteface||interface
+integreated||integrated
+integrety||integrity
+integrey||integrity
+intendet||intended
+intented||intended
+interanl||internal
+interchangable||interchangeable
+interferring||interfering
+interger||integer
+intermittant||intermittent
+internel||internal
+interoprability||interoperability
+interrface||interface
+interrrupt||interrupt
+interrup||interrupt
+interrups||interrupts
+interruptted||interrupted
+interupted||interrupted
+interupt||interrupt
+intial||initial
+intialisation||initialisation
+intialised||initialised
+intialise||initialise
+intialization||initialization
+intialized||initialized
+intialize||initialize
+intregral||integral
+intrrupt||interrupt
+intterrupt||interrupt
+intuative||intuitive
+invaid||invalid
+invalde||invalid
+invalide||invalid
+invalud||invalid
+invididual||individual
+invokation||invocation
+invokations||invocations
+irrelevent||irrelevant
+isnt||isn't
+isssue||issue
+iternations||iterations
+itertation||iteration
+itslef||itself
+jave||java
+jeffies||jiffies
+juse||just
+jus||just
+kown||known
+langage||language
+langauage||language
+langauge||language
+langugage||language
+lauch||launch
+layed||laid
+leightweight||lightweight
+lengh||length
+lenght||length
+lenth||length
+lesstiff||lesstif
+libaries||libraries
+libary||library
+librairies||libraries
+libraris||libraries
+licenceing||licencing
+loggging||logging
+loggin||login
+logile||logfile
+loosing||losing
+losted||lost
+machinary||machinery
+maintainance||maintenance
+maintainence||maintenance
+maintan||maintain
+makeing||making
+malplaced||misplaced
+malplace||misplace
+managable||manageable
+managment||management
+mangement||management
+manoeuvering||maneuvering
+mappping||mapping
+mathimatical||mathematical
+mathimatic||mathematic
+mathimatics||mathematics
+maxium||maximum
+mechamism||mechanism
+meetign||meeting
+ment||meant
+mergable||mergeable
+mesage||message
+messags||messages
+messgaes||messages
+messsage||message
+messsages||messages
+micropone||microphone
+microprocesspr||microprocessor
+milliseonds||milliseconds
+minium||minimum
+minimam||minimum
+minumum||minimum
+misalinged||misaligned
+miscelleneous||miscellaneous
+misformed||malformed
+mispelled||misspelled
+mispelt||misspelt
+mising||missing
+missmanaged||mismanaged
+missmatch||mismatch
+miximum||maximum
+mmnemonic||mnemonic
+mnay||many
+modulues||modules
+momery||memory
+memomry||memory
+monochorome||monochrome
+monochromo||monochrome
+monocrome||monochrome
+mopdule||module
+mroe||more
+mulitplied||multiplied
+multidimensionnal||multidimensional
+multple||multiple
+mumber||number
+muticast||multicast
+mutiple||multiple
+mutli||multi
+nams||names
+navagating||navigating
+nead||need
+neccecary||necessary
+neccesary||necessary
+neccessary||necessary
+necesary||necessary
+neded||needed
+negaive||negative
+negoitation||negotiation
+negotation||negotiation
+nerver||never
+nescessary||necessary
+nessessary||necessary
+noticable||noticeable
+notications||notifications
+notifed||notified
+numebr||number
+numner||number
+obtaion||obtain
+occassionally||occasionally
+occationally||occasionally
+occurance||occurrence
+occurances||occurrences
+occured||occurred
+occurence||occurrence
+occure||occurred
+occured||occurred
+occuring||occurring
+offet||offset
+omited||omitted
+omiting||omitting
+omitt||omit
+ommiting||omitting
+ommitted||omitted
+onself||oneself
+ony||only
+operatione||operation
+opertaions||operations
+optionnal||optional
+optmizations||optimizations
+orientatied||orientated
+orientied||oriented
+orignal||original
+otherise||otherwise
+ouput||output
+oustanding||outstanding
+overaall||overall
+overhread||overhead
+overlaping||overlapping
+overide||override
+overrided||overridden
+overriden||overridden
+overun||overrun
+overwritting||overwriting
+overwriten||overwritten
+pacakge||package
+pachage||package
+packacge||package
+packege||package
+packge||package
+packtes||packets
+pakage||package
+pallette||palette
+paln||plan
+paramameters||parameters
+paramaters||parameters
+paramater||parameter
+parametes||parameters
+parametised||parametrised
+paramter||parameter
+paramters||parameters
+particuarly||particularly
+particularily||particularly
+partiton||partition
+pased||passed
+passin||passing
+pathes||paths
+pecularities||peculiarities
+peformance||performance
+peice||piece
+pendantic||pedantic
+peprocessor||preprocessor
+perfoming||performing
+permissons||permissions
+peroid||period
+persistance||persistence
+persistant||persistent
+plalform||platform
+platfrom||platform
+plattform||platform
+pleaes||please
+ploting||plotting
+plugable||pluggable
+poinnter||pointer
+pointeur||pointer
+poiter||pointer
+posible||possible
+positon||position
+possibilites||possibilities
+powerfull||powerful
+preapre||prepare
+preceeded||preceded
+preceeding||preceding
+preceed||precede
+precendence||precedence
+precission||precision
+preemptable||preemptible
+prefered||preferred
+prefferably||preferably
+premption||preemption
+prepaired||prepared
+pressre||pressure
+primative||primitive
+princliple||principle
+priorty||priority
+privilaged||privileged
+privilage||privilege
+priviledge||privilege
+priviledges||privileges
+probaly||probably
+procceed||proceed
+proccesors||processors
+procesed||processed
+proces||process
+procesing||processing
+processessing||processing
+processess||processes
+processpr||processor
+processsed||processed
+processsing||processing
+procteted||protected
+prodecure||procedure
+progams||programs
+progess||progress
+programers||programmers
+programm||program
+programms||programs
+progresss||progress
+promiscous||promiscuous
+promps||prompts
+pronnounced||pronounced
+prononciation||pronunciation
+pronouce||pronounce
+pronunce||pronounce
+propery||property
+propigate||propagate
+propigation||propagation
+propogate||propagate
+prosess||process
+protable||portable
+protcol||protocol
+protecion||protection
+protocoll||protocol
+promixity||proximity
+psudo||pseudo
+psuedo||pseudo
+psychadelic||psychedelic
+pwoer||power
+quering||querying
+randomally||randomly
+raoming||roaming
+reasearcher||researcher
+reasearchers||researchers
+reasearch||research
+recepient||recipient
+receving||receiving
+recieved||received
+recieve||receive
+reciever||receiver
+recieves||receives
+recogniced||recognised
+recognizeable||recognizable
+recommanded||recommended
+recyle||recycle
+redircet||redirect
+redirectrion||redirection
+reename||rename
+refcounf||refcount
+refence||reference
+refered||referred
+referenace||reference
+refering||referring
+refernces||references
+refernnce||reference
+refrence||reference
+registerd||registered
+registeresd||registered
+registerred||registered
+registes||registers
+registraration||registration
+regsiter||register
+regster||register
+regualar||regular
+reguator||regulator
+regulamentations||regulations
+reigstration||registration
+releated||related
+relevent||relevant
+remoote||remote
+remore||remote
+removeable||removable
+repectively||respectively
+replacable||replaceable
+replacments||replacements
+replys||replies
+reponse||response
+representaion||representation
+reqeust||request
+requestied||requested
+requiere||require
+requirment||requirement
+requred||required
+requried||required
+requst||request
+reseting||resetting
+resizeable||resizable
+resouce||resource
+resouces||resources
+resoures||resources
+responce||response
+ressizes||resizes
+ressource||resource
+ressources||resources
+retransmited||retransmitted
+retreived||retrieved
+retreive||retrieve
+retrive||retrieve
+retuned||returned
+reudce||reduce
+reuest||request
+reuqest||request
+reutnred||returned
+revsion||revision
+rmeoved||removed
+rmeove||remove
+rmeoves||removes
+rountine||routine
+routins||routines
+rquest||request
+runing||running
+runned||ran
+runnning||running
+runtine||runtime
+sacrifying||sacrificing
+safly||safely
+safty||safety
+savable||saveable
+scaned||scanned
+scaning||scanning
+scarch||search
+seach||search
+searchs||searches
+secquence||sequence
+secund||second
+segement||segment
+senarios||scenarios
+sentivite||sensitive
+separatly||separately
+sepcify||specify
+sepc||spec
+seperated||separated
+seperately||separately
+seperate||separate
+seperatly||separately
+seperator||separator
+sepperate||separate
+sequece||sequence
+sequencial||sequential
+serveral||several
+setts||sets
+settting||setting
+shotdown||shutdown
+shoud||should
+shouldnt||shouldn't
+shoule||should
+shrinked||shrunk
+siginificantly||significantly
+signabl||signal
+similary||similarly
+similiar||similar
+simlar||similar
+simliar||similar
+simpified||simplified
+singaled||signaled
+singal||signal
+singed||signed
+sleeped||slept
+softwares||software
+speach||speech
+specfic||specific
+speciefied||specified
+specifc||specific
+specifed||specified
+specificatin||specification
+specificaton||specification
+specifing||specifying
+specifiying||specifying
+speficied||specified
+speicify||specify
+speling||spelling
+spinlcok||spinlock
+spinock||spinlock
+splitted||split
+spreaded||spread
+spurrious||spurious
+sructure||structure
+stablilization||stabilization
+staically||statically
+staion||station
+standardss||standards
+standartization||standardization
+standart||standard
+staticly||statically
+stoped||stopped
+stoppped||stopped
+straming||streaming
+struc||struct
+structres||structures
+stuct||struct
+strucuture||structure
+stucture||structure
+sturcture||structure
+subdirectoires||subdirectories
+suble||subtle
+substract||subtract
+succesfully||successfully
+succesful||successful
+successed||succeeded
+successfull||successful
+successfuly||successfully
+sucessfully||successfully
+sucess||success
+superflous||superfluous
+superseeded||superseded
+suplied||supplied
+suported||supported
+suport||support
+supportet||supported
+suppored||supported
+supportin||supporting
+suppoted||supported
+suppported||supported
+suppport||support
+supress||suppress
+surpresses||suppresses
+susbsystem||subsystem
+suspeneded||suspended
+suspicously||suspiciously
+swaping||swapping
+switchs||switches
+swith||switch
+swithable||switchable
+swithc||switch
+swithced||switched
+swithcing||switching
+swithed||switched
+swithing||switching
+symetric||symmetric
+synax||syntax
+synchonized||synchronized
+syncronize||synchronize
+syncronized||synchronized
+syncronizing||synchronizing
+syncronus||synchronous
+syste||system
+sytem||system
+sythesis||synthesis
+taht||that
+targetted||targeted
+targetting||targeting
+teh||the
+temorary||temporary
+temproarily||temporarily
+therfore||therefore
+thier||their
+threds||threads
+threshhold||threshold
+throught||through
+thses||these
+tiggered||triggered
+tipically||typically
+timout||timeout
+tmis||this
+torerable||tolerable
+tramsmitted||transmitted
+tramsmit||transmit
+tranfer||transfer
+transciever||transceiver
+transferd||transferred
+transfered||transferred
+transfering||transferring
+transision||transition
+transmittd||transmitted
+transormed||transformed
+trasfer||transfer
+trasmission||transmission
+treshold||threshold
+trigerring||triggering
+trun||turn
+ture||true
+tyep||type
+udpate||update
+uesd||used
+uncommited||uncommitted
+unconditionaly||unconditionally
+underun||underrun
+unecessary||unnecessary
+unexecpted||unexpected
+unexepected||unexpected
+unexpcted||unexpected
+unexpectd||unexpected
+unexpeted||unexpected
+unexpexted||unexpected
+unfortunatelly||unfortunately
+unifiy||unify
+unintialized||uninitialized
+unkmown||unknown
+unknonw||unknown
+unknow||unknown
+unkown||unknown
+unneded||unneeded
+unneedingly||unnecessarily
+unnsupported||unsupported
+unmached||unmatched
+unregester||unregister
+unresgister||unregister
+unrgesiter||unregister
+unsinged||unsigned
+unstabel||unstable
+unsolicitied||unsolicited
+unsuccessfull||unsuccessful
+unsuported||unsupported
+untill||until
+unuseful||useless
+upate||update
+usefule||useful
+usefull||useful
+usege||usage
+usera||users
+usualy||usually
+utilites||utilities
+utillities||utilities
+utilties||utilities
+utiltity||utility
+utitity||utility
+utitlty||utility
+vaid||valid
+vaild||valid
+valide||valid
+variantions||variations
+varible||variable
+varient||variant
+vaule||value
+verbse||verbose
+verisons||versions
+verison||version
+verson||version
+vicefersa||vice-versa
+virtal||virtual
+virtaul||virtual
+virtiual||virtual
+visiters||visitors
+vitual||virtual
+wakeus||wakeups
+wating||waiting
+wether||whether
+whataver||whatever
+whcih||which
+whenver||whenever
+wheter||whether
+whe||when
+wierd||weird
+wiil||will
+wirte||write
+withing||within
+wnat||want
+workarould||workaround
+writeing||writing
+writting||writing
+zombe||zombie
+zomebie||zombie
diff --git a/test/dm/eth.c b/test/dm/eth.c
index 122fab9..67fd660 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -110,6 +110,7 @@
 	char ethaddr[DM_TEST_ETH_NUM][18];
 	int i;
 
+	memset(ethaddr, '\0', sizeof(ethaddr));
 	net_ping_ip = string_to_ip("1.1.2.2");
 
 	/* Prepare the test scenario */
@@ -119,7 +120,7 @@
 		ut_assertok(device_remove(dev[i], DM_REMOVE_NORMAL));
 
 		/* Invalidate MAC address */
-		strcpy(ethaddr[i], env_get(addrname[i]));
+		strncpy(ethaddr[i], env_get(addrname[i]), 17);
 		/* Must disable access protection for ethaddr before clearing */
 		env_set(".flags", addrname[i]);
 		env_set(addrname[i], NULL);
@@ -187,7 +188,8 @@
 	net_ping_ip = string_to_ip("1.1.2.2");
 
 	/* Invalidate eth1's MAC address */
-	strcpy(ethaddr, env_get("eth1addr"));
+	memset(ethaddr, '\0', sizeof(ethaddr));
+	strncpy(ethaddr, env_get("eth1addr"), 17);
 	/* Must disable access protection for eth1addr before clearing */
 	env_set(".flags", "eth1addr");
 	env_set("eth1addr", NULL);
@@ -200,7 +202,7 @@
 
 	if (!retval) {
 		/* Invalidate eth0's MAC address */
-		strcpy(ethaddr, env_get("ethaddr"));
+		strncpy(ethaddr, env_get("ethaddr"), 17);
 		/* Must disable access protection for ethaddr before clearing */
 		env_set(".flags", "ethaddr");
 		env_set("ethaddr", NULL);
diff --git a/test/dm/usb.c b/test/dm/usb.c
index b46ae60..4fd249b 100644
--- a/test/dm/usb.c
+++ b/test/dm/usb.c
@@ -99,10 +99,10 @@
 	return count;
 }
 
-/* test that we can remove an emulated device and it is then not found */
-static int dm_test_usb_remove(struct unit_test_state *uts)
+/* test that no USB devices are found after we stop the stack */
+static int dm_test_usb_stop(struct unit_test_state *uts)
 {
-	struct udevice *dev, *emul;
+	struct udevice *dev;
 
 	/* Scan and check that all devices are present */
 	state_set_skip_delays(true);
@@ -112,164 +112,11 @@
 	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
 	ut_asserteq(6, count_usb_devices());
 	ut_assertok(usb_stop());
-	ut_asserteq(6, count_usb_devices());
-
-	/* Remove the second emulation device */
-	ut_assertok(uclass_find_device_by_name(UCLASS_USB_EMUL, "flash-stick@1",
-					       &dev));
-	ut_assertok(device_unbind(dev));
-
-	/* Rescan - only the first and third should be present */
-	ut_assertok(usb_init());
-	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
-	ut_assertok(usb_emul_find_for_dev(dev, &emul));
-	ut_asserteq_str("flash-stick@0", emul->name);
-	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
-	ut_assertok(usb_emul_find_for_dev(dev, &emul));
-	ut_asserteq_str("flash-stick@2", emul->name);
-
-	ut_asserteq(-ENODEV, uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
-
-	ut_asserteq(5, count_usb_devices());
-	ut_assertok(usb_stop());
-	ut_asserteq(5, count_usb_devices());
+	ut_asserteq(0, count_usb_devices());
 
 	return 0;
 }
-DM_TEST(dm_test_usb_remove, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-
-const char usb_tree_base[] =
-"  1  Hub (12 Mb/s, 100mA)\n"
-"  |  sandbox hub 2345\n"
-"  |\n"
-"  |\b+-2  Mass Storage (12 Mb/s, 100mA)\n"
-"  |    sandbox flash flash-stick@0\n"
-"  |  \n"
-"  |\b+-3  Mass Storage (12 Mb/s, 100mA)\n"
-"  |    sandbox flash flash-stick@1\n"
-"  |  \n"
-"  |\b+-4  Mass Storage (12 Mb/s, 100mA)\n"
-"  |    sandbox flash flash-stick@2\n"
-"  |  \n"
-"  |\b+-5  Human Interface (12 Mb/s, 100mA)\n"
-"       sandbox keyboard keyb@3\n"
-"     \n";
-
-/* test that the 'usb tree' command output looks correct */
-static int dm_test_usb_tree(struct unit_test_state *uts)
-{
-	char *data;
-	int len;
-
-	state_set_skip_delays(true);
-	ut_assertok(usb_init());
-	console_record_reset_enable();
-	usb_show_tree();
-	len = membuff_getraw(&gd->console_out, -1, true, &data);
-	if (len)
-		data[len] = '\0';
-	ut_asserteq_str(usb_tree_base, data);
-	ut_assertok(usb_stop());
-
-	return 0;
-}
-DM_TEST(dm_test_usb_tree, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-
-const char usb_tree_remove[] =
-"  1  Hub (12 Mb/s, 100mA)\n"
-"  |  sandbox hub 2345\n"
-"  |\n"
-"  |\b+-2  Mass Storage (12 Mb/s, 100mA)\n"
-"  |    sandbox flash flash-stick@0\n"
-"  |  \n"
-"  |\b+-3  Mass Storage (12 Mb/s, 100mA)\n"
-"  |    sandbox flash flash-stick@2\n"
-"  |  \n"
-"  |\b+-4  Human Interface (12 Mb/s, 100mA)\n"
-"       sandbox keyboard keyb@3\n"
-"     \n";
-
-/*
- * test that the 'usb tree' command output looks correct when we remove a
- * device
- */
-static int dm_test_usb_tree_remove(struct unit_test_state *uts)
-{
-	struct udevice *dev;
-	char *data;
-	int len;
-
-	/* Remove the second emulation device */
-	ut_assertok(uclass_find_device_by_name(UCLASS_USB_EMUL, "flash-stick@1",
-					       &dev));
-	ut_assertok(device_unbind(dev));
-
-	state_set_skip_delays(true);
-	ut_assertok(usb_init());
-	console_record_reset_enable();
-	usb_show_tree();
-	len = membuff_getraw(&gd->console_out, -1, true, &data);
-	if (len)
-		data[len] = '\0';
-	ut_asserteq_str(usb_tree_remove, data);
-	ut_assertok(usb_stop());
-
-	return 0;
-}
-DM_TEST(dm_test_usb_tree_remove, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-
-const char usb_tree_reorder[] =
-"  1  Hub (12 Mb/s, 100mA)\n"
-"  |  sandbox hub 2345\n"
-"  |\n"
-"  |\b+-2  Mass Storage (12 Mb/s, 100mA)\n"
-"  |    sandbox flash flash-stick@0\n"
-"  |  \n"
-"  |\b+-3  Mass Storage (12 Mb/s, 100mA)\n"
-"  |    sandbox flash flash-stick@2\n"
-"  |  \n"
-"  |\b+-4  Human Interface (12 Mb/s, 100mA)\n"
-"  |    sandbox keyboard keyb@3\n"
-"  |  \n"
-"  |\b+-5  Mass Storage (12 Mb/s, 100mA)\n"
-"       sandbox flash flash-stick@1\n"
-"     \n";
-
-/*
- * test that the 'usb tree' command output looks correct when we reorder two
- * devices.
- */
-static int dm_test_usb_tree_reorder(struct unit_test_state *uts)
-{
-	struct udevice *dev, *parent;
-	char *data;
-	int len;
-
-	/* Remove the second emulation device */
-	ut_assertok(uclass_find_device_by_name(UCLASS_USB_EMUL, "flash-stick@1",
-					       &dev));
-	parent = dev->parent;
-
-	/* Reorder the devices in the parent list and uclass list */
-	list_del(&dev->sibling_node);
-	list_add_tail(&dev->sibling_node, &parent->child_head);
-
-	list_del(&dev->uclass_node);
-	list_add_tail(&dev->uclass_node, &dev->uclass->dev_head);
-
-	state_set_skip_delays(true);
-	ut_assertok(usb_init());
-	console_record_reset_enable();
-	usb_show_tree();
-	len = membuff_getraw(&gd->console_out, -1, true, &data);
-	if (len)
-		data[len] = '\0';
-	ut_asserteq_str(usb_tree_reorder, data);
-	ut_assertok(usb_stop());
-
-	return 0;
-}
-DM_TEST(dm_test_usb_tree_reorder, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+DM_TEST(dm_test_usb_stop, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
 
 static int dm_test_usb_keyb(struct unit_test_state *uts)
 {
diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index b194864..20d5dd8 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -9,14 +9,18 @@
 # It currently tests the fs/sb and native commands for ext4 and fat partitions
 # Expected results are as follows:
 # EXT4 tests:
-# fs-test.sb.ext4.out: Summary: PASS: 23 FAIL: 0
-# fs-test.ext4.out: Summary: PASS: 23 FAIL: 0
-# fs-test.fs.ext4.out: Summary: PASS: 23 FAIL: 0
-# FAT tests:
-# fs-test.sb.fat.out: Summary: PASS: 23 FAIL: 0
-# fs-test.fat.out: Summary: PASS: 20 FAIL: 3
-# fs-test.fs.fat.out: Summary: PASS: 20 FAIL: 3
-# Total Summary: TOTAL PASS: 132 TOTAL FAIL: 6
+# fs-test.sb.ext4.out: Summary: PASS: 24 FAIL: 0
+# fs-test.ext4.out: Summary: PASS: 24 FAIL: 0
+# fs-test.fs.ext4.out: Summary: PASS: 24 FAIL: 0
+# FAT16 tests:
+# fs-test.sb.fat16.out: Summary: PASS: 24 FAIL: 0
+# fs-test.fat16.out: Summary: PASS: 21 FAIL: 3
+# fs-test.fs.fat16.out: Summary: PASS: 21 FAIL: 3
+# FAT32 tests:
+# fs-test.sb.fat32.out: Summary: PASS: 24 FAIL: 0
+# fs-test.fat32.out: Summary: PASS: 21 FAIL: 3
+# fs-test.fs.fat32.out: Summary: PASS: 21 FAIL: 3
+# Total Summary: TOTAL PASS: 204 TOTAL FAIL: 12
 
 # pre-requisite binaries list.
 PREREQ_BINS="md5sum mkfs mount umount dd fallocate mkdir"
@@ -41,7 +45,7 @@
 BIG_FILE="2.5GB.file"
 
 # $MD5_FILE will have the expected md5s when we do the test
-# They shall have a suffix which represents their file system (ext4/fat)
+# They shall have a suffix which represents their file system (ext4/fat16/...)
 MD5_FILE="${OUT_DIR}/md5s.list"
 
 # $OUT shall be the prefix of the test output. Their suffix will be .out
@@ -104,15 +108,25 @@
 }
 
 # 1st parameter is the name of the image file to be created
-# 2nd parameter is the filesystem - fat ext4 etc
+# 2nd parameter is the filesystem - fat16 ext4 etc
 # -F cant be used with fat as it means something else.
 function create_image() {
 	# Create image if not already present - saves time, while debugging
-	if [ "$2" = "ext4" ]; then
+	case "$2" in
+		fat16)
+		MKFS_OPTION="-F 16"
+		FS_TYPE="fat"
+		;;
+		fat32)
+		MKFS_OPTION="-F 32"
+		FS_TYPE="fat"
+		;;
+		ext4)
 		MKFS_OPTION="-F"
-	else
-		MKFS_OPTION=""
-	fi
+		FS_TYPE="ext4"
+		;;
+	esac
+
 	if [ ! -f "$1" ]; then
 		fallocate -l 3G "$1" &> /dev/null
 		if [ $? -ne 0 ]; then
@@ -123,8 +137,8 @@
 				exit $?
 			fi
 		fi
-		mkfs -t "$2" $MKFS_OPTION "$1" &> /dev/null
-		if [ $? -ne 0 -a "$2" = "fat" ]; then
+		mkfs -t "$FS_TYPE" $MKFS_OPTION "$1" &> /dev/null
+		if [ $? -ne 0 -a "$FS_TYPE" = "fat" ]; then
 			# If we fail and we did fat, try vfat.
 			mkfs -t vfat $MKFS_OPTION "$1" &> /dev/null
 		fi
@@ -136,7 +150,7 @@
 }
 
 # 1st parameter is image file
-# 2nd parameter is file system type - fat/ext4
+# 2nd parameter is file system type - fat16/ext4/...
 # 3rd parameter is name of small file
 # 4th parameter is name of big file
 # 5th parameter is fs/nonfs/sb - to dictate generic fs commands or
@@ -149,7 +163,7 @@
 	length="0x00100000"
 
 	case "$2" in
-		fat)
+		fat*)
 		FPATH=""
 		PREFIX="fat"
 		WRITE="write"
@@ -215,10 +229,14 @@
 # We want ${PREFIX}size host 0:0 $3 for host commands and
 # sb size hostfs - $3 for hostfs commands.
 # 1MB is 0x0010 0000
-# Test Case 2 - size of small file
+# Test Case 2a - size of small file
 ${PREFIX}size host${SUFFIX} ${FPATH}$FILE_SMALL
 printenv filesize
 setenv filesize
+# Test Case 2b - size of small file via a path using '..'
+${PREFIX}size host${SUFFIX} ${FPATH}SUBDIR/../$FILE_SMALL
+printenv filesize
+setenv filesize
 
 # 2.5GB (1024*1024*2500) is 0x9C40 0000
 # Test Case 3 - size of big file
@@ -333,6 +351,9 @@
 	mkdir -p "$MOUNT_DIR"
 	sudo mount -o loop,rw "$1" "$MOUNT_DIR"
 
+	# Create a subdirectory.
+	sudo mkdir -p "$MOUNT_DIR/SUBDIR"
+
 	# Create big file in this image.
 	# Note that we work only on the start 1MB, couple MBs in the 2GB range
 	# and the last 1 MB of the huge 2.5GB file.
@@ -439,16 +460,19 @@
 	FAIL=0
 
 	# Check if the ls is showing correct results for 2.5 gb file
-	grep -A6 "Test Case 1 " "$1" | egrep -iq "2621440000 *$4"
+	grep -A7 "Test Case 1 " "$1" | egrep -iq "2621440000 *$4"
 	pass_fail "TC1: ls of $4"
 
 	# Check if the ls is showing correct results for 1 mb file
-	grep -A6 "Test Case 1 " "$1" | egrep -iq "1048576 *$3"
+	grep -A7 "Test Case 1 " "$1" | egrep -iq "1048576 *$3"
 	pass_fail "TC1: ls of $3"
 
 	# Check size command on 1MB.file
-	egrep -A3 "Test Case 2 " "$1" | grep -q "filesize=100000"
+	egrep -A3 "Test Case 2a " "$1" | grep -q "filesize=100000"
 	pass_fail "TC2: size of $3"
+	# Check size command on 1MB.file via a path using '..'
+	egrep -A3 "Test Case 2b " "$1" | grep -q "filesize=100000"
+	pass_fail "TC2: size of $3 via a path using '..'"
 
 	# Check size command on 2.5GB.file
 	egrep -A3 "Test Case 3 " "$1" | grep -q "filesize=9c400000"
@@ -550,7 +574,7 @@
 # In each loop, for a given file system image, we test both the
 # fs command, like load/size/write, the file system specific command
 # like: ext4load/ext4size/ext4write and the sb load/ls/save commands.
-for fs in ext4 fat; do
+for fs in ext4 fat16 fat32; do
 
 	echo "Creating $fs image if not already present."
 	IMAGE=${IMG}.${fs}.img
@@ -563,11 +587,14 @@
 
 	# Lets mount the image and test sb hostfs commands
 	mkdir -p "$MOUNT_DIR"
-	if [ "$fs" = "fat" ]; then
+	case "$fs" in
+		fat*)
 		uid="uid=`id -u`"
-	else
+		;;
+		*)
 		uid=""
-	fi
+		;;
+	esac
 	sudo mount -o loop,rw,$uid "$IMAGE" "$MOUNT_DIR"
 	sudo chmod 777 "$MOUNT_DIR"
 
diff --git a/test/overlay/cmd_ut_overlay.c b/test/overlay/cmd_ut_overlay.c
index 24891ee..c730a11 100644
--- a/test/overlay/cmd_ut_overlay.c
+++ b/test/overlay/cmd_ut_overlay.c
@@ -226,6 +226,7 @@
 	void *fdt_overlay = &__dtb_test_fdt_overlay_begin;
 	void *fdt_overlay_stacked = &__dtb_test_fdt_overlay_stacked_begin;
 	void *fdt_base_copy, *fdt_overlay_copy, *fdt_overlay_stacked_copy;
+	int ret = -ENOMEM;
 
 	uts = calloc(1, sizeof(*uts));
 	if (!uts)
@@ -236,16 +237,16 @@
 
 	fdt_base_copy = malloc(FDT_COPY_SIZE);
 	if (!fdt_base_copy)
-		return -ENOMEM;
+		goto err1;
 	uts->priv = fdt_base_copy;
 
 	fdt_overlay_copy = malloc(FDT_COPY_SIZE);
 	if (!fdt_overlay_copy)
-		return -ENOMEM;
+		goto err2;
 
 	fdt_overlay_stacked_copy = malloc(FDT_COPY_SIZE);
 	if (!fdt_overlay_stacked_copy)
-		return -ENOMEM;
+		goto err3;
 
 	/*
 	 * Resize the FDT to 4k so that we have room to operate on
@@ -293,11 +294,18 @@
 	}
 
 	printf("Failures: %d\n", uts->fail_count);
+	if (!uts->fail_count)
+		ret = 0;
+	else
+		ret = CMD_RET_FAILURE;
 
 	free(fdt_overlay_stacked_copy);
+err3:
 	free(fdt_overlay_copy);
+err2:
 	free(fdt_base_copy);
+err1:
 	free(uts);
 
-	return uts->fail_count ? CMD_RET_FAILURE : 0;
+	return ret;
 }
diff --git a/test/py/README.md b/test/py/README.md
index 829c7ef..ea4b66a 100644
--- a/test/py/README.md
+++ b/test/py/README.md
@@ -22,12 +22,17 @@
 the appropriate time.
 
 On Debian or Debian-like distributions, the following packages are required.
-Similar package names should exist in other distributions.
+Some packages are required to execute any test, and others only for specific
+tests. Similar package names should exist in other distributions.
 
 | Package        | Version tested (Ubuntu 14.04) |
 | -------------- | ----------------------------- |
 | python         | 2.7.5-5ubuntu3                |
 | python-pytest  | 2.5.1-1                       |
+| gdisk          | 0.8.8-1ubuntu0.1              |
+| dfu-util       | 0.5-1                         |
+| dtc            | 1.4.0+dfsg-1                  |
+| openssl        | 1.0.1f-1ubuntu2.22            |
 
 The test script supports either:
 
diff --git a/test/py/conftest.py b/test/py/conftest.py
index 65e1d75..6e66a48 100644
--- a/test/py/conftest.py
+++ b/test/py/conftest.py
@@ -429,12 +429,12 @@
     for board in mark.args:
         if board.startswith('!'):
             if ubconfig.board_type == board[1:]:
-                pytest.skip('board not supported')
+                pytest.skip('board "%s" not supported' % ubconfig.board_type)
                 return
         else:
             required_boards.append(board)
     if required_boards and ubconfig.board_type not in required_boards:
-        pytest.skip('board not supported')
+        pytest.skip('board "%s" not supported' % ubconfig.board_type)
 
 def setup_buildconfigspec(item):
     """Process any 'buildconfigspec' marker for a test.
@@ -455,7 +455,35 @@
         return
     for option in mark.args:
         if not ubconfig.buildconfig.get('config_' + option.lower(), None):
-            pytest.skip('.config feature not enabled')
+            pytest.skip('.config feature "%s" not enabled' % option.lower())
+
+def tool_is_in_path(tool):
+    for path in os.environ["PATH"].split(os.pathsep):
+        fn = os.path.join(path, tool)
+        if os.path.isfile(fn) and os.access(fn, os.X_OK):
+            return True
+    return False
+
+def setup_requiredtool(item):
+    """Process any 'requiredtool' marker for a test.
+
+    Such a marker lists some external tool (binary, executable, application)
+    that the test requires. If tests are being executed on a system that
+    doesn't have the required tool, the test is marked to be skipped.
+
+    Args:
+        item: The pytest test item.
+
+    Returns:
+        Nothing.
+    """
+
+    mark = item.get_marker('requiredtool')
+    if not mark:
+        return
+    for tool in mark.args:
+        if not tool_is_in_path(tool):
+            pytest.skip('tool "%s" not in $PATH' % tool)
 
 def start_test_section(item):
     anchors[item.name] = log.start_section(item.name)
@@ -476,6 +504,7 @@
     start_test_section(item)
     setup_boardspec(item)
     setup_buildconfigspec(item)
+    setup_requiredtool(item)
 
 def pytest_runtest_protocol(item, nextitem):
     """pytest hook: Called to execute a test.
diff --git a/test/py/multiplexed_log.py b/test/py/multiplexed_log.py
index bf926c3..5bc1bc4 100644
--- a/test/py/multiplexed_log.py
+++ b/test/py/multiplexed_log.py
@@ -365,13 +365,13 @@
 
         self._terminate_stream()
         self.f.write('<div class="' + note_type + '">\n')
-        if anchor:
-            self.f.write('<a href="#%s">\n' % anchor)
         self.f.write('<pre>')
-        self.f.write(self._escape(msg))
-        self.f.write('\n</pre>\n')
         if anchor:
-            self.f.write('</a>\n')
+            self.f.write('<a href="#%s">' % anchor)
+        self.f.write(self._escape(msg))
+        if anchor:
+            self.f.write('</a>')
+        self.f.write('\n</pre>\n')
         self.f.write('</div>\n')
 
     def start_section(self, marker, anchor=None):
diff --git a/test/py/tests/test_dfu.py b/test/py/tests/test_dfu.py
index fba67d5..8f6877c 100644
--- a/test/py/tests/test_dfu.py
+++ b/test/py/tests/test_dfu.py
@@ -113,6 +113,7 @@
 first_usb_dev_port = None
 
 @pytest.mark.buildconfigspec('cmd_dfu')
+@pytest.mark.requiredtool('dfu-util')
 def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
     """Test the "dfu" command; the host system must be able to enumerate a USB
     device when "dfu" is running, various DFU transfers are tested, and the
diff --git a/test/py/tests/test_efi_selftest.py b/test/py/tests/test_efi_selftest.py
new file mode 100644
index 0000000..76e282a
--- /dev/null
+++ b/test/py/tests/test_efi_selftest.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+# Copyright (c) 2017, Heinrich Schuchardt <xypron.glpk@gmx.de>
+#
+# SPDX-License-Identifier: GPL-2.0
+
+# Test efi API implementation
+
+import pytest
+import u_boot_utils
+
+@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
+def test_efi_selftest(u_boot_console):
+	"""
+	Run bootefi selftest
+	"""
+
+	u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False)
+	m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key'])
+	if m != 0:
+		raise Exception('Failures occured during the EFI selftest')
+	u_boot_console.run_command(cmd='', wait_for_echo=False, wait_for_prompt=False);
+	m = u_boot_console.p.expect(['resetting', 'U-Boot'])
+	if m != 0:
+		raise Exception('Reset failed during the EFI selftest')
+	u_boot_console.restart_uboot();
diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py
index 7e6b96d..4b32bb1 100755
--- a/test/py/tests/test_fit.py
+++ b/test/py/tests/test_fit.py
@@ -111,6 +111,7 @@
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('fit_signature')
+@pytest.mark.requiredtool('dtc')
 def test_fit(u_boot_console):
     def make_fname(leaf):
         """Make a temporary filename
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index e2bbd08..ec25fbb 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -38,15 +38,14 @@
             fd = os.open(self.path, os.O_RDWR | os.O_CREAT)
             os.ftruncate(fd, 4194304)
             os.close(fd)
-            sgdisk = '/sbin/sgdisk'
-            cmd = (sgdisk, '-U', '375a56f7-d6c9-4e81-b5f0-09d41ca89efe',
+            cmd = ('sgdisk', '-U', '375a56f7-d6c9-4e81-b5f0-09d41ca89efe',
                 self.path)
             u_boot_utils.run_and_log(u_boot_console, cmd)
-            cmd = (sgdisk, '--new=1:2048:2560', self.path)
+            cmd = ('sgdisk', '--new=1:2048:2560', self.path)
             u_boot_utils.run_and_log(u_boot_console, cmd)
-            cmd = (sgdisk, '--new=2:4096:4608', self.path)
+            cmd = ('sgdisk', '--new=2:4096:4608', self.path)
             u_boot_utils.run_and_log(u_boot_console, cmd)
-            cmd = (sgdisk, '-l', self.path)
+            cmd = ('sgdisk', '-l', self.path)
             u_boot_utils.run_and_log(u_boot_console, cmd)
 
 gtdi = None
@@ -64,6 +63,7 @@
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.requiredtool('sgdisk')
 def test_gpt_guid(state_disk_image, u_boot_console):
     """Test the gpt guid command."""
 
@@ -73,6 +73,7 @@
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.requiredtool('sgdisk')
 def test_gpt_save_guid(state_disk_image, u_boot_console):
     """Test the gpt guid command to save GUID into a string."""
 
@@ -86,6 +87,7 @@
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.buildconfigspec('cmd_gpt_rename')
+@pytest.mark.requiredtool('sgdisk')
 def test_gpt_rename_partition(state_disk_image, u_boot_console):
     """Test the gpt rename command to write partition names."""
 
@@ -101,6 +103,7 @@
 @pytest.mark.buildconfigspec('cmd_gpt')
 @pytest.mark.buildconfigspec('cmd_gpt_rename')
 @pytest.mark.buildconfigspec('cmd_part')
+@pytest.mark.requiredtool('sgdisk')
 def test_gpt_swap_partitions(state_disk_image, u_boot_console):
     """Test the gpt swap command to exchange two partition names."""
 
diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py
index 6e62820..c4da79d 100644
--- a/test/py/tests/test_vboot.py
+++ b/test/py/tests/test_vboot.py
@@ -31,6 +31,10 @@
 
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.buildconfigspec('fit_signature')
+@pytest.mark.requiredtool('dtc')
+@pytest.mark.requiredtool('fdtget')
+@pytest.mark.requiredtool('fdtput')
+@pytest.mark.requiredtool('openssl')
 def test_vboot(u_boot_console):
     """Test verified boot signing with mkimage and verification with 'bootm'.
 
diff --git a/tools/buildman/kconfiglib.py b/tools/buildman/kconfiglib.py
index 352ad43..68b470a 100644
--- a/tools/buildman/kconfiglib.py
+++ b/tools/buildman/kconfiglib.py
@@ -73,6 +73,7 @@
 might add it in a safe way as a client API instead."""
 
 import os
+import platform
 import re
 import sys
 
@@ -137,10 +138,8 @@
         # The set of all symbols, indexed by name (a string)
         self.syms = {}
         # Python 2/3 compatibility hack. This is the only one needed.
-        if sys.version_info[0] >= 3:
-            self.syms_iter = self.syms.values
-        else:
-            self.syms_iter = self.syms.itervalues
+        self.syms_iter = self.syms.values if sys.version_info[0] >= 3 else \
+                         self.syms.itervalues
 
         # The set of all defined symbols in the configuration in the order they
         # appear in the Kconfig files. This excludes the special symbols n, m,
@@ -173,7 +172,7 @@
         self.m = register_special_symbol(TRISTATE, "m", "m")
         self.y = register_special_symbol(TRISTATE, "y", "y")
         # DEFCONFIG_LIST uses this
-        register_special_symbol(STRING, "UNAME_RELEASE", os.uname()[2])
+        register_special_symbol(STRING, "UNAME_RELEASE", platform.uname()[2])
 
         # The symbol with "option defconfig_list" set, containing a list of
         # default .config files
@@ -183,16 +182,20 @@
         self.arch = os.environ.get("ARCH")
         self.srcarch = os.environ.get("SRCARCH")
 
+        # If you set CONFIG_ in the environment, Kconfig will prefix all symbols
+        # with its value when saving the configuration, instead of using the default, "CONFIG_".
+        self.config_prefix = os.environ.get("CONFIG_")
+        if self.config_prefix is None:
+            self.config_prefix = "CONFIG_"
+
         # See Config.__init__(). We need this for get_defconfig_filename().
         self.srctree = os.environ.get("srctree")
         if self.srctree is None:
             self.srctree = "."
 
         self.filename = filename
-        if base_dir is None:
-            self.base_dir = self.srctree
-        else:
-            self.base_dir = os.path.expandvars(base_dir)
+        self.base_dir = self.srctree if base_dir is None else \
+                        os.path.expandvars(base_dir)
 
         # The 'mainmenu' text
         self.mainmenu_text = None
@@ -222,7 +225,8 @@
         self._transform_m = None
 
         # Parse the Kconfig files
-        self.top_block = self._parse_file(filename, None, None, None)
+        self.top_block = []
+        self._parse_file(filename, None, None, None, self.top_block)
 
         # Build Symbol.dep for all symbols
         self._build_dep()
@@ -405,6 +409,10 @@
         """
 
         self._warnings = []
+        # Regular expressions for parsing .config files
+        _set_re_match = re.compile(r"{}(\w+)=(.*)".format(self.config_prefix)).match
+        _unset_re_match = re.compile(r"# {}(\w+) is not set".format(self.config_prefix)).match
+
         # Put this first so that a missing file doesn't screw up our state
         filename = os.path.expandvars(filename)
         line_feeder = _FileFeed(filename)
@@ -524,14 +532,12 @@
         with open(filename, "w") as f:
             # Write header
             if header is not None:
-                f.write(_comment(header))
-                f.write("\n")
+                f.write(_comment(header) + "\n")
 
             # Build and write configuration
             conf_strings = []
             _make_block_conf(self.top_block, conf_strings.append)
-            f.write("\n".join(conf_strings))
-            f.write("\n")
+            f.write("\n".join(conf_strings) + "\n")
 
     def eval(self, s):
         """Returns the value of the expression 's' -- where 's' is represented
@@ -609,16 +615,18 @@
     # Kconfig parsing
     #
 
-    def _parse_file(self, filename, parent, deps, visible_if_deps, res=None):
-        """Parses the Kconfig file 'filename'. Returns a list with the Items in
-        the file. See _parse_block() for the meaning of the parameters."""
-        return self._parse_block(_FileFeed(filename), None, parent, deps,
-                                 visible_if_deps, res)
+    def _parse_file(self, filename, parent, deps, visible_if_deps, block):
+        """Parses the Kconfig file 'filename'. Appends the Items in the file
+        (and any file it sources) to the list passed in the 'block' parameter.
+        See _parse_block() for the meaning of the parameters."""
+        self._parse_block(_FileFeed(filename), None, parent, deps,
+                          visible_if_deps, block)
 
     def _parse_block(self, line_feeder, end_marker, parent, deps,
-                     visible_if_deps, res=None):
+                     visible_if_deps, block):
         """Parses a block, which is the contents of either a file or an if,
-        menu, or choice statement. Returns a list with the Items in the block.
+        menu, or choice statement. Appends the Items to the list passed in the
+        'block' parameter.
 
         line_feeder: A _FileFeed instance feeding lines from a file. The
           Kconfig language is line-based in practice.
@@ -634,10 +642,7 @@
         visible_if_deps (default: None): 'visible if' dependencies from
            enclosing menus.
 
-        res (default: None): The list to add items to. If None, a new list is
-           created to hold the items."""
-
-        block = [] if res is None else res
+        block: The list to add items to."""
 
         while 1:
             # Do we already have a tokenized line that we determined wasn't
@@ -656,7 +661,7 @@
                     if end_marker is not None:
                         raise Kconfig_Syntax_Error("Unexpected end of file {0}"
                                                  .format(line_feeder.filename))
-                    return block
+                    return
 
                 tokens = self._tokenize(line, False, line_feeder.filename,
                                         line_feeder.linenr)
@@ -679,14 +684,13 @@
                 # choice statements, the choice statement takes precedence.
                 if not sym.is_defined_ or isinstance(parent, Choice):
                     sym.parent = parent
-
                 sym.is_defined_ = True
 
+                self._parse_properties(line_feeder, sym, deps, visible_if_deps)
+
                 self.kconfig_syms.append(sym)
                 block.append(sym)
 
-                self._parse_properties(line_feeder, sym, deps, visible_if_deps)
-
             elif t0 == T_SOURCE:
                 kconfig_file = tokens.get_next()
                 exp_kconfig_file = self._expand_sym_refs(kconfig_file)
@@ -705,7 +709,7 @@
 
             elif t0 == end_marker:
                 # We have reached the end of the block
-                return block
+                return
 
             elif t0 == T_IF:
                 # If statements are treated as syntactic sugar for adding
@@ -722,38 +726,39 @@
 
             elif t0 == T_COMMENT:
                 comment = Comment()
-
                 comment.config = self
                 comment.parent = parent
                 comment.filename = line_feeder.filename
                 comment.linenr = line_feeder.linenr
                 comment.text = tokens.get_next()
 
-                self.comments.append(comment)
-                block.append(comment)
-
                 self._parse_properties(line_feeder, comment, deps,
                                        visible_if_deps)
 
+                self.comments.append(comment)
+                block.append(comment)
+
             elif t0 == T_MENU:
                 menu = Menu()
-
                 menu.config = self
                 menu.parent = parent
                 menu.filename = line_feeder.filename
                 menu.linenr = line_feeder.linenr
                 menu.title = tokens.get_next()
 
-                self.menus.append(menu)
-                block.append(menu)
-
-                # Parse properties and contents
                 self._parse_properties(line_feeder, menu, deps,
                                        visible_if_deps)
-                menu.block = self._parse_block(line_feeder, T_ENDMENU, menu,
-                                               menu.dep_expr,
-                                               _make_and(visible_if_deps,
-                                                         menu.visible_if_expr))
+
+                # This needs to go before _parse_block() so that we get the
+                # proper menu ordering in the case of nested functions
+                self.menus.append(menu)
+                # Parse contents and put Items in menu.block
+                self._parse_block(line_feeder, T_ENDMENU, menu, menu.dep_expr,
+                                  _make_and(visible_if_deps,
+                                            menu.visible_if_expr),
+                                  menu.block)
+
+                block.append(menu)
 
             elif t0 == T_CHOICE:
                 name = tokens.get_next()
@@ -775,11 +780,12 @@
                 choice.def_locations.append((line_feeder.filename,
                                              line_feeder.linenr))
 
-                # Parse properties and contents
                 self._parse_properties(line_feeder, choice, deps,
                                        visible_if_deps)
-                choice.block = self._parse_block(line_feeder, T_ENDCHOICE,
-                                                 choice, deps, visible_if_deps)
+
+                # Parse contents and put Items in choice.block
+                self._parse_block(line_feeder, T_ENDCHOICE, choice, deps,
+                                  visible_if_deps, choice.block)
 
                 choice._determine_actual_symbols()
 
@@ -819,19 +825,19 @@
             """Parses '<expr1> if <expr2>' constructs, where the 'if' part is
             optional. Returns a tuple containing the parsed expressions, with
             None as the second element if the 'if' part is missing."""
-            val = self._parse_expr(tokens, stmt, line, filename, linenr, False)
-            if tokens.check(T_IF):
-                return (val, self._parse_expr(tokens, stmt, line, filename,
-                                              linenr))
-            return (val, None)
+            return (self._parse_expr(tokens, stmt, line, filename, linenr,
+                                     False),
+                    self._parse_expr(tokens, stmt, line, filename, linenr)
+                    if tokens.check(T_IF) else None)
 
         # In case the symbol is defined in multiple locations, we need to
-        # remember what prompts, defaults, and selects are new for this
-        # definition, as "depends on" should only apply to the local
+        # remember what prompts, defaults, selects, and implies are new for
+        # this definition, as "depends on" should only apply to the local
         # definition.
         new_prompt = None
         new_def_exprs = []
         new_selects = []
+        new_implies = []
 
         # Dependencies from 'depends on' statements
         depends_on_expr = None
@@ -897,18 +903,27 @@
 
                 line_feeder.unget()
 
-            elif t0 == T_SELECT or t0 == T_IMPLY:
+            elif t0 == T_SELECT:
                 target = tokens.get_next()
 
                 stmt.referenced_syms.add(target)
                 stmt.selected_syms.add(target)
 
-                if tokens.check(T_IF):
-                    new_selects.append((target,
-                                        self._parse_expr(tokens, stmt, line,
-                                                         filename, linenr)))
-                else:
-                    new_selects.append((target, None))
+                new_selects.append(
+                    (target,
+                     self._parse_expr(tokens, stmt, line, filename, linenr)
+                     if tokens.check(T_IF) else None))
+
+            elif t0 == T_IMPLY:
+                target = tokens.get_next()
+
+                stmt.referenced_syms.add(target)
+                stmt.implied_syms.add(target)
+
+                new_implies.append(
+                    (target,
+                     self._parse_expr(tokens, stmt, line, filename, linenr)
+                     if tokens.check(T_IF) else None))
 
             elif t0 in (T_BOOL, T_TRISTATE, T_INT, T_HEX, T_STRING):
                 stmt.type = TOKEN_TO_TYPE[t0]
@@ -939,12 +954,10 @@
                 stmt.referenced_syms.add(low)
                 stmt.referenced_syms.add(high)
 
-                if tokens.check(T_IF):
-                    stmt.ranges.append((low, high,
-                                        self._parse_expr(tokens, stmt, line,
-                                                         filename, linenr)))
-                else:
-                    stmt.ranges.append((low, high, None))
+                stmt.ranges.append(
+                    (low, high,
+                     self._parse_expr(tokens, stmt, line, filename, linenr)
+                     if tokens.check(T_IF) else None))
 
             elif t0 == T_DEF_TRISTATE:
                 stmt.type = TRISTATE
@@ -1051,21 +1064,20 @@
             # Symbol or Choice
 
             # See comment for 'menu_dep'
-            stmt.menu_dep = depends_on_expr
+            stmt.menu_dep = _make_and(deps, depends_on_expr)
 
             # Propagate dependencies to prompts
 
             if new_prompt is not None:
-                # Propagate 'visible if' dependencies from enclosing menus
                 prompt, cond_expr = new_prompt
-                cond_expr = _make_and(cond_expr, visible_if_deps)
-                # Propagate 'depends on' dependencies
-                new_prompt = (prompt, _make_and(cond_expr, depends_on_expr))
+                # Propagate 'visible if' dependencies from menus and local
+                # 'depends on' dependencies
+                cond_expr = _make_and(_make_and(cond_expr, visible_if_deps),
+                                      depends_on_expr)
                 # Save original
-                stmt.orig_prompts.append(new_prompt)
+                stmt.orig_prompts.append((prompt, cond_expr))
                 # Finalize with dependencies from enclosing menus and ifs
-                stmt.prompts.append((new_prompt[0],
-                                     _make_and(new_prompt[1], deps)))
+                stmt.prompts.append((prompt, _make_and(cond_expr, deps)))
 
             # Propagate dependencies to defaults
 
@@ -1078,20 +1090,27 @@
             stmt.def_exprs.extend([(val_expr, _make_and(cond_expr, deps))
                                    for val_expr, cond_expr in new_def_exprs])
 
-            # Propagate dependencies to selects
+            # Propagate dependencies to selects and implies
 
-            # Only symbols can select
+            # Only symbols can select and imply
             if isinstance(stmt, Symbol):
                 # Propagate 'depends on' dependencies
                 new_selects = [(target, _make_and(cond_expr, depends_on_expr))
                                for target, cond_expr in new_selects]
+                new_implies = [(target, _make_and(cond_expr, depends_on_expr))
+                               for target, cond_expr in new_implies]
                 # Save original
                 stmt.orig_selects.extend(new_selects)
+                stmt.orig_implies.extend(new_implies)
                 # Finalize with dependencies from enclosing menus and ifs
                 for target, cond in new_selects:
-                    target.rev_dep = _make_or(target.rev_dep,
-                                              _make_and(stmt,
-                                                        _make_and(cond, deps)))
+                    target.rev_dep = \
+                        _make_or(target.rev_dep,
+                                 _make_and(stmt, _make_and(cond, deps)))
+                for target, cond in new_implies:
+                    target.weak_rev_dep = \
+                        _make_or(target.weak_rev_dep,
+                                 _make_and(stmt, _make_and(cond, deps)))
 
     def _parse_expr(self, feed, cur_item, line, filename=None, linenr=None,
                     transform_m=True):
@@ -1483,7 +1502,8 @@
 
         # The directly dependent symbols of a symbol are:
         #  - Any symbols whose prompts, default values, rev_dep (select
-        #    condition), or ranges depend on the symbol
+        #    condition), weak_rev_dep (imply condition) or ranges depend on the
+        #    symbol
         #  - Any symbols that belong to the same choice statement as the symbol
         #    (these won't be included in 'dep' as that makes the dependency
         #    graph unwieldy, but Symbol._get_dependent() will include them)
@@ -1497,6 +1517,7 @@
                 add_expr_deps(e, sym)
 
             add_expr_deps(sym.rev_dep, sym)
+            add_expr_deps(sym.weak_rev_dep, sym)
 
             for l, u, e in sym.ranges:
                 add_expr_deps(l, sym)
@@ -1625,20 +1646,16 @@
         else:
             prompts_str_rows = []
             for prompt, cond_expr in sc.orig_prompts:
-                if cond_expr is None:
-                    prompts_str_rows.append(' "{0}"'.format(prompt))
-                else:
-                    prompts_str_rows.append(
-                      ' "{0}" if {1}'.format(prompt,
-                                             self._expr_val_str(cond_expr)))
+                prompts_str_rows.append(
+                    ' "{0}"'.format(prompt) if cond_expr is None else
+                    ' "{0}" if {1}'.format(prompt,
+                                           self._expr_val_str(cond_expr)))
             prompts_str = "\n".join(prompts_str_rows)
 
         # Build locations string
-        if not sc.def_locations:
-            locations_str = "(no locations)"
-        else:
-            locations_str = " ".join(["{0}:{1}".format(filename, linenr) for
-                                      (filename, linenr) in sc.def_locations])
+        locations_str = "(no locations)" if not sc.def_locations else \
+                        " ".join(["{0}:{1}".format(filename, linenr) for
+                                  filename, linenr in sc.def_locations])
 
         # Build additional-dependencies-from-menus-and-ifs string
         additional_deps_str = " " + \
@@ -1657,13 +1674,11 @@
                 else:
                     ranges_str_rows = []
                     for l, u, cond_expr in sc.ranges:
-                        if cond_expr is None:
-                            ranges_str_rows.append(" [{0}, {1}]".format(s(l),
-                                                                        s(u)))
-                        else:
-                            ranges_str_rows.append(" [{0}, {1}] if {2}"
-                              .format(s(l), s(u),
-                                      self._expr_val_str(cond_expr)))
+                        ranges_str_rows.append(
+                            " [{0}, {1}]".format(s(l), s(u))
+                            if cond_expr is None else
+                            " [{0}, {1}] if {2}"
+                            .format(s(l), s(u), self._expr_val_str(cond_expr)))
                     ranges_str = "\n".join(ranges_str_rows)
 
             # Build default values string
@@ -1685,14 +1700,24 @@
             else:
                 selects_str_rows = []
                 for target, cond_expr in sc.orig_selects:
-                    if cond_expr is None:
-                        selects_str_rows.append(" {0}".format(target.name))
-                    else:
-                        selects_str_rows.append(
-                          " {0} if {1}".format(target.name,
-                                               self._expr_val_str(cond_expr)))
+                    selects_str_rows.append(
+                        " {0}".format(target.name) if cond_expr is None else
+                        " {0} if {1}".format(target.name,
+                                             self._expr_val_str(cond_expr)))
                 selects_str = "\n".join(selects_str_rows)
 
+            # Build implies string
+            if not sc.orig_implies:
+                implies_str = " (no implies)"
+            else:
+                implies_str_rows = []
+                for target, cond_expr in sc.orig_implies:
+                    implies_str_rows.append(
+                        " {0}".format(target.name) if cond_expr is None else
+                        " {0} if {1}".format(target.name,
+                                             self._expr_val_str(cond_expr)))
+                implies_str = "\n".join(implies_str_rows)
+
             res = _lines("Symbol " +
                            ("(no name)" if sc.name is None else sc.name),
                          "Type           : " + TYPENAME[sc.type],
@@ -1711,9 +1736,16 @@
                           defaults_str,
                           "Selects:",
                           selects_str,
+                          "Implies:",
+                          implies_str,
                           "Reverse (select-related) dependencies:",
-                          " (no reverse dependencies)" if sc.rev_dep == "n"
-                            else " " + self._expr_val_str(sc.rev_dep),
+                          " (no reverse dependencies)"
+                          if sc.rev_dep == "n"
+                          else " " + self._expr_val_str(sc.rev_dep),
+                          "Weak reverse (imply-related) dependencies:",
+                          " (no weak reverse dependencies)"
+                          if sc.weak_rev_dep == "n"
+                          else " " + self._expr_val_str(sc.weak_rev_dep),
                           "Additional dependencies from enclosing menus "
                             "and ifs:",
                           additional_deps_str,
@@ -1735,11 +1767,10 @@
         else:
             defaults_str_rows = []
             for sym, cond_expr in sc.orig_def_exprs:
-                if cond_expr is None:
-                    defaults_str_rows.append(" {0}".format(sym.name))
-                else:
-                    defaults_str_rows.append(" {0} if {1}".format(sym.name,
-                                                self._expr_val_str(cond_expr)))
+                defaults_str_rows.append(
+                    " {0}".format(sym.name) if cond_expr is None else
+                    " {0} if {1}".format(sym.name,
+                                         self._expr_val_str(cond_expr)))
             defaults_str = "\n".join(defaults_str_rows)
 
         # Build contained symbols string
@@ -1919,26 +1950,25 @@
                     self.write_to_conf = (mode != "n")
 
                     if mode == "y":
-                        if choice.get_selection() is self:
-                            new_val = "y"
-                        else:
-                            new_val = "n"
+                        new_val = "y" if choice.get_selection() is self \
+                                  else "n"
                     elif mode == "m":
                         if self.user_val == "m" or self.user_val == "y":
                             new_val = "m"
 
             else:
                 # If the symbol is visible and has a user value, use that.
-                # Otherwise, look at defaults.
-                use_defaults = True
+                # Otherwise, look at defaults and weak reverse dependencies
+                # (implies).
+                use_defaults_and_weak_rev_deps = True
 
                 if vis != "n":
                     self.write_to_conf = True
                     if self.user_val is not None:
                         new_val = self.config._eval_min(self.user_val, vis)
-                        use_defaults = False
+                        use_defaults_and_weak_rev_deps = False
 
-                if use_defaults:
+                if use_defaults_and_weak_rev_deps:
                     for val_expr, cond_expr in self.def_exprs:
                         cond_eval = self.config._eval_expr(cond_expr)
                         if cond_eval != "n":
@@ -1947,14 +1977,25 @@
                                                             cond_eval)
                             break
 
+                    weak_rev_dep_val = \
+                        self.config._eval_expr(self.weak_rev_dep)
+                    if weak_rev_dep_val != "n":
+                        self.write_to_conf = True
+                        new_val = self.config._eval_max(new_val,
+                                                        weak_rev_dep_val)
+
                 # Reverse (select-related) dependencies take precedence
                 rev_dep_val = self.config._eval_expr(self.rev_dep)
                 if rev_dep_val != "n":
                     self.write_to_conf = True
                     new_val = self.config._eval_max(new_val, rev_dep_val)
 
-            # Promote "m" to "y" for booleans
-            if new_val == "m" and self.type == BOOL:
+            # We need to promote "m" to "y" in two circumstances:
+            #  1) If our type is boolean
+            #  2) If our weak_rev_dep (from IMPLY) is "y"
+            if new_val == "m" and \
+               (self.type == BOOL or
+                self.config._eval_expr(self.weak_rev_dep) == "y"):
                 new_val = "y"
 
         elif self.type == INT or self.type == HEX:
@@ -2189,6 +2230,13 @@
         get_referenced_symbols()."""
         return self.selected_syms
 
+    def get_implied_symbols(self):
+        """Returns the set() of all symbols X for which this symbol has an
+        'imply X' or 'imply X if Y' (regardless of whether Y is satisfied or
+        not). This is a subset of the symbols returned by
+        get_referenced_symbols()."""
+        return self.implied_syms
+
     def set_user_value(self, v):
         """Sets the user value of the symbol.
 
@@ -2304,16 +2352,18 @@
         self.ranges = [] # 'range' properties (for int and hex)
         self.help = None # Help text
         self.rev_dep = "n" # Reverse (select-related) dependencies
+        self.weak_rev_dep = "n" # Weak reverse (imply-related) dependencies
         self.config = None
         self.parent = None
 
         self.user_val = None # Value set by user
 
-        # The prompt, default value and select conditions without any
+        # The prompt, default value, select, and imply conditions without any
         # dependencies from menus and ifs propagated to them
         self.orig_prompts = []
         self.orig_def_exprs = []
         self.orig_selects = []
+        self.orig_implies = []
 
         # Dependencies inherited from containing menus and ifs
         self.deps_from_containing = None
@@ -2323,13 +2373,15 @@
         # The set of symbols selected by this symbol (see
         # get_selected_symbols())
         self.selected_syms = set()
+        # The set of symbols implied by this symbol (see get_implied_symbols())
+        self.implied_syms = set()
         # Like 'referenced_syms', but includes symbols from
         # dependencies inherited from enclosing menus and ifs
         self.all_referenced_syms = set()
 
-        # This records only dependencies specified with 'depends on'. Needed
-        # when determining actual choice items (hrrrr...). See also
-        # Choice._determine_actual_symbols().
+        # This records only dependencies from enclosing ifs and menus together
+        # with local 'depends on' dependencies. Needed when determining actual
+        # choice items (hrrrr...). See Choice._determine_actual_symbols().
         self.menu_dep = None
 
         # See Symbol.get_ref/def_locations().
@@ -2470,18 +2522,17 @@
             return
 
         if self.type == BOOL or self.type == TRISTATE:
-            if val == "y" or val == "m":
-                append_fn("CONFIG_{0}={1}".format(self.name, val))
-            else:
-                append_fn("# CONFIG_{0} is not set".format(self.name))
+            append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val)
+                      if val == "y" or val == "m" else
+                      "# {0}{1} is not set".format(self.config.config_prefix, self.name))
 
         elif self.type == INT or self.type == HEX:
-            append_fn("CONFIG_{0}={1}".format(self.name, val))
+            append_fn("{0}{1}={2}".format(self.config.config_prefix, self.name, val))
 
         elif self.type == STRING:
             # Escape \ and "
-            append_fn('CONFIG_{0}="{1}"'
-                      .format(self.name,
+            append_fn('{0}{1}="{2}"'
+                      .format(self.config.config_prefix, self.name,
                               val.replace("\\", "\\\\").replace('"', '\\"')))
 
         else:
@@ -2635,7 +2686,7 @@
         self.title = None
         self.dep_expr = None
         self.visible_if_expr = None
-        self.block = None
+        self.block = [] # List of contained items
         self.config = None
         self.parent = None
 
@@ -2852,7 +2903,7 @@
         self.prompts = []
         self.def_exprs = [] # 'default' properties
         self.help = None # Help text
-        self.block = None # List of contained items
+        self.block = [] # List of contained items
         self.config = None
         self.parent = None
 
@@ -3177,7 +3228,13 @@
             vis = sc.config._eval_max(vis, cond_expr)
 
         if isinstance(sc, Symbol) and sc.is_choice_sym:
-            vis = sc.config._eval_min(vis, _get_visibility(sc.parent))
+            if sc.type == TRISTATE and vis == "m" and \
+               sc.parent.get_mode() == "y":
+                # Choice symbols with visibility "m" are not visible if the
+                # choice has mode "y"
+                vis = "n"
+            else:
+                vis = sc.config._eval_min(vis, _get_visibility(sc.parent))
 
         # Promote "m" to "y" if we're dealing with a non-tristate
         if vis == "m" and sc.type != TRISTATE:
@@ -3434,7 +3491,7 @@
    "prompt": T_PROMPT, "default": T_DEFAULT, "bool": T_BOOL, "boolean": T_BOOL,
    "tristate": T_TRISTATE, "int": T_INT, "hex": T_HEX, "def_bool": T_DEF_BOOL,
    "def_tristate": T_DEF_TRISTATE, "string": T_STRING, "select": T_SELECT,
-   "imply": T_IMPLY, "range": T_RANGE, "option": T_OPTION,
+   "imply" : T_IMPLY, "range": T_RANGE, "option": T_OPTION,
    "allnoconfig_y": T_ALLNOCONFIG_Y, "env": T_ENV,
    "defconfig_list": T_DEFCONFIG_LIST, "modules": T_MODULES,
    "visible": T_VISIBLE}.get
@@ -3455,10 +3512,6 @@
 # trailing whitespace as an optimization.
 _id_keyword_re_match = re.compile(r"\s*([\w./-]+)\s*").match
 
-# Regular expressions for parsing .config files
-_set_re_match = re.compile(r"CONFIG_(\w+)=(.*)").match
-_unset_re_match = re.compile(r"# CONFIG_(\w+) is not set").match
-
 # Regular expression for finding $-references to symbols in strings
 _sym_ref_re_search = re.compile(r"\$[A-Za-z0-9_]+").search
 
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 4dc8bd8..30257b1 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -372,7 +372,7 @@
 	if (fd < 0) {
 		fprintf(stderr, "%s: Can't open %s: %s\n",
 			params->cmdname, fname, strerror(errno));
-		goto err;
+		goto err_buf;
 	}
 	ret = write(fd, buf, size);
 	if (ret != size) {
@@ -501,6 +501,7 @@
 		ret = -EIO;
 		goto err;
 	}
+	free(buf);
 	close(fd);
 	return 0;
 
@@ -536,21 +537,21 @@
 		fprintf(stderr, "%s: Failed to allocate memory (%d bytes)\n",
 			__func__, size);
 		ret = -ENOMEM;
-		goto err;
+		goto err_has_fd;
 	}
 	ret = fdt_open_into(old_fdt, fdt, size);
 	if (ret) {
 		debug("%s: Failed to expand FIT: %s\n", __func__,
 		      fdt_strerror(errno));
 		ret = -EINVAL;
-		goto err;
+		goto err_has_fd;
 	}
 
 	images = fdt_path_offset(fdt, FIT_IMAGES_PATH);
 	if (images < 0) {
 		debug("%s: Cannot find /images node: %d\n", __func__, images);
 		ret = -EINVAL;
-		goto err;
+		goto err_has_fd;
 	}
 
 	for (node = fdt_first_subnode(fdt, images);
@@ -571,11 +572,11 @@
 			debug("%s: Failed to write property: %s\n", __func__,
 			      fdt_strerror(ret));
 			ret = -EINVAL;
-			goto err;
+			goto err_has_fd;
 		}
 	}
 
-	munmap(old_fdt, sbuf.st_size);
+	/* Close the old fd so we can re-use it. */
 	close(fd);
 
 	/* Pack the FDT and place the data after it */
@@ -588,21 +589,23 @@
 	if (fd < 0) {
 		fprintf(stderr, "%s: Can't open %s: %s\n",
 			params->cmdname, fname, strerror(errno));
-		free(fdt);
-		return -EIO;
+		ret = -EIO;
+		goto err_no_fd;
 	}
 	if (write(fd, fdt, new_size) != new_size) {
 		debug("%s: Failed to write external data to file %s\n",
 		      __func__, strerror(errno));
 		ret = -EIO;
-		goto err;
+		goto err_has_fd;
 	}
 
 	ret = 0;
 
-err:
-	free(fdt);
+err_has_fd:
 	close(fd);
+err_no_fd:
+	munmap(old_fdt, sbuf.st_size);
+	free(fdt);
 	return ret;
 }
 
diff --git a/tools/moveconfig.py b/tools/moveconfig.py
index 6f549a5..e311646 100755
--- a/tools/moveconfig.py
+++ b/tools/moveconfig.py
@@ -1472,7 +1472,7 @@
     """
     sym = kconf.get_symbol(imply_config)
     if sym:
-        for sel in sym.get_selected_symbols():
+        for sel in sym.get_selected_symbols() | sym.get_implied_symbols():
             if sel.get_name() == config:
                 return sym
     return None
diff --git a/tools/rkcommon.c b/tools/rkcommon.c
index 04e8272..1a24e16 100644
--- a/tools/rkcommon.c
+++ b/tools/rkcommon.c
@@ -73,6 +73,7 @@
 
 static struct spl_info spl_infos[] = {
 	{ "rk3036", "RK30", 0x1000, false, false },
+	{ "rk3128", "RK31", 0x1800, false, false },
 	{ "rk3188", "RK31", 0x8000 - 0x800, true, false },
 	{ "rk322x", "RK32", 0x8000 - 0x1000, false, false },
 	{ "rk3288", "RK32", 0x8000, false, false },