Merge git://git.denx.de/u-boot-fsl-qoriq
diff --git a/README b/README
index 9d351ec..075d919 100644
--- a/README
+++ b/README
@@ -827,7 +827,6 @@
 		CONFIG_CMD_BOOTI	* ARM64 Linux kernel Image support
 		CONFIG_CMD_CACHE	* icache, dcache
 		CONFIG_CMD_CONSOLE	  coninfo
-		CONFIG_CMD_CRC32	* crc32
 		CONFIG_CMD_DHCP		* DHCP support
 		CONFIG_CMD_DIAG		* Diagnostics
 		CONFIG_CMD_ECHO		  echo arguments
@@ -841,7 +840,6 @@
 					  that work for multiple fs types
 		CONFIG_CMD_FS_UUID	* Look up a filesystem UUID
 		CONFIG_CMD_SAVEENV	  saveenv
-		CONFIG_CMD_FAT		* FAT command support
 		CONFIG_CMD_FLASH	  flinfo, erase, protect
 		CONFIG_CMD_FPGA		  FPGA device initialization support
 		CONFIG_CMD_GO		* the 'go' command (exec code)
@@ -889,8 +887,6 @@
 		CONFIG_CMD_SETGETDCR	  Support for DCR Register access
 					  (4xx only)
 		CONFIG_CMD_SF		* Read/write/erase SPI NOR flash
-		CONFIG_CMD_SHA1SUM	* print sha1 memory digest
-					  (requires CONFIG_CMD_MEMORY)
 		CONFIG_CMD_SOFTSWITCH	* Soft switch setting command for BF60x
 		CONFIG_CMD_SOURCE	  "source" command Support
 		CONFIG_CMD_SPI		* SPI serial bus support
@@ -1068,8 +1064,6 @@
 - Partition Labels (disklabels) Supported:
 		Zero or more of the following:
 		CONFIG_MAC_PARTITION   Apple's MacOS partition table.
-		CONFIG_DOS_PARTITION   MS Dos partition table, traditional on the
-				       Intel architecture, USB sticks, etc.
 		CONFIG_ISO_PARTITION   ISO partition table, used on CDROM etc.
 		CONFIG_EFI_PARTITION   GPT partition table, common when EFI is the
 				       bootloader.  Note 2TB partition limit; see
@@ -1522,21 +1516,6 @@
 		CONFIG_SYS_JFFS2_FIRST_BANK, CONFIG_SYS_JFFS2_NUM_BANKS
 		Define these for a default partition on a NOR device
 
-- FAT(File Allocation Table) filesystem write function support:
-		CONFIG_FAT_WRITE
-
-		Define this to enable support for saving memory data as a
-		file in FAT formatted partition.
-
-		This will also enable the command "fatwrite" enabling the
-		user to write files to FAT.
-
-- FAT(File Allocation Table) filesystem cluster size:
-		CONFIG_FS_FAT_MAX_CLUSTSIZE
-
-		Define the max cluster size for fat operations else
-		a default value of 65536 will be defined.
-
 - Keyboard Support:
 		See Kconfig help for available keyboard drivers.
 
@@ -2679,15 +2658,6 @@
 		A better solution is to properly configure the firewall,
 		but sometimes that is not allowed.
 
-- Hashing support:
-		CONFIG_HASH_VERIFY
-
-		Enable the hash verify command (hash -v). This adds to code
-		size a little.
-
-		Note: There is also a sha1sum command, which should perhaps
-		be deprecated in favour of 'hash sha1'.
-
 - bootcount support:
 		CONFIG_BOOTCOUNT_LIMIT
 
@@ -3882,7 +3852,7 @@
          environment.
 
        - CONFIG_FAT_WRITE:
-         This should be defined. Otherwise it cannot save the environment file.
+         This must be enabled. Otherwise it cannot save the environment file.
 
 - CONFIG_ENV_IS_IN_MMC:
 
diff --git a/arch/Kconfig b/arch/Kconfig
index 02e887a..e447671 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -74,8 +74,11 @@
 	imply CMD_HASH
 	imply CMD_IO
 	imply CMD_IOTRACE
-	imply LZMA
 	imply CMD_LZMADEC
+	imply CRC32_VERIFY
+	imply FAT_WRITE
+	imply HASH_VERIFY
+	imply LZMA
 
 config SH
 	bool "SuperH architecture"
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 91f50b0..deb7b24 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -477,6 +477,7 @@
 	select DM_SERIAL
 	select DM_GPIO
 	select OF_CONTROL
+	imply FAT_WRITE
 
 config TARGET_VEXPRESS_CA15_TC2
 	bool "Support vexpress_ca15_tc2"
@@ -495,15 +496,22 @@
 config TARGET_BCM23550_W1D
 	bool "Support bcm23550_w1d"
 	select CPU_V7
+	imply CRC32_VERIFY
+	imply FAT_WRITE
 
 config TARGET_BCM28155_AP
 	bool "Support bcm28155_ap"
 	select CPU_V7
+	imply CRC32_VERIFY
+	imply FAT_WRITE
 
 config TARGET_BCMCYGNUS
 	bool "Support bcmcygnus"
 	select CPU_V7
+	imply CRC32_VERIFY
 	imply CMD_HASH
+	imply FAT_WRITE
+	imply HASH_VERIFY
 
 config TARGET_BCMNSP
 	bool "Support bcmnsp"
@@ -526,6 +534,7 @@
 	select DM_SPI
 	select DM_GPIO
 	select DM_KEYBOARD
+	imply FAT_WRITE
 
 config ARCH_S5PC1XX
 	bool "Samsung S5PC1XX"
@@ -598,6 +607,7 @@
 	select DM
 	select DM_SERIAL
 	select BOARD_EARLY_INIT_F
+	imply FAT_WRITE
 	imply SYS_THUMB_BUILD
 
 config TARGET_S32V234EVB
@@ -629,6 +639,8 @@
 	select ARCH_MISC_INIT
 	select SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
 	select SYS_THUMB_BUILD
+	imply CRC32_VERIFY
+	imply FAT_WRITE
 
 config ARCH_SUNXI
 	bool "Support sunxi (Allwinner) SoCs"
@@ -652,6 +664,7 @@
 	select USB_STORAGE if DISTRO_DEFAULTS
 	select USB_KEYBOARD if DISTRO_DEFAULTS
 	select USE_TINY_PRINTF
+	imply FAT_WRITE
 	imply PRE_CONSOLE_BUFFER
 	imply SPL_GPIO_SUPPORT
 	imply SPL_LIBCOMMON_SUPPORT
@@ -695,6 +708,7 @@
 	select SPL_CLK
 	select CLK_ZYNQ
 	imply CMD_CLK
+	imply FAT_WRITE
 
 config ARCH_ZYNQMP
 	bool "Support Xilinx ZynqMP Platform"
@@ -708,9 +722,11 @@
 	select SPL_BOARD_INIT if SPL
 	select SPL_CLK
 	select DM_USB if USB
+	imply FAT_WRITE
 
 config TEGRA
 	bool "NVIDIA Tegra"
+	imply FAT_WRITE
 
 config TARGET_VEXPRESS64_AEMV8A
 	bool "Support vexpress_aemv8a"
@@ -969,6 +985,7 @@
 	select SPL_OF_CONTROL if SPL
 	select SPL_PINCTRL if SPL
 	select SUPPORT_SPL
+	imply FAT_WRITE
 	help
 	  Support for UniPhier SoC family developed by Socionext Inc.
 	  (formerly, System LSI Business Division of Panasonic Corporation)
@@ -1011,6 +1028,7 @@
 	select DM_USB if USB
 	select DM_PWM
 	select DM_REGULATOR
+	imply FAT_WRITE
 
 config TARGET_THUNDERX_88XX
 	bool "Support ThunderX 88xx"
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
index 05c4577..f5f4840 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
@@ -79,13 +79,13 @@
 		puts("couldn't find /cpus node\n");
 		return;
 	}
-	of_bus_default_count_cells(blob, off, &addr_cells, NULL);
+	fdt_support_default_count_cells(blob, off, &addr_cells, NULL);
 
 	off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
 	while (off != -FDT_ERR_NOTFOUND) {
 		reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0);
 		if (reg) {
-			core_id = of_read_number(reg, addr_cells);
+			core_id = fdt_read_number(reg, addr_cells);
 			if (core_id  == 0 || (is_core_online(core_id))) {
 				val = spin_tbl_addr;
 				val += id_to_core(core_id) *
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 2b1a4e9..b95920a 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -309,6 +309,7 @@
 	sun8i-h3-orangepi-pc-plus.dtb \
 	sun8i-h3-orangepi-plus.dtb \
 	sun8i-h3-orangepi-plus2e.dtb \
+	sun8i-h3-nanopi-m1.dtb \
 	sun8i-h3-nanopi-neo.dtb \
 	sun8i-h3-nanopi-neo-air.dtb
 dtb-$(CONFIG_MACH_SUN8I_R40) += \
@@ -316,8 +317,10 @@
 dtb-$(CONFIG_MACH_SUN8I_V3S) += \
 	sun8i-v3s-licheepi-zero.dtb
 dtb-$(CONFIG_MACH_SUN50I_H5) += \
-	sun50i-h5-orangepi-pc2.dtb
+	sun50i-h5-orangepi-pc2.dtb \
+	sun50i-h5-orangepi-prime.dtb
 dtb-$(CONFIG_MACH_SUN50I) += \
+	sun50i-a64-bananapi-m64.dtb \
 	sun50i-a64-pine64-plus.dtb \
 	sun50i-a64-pine64.dtb
 dtb-$(CONFIG_MACH_SUN9I) += \
diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts
index 85761af..5f06252 100644
--- a/arch/arm/dts/armada-3720-db.dts
+++ b/arch/arm/dts/armada-3720-db.dts
@@ -81,11 +81,15 @@
 };
 
 &eth0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
 	status = "okay";
 	phy-mode = "rgmii";
 };
 
 &i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
 	status = "okay";
 };
 
@@ -117,6 +121,8 @@
 
 &spi0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi_quad_pins>;
 
 	spi-flash@0 {
 		#address-cells = <1>;
@@ -130,6 +136,8 @@
 
 /* Exported on the micro USB connector CON32 through an FTDI */
 &uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
 	status = "okay";
 };
 
diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi
index 5bea63b..6902342 100644
--- a/arch/arm/dts/armada-37xx.dtsi
+++ b/arch/arm/dts/armada-37xx.dtsi
@@ -106,6 +106,79 @@
 				status = "disabled";
 			};
 
+			pinctrl_nb: pinctrl-nb@13800 {
+				compatible = "marvell,armada3710-nb-pinctrl",
+				"syscon", "simple-mfd";
+				reg = <0x13800 0x100>, <0x13C00 0x20>;
+				gpionb: gpionb {
+					#gpio-cells = <2>;
+					gpio-ranges = <&pinctrl_nb 0 0 36>;
+					gpio-controller;
+					interrupts =
+					<GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+
+				};
+
+				spi_quad_pins: spi-quad-pins {
+					groups = "spi_quad";
+					function = "spi";
+				};
+
+				i2c1_pins: i2c1-pins {
+					groups = "i2c1";
+					function = "i2c";
+				};
+
+				i2c2_pins: i2c2-pins {
+					groups = "i2c2";
+					function = "i2c";
+				};
+
+				uart1_pins: uart1-pins {
+					groups = "uart1";
+					function = "uart";
+				};
+
+				uart2_pins: uart2-pins {
+					groups = "uart2";
+					function = "uart";
+				};
+			};
+
+			pinctrl_sb: pinctrl-sb@18800 {
+				compatible = "marvell,armada3710-sb-pinctrl",
+				"syscon", "simple-mfd";
+				reg = <0x18800 0x100>, <0x18C00 0x20>;
+				gpiosb: gpiosb {
+					#gpio-cells = <2>;
+					gpio-ranges = <&pinctrl_sb 0 0 29>;
+					gpio-controller;
+					interrupts =
+					<GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+				};
+
+				rgmii_pins: mii-pins {
+					groups = "rgmii";
+					function = "mii";
+				};
+
+			};
+
 			usb3: usb@58000 {
 				compatible = "marvell,armada3700-xhci",
 				"generic-xhci";
diff --git a/arch/arm/dts/armada-7040-db.dts b/arch/arm/dts/armada-7040-db.dts
index b140b34..cfd2b4b 100644
--- a/arch/arm/dts/armada-7040-db.dts
+++ b/arch/arm/dts/armada-7040-db.dts
@@ -169,8 +169,7 @@
 	};
 
 	phy2 {
-		phy-type = <PHY_TYPE_SGMII0>;
-		phy-speed = <PHY_SPEED_1_25G>;
+		phy-type = <PHY_TYPE_SFI>;
 	};
 
 	phy3 {
@@ -224,6 +223,11 @@
 	status = "okay";
 };
 
+&cpm_eth0 {
+	status = "okay";
+	phy-mode = "sfi"; /* lane-2 */
+};
+
 &cpm_eth1 {
 	status = "okay";
 	phy = <&phy0>;
diff --git a/arch/arm/dts/sun50i-a64-pine64-common.dtsi b/arch/arm/dts/sun50i-a64-bananapi-m64.dts
similarity index 70%
copy from arch/arm/dts/sun50i-a64-pine64-common.dtsi
copy to arch/arm/dts/sun50i-a64-bananapi-m64.dts
index 9ec81c6..02db114 100644
--- a/arch/arm/dts/sun50i-a64-pine64-common.dtsi
+++ b/arch/arm/dts/sun50i-a64-bananapi-m64.dts
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016 ARM Ltd.
+ * Copyright (C) 2017 Jagan Teki <jteki@openedev.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
@@ -40,31 +41,70 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
+/dts-v1/;
+
 #include "sun50i-a64.dtsi"
 
+#include <dt-bindings/gpio/gpio.h>
+
 / {
+	model = "BananaPi-M64";
+	compatible = "sinovoip,bananapi-m64", "allwinner,sun50i-a64";
 
 	aliases {
 		serial0 = &uart0;
-		ethernet0 = &emac;
+		serial1 = &uart1;
 	};
 
-	soc {
-		reg_vcc3v3: vcc3v3 {
-			compatible = "regulator-fixed";
-			regulator-name = "vcc3v3";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-		};
+	chosen {
+		stdout-path = "serial0:115200n8";
 	};
+
+	reg_vcc3v3: vcc3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+};
+
+&i2c1_pins {
+	bias-pull-up;
 };
 
 &mmc0 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&mmc0_pins>, <&mmc0_default_cd_pin>;
+	pinctrl-0 = <&mmc0_pins>;
 	vmmc-supply = <&reg_vcc3v3>;
-	cd-gpios = <&pio 5 6 0>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
 	cd-inverted;
+	disable-wp;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+};
+
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <8>;
+	non-removable;
+	cap-mmc-hw-reset;
 	status = "okay";
 };
 
@@ -74,20 +114,8 @@
 	status = "okay";
 };
 
-&i2c1 {
+&uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&i2c1_pins>;
+	pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
 	status = "okay";
 };
-
-&usbphy {
-       status = "okay";
-};
-
-&ohci1 {
-       status = "okay";
-};
-
-&ehci1 {
-       status = "okay";
-};
diff --git a/arch/arm/dts/sun50i-a64-pine64-plus-u-boot.dtsi b/arch/arm/dts/sun50i-a64-pine64-plus-u-boot.dtsi
new file mode 100644
index 0000000..9c61bea
--- /dev/null
+++ b/arch/arm/dts/sun50i-a64-pine64-plus-u-boot.dtsi
@@ -0,0 +1,50 @@
+/ {
+	aliases {
+		ethernet0 = &emac;
+	};
+
+	soc {
+		emac: ethernet@01c30000 {
+			compatible = "allwinner,sun50i-a64-emac";
+			reg = <0x01c30000 0x2000>, <0x01c00030 0x4>;
+			reg-names = "emac", "syscon";
+			interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+			resets = <&ccu RST_BUS_EMAC>;
+			reset-names = "ahb";
+			clocks = <&ccu CLK_BUS_EMAC>;
+			clock-names = "ahb";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&rgmii_pins>;
+			phy-mode = "rgmii";
+			phy = <&phy1>;
+			status = "okay";
+
+			phy1: ethernet-phy@1 {
+				reg = <1>;
+			};
+		};
+	};
+};
+
+&pio {
+	rmii_pins: rmii_pins {
+		allwinner,pins = "PD10", "PD11", "PD13", "PD14",
+				 "PD17", "PD18", "PD19", "PD20",
+				 "PD22", "PD23";
+		allwinner,function = "emac";
+		allwinner,drive = <3>;
+		allwinner,pull = <0>;
+	};
+
+	rgmii_pins: rgmii_pins {
+		allwinner,pins = "PD8", "PD9", "PD10", "PD11",
+				 "PD12", "PD13", "PD15",
+				 "PD16", "PD17", "PD18", "PD19",
+				 "PD20", "PD21", "PD22", "PD23";
+		allwinner,function = "emac";
+		allwinner,drive = <3>;
+		allwinner,pull = <0>;
+	};
+};
diff --git a/arch/arm/dts/sun50i-a64-pine64-plus.dts b/arch/arm/dts/sun50i-a64-pine64-plus.dts
index 389c609..790d14d 100644
--- a/arch/arm/dts/sun50i-a64-pine64-plus.dts
+++ b/arch/arm/dts/sun50i-a64-pine64-plus.dts
@@ -40,33 +40,11 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/dts-v1/;
-
-#include "sun50i-a64-pine64-common.dtsi"
+#include "sun50i-a64-pine64.dts"
 
 / {
 	model = "Pine64+";
 	compatible = "pine64,pine64-plus", "allwinner,sun50i-a64";
 
-	chosen {
-		stdout-path = "serial0:115200n8";
-	};
-
-	/* There is a model with 2GB of DRAM, but U-Boot fixes this for us. */
-	memory {
-		reg = <0x40000000 0x40000000>;
-	};
+	/* TODO: Camera, Ethernet PHY, touchscreen, etc. */
 };
-
-&emac {
-	pinctrl-names = "default";
-	pinctrl-0 = <&rgmii_pins>;
-	phy-mode = "rgmii";
-	phy = <&phy1>;
-	status = "okay";
-
-	phy1: ethernet-phy@1 {
-	reg = <1>;
-	};
-};
-
diff --git a/arch/arm/dts/sun50i-a64-pine64.dts b/arch/arm/dts/sun50i-a64-pine64.dts
index ebe029e..c680ed3 100644
--- a/arch/arm/dts/sun50i-a64-pine64.dts
+++ b/arch/arm/dts/sun50i-a64-pine64.dts
@@ -42,17 +42,70 @@
 
 /dts-v1/;
 
-#include "sun50i-a64-pine64-common.dtsi"
+#include "sun50i-a64.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "Pine64";
 	compatible = "pine64,pine64", "allwinner,sun50i-a64";
 
+	aliases {
+		serial0 = &uart0;
+	};
+
 	chosen {
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
-		reg = <0x40000000 0x20000000>;
+	reg_vcc3v3: vcc3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
 	};
 };
+
+&ehci1 {
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+};
+
+&i2c1_pins {
+	bias-pull-up;
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins>;
+	vmmc-supply = <&reg_vcc3v3>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+	disable-wp;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins_a>;
+	status = "okay";
+};
+
+&usb_otg {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-a64.dtsi b/arch/arm/dts/sun50i-a64.dtsi
index bef0d00..c7f669f 100644
--- a/arch/arm/dts/sun50i-a64.dtsi
+++ b/arch/arm/dts/sun50i-a64.dtsi
@@ -42,8 +42,9 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <dt-bindings/clock/sun50i-a64-ccu.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
+#include <dt-bindings/reset/sun50i-a64-ccu.h>
 
 / {
 	interrupt-parent = <&gic>;
@@ -54,28 +55,28 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		cpu@0 {
+		cpu0: cpu@0 {
 			compatible = "arm,cortex-a53", "arm,armv8";
 			device_type = "cpu";
 			reg = <0>;
 			enable-method = "psci";
 		};
 
-		cpu@1 {
+		cpu1: cpu@1 {
 			compatible = "arm,cortex-a53", "arm,armv8";
 			device_type = "cpu";
 			reg = <1>;
 			enable-method = "psci";
 		};
 
-		cpu@2 {
+		cpu2: cpu@2 {
 			compatible = "arm,cortex-a53", "arm,armv8";
 			device_type = "cpu";
 			reg = <2>;
 			enable-method = "psci";
 		};
 
-		cpu@3 {
+		cpu3: cpu@3 {
 			compatible = "arm,cortex-a53", "arm,armv8";
 			device_type = "cpu";
 			reg = <3>;
@@ -83,30 +84,33 @@
 		};
 	};
 
+	osc24M: osc24M_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "osc24M";
+	};
+
+	osc32k: osc32k_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+		clock-output-names = "osc32k";
+	};
+
+	iosc: internal-osc-clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <16000000>;
+		clock-accuracy = <300000000>;
+		clock-output-names = "iosc";
+	};
+
 	psci {
 		compatible = "arm,psci-0.2";
 		method = "smc";
 	};
 
-	memory {
-		device_type = "memory";
-		reg = <0x40000000 0>;
-	};
-
-	gic: interrupt-controller@1c81000 {
-		compatible = "arm,gic-400";
-		interrupt-controller;
-		#interrupt-cells = <3>;
-		#address-cells = <0>;
-
-		reg = <0x01c81000 0x1000>,
-		      <0x01c82000 0x2000>,
-		      <0x01c84000 0x2000>,
-		      <0x01c86000 0x2000>;
-		interrupts = <GIC_PPI 9
-		      (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
-	};
-
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13
@@ -119,199 +123,6 @@
 			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
 	};
 
-	clocks {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-
-		osc24M: osc24M_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <24000000>;
-			clock-output-names = "osc24M";
-		};
-
-		osc32k: osc32k_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <32768>;
-			clock-output-names = "osc32k";
-		};
-
-		pll1: pll1_clk@1c20000 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun8i-a23-pll1-clk";
-			reg = <0x01c20000 0x4>;
-			clocks = <&osc24M>;
-			clock-output-names = "pll1";
-		};
-
-		pll6: pll6_clk@1c20028 {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun6i-a31-pll6-clk";
-			reg = <0x01c20028 0x4>;
-			clocks = <&osc24M>;
-			clock-output-names = "pll6", "pll6x2";
-		};
-
-		pll6d2: pll6d2_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-factor-clock";
-			clock-div = <2>;
-			clock-mult = <1>;
-			clocks = <&pll6 0>;
-			clock-output-names = "pll6d2";
-		};
-
-		pll7: pll7_clk@1c2002c {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun6i-a31-pll6-clk";
-			reg = <0x01c2002c 0x4>;
-			clocks = <&osc24M>;
-			clock-output-names = "pll7", "pll7x2";
-		};
-
-		cpu: cpu_clk@1c20050 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-cpu-clk";
-			reg = <0x01c20050 0x4>;
-			clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>;
-			clock-output-names = "cpu";
-			critical-clocks = <0>;
-		};
-
-		axi: axi_clk@1c20050 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-axi-clk";
-			reg = <0x01c20050 0x4>;
-			clocks = <&cpu>;
-			clock-output-names = "axi";
-		};
-
-		ahb1: ahb1_clk@1c20054 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun6i-a31-ahb1-clk";
-			reg = <0x01c20054 0x4>;
-			clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>;
-			clock-output-names = "ahb1";
-		};
-
-		ahb2: ahb2_clk@1c2005c {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun8i-h3-ahb2-clk";
-			reg = <0x01c2005c 0x4>;
-			clocks = <&ahb1>, <&pll6d2>;
-			clock-output-names = "ahb2";
-		};
-
-		apb1: apb1_clk@1c20054 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-apb0-clk";
-			reg = <0x01c20054 0x4>;
-			clocks = <&ahb1>;
-			clock-output-names = "apb1";
-		};
-
-		apb2: apb2_clk@1c20058 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-apb1-clk";
-			reg = <0x01c20058 0x4>;
-			clocks = <&osc32k>, <&osc24M>, <&pll6 1>, <&pll6 1>;
-			clock-output-names = "apb2";
-		};
-
-		bus_gates: bus_gates_clk@1c20060 {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun50i-a64-bus-gates-clk",
-				     "allwinner,sunxi-multi-bus-gates-clk";
-			reg = <0x01c20060 0x14>;
-			ahb1_parent {
-				clocks = <&ahb1>;
-				clock-indices = <1>, <5>,
-						<6>, <8>,
-						<9>, <10>,
-						<13>, <14>,
-						<18>, <19>,
-						<20>, <21>,
-						<23>, <24>,
-						<25>, <28>,
-						<32>, <35>,
-						<36>, <37>,
-						<40>, <43>,
-						<44>, <52>,
-						<53>, <54>,
-						<135>;
-				clock-output-names = "bus_mipidsi", "bus_ce",
-						"bus_dma", "bus_mmc0",
-						"bus_mmc1", "bus_mmc2",
-						"bus_nand", "bus_sdram",
-						"bus_ts", "bus_hstimer",
-						"bus_spi0", "bus_spi1",
-						"bus_otg", "bus_otg_ehci0",
-						"bus_ehci0", "bus_otg_ohci0",
-						"bus_ve", "bus_lcd0",
-						"bus_lcd1", "bus_deint",
-						"bus_csi", "bus_hdmi",
-						"bus_de", "bus_gpu",
-						"bus_msgbox", "bus_spinlock",
-						"bus_dbg";
-			};
-			ahb2_parent {
-				clocks = <&ahb2>;
-				clock-indices = <17>, <29>;
-				clock-output-names = "bus_gmac", "bus_ohci0";
-			};
-			apb1_parent {
-				clocks = <&apb1>;
-				clock-indices = <64>, <65>,
-						<69>, <72>,
-						<76>, <77>,
-						<78>;
-				clock-output-names = "bus_codec", "bus_spdif",
-						"bus_pio", "bus_ths",
-						"bus_i2s0", "bus_i2s1",
-						"bus_i2s2";
-			};
-			abp2_parent {
-				clocks = <&apb2>;
-				clock-indices = <96>, <97>,
-						<98>, <101>,
-						<112>, <113>,
-						<114>, <115>,
-						<116>;
-				clock-output-names = "bus_i2c0", "bus_i2c1",
-						"bus_i2c2", "bus_scr",
-						"bus_uart0", "bus_uart1",
-						"bus_uart2", "bus_uart3",
-						"bus_uart4";
-			};
-		};
-
-		mmc0_clk: mmc0_clk@1c20088 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
-			reg = <0x01c20088 0x4>;
-			clocks = <&osc24M>, <&pll6 1>, <&pll7 1>;
-			clock-output-names = "mmc0";
-                };
-
-		mmc1_clk: mmc1_clk@1c2008c {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
-			reg = <0x01c2008c 0x4>;
-			clocks = <&osc24M>, <&pll6 1>, <&pll7 1>;
-			clock-output-names = "mmc1";
-		};
-
-		mmc2_clk: mmc2_clk@1c20090 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
-			reg = <0x01c20090 0x4>;
-			clocks = <&osc24M>, <&pll6 1>, <&pll7 1>;
-			clock-output-names = "mmc2";
-		};
-	};
-
 	soc {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -319,230 +130,171 @@
 		ranges;
 
 		mmc0: mmc@1c0f000 {
-			compatible = "allwinner,sun50i-a64-mmc",
-				     "allwinner,sun5i-a13-mmc";
+			compatible = "allwinner,sun50i-a64-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&bus_gates 8>, <&mmc0_clk>,
-				 <&mmc0_clk>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc",
-				      "output", "sample";
-			resets = <&ahb_rst 8>;
+			clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC0>;
 			reset-names = "ahb";
 			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
 		};
 
 		mmc1: mmc@1c10000 {
-			compatible = "allwinner,sun50i-a64-mmc",
-				     "allwinner,sun5i-a13-mmc";
+			compatible = "allwinner,sun50i-a64-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&bus_gates 9>, <&mmc1_clk>,
-				 <&mmc1_clk>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc",
-				      "output", "sample";
-			resets = <&ahb_rst 9>;
+			clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC1>;
 			reset-names = "ahb";
 			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
 		};
 
 		mmc2: mmc@1c11000 {
-			compatible = "allwinner,sun50i-a64-mmc",
-				     "allwinner,sun5i-a13-mmc";
+			compatible = "allwinner,sun50i-a64-emmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&bus_gates 10>, <&mmc2_clk>,
-				 <&mmc2_clk>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc",
-				      "output", "sample";
-			resets = <&ahb_rst 10>;
+			clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC2>;
 			reset-names = "ahb";
 			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <200000000>;
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
 		};
 
+		usb_otg: usb@01c19000 {
+			compatible = "allwinner,sun8i-a33-musb";
+			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 = "allwinner,sun50i-a64-usb-phy";
+			reg = <0x01c19400 0x14>,
+			      <0x01c1a800 0x4>,
+			      <0x01c1b800 0x4>;
+			reg-names = "phy_ctrl",
+				    "pmu0",
+				    "pmu1";
+			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>;
+		};
+
+		ehci1: usb@01c1b000 {
+			compatible = "allwinner,sun50i-a64-ehci", "generic-ehci";
+			reg = <0x01c1b000 0x100>;
+			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI1>,
+				 <&ccu CLK_BUS_EHCI1>,
+				 <&ccu CLK_USB_OHCI1>;
+			resets = <&ccu RST_BUS_OHCI1>,
+				 <&ccu RST_BUS_EHCI1>;
+			phys = <&usbphy 1>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci1: usb@01c1b400 {
+			compatible = "allwinner,sun50i-a64-ohci", "generic-ohci";
+			reg = <0x01c1b400 0x100>;
+			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI1>,
+				 <&ccu CLK_USB_OHCI1>;
+			resets = <&ccu RST_BUS_OHCI1>;
+			phys = <&usbphy 1>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ccu: clock@01c20000 {
+			compatible = "allwinner,sun50i-a64-ccu";
+			reg = <0x01c20000 0x400>;
+			clocks = <&osc24M>, <&osc32k>;
+			clock-names = "hosc", "losc";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
 		pio: pinctrl@1c20800 {
 			compatible = "allwinner,sun50i-a64-pinctrl";
 			reg = <0x01c20800 0x400>;
 			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bus_gates 69>;
+			clocks = <&ccu 58>;
 			gpio-controller;
 			#gpio-cells = <3>;
 			interrupt-controller;
-			#interrupt-cells = <2>;
-
-			uart0_pins_a: uart0@0 {
-				allwinner,pins = "PB8", "PB9";
-				allwinner,function = "uart0";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
-
-			uart0_pins_b: uart0@1 {
-				allwinner,pins = "PF2", "PF3";
-				allwinner,function = "uart0";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
-
-			uart1_2pins: uart1_2@0 {
-				allwinner,pins = "PG6", "PG7";
-				allwinner,function = "uart1";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
-
-			uart1_4pins: uart1_4@0 {
-				allwinner,pins = "PG6", "PG7", "PG8", "PG9";
-				allwinner,function = "uart1";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
-
-			uart2_2pins: uart2_2@0 {
-				allwinner,pins = "PB0", "PB1";
-				allwinner,function = "uart2";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
-
-			uart2_4pins: uart2_4@0 {
-				allwinner,pins = "PB0", "PB1", "PB2", "PB3";
-				allwinner,function = "uart2";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
-
-			uart3_pins_a: uart3@0 {
-				allwinner,pins = "PD0", "PD1";
-				allwinner,function = "uart3";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
-
-			uart3_2pins_b: uart3_2@1 {
-				allwinner,pins = "PH4", "PH5";
-				allwinner,function = "uart3";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
-
-			uart3_4pins_b: uart3_4@1 {
-				allwinner,pins = "PH4", "PH5", "PH6", "PH7";
-				allwinner,function = "uart3";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
-
-			uart4_2pins: uart4_2@0 {
-				allwinner,pins = "PD2", "PD3";
-				allwinner,function = "uart4";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
-
-			uart4_4pins: uart4_4@0 {
-				allwinner,pins = "PD2", "PD3", "PD4", "PD5";
-				allwinner,function = "uart4";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
-
-			mmc0_pins: 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>;
-			};
-
-			mmc0_default_cd_pin: mmc0_cd_pin@0 {
-				allwinner,pins = "PF6";
-				allwinner,function = "gpio_in";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
-			};
-
-			mmc1_pins: 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>;
-			};
-
-			mmc2_pins: mmc2@0 {
-				allwinner,pins = "PC1", "PC5", "PC6", "PC8",
-						 "PC9", "PC10";
-				allwinner,function = "mmc2";
-				allwinner,drive = <SUN4I_PINCTRL_30_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
-
-			i2c0_pins: i2c0_pins {
-				allwinner,pins = "PH0", "PH1";
-				allwinner,function = "i2c0";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
+			#interrupt-cells = <3>;
 
 			i2c1_pins: i2c1_pins {
-				allwinner,pins = "PH2", "PH3";
-				allwinner,function = "i2c1";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+				pins = "PH2", "PH3";
+				function = "i2c1";
 			};
 
-			i2c2_pins: i2c2_pins {
-				allwinner,pins = "PE14", "PE15";
-				allwinner,function = "i2c2";
-				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			mmc0_pins: mmc0-pins {
+				pins = "PF0", "PF1", "PF2", "PF3",
+				       "PF4", "PF5";
+				function = "mmc0";
+				drive-strength = <30>;
+				bias-pull-up;
 			};
 
-			rmii_pins: rmii_pins {
-				allwinner,pins = "PD10", "PD11", "PD13", "PD14",
-						 "PD17", "PD18", "PD19", "PD20",
-						 "PD22", "PD23";
-				allwinner,function = "emac";
-				allwinner,drive = <SUN4I_PINCTRL_40_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			mmc1_pins: mmc1-pins {
+				pins = "PG0", "PG1", "PG2", "PG3",
+				       "PG4", "PG5";
+				function = "mmc1";
+				drive-strength = <30>;
+				bias-pull-up;
 			};
 
-			rgmii_pins: rgmii_pins {
-				allwinner,pins = "PD8", "PD9", "PD10", "PD11",
-						 "PD12", "PD13", "PD15",
-						 "PD16", "PD17", "PD18", "PD19",
-						 "PD20", "PD21", "PD22", "PD23";
-				allwinner,function = "emac";
-				allwinner,drive = <SUN4I_PINCTRL_40_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			mmc2_pins: mmc2-pins {
+				pins = "PC1", "PC5", "PC6", "PC8", "PC9",
+				       "PC10","PC11", "PC12", "PC13",
+				       "PC14", "PC15", "PC16";
+				function = "mmc2";
+				drive-strength = <30>;
+				bias-pull-up;
 			};
-		};
 
-		ahb_rst: reset@1c202c0 {
-			#reset-cells = <1>;
-			compatible = "allwinner,sun6i-a31-clock-reset";
-			reg = <0x01c202c0 0xc>;
-		};
+			uart0_pins_a: uart0@0 {
+				pins = "PB8", "PB9";
+				function = "uart0";
+			};
 
-		apb1_rst: reset@1c202d0 {
-			#reset-cells = <1>;
-			compatible = "allwinner,sun6i-a31-clock-reset";
-			reg = <0x01c202d0 0x4>;
-		};
+			uart1_pins: uart1_pins {
+				pins = "PG6", "PG7";
+				function = "uart1";
+			};
 
-		apb2_rst: reset@1c202d8 {
-			#reset-cells = <1>;
-			compatible = "allwinner,sun6i-a31-clock-reset";
-			reg = <0x01c202d8 0x4>;
+			uart1_rts_cts_pins: uart1_rts_cts_pins {
+				pins = "PG8", "PG9";
+				function = "uart1";
+			};
 		};
 
 		uart0: serial@1c28000 {
@@ -551,8 +303,8 @@
 			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&bus_gates 112>;
-			resets = <&apb2_rst 16>;
+			clocks = <&ccu 67>;
+			resets = <&ccu 46>;
 			status = "disabled";
 		};
 
@@ -562,8 +314,8 @@
 			interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&bus_gates 113>;
-			resets = <&apb2_rst 17>;
+			clocks = <&ccu 68>;
+			resets = <&ccu 47>;
 			status = "disabled";
 		};
 
@@ -573,8 +325,8 @@
 			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&bus_gates 114>;
-			resets = <&apb2_rst 18>;
+			clocks = <&ccu 69>;
+			resets = <&ccu 48>;
 			status = "disabled";
 		};
 
@@ -584,8 +336,8 @@
 			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&bus_gates 115>;
-			resets = <&apb2_rst 19>;
+			clocks = <&ccu 70>;
+			resets = <&ccu 49>;
 			status = "disabled";
 		};
 
@@ -595,24 +347,17 @@
 			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&bus_gates 116>;
-			resets = <&apb2_rst 20>;
+			clocks = <&ccu 71>;
+			resets = <&ccu 50>;
 			status = "disabled";
 		};
 
-		rtc: rtc@1f00000 {
-			compatible = "allwinner,sun6i-a31-rtc";
-			reg = <0x01f00000 0x54>;
-			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
-		};
-
 		i2c0: i2c@1c2ac00 {
 			compatible = "allwinner,sun6i-a31-i2c";
 			reg = <0x01c2ac00 0x400>;
 			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bus_gates 96>;
-			resets = <&apb2_rst 0>;
+			clocks = <&ccu 63>;
+			resets = <&ccu 42>;
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -622,8 +367,8 @@
 			compatible = "allwinner,sun6i-a31-i2c";
 			reg = <0x01c2b000 0x400>;
 			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bus_gates 97>;
-			resets = <&apb2_rst 1>;
+			clocks = <&ccu 64>;
+			resets = <&ccu 43>;
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -633,54 +378,50 @@
 			compatible = "allwinner,sun6i-a31-i2c";
 			reg = <0x01c2b400 0x400>;
 			interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bus_gates 98>;
-			resets = <&apb2_rst 2>;
+			clocks = <&ccu 65>;
+			resets = <&ccu 44>;
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
 		};
 
-		emac: ethernet@01c30000 {
-			compatible = "allwinner,sun50i-a64-emac";
-			reg = <0x01c30000 0x2000>, <0x01c00030 0x4>;
-			reg-names = "emac", "syscon";
-			interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
-			resets = <&ahb_rst 17>;
-			reset-names = "ahb";
-			clocks = <&bus_gates 17>;
-			clock-names = "ahb";
-			status = "disabled";
-			#address-cells = <1>;
-			#size-cells = <0>;
+		gic: interrupt-controller@1c81000 {
+			compatible = "arm,gic-400";
+			reg = <0x01c81000 0x1000>,
+			      <0x01c82000 0x2000>,
+			      <0x01c84000 0x2000>,
+			      <0x01c86000 0x2000>;
+			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
 		};
 
-		usbphy: phy@1c1b810 {
-			compatible = "allwinner,sun50i-a64-usb-phy",
-				     "allwinner,sun8i-a33-usb-phy";
-			reg = <0x01c1b810 0x14>, <0x01c1b800 0x4>;
-			reg-names = "phy_ctrl", "pmu1";
-			status = "disabled";
-			#phy-cells = <1>;
+		rtc: rtc@1f00000 {
+			compatible = "allwinner,sun6i-a31-rtc";
+			reg = <0x01f00000 0x54>;
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
-		ehci1: usb@01c1b000 {
-			compatible = "allwinner,sun50i-a64-ehci",
-				     "generic-ehci";
-			reg = <0x01c1b000 0x100>;
-			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
-			phys = <&usbphy 1>;
-			phy-names = "usb";
-			status = "disabled";
+		r_ccu: clock@1f01400 {
+			compatible = "allwinner,sun50i-a64-r-ccu";
+			reg = <0x01f01400 0x100>;
+			clocks = <&osc24M>, <&osc32k>, <&iosc>;
+			clock-names = "hosc", "losc", "iosc";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
 		};
 
-		ohci1: usb@01c1b400 {
-			compatible = "allwinner,sun50i-a64-ohci",
-				     "generic-ohci";
-			reg = <0x01c1b400 0x100>;
-			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
-			phys = <&usbphy 1>;
-			phy-names = "usb";
-			status = "enabled";
+		r_pio: pinctrl@01f02c00 {
+			compatible = "allwinner,sun50i-a64-r-pinctrl";
+			reg = <0x01f02c00 0x400>;
+			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&r_ccu 3>, <&osc24M>, <&osc32k>;
+			clock-names = "apb", "hosc", "losc";
+			gpio-controller;
+			#gpio-cells = <3>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
 		};
 	};
 };
diff --git a/arch/arm/dts/sun50i-h5-orangepi-pc2.dts b/arch/arm/dts/sun50i-h5-orangepi-pc2.dts
index de60f78..780d59a 100644
--- a/arch/arm/dts/sun50i-h5-orangepi-pc2.dts
+++ b/arch/arm/dts/sun50i-h5-orangepi-pc2.dts
@@ -42,40 +42,14 @@
 
 /dts-v1/;
 
-#include "sun8i-h3.dtsi"
+#include "sun50i-h5.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "OrangePi PC 2";
 	compatible = "xunlong,orangepi-pc-2", "allwinner,sun50i-h5";
 
-	cpus {
-		cpu@0 {
-			compatible = "arm,cortex-a53", "arm,armv8";
-			enable-method = "psci";
-		};
-		cpu@1 {
-			compatible = "arm,cortex-a53", "arm,armv8";
-			enable-method = "psci";
-		};
-		cpu@2 {
-			compatible = "arm,cortex-a53", "arm,armv8";
-			enable-method = "psci";
-		};
-		cpu@3 {
-			compatible = "arm,cortex-a53", "arm,armv8";
-			enable-method = "psci";
-		};
-	};
-
-	psci {
-		compatible = "arm,psci-0.2";
-		method = "smc";
-	};
-
-	timer {
-		compatible = "arm,armv8-timer";
-	};
-
 	chosen {
 		stdout-path = "serial0:115200n8";
 	};
@@ -99,10 +73,6 @@
 	};
 };
 
-&gic {
-	compatible = "arm,gic-400";
-};
-
 &mmc0 {
 	compatible = "allwinner,sun50i-h5-mmc",
 		     "allwinner,sun50i-a64-mmc",
@@ -111,7 +81,7 @@
 	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
 	vmmc-supply = <&reg_vcc3v3>;
 	bus-width = <4>;
-	cd-gpios = <&pio 5 6 0>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
 	cd-inverted;
 	status = "okay";
 };
diff --git a/arch/arm/dts/sun50i-a64-pine64-common.dtsi b/arch/arm/dts/sun50i-h5-orangepi-prime.dts
similarity index 80%
rename from arch/arm/dts/sun50i-a64-pine64-common.dtsi
rename to arch/arm/dts/sun50i-h5-orangepi-prime.dts
index 9ec81c6..67eade7 100644
--- a/arch/arm/dts/sun50i-a64-pine64-common.dtsi
+++ b/arch/arm/dts/sun50i-h5-orangepi-prime.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 ARM Ltd.
+ * Copyright (C) 2017 Jagan Teki <jteki@openedev.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
@@ -40,13 +40,26 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include "sun50i-a64.dtsi"
+/dts-v1/;
+
+#include "sun50i-h5.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
 
 / {
+	model = "OrangePi Prime";
+	compatible = "xunlong,orangepi-prime", "allwinner,sun50i-h5";
 
 	aliases {
 		serial0 = &uart0;
-		ethernet0 = &emac;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		reg = <0x40000000 0x80000000>;
 	};
 
 	soc {
@@ -60,10 +73,14 @@
 };
 
 &mmc0 {
+	compatible = "allwinner,sun50i-h5-mmc",
+		     "allwinner,sun50i-a64-mmc",
+		     "allwinner,sun5i-a13-mmc";
 	pinctrl-names = "default";
-	pinctrl-0 = <&mmc0_pins>, <&mmc0_default_cd_pin>;
+	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
 	vmmc-supply = <&reg_vcc3v3>;
-	cd-gpios = <&pio 5 6 0>;
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
 	cd-inverted;
 	status = "okay";
 };
@@ -74,20 +91,14 @@
 	status = "okay";
 };
 
-&i2c1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&i2c1_pins>;
+&usbphy {
 	status = "okay";
 };
 
-&usbphy {
-       status = "okay";
-};
-
 &ohci1 {
-       status = "okay";
+	status = "okay";
 };
 
 &ehci1 {
-       status = "okay";
+	status = "okay";
 };
diff --git a/arch/arm/dts/sun50i-a64-pine64-common.dtsi b/arch/arm/dts/sun50i-h5.dtsi
similarity index 73%
copy from arch/arm/dts/sun50i-a64-pine64-common.dtsi
copy to arch/arm/dts/sun50i-h5.dtsi
index 9ec81c6..4904c18 100644
--- a/arch/arm/dts/sun50i-a64-pine64-common.dtsi
+++ b/arch/arm/dts/sun50i-h5.dtsi
@@ -40,54 +40,38 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include "sun50i-a64.dtsi"
+#include "sun8i-h3.dtsi"
 
 / {
-
-	aliases {
-		serial0 = &uart0;
-		ethernet0 = &emac;
-	};
-
-	soc {
-		reg_vcc3v3: vcc3v3 {
-			compatible = "regulator-fixed";
-			regulator-name = "vcc3v3";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
+	cpus {
+		cpu@0 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			enable-method = "psci";
+		};
+		cpu@1 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			enable-method = "psci";
+		};
+		cpu@2 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			enable-method = "psci";
+		};
+		cpu@3 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			enable-method = "psci";
 		};
 	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+	};
 };
 
-&mmc0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&mmc0_pins>, <&mmc0_default_cd_pin>;
-	vmmc-supply = <&reg_vcc3v3>;
-	cd-gpios = <&pio 5 6 0>;
-	cd-inverted;
-	status = "okay";
-};
-
-&uart0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&uart0_pins_a>;
-	status = "okay";
-};
-
-&i2c1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&i2c1_pins>;
-	status = "okay";
-};
-
-&usbphy {
-       status = "okay";
-};
-
-&ohci1 {
-       status = "okay";
-};
-
-&ehci1 {
-       status = "okay";
+&gic {
+	compatible = "arm,gic-400";
 };
diff --git a/arch/arm/dts/sun50i-a64-pine64-common.dtsi b/arch/arm/dts/sun8i-h3-nanopi-m1.dts
similarity index 69%
copy from arch/arm/dts/sun50i-a64-pine64-common.dtsi
copy to arch/arm/dts/sun8i-h3-nanopi-m1.dts
index 9ec81c6..ec63d10 100644
--- a/arch/arm/dts/sun50i-a64-pine64-common.dtsi
+++ b/arch/arm/dts/sun8i-h3-nanopi-m1.dts
@@ -1,17 +1,17 @@
 /*
- * Copyright (c) 2016 ARM Ltd.
+ * Copyright (C) 2016 Milo Kim <woogyom.kim@gmail.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 library is free software; you can redistribute it and/or
+ *  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 library is distributed in the hope that it will be useful,
+ *     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.
@@ -40,54 +40,25 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include "sun50i-a64.dtsi"
+#include "sun8i-h3-nanopi.dtsi"
 
 / {
-
-	aliases {
-		serial0 = &uart0;
-		ethernet0 = &emac;
-	};
-
-	soc {
-		reg_vcc3v3: vcc3v3 {
-			compatible = "regulator-fixed";
-			regulator-name = "vcc3v3";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-		};
-	};
-};
-
-&mmc0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&mmc0_pins>, <&mmc0_default_cd_pin>;
-	vmmc-supply = <&reg_vcc3v3>;
-	cd-gpios = <&pio 5 6 0>;
-	cd-inverted;
-	status = "okay";
-};
-
-&uart0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&uart0_pins_a>;
-	status = "okay";
-};
-
-&i2c1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&i2c1_pins>;
-	status = "okay";
-};
-
-&usbphy {
-       status = "okay";
-};
-
-&ohci1 {
-       status = "okay";
+	model = "FriendlyArm NanoPi M1";
+	compatible = "friendlyarm,nanopi-m1", "allwinner,sun8i-h3";
 };
 
 &ehci1 {
-       status = "okay";
+	status = "okay";
+};
+
+&ehci2 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&ohci2 {
+	status = "okay";
 };
diff --git a/arch/arm/dts/sun8i-h3-nanopi-neo.dts b/arch/arm/dts/sun8i-h3-nanopi-neo.dts
index 096ff0b..5113059 100644
--- a/arch/arm/dts/sun8i-h3-nanopi-neo.dts
+++ b/arch/arm/dts/sun8i-h3-nanopi-neo.dts
@@ -40,88 +40,11 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/dts-v1/;
-#include "sun8i-h3.dtsi"
-#include "sunxi-common-regulators.dtsi"
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
+#include "sun8i-h3-nanopi.dtsi"
 
 / {
 	model = "FriendlyARM NanoPi NEO";
 	compatible = "friendlyarm,nanopi-neo", "allwinner,sun8i-h3";
-
-	aliases {
-		serial0 = &uart0;
-	};
-
-	chosen {
-		stdout-path = "serial0:115200n8";
-	};
-
-	leds {
-		compatible = "gpio-leds";
-		pinctrl-names = "default";
-		pinctrl-0 = <&leds_opc>, <&leds_r_opc>;
-
-		pwr {
-			label = "nanopi:green:pwr";
-			gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
-			default-state = "on";
-		};
-
-		status {
-			label = "nanopi:blue:status";
-			gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>; /* PA10 */
-		};
-	};
-};
-
-&ehci3 {
-	status = "okay";
-};
-
-&mmc0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
-	vmmc-supply = <&reg_vcc3v3>;
-	bus-width = <4>;
-	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
-	cd-inverted;
-	status = "okay";
-};
-
-&ohci3 {
-	status = "okay";
-};
-
-&pio {
-	leds_opc: led-pins {
-		allwinner,pins = "PA10";
-		allwinner,function = "gpio_out";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-	};
-};
-
-&r_pio {
-	leds_r_opc: led-pins {
-		allwinner,pins = "PL10";
-		allwinner,function = "gpio_out";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-	};
-};
-
-&uart0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&uart0_pins_a>;
-	status = "okay";
-};
-
-&usbphy {
-	/* USB VBUS is always on */
-	status = "okay";
 };
 
 &emac {
diff --git a/arch/arm/dts/sun8i-h3-nanopi.dtsi b/arch/arm/dts/sun8i-h3-nanopi.dtsi
new file mode 100644
index 0000000..c6decee
--- /dev/null
+++ b/arch/arm/dts/sun8i-h3-nanopi.dtsi
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2016 James Pettigrew <james@innovum.com.au>
+ * Copyright (C) 2016 Milo Kim <woogyom.kim@gmail.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.
+ */
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_npi>, <&leds_r_npi>;
+
+		status {
+			label = "nanopi:blue:status";
+			gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		pwr {
+			label = "nanopi:green:pwr";
+			gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+		};
+	};
+
+	r_gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "k1";
+		pinctrl-names = "default";
+		pinctrl-0 = <&sw_r_npi>;
+
+		k1@0 {
+			label = "k1";
+			linux,code = <KEY_POWER>;
+			gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&ehci3 {
+	status = "okay";
+};
+
+&mmc0 {
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
+	status = "okay";
+	vmmc-supply = <&reg_vcc3v3>;
+};
+
+&ohci3 {
+	status = "okay";
+};
+
+&pio {
+	leds_npi: led_pins@0 {
+		pins = "PA10";
+		function = "gpio_out";
+	};
+};
+
+&r_pio {
+	leds_r_npi: led_pins@0 {
+		pins = "PL10";
+		function = "gpio_out";
+	};
+
+	sw_r_npi: key_pins@0 {
+		pins = "PL3";
+		function = "gpio_in";
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins_a>;
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 4dbe6a5..eb24222 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -14,7 +14,7 @@
 
 #include <common.h>
 #include <command.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <dm/root.h>
 #include <image.h>
 #include <u-boot/zlib.h>
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 5b6c5ea..c57935e 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -18,7 +18,9 @@
 	select CPU_V7
 	select BOARD_EARLY_INIT_F
 	select SHA_HW_ACCEL
+	imply CRC32_VERIFY
 	imply CMD_HASH
+	imply HASH_VERIFY
 	help
 	  Samsung Exynos5 SoC family are based on ARM Cortex-A15 CPU (and
 	  Cortex-A7 CPU in big.LITTLE configuration). There are multiple SoCs
diff --git a/arch/arm/mach-mvebu/arm64-common.c b/arch/arm/mach-mvebu/arm64-common.c
index c2c176e..69cb21d 100644
--- a/arch/arm/mach-mvebu/arm64-common.c
+++ b/arch/arm/mach-mvebu/arm64-common.c
@@ -46,75 +46,17 @@
 
 /* DRAM init code ... */
 
-static const void *get_memory_reg_prop(const void *fdt, int *lenp)
+int dram_init_banksize(void)
 {
-	int offset;
-
-	offset = fdt_path_offset(fdt, "/memory");
-	if (offset < 0)
-		return NULL;
-
-	return fdt_getprop(fdt, offset, "reg", lenp);
-}
-
-int dram_init(void)
-{
-	const void *fdt = gd->fdt_blob;
-	const fdt32_t *val;
-	int ac, sc, len;
-
-	ac = fdt_address_cells(fdt, 0);
-	sc = fdt_size_cells(fdt, 0);
-	if (ac < 0 || sc < 1 || sc > 2) {
-		printf("invalid address/size cells\n");
-		return -EINVAL;
-	}
-
-	val = get_memory_reg_prop(fdt, &len);
-	if (len / sizeof(*val) < ac + sc)
-		return -EINVAL;
-
-	val += ac;
-
-	gd->ram_size = fdtdec_get_number(val, sc);
-
-	debug("DRAM size = %08lx\n", (unsigned long)gd->ram_size);
+	fdtdec_setup_memory_banksize();
 
 	return 0;
 }
 
-int dram_init_banksize(void)
+int dram_init(void)
 {
-	const void *fdt = gd->fdt_blob;
-	const fdt32_t *val;
-	int ac, sc, cells, len, i;
-
-	val = get_memory_reg_prop(fdt, &len);
-	if (len < 0)
-		return -ENXIO;
-
-	ac = fdt_address_cells(fdt, 0);
-	sc = fdt_size_cells(fdt, 0);
-	if (ac < 1 || ac > 2 || sc < 1 || sc > 2) {
-		printf("invalid address/size cells\n");
-		return -ENXIO;
-	}
-
-	cells = ac + sc;
-
-	len /= sizeof(*val);
-
-	for (i = 0; i < CONFIG_NR_DRAM_BANKS && len >= cells;
-	     i++, len -= cells) {
-		gd->bd->bi_dram[i].start = fdtdec_get_number(val, ac);
-		val += ac;
-		gd->bd->bi_dram[i].size = fdtdec_get_number(val, sc);
-		val += sc;
-
-		debug("DRAM bank %d: start = %08lx, size = %08lx\n",
-		      i, (unsigned long)gd->bd->bi_dram[i].start,
-		      (unsigned long)gd->bd->bi_dram[i].size);
-	}
+	if (fdtdec_setup_memory_size() != 0)
+		return -EINVAL;
 
 	return 0;
 }
diff --git a/arch/arm/mach-mvebu/sata.c b/arch/arm/mach-mvebu/sata.c
index 140a295..5d8032b 100644
--- a/arch/arm/mach-mvebu/sata.c
+++ b/arch/arm/mach-mvebu/sata.c
@@ -35,7 +35,7 @@
 	 */
 	board_ahci_enable();
 
-	ahci_init(dev_get_addr_ptr(dev));
+	ahci_init(devfdt_get_addr_ptr(dev));
 
 	return 0;
 }
diff --git a/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c b/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
index fea8007..946a9f1 100644
--- a/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
+++ b/arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
@@ -852,7 +852,7 @@
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct rk3188_sdram_params *params = dev_get_platdata(dev);
 	const void *blob = gd->fdt_blob;
-	int node = dev->of_offset;
+	int node = dev_of_offset(dev);
 	int ret;
 
 	/* rk3188 supports only one-channel */
diff --git a/arch/arm/mach-rockchip/rk3328/clk_rk3328.c b/arch/arm/mach-rockchip/rk3328/clk_rk3328.c
index 1205516..4dcac27 100644
--- a/arch/arm/mach-rockchip/rk3328/clk_rk3328.c
+++ b/arch/arm/mach-rockchip/rk3328/clk_rk3328.c
@@ -25,7 +25,7 @@
 	if (ret)
 		return ERR_PTR(ret);
 
-	priv = dev_get_addr_ptr(dev);
+	priv = devfdt_get_addr_ptr(dev);
 
 	return priv->cru;
 }
diff --git a/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c b/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
index 536879d..a3ae8bd 100644
--- a/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
+++ b/arch/arm/mach-rockchip/rk3399/sdram_rk3399.c
@@ -1128,7 +1128,7 @@
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct rockchip_dmc_plat *plat = dev_get_platdata(dev);
 	const void *blob = gd->fdt_blob;
-	int node = dev->of_offset;
+	int node = dev_of_offset(dev);
 	int ret;
 
 	ret = fdtdec_get_int_array(blob, node, "rockchip,sdram-params",
diff --git a/arch/arm/mach-snapdragon/clock-apq8016.c b/arch/arm/mach-snapdragon/clock-apq8016.c
index c2cf924..da05015 100644
--- a/arch/arm/mach-snapdragon/clock-apq8016.c
+++ b/arch/arm/mach-snapdragon/clock-apq8016.c
@@ -235,7 +235,7 @@
 {
 	struct msm_clk_priv *priv = dev_get_priv(dev);
 
-	priv->base = dev_get_addr(dev);
+	priv->base = devfdt_get_addr(dev);
 	if (priv->base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 940257b..89d2a49 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -38,6 +38,7 @@
 	select OF_CONTROL
 	select VIDCONSOLE_AS_LCD if DM_VIDEO
 	select BOARD_EARLY_INIT_F
+	imply CRC32_VERIFY
 
 config TEGRA_NO_BPMP
 	bool "Tegra common options for SoCs without BPMP"
diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c
index bf16166..966cf9f 100644
--- a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c
+++ b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c
@@ -60,9 +60,9 @@
 
 	gd->ram_size = 0;
 	for (i = 0; i < len; i++) {
-		ram_banks[i].start = of_read_number(prop, na);
+		ram_banks[i].start = fdt_read_number(prop, na);
 		prop += na;
-		ram_banks[i].size = of_read_number(prop, ns);
+		ram_banks[i].size = fdt_read_number(prop, ns);
 		prop += ns;
 		gd->ram_size += ram_banks[i].size;
 	}
diff --git a/arch/arm/mach-uniphier/pinctrl-glue.c b/arch/arm/mach-uniphier/pinctrl-glue.c
index c52c6a6..3a9ec9c 100644
--- a/arch/arm/mach-uniphier/pinctrl-glue.c
+++ b/arch/arm/mach-uniphier/pinctrl-glue.c
@@ -5,10 +5,10 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#include <common.h>
 #include <linux/errno.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
-#include <dm/uclass.h>
 
 #include "init.h"
 
diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
index 4c02c48..a190485 100644
--- a/arch/mips/dts/Makefile
+++ b/arch/mips/dts/Makefile
@@ -9,8 +9,11 @@
 dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb
 dtb-$(CONFIG_TARGET_XILFPGA) += nexys4ddr.dtb
 dtb-$(CONFIG_BOARD_COMTREND_AR5387UN) += comtrend,ar-5387un.dtb
+dtb-$(CONFIG_BOARD_COMTREND_CT5361) += comtrend,ct-5361.dtb
 dtb-$(CONFIG_BOARD_COMTREND_VR3032U) += comtrend,vr-3032u.dtb
 dtb-$(CONFIG_BOARD_HUAWEI_HG556A) += huawei,hg556a.dtb
+dtb-$(CONFIG_BOARD_NETGEAR_CG3100D) += netgear,cg3100d.dtb
+dtb-$(CONFIG_BOARD_SAGEM_FAST1704) += sagem,f@st1704.dtb
 dtb-$(CONFIG_BOARD_TPLINK_WDR4300) += tplink_wdr4300.dtb
 
 targets += $(dtb-y)
diff --git a/arch/mips/dts/brcm,bcm3380.dtsi b/arch/mips/dts/brcm,bcm3380.dtsi
new file mode 100644
index 0000000..64245eb
--- /dev/null
+++ b/arch/mips/dts/brcm,bcm3380.dtsi
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <dt-bindings/clock/bcm3380-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/reset/bcm3380-reset.h>
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "brcm,bcm3380";
+
+	cpus {
+		reg = <0x14e00000 0x4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		u-boot,dm-pre-reloc;
+
+		cpu@0 {
+			compatible = "brcm,bcm3380-cpu", "mips,mips4Kc";
+			device_type = "cpu";
+			reg = <0>;
+			u-boot,dm-pre-reloc;
+		};
+
+		cpu@1 {
+			compatible = "brcm,bcm3380-cpu", "mips,mips4Kc";
+			device_type = "cpu";
+			reg = <1>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		u-boot,dm-pre-reloc;
+
+		periph_osc: periph-osc {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <48000000>;
+			u-boot,dm-pre-reloc;
+		};
+
+		periph_clk0: periph-clk@14e00004 {
+			compatible = "brcm,bcm6345-clk";
+			reg = <0x14e00004 0x4>;
+			#clock-cells = <1>;
+		};
+
+		periph_clk1: periph-clk@14e00008 {
+			compatible = "brcm,bcm6345-clk";
+			reg = <0x14e00008 0x4>;
+			#clock-cells = <1>;
+		};
+	};
+
+	ubus {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		u-boot,dm-pre-reloc;
+
+		memory-controller@12000000 {
+			compatible = "brcm,bcm6328-mc";
+			reg = <0x12000000 0x1000>;
+			u-boot,dm-pre-reloc;
+		};
+
+		periph_rst0: reset-controller@14e0008c {
+			compatible = "brcm,bcm6345-reset";
+			reg = <0x14e0008c 0x4>;
+			#reset-cells = <1>;
+		};
+
+		periph_rst1: reset-controller@14e00090 {
+			compatible = "brcm,bcm6345-reset";
+			reg = <0x14e00090 0x4>;
+			#reset-cells = <1>;
+		};
+
+		pll_cntl: syscon@14e00094 {
+			compatible = "syscon";
+			reg = <0x14e00094 0x4>;
+		};
+
+		syscon-reboot {
+			compatible = "syscon-reboot";
+			regmap = <&pll_cntl>;
+			offset = <0x0>;
+			mask = <0x1>;
+		};
+
+		wdt: watchdog@14e000dc {
+			compatible = "brcm,bcm6345-wdt";
+			reg = <0x14e000dc 0xc>;
+
+			clocks = <&periph_osc>;
+		};
+
+		wdt-reboot {
+			compatible = "wdt-reboot";
+			wdt = <&wdt>;
+		};
+
+		gpio0: gpio-controller@14e00100 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x14e00100 0x4>, <0x14e00108 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio1: gpio-controller@14e00104 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x14e00104 0x4>, <0x14e0010c 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			ngpios = <3>;
+
+			status = "disabled";
+		};
+
+		uart0: serial@14e00200 {
+			compatible = "brcm,bcm6345-uart";
+			reg = <0x14e00200 0x18>;
+			clocks = <&periph_osc>;
+
+			status = "disabled";
+		};
+
+		uart1: serial@14e00220 {
+			compatible = "brcm,bcm6345-uart";
+			reg = <0x14e00220 0x18>;
+			clocks = <&periph_osc>;
+
+			status = "disabled";
+		};
+
+		leds: led-controller@14e00f00 {
+			compatible = "brcm,bcm6328-leds";
+			reg = <0x14e00f00 0x1c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index b03763f..113a96b 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -84,6 +84,17 @@
 			#reset-cells = <1>;
 		};
 
+		wdt: watchdog@1000009c {
+			compatible = "brcm,bcm6345-wdt";
+			reg = <0x1000009c 0xc>;
+			clocks = <&periph_osc>;
+		};
+
+		wdt-reboot {
+			compatible = "wdt-reboot";
+			wdt = <&wdt>;
+		};
+
 		gpio1: gpio-controller@100000c0 {
 			compatible = "brcm,bcm6345-gpio";
 			reg = <0x100000c0 0x4>, <0x100000c8 0x4>;
diff --git a/arch/mips/dts/brcm,bcm6328.dtsi b/arch/mips/dts/brcm,bcm6328.dtsi
index 3926885..a996075 100644
--- a/arch/mips/dts/brcm,bcm6328.dtsi
+++ b/arch/mips/dts/brcm,bcm6328.dtsi
@@ -78,6 +78,17 @@
 			mask = <0x1>;
 		};
 
+		wdt: watchdog@1000005c {
+			compatible = "brcm,bcm6345-wdt";
+			reg = <0x1000005c 0xc>;
+			clocks = <&periph_osc>;
+		};
+
+		wdt-reboot {
+			compatible = "wdt-reboot";
+			wdt = <&wdt>;
+		};
+
 		gpio: gpio-controller@10000084 {
 			compatible = "brcm,bcm6345-gpio";
 			reg = <0x10000084 0x4>, <0x1000008c 0x4>;
diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
new file mode 100644
index 0000000..eb51a43
--- /dev/null
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <dt-bindings/clock/bcm6338-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/reset/bcm6338-reset.h>
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "brcm,bcm6338";
+
+	cpus {
+		reg = <0xfffe0000 0x4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		u-boot,dm-pre-reloc;
+
+		cpu@0 {
+			compatible = "brcm,bcm6338-cpu", "mips,mips4Kc";
+			device_type = "cpu";
+			reg = <0>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		u-boot,dm-pre-reloc;
+
+		periph_osc: periph-osc {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <50000000>;
+			u-boot,dm-pre-reloc;
+		};
+
+		periph_clk: periph-clk {
+			compatible = "brcm,bcm6345-clk";
+			reg = <0xfffe0004 0x4>;
+			#clock-cells = <1>;
+		};
+	};
+
+	pflash: nor@1fc00000 {
+		compatible = "cfi-flash";
+		reg = <0x1fc00000 0x400000>;
+		bank-width = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		status = "disabled";
+	};
+
+	ubus {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		u-boot,dm-pre-reloc;
+
+		pll_cntl: syscon@fffe0008 {
+			compatible = "syscon";
+			reg = <0xfffe0008 0x4>;
+		};
+
+		syscon-reboot {
+			compatible = "syscon-reboot";
+			regmap = <&pll_cntl>;
+			offset = <0x0>;
+			mask = <0x1>;
+		};
+
+		periph_rst: reset-controller@fffe0028 {
+			compatible = "brcm,bcm6345-reset";
+			reg = <0xfffe0028 0x4>;
+			#reset-cells = <1>;
+		};
+
+		wdt: watchdog@fffe021c {
+			compatible = "brcm,bcm6345-wdt";
+			reg = <0xfffe021c 0xc>;
+			clocks = <&periph_osc>;
+		};
+
+		wdt-reboot {
+			compatible = "wdt-reboot";
+			wdt = <&wdt>;
+		};
+
+		uart0: serial@fffe0300 {
+			compatible = "brcm,bcm6345-uart";
+			reg = <0xfffe0300 0x18>;
+			clocks = <&periph_osc>;
+
+			status = "disabled";
+		};
+
+		gpio: gpio-controller@fffe0404 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0xfffe0404 0x4>, <0xfffe040c 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			ngpios = <8>;
+
+			status = "disabled";
+		};
+
+		memory-controller@fffe3100 {
+			compatible = "brcm,bcm6338-mc";
+			reg = <0xfffe3100 0x38>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+};
diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
new file mode 100644
index 0000000..711b643
--- /dev/null
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <dt-bindings/clock/bcm6348-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/reset/bcm6348-reset.h>
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "brcm,bcm6348";
+
+	cpus {
+		reg = <0xfffe0000 0x4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		u-boot,dm-pre-reloc;
+
+		cpu@0 {
+			compatible = "brcm,bcm6348-cpu", "mips,mips4Kc";
+			device_type = "cpu";
+			reg = <0>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		u-boot,dm-pre-reloc;
+
+		periph_osc: periph-osc {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <50000000>;
+			u-boot,dm-pre-reloc;
+		};
+
+		periph_clk: periph-clk {
+			compatible = "brcm,bcm6345-clk";
+			reg = <0xfffe0004 0x4>;
+			#clock-cells = <1>;
+		};
+	};
+
+	pflash: nor@1fc00000 {
+		compatible = "cfi-flash";
+		reg = <0x1fc00000 0x2000000>;
+		bank-width = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		status = "disabled";
+	};
+
+	ubus {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		u-boot,dm-pre-reloc;
+
+		pll_cntl: syscon@fffe0008 {
+			compatible = "syscon";
+			reg = <0xfffe0008 0x4>;
+		};
+
+		syscon-reboot {
+			compatible = "syscon-reboot";
+			regmap = <&pll_cntl>;
+			offset = <0x0>;
+			mask = <0x1>;
+		};
+
+		periph_rst: reset-controller@fffe0028 {
+			compatible = "brcm,bcm6345-reset";
+			reg = <0xfffe0028 0x4>;
+			#reset-cells = <1>;
+		};
+
+		wdt: watchdog@fffe021c {
+			compatible = "brcm,bcm6345-wdt";
+			reg = <0xfffe021c 0xc>;
+			clocks = <&periph_osc>;
+		};
+
+		wdt-reboot {
+			compatible = "wdt-reboot";
+			wdt = <&wdt>;
+		};
+
+		uart0: serial@fffe0300 {
+			compatible = "brcm,bcm6345-uart";
+			reg = <0xfffe0300 0x18>;
+			clocks = <&periph_osc>;
+
+			status = "disabled";
+		};
+
+		gpio1: gpio-controller@fffe0400 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0xfffe0400 0x4>, <0xfffe0408 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			ngpios = <5>;
+
+			status = "disabled";
+		};
+
+		gpio0: gpio-controller@fffe0404 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0xfffe0404 0x4>, <0xfffe040c 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		memory-controller@fffe2300 {
+			compatible = "brcm,bcm6338-mc";
+			reg = <0xfffe2300 0x38>;
+			u-boot,dm-pre-reloc;
+		};
+	};
+};
diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 0dad998..4f63cf8 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -87,6 +87,17 @@
 			#reset-cells = <1>;
 		};
 
+		wdt: watchdog@fffe005c {
+			compatible = "brcm,bcm6345-wdt";
+			reg = <0xfffe005c 0xc>;
+			clocks = <&periph_osc>;
+		};
+
+		wdt-reboot {
+			compatible = "wdt-reboot";
+			wdt = <&wdt>;
+		};
+
 		gpio1: gpio-controller@fffe0080 {
 			compatible = "brcm,bcm6345-gpio";
 			reg = <0xfffe0080 0x4>, <0xfffe0088 0x4>;
diff --git a/arch/mips/dts/comtrend,ct-5361.dts b/arch/mips/dts/comtrend,ct-5361.dts
new file mode 100644
index 0000000..c909a52
--- /dev/null
+++ b/arch/mips/dts/comtrend,ct-5361.dts
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+#include "brcm,bcm6348.dtsi"
+
+/ {
+	model = "Comtrend CT-5361";
+	compatible = "comtrend,ct-5361", "brcm,bcm6348";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		power_green {
+			label = "CT-5361:green:power";
+			gpios = <&gpio0 0 1>;
+		};
+
+		alarm_red {
+			label = "CT-5361:red:alarm";
+			gpios = <&gpio0 2 1>;
+		};
+	};
+};
+
+&gpio0 {
+	status = "okay";
+};
+
+&pflash {
+	status = "okay";
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
diff --git a/arch/mips/dts/netgear,cg3100d.dts b/arch/mips/dts/netgear,cg3100d.dts
new file mode 100644
index 0000000..db1e2e7
--- /dev/null
+++ b/arch/mips/dts/netgear,cg3100d.dts
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+#include "brcm,bcm3380.dtsi"
+
+/ {
+	model = "Netgear CG3100D";
+	compatible = "netgear,cg3100d", "brcm,bcm3380";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		wifi_green {
+			label = "CG3100D:green:wifi";
+			gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+		};
+
+		wps_green {
+			label = "CG3100D:green:wps";
+			gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>;
+		};
+
+		power_red {
+			label = "CG3100D:red:power";
+			gpios = <&gpio0 19 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&leds {
+	status = "okay";
+
+	led@0 {
+		reg = <0>;
+		active-low;
+		label = "CG3100D:green:power";
+	};
+
+	led@1 {
+		reg = <1>;
+		active-low;
+		label = "CG3100D:green:downlink";
+	};
+
+	led@2 {
+		reg = <2>;
+		active-low;
+		label = "CG3100D:orange:downlink";
+	};
+
+	led@3 {
+		reg = <3>;
+		active-low;
+		label = "CG3100D:green:uplink";
+	};
+
+	led@4 {
+		reg = <4>;
+		active-low;
+		label = "CG3100D:orange:uplink";
+	};
+
+	led@6 {
+		reg = <6>;
+		active-low;
+		label = "CG3100D:green:inet";
+	};
+
+	led@7 {
+		reg = <7>;
+		active-low;
+		label = "CG3100D:green:stby";
+	};
+};
+
+&gpio0 {
+	status = "okay";
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
diff --git a/arch/mips/dts/sagem,f@st1704.dts b/arch/mips/dts/sagem,f@st1704.dts
new file mode 100644
index 0000000..be15fe5
--- /dev/null
+++ b/arch/mips/dts/sagem,f@st1704.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+#include "brcm,bcm6338.dtsi"
+
+/ {
+	model = "Sagem F@ST1704";
+	compatible = "sagem,f@st1704", "brcm,bcm6338";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		inet_green {
+			label = "F@ST1704:green:inet";
+			gpios = <&gpio 0 GPIO_ACTIVE_LOW>;
+		};
+
+		power_green {
+			label = "F@ST1704:green:power";
+			gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
+		};
+
+		inet_red {
+			label = "F@ST1704:red:inet";
+			gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&gpio {
+	status = "okay";
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
diff --git a/arch/mips/mach-bmips/Kconfig b/arch/mips/mach-bmips/Kconfig
index 4a0c383..e3e1da3 100644
--- a/arch/mips/mach-bmips/Kconfig
+++ b/arch/mips/mach-bmips/Kconfig
@@ -2,13 +2,27 @@
 	depends on ARCH_BMIPS
 
 config SYS_SOC
+	default "bcm3380" if SOC_BMIPS_BCM3380
 	default "bcm6328" if SOC_BMIPS_BCM6328
+	default "bcm6338" if SOC_BMIPS_BCM6338
+	default "bcm6348" if SOC_BMIPS_BCM6348
 	default "bcm6358" if SOC_BMIPS_BCM6358
 	default "bcm63268" if SOC_BMIPS_BCM63268
 
 choice
 	prompt "Broadcom MIPS SoC select"
 
+config SOC_BMIPS_BCM3380
+	bool "BMIPS BCM3380 family"
+	select SUPPORTS_BIG_ENDIAN
+	select SUPPORTS_CPU_MIPS32_R1
+	select MIPS_TUNE_4KC
+	select MIPS_L1_CACHE_SHIFT_4
+	select SWAP_IO_SPACE
+	select SYSRESET_WATCHDOG
+	help
+	  This supports BMIPS BCM3380 family.
+
 config SOC_BMIPS_BCM6328
 	bool "BMIPS BCM6328 family"
 	select SUPPORTS_BIG_ENDIAN
@@ -20,6 +34,28 @@
 	help
 	  This supports BMIPS BCM6328 family including BCM63281 and BCM63283.
 
+config SOC_BMIPS_BCM6338
+	bool "BMIPS BCM6338 family"
+	select SUPPORTS_BIG_ENDIAN
+	select SUPPORTS_CPU_MIPS32_R1
+	select MIPS_TUNE_4KC
+	select MIPS_L1_CACHE_SHIFT_4
+	select SWAP_IO_SPACE
+	select SYSRESET_SYSCON
+	help
+	  This supports BMIPS BCM6338 family.
+
+config SOC_BMIPS_BCM6348
+	bool "BMIPS BCM6348 family"
+	select SUPPORTS_BIG_ENDIAN
+	select SUPPORTS_CPU_MIPS32_R1
+	select MIPS_TUNE_4KC
+	select MIPS_L1_CACHE_SHIFT_4
+	select SWAP_IO_SPACE
+	select SYSRESET_WATCHDOG
+	help
+	  This supports BMIPS BCM6348 family.
+
 config SOC_BMIPS_BCM6358
 	bool "BMIPS BCM6358 family"
 	select SUPPORTS_BIG_ENDIAN
@@ -52,21 +88,78 @@
 	bool "Comtrend AR-5387un"
 	depends on SOC_BMIPS_BCM6328
 	select BMIPS_SUPPORTS_BOOT_RAM
+	help
+	  Comtrend AR-5387un boards have a BCM6328 SoC with 64 MB of RAM and 16
+	  MB of flash (SPI).
+	  Between its different peripherals there's an integrated switch with 4
+	  ethernet ports, 1 USB port, 1 UART, GPIO buttons and LEDs, and
+	  a BCM43225 (PCIe).
+
+config BOARD_COMTREND_CT5361
+	bool "Comtrend CT-5361"
+	depends on SOC_BMIPS_BCM6348
+	select BMIPS_SUPPORTS_BOOT_RAM
+	help
+	  Comtrend CT-5361 boards have a BCM6348 SoC with 16 MB of RAM and 4 MB
+	  of flash (CFI).
+	  Between its different peripherals there's a BCM5325 switch with 4
+	  ethernet ports, 1 USB port, 1 UART, GPIO buttons and LEDs, and a
+	  BCM4312 (miniPCI).
 
 config BOARD_COMTREND_VR3032U
 	bool "Comtrend VR-3032u board"
 	depends on SOC_BMIPS_BCM63268
 	select BMIPS_SUPPORTS_BOOT_RAM
+	help
+	  Comtrend VR-3032u boards have a BCM63268 SoC with 64 MB of RAM and
+	  128 MB of flash (NAND).
+	  Between its different peripherals there's an integrated switch with 4
+	  ethernet ports, 1 USB port, 1 UART, GPIO buttons and LEDs,
+	  and a BCM6362 (integrated).
 
 config BOARD_HUAWEI_HG556A
 	bool "Huawei EchoLife HG556a"
 	depends on SOC_BMIPS_BCM6358
 	select BMIPS_SUPPORTS_BOOT_RAM
+	help
+	  Huawei EchoLife HG556a boards have a BCM6358 SoC with 64 MB of RAM
+	  and 16 MB of flash (CFI).
+	  Between its different peripherals there's a BCM5325 switch with 4
+	  ethernet ports, 3 USB ports, 1 UART, GPIO buttons and LEDs, and
+	  a RT3062F/AR9223 (PCI).
+
+config BOARD_NETGEAR_CG3100D
+	bool "Netgear CG3100D"
+	depends on SOC_BMIPS_BCM3380
+	select BMIPS_SUPPORTS_BOOT_RAM
+	help
+	  Netgear CG3100D boards have a BCM3380 SoC with 64 MB of RAM and 8 MB
+	  of flash (SPI).
+	  Between its different peripherals there's a BCM53115 switch with 4
+	  ethernet ports, 1 UART, GPIO buttons and LEDs, and a BCM43225
+	  (miniPCIe).
+
+config BOARD_SAGEM_FAST1704
+	bool "Sagem F@ST1704"
+	depends on SOC_BMIPS_BCM6338
+	select BMIPS_SUPPORTS_BOOT_RAM
+	help
+	  Sagem F@ST1704 boards have a BCM6338 SoC with 16 MB of RAM and 4 MB
+	  of flash (SPI).
+	  Between its different peripherals there's a BCM5325 switch with 4
+	  ethernet ports, 1 UART, GPIO buttons and LEDs, and a BCM4312
+	  (miniPCI).
 
 config BOARD_SFR_NB4_SER
 	bool "SFR NeufBox 4 (Sercomm)"
 	depends on SOC_BMIPS_BCM6358
 	select BMIPS_SUPPORTS_BOOT_RAM
+	help
+	  SFR NeufBox 4 (Sercomm) boards have a BCM6358 SoC with 32 MB of RAM
+	  and 8 MB of flash (CFI).
+	  Between its different peripherals there's a BCM5325 switch with 4
+	  ethernet ports, 2 USB ports, 1 UART, GPIO buttons and LEDs, and
+	  a BCM4318 (PCI).
 
 endchoice
 
@@ -87,8 +180,11 @@
 	bool
 
 source "board/comtrend/ar5387un/Kconfig"
+source "board/comtrend/ct5361/Kconfig"
 source "board/comtrend/vr3032u/Kconfig"
 source "board/huawei/hg556a/Kconfig"
+source "board/netgear/cg3100d/Kconfig"
+source "board/sagem/f@st1704/Kconfig"
 source "board/sfr/nb4_ser/Kconfig"
 
 endmenu
diff --git a/arch/mips/mach-bmips/include/ioremap.h b/arch/mips/mach-bmips/include/ioremap.h
index 404690e..a57f55d 100644
--- a/arch/mips/mach-bmips/include/ioremap.h
+++ b/arch/mips/mach-bmips/include/ioremap.h
@@ -18,7 +18,9 @@
 
 static inline int is_bmips_internal_registers(phys_addr_t offset)
 {
-#if defined(CONFIG_SOC_BMIPS_BCM6358)
+#if defined(CONFIG_SOC_BMIPS_BCM6338) || \
+	defined(CONFIG_SOC_BMIPS_BCM6348) || \
+	defined(CONFIG_SOC_BMIPS_BCM6358)
 	if (offset >= 0xfffe0000)
 		return 1;
 #endif
diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index 2def722..3fe99b8 100644
--- a/arch/sandbox/cpu/cpu.c
+++ b/arch/sandbox/cpu/cpu.c
@@ -4,6 +4,7 @@
  */
 #define DEBUG
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <libfdt.h>
 #include <os.h>
diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c
index 2b4dbd3..0758448 100644
--- a/arch/sandbox/cpu/state.c
+++ b/arch/sandbox/cpu/state.c
@@ -351,6 +351,16 @@
 	return state->skip_delays;
 }
 
+void state_reset_for_test(struct sandbox_state *state)
+{
+	/* No reset yet, so mark it as such. Always allow power reset */
+	state->last_sysreset = SYSRESET_COUNT;
+	state->sysreset_allowed[SYSRESET_POWER] = true;
+
+	memset(&state->wdt, '\0', sizeof(state->wdt));
+	memset(state->spi, '\0', sizeof(state->spi));
+}
+
 int state_init(void)
 {
 	state = &main_state;
@@ -359,10 +369,7 @@
 	state->ram_buf = os_malloc(state->ram_size);
 	assert(state->ram_buf);
 
-	/* No reset yet, so mark it as such. Always allow power reset */
-	state->last_sysreset = SYSRESET_COUNT;
-	state->sysreset_allowed[SYSRESET_POWER] = true;
-
+	state_reset_for_test(state);
 	/*
 	 * Example of how to use GPIOs:
 	 *
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 9077a82..7dde95d 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -12,6 +12,8 @@
 		eth3 = &eth_3;
 		eth5 = &eth_5;
 		i2c0 = "/i2c@0";
+		mmc0 = "/mmc0";
+		mmc1 = "/mmc1";
 		pci0 = &pci;
 		remoteproc1 = &rproc_1;
 		remoteproc2 = &rproc_2;
@@ -259,7 +261,15 @@
 		mbox-names = "other", "test";
 	};
 
-	mmc {
+	mmc2 {
+		compatible = "sandbox,mmc";
+	};
+
+	mmc1 {
+		compatible = "sandbox,mmc";
+	};
+
+	mmc0 {
 		compatible = "sandbox,mmc";
 	};
 
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 987cc7b..617f952 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -214,6 +214,13 @@
 bool state_get_skip_delays(void);
 
 /**
+ * state_reset_for_test() - Reset ready to re-run tests
+ *
+ * This clears out any test state ready for another test run.
+ */
+void state_reset_for_test(struct sandbox_state *state);
+
+/**
  * Initialize the test system state
  */
 int state_init(void);
diff --git a/board/amlogic/odroid-c2/odroid-c2.c b/board/amlogic/odroid-c2/odroid-c2.c
index b61daaa..9306b56 100644
--- a/board/amlogic/odroid-c2/odroid-c2.c
+++ b/board/amlogic/odroid-c2/odroid-c2.c
@@ -5,10 +5,10 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/io.h>
 #include <asm/arch/gxbb.h>
 #include <asm/arch/sm.h>
-#include <dm/platdata.h>
 #include <phy.h>
 
 #define EFUSE_SN_OFFSET		20
diff --git a/board/armltd/integrator/integrator.c b/board/armltd/integrator/integrator.c
index cbe7061..fabb8b1 100644
--- a/board/armltd/integrator/integrator.c
+++ b/board/armltd/integrator/integrator.c
@@ -18,9 +18,9 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <netdev.h>
 #include <asm/io.h>
-#include <dm/platdata.h>
 #include <dm/platform_data/serial_pl01x.h>
 #include "arm-ebi.h"
 #include "integrator-sc.h"
diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c
index 0a22417..26e22c4 100644
--- a/board/armltd/vexpress64/vexpress64.c
+++ b/board/armltd/vexpress64/vexpress64.c
@@ -6,12 +6,12 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 #include <common.h>
+#include <dm.h>
 #include <malloc.h>
 #include <errno.h>
 #include <netdev.h>
 #include <asm/io.h>
 #include <linux/compiler.h>
-#include <dm/platdata.h>
 #include <dm/platform_data/serial_pl01x.h>
 #include "pcie.h"
 #include <asm/armv8/mmu.h>
diff --git a/board/beckhoff/mx53cx9020/mx53cx9020.c b/board/beckhoff/mx53cx9020/mx53cx9020.c
index c5d55dc..e903bc1 100644
--- a/board/beckhoff/mx53cx9020/mx53cx9020.c
+++ b/board/beckhoff/mx53cx9020/mx53cx9020.c
@@ -9,6 +9,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/sys_proto.h>
@@ -26,7 +27,6 @@
 #include <linux/fb.h>
 #include <ipu_pixfmt.h>
 #include <fs.h>
-#include <dm/platdata.h>
 #include <dm/platform_data/serial_mxc.h>
 
 enum LED_GPIOS {
diff --git a/board/cadence/xtfpga/xtfpga.c b/board/cadence/xtfpga/xtfpga.c
index 39b9b12..0265e9b 100644
--- a/board/cadence/xtfpga/xtfpga.c
+++ b/board/cadence/xtfpga/xtfpga.c
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <command.h>
-#include <dm/platdata.h>
+#include <dm.h>
 #include <dm/platform_data/net_ethoc.h>
 #include <linux/ctype.h>
 #include <linux/string.h>
diff --git a/board/cavium/thunderx/thunderx.c b/board/cavium/thunderx/thunderx.c
index 960ca53..02253af 100644
--- a/board/cavium/thunderx/thunderx.c
+++ b/board/cavium/thunderx/thunderx.c
@@ -5,6 +5,7 @@
 **/
 
 #include <common.h>
+#include <dm.h>
 #include <malloc.h>
 #include <errno.h>
 #include <linux/compiler.h>
@@ -13,7 +14,6 @@
 #include <asm/armv8/mmu.h>
 
 #if !CONFIG_IS_ENABLED(OF_CONTROL)
-#include <dm/platdata.h>
 #include <dm/platform_data/serial_pl01x.h>
 
 static const struct pl01x_serial_platdata serial0 = {
diff --git a/board/comtrend/ct5361/Kconfig b/board/comtrend/ct5361/Kconfig
new file mode 100644
index 0000000..d77d814
--- /dev/null
+++ b/board/comtrend/ct5361/Kconfig
@@ -0,0 +1,12 @@
+if BOARD_COMTREND_CT5361
+
+config SYS_BOARD
+	default "ct5361"
+
+config SYS_VENDOR
+	default "comtrend"
+
+config SYS_CONFIG_NAME
+	default "comtrend_ct5361"
+
+endif
diff --git a/board/comtrend/ct5361/MAINTAINERS b/board/comtrend/ct5361/MAINTAINERS
new file mode 100644
index 0000000..aea737a
--- /dev/null
+++ b/board/comtrend/ct5361/MAINTAINERS
@@ -0,0 +1,6 @@
+COMTREND CT-5361 BOARD
+M:	Álvaro Fernández Rojas <noltari@gmail.com>
+S:	Maintained
+F:	board/comtrend/ct-5361/
+F:	include/configs/comtrend_ct5361.h
+F:	configs/comtrend_ct5361_ram_defconfig
diff --git a/board/comtrend/ct5361/Makefile b/board/comtrend/ct5361/Makefile
new file mode 100644
index 0000000..872e80a
--- /dev/null
+++ b/board/comtrend/ct5361/Makefile
@@ -0,0 +1,5 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += ct-5361.o
diff --git a/board/comtrend/ct5361/ct-5361.c b/board/comtrend/ct5361/ct-5361.c
new file mode 100644
index 0000000..d181ca6
--- /dev/null
+++ b/board/comtrend/ct5361/ct-5361.c
@@ -0,0 +1,7 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
diff --git a/board/freescale/common/fsl_chain_of_trust.c b/board/freescale/common/fsl_chain_of_trust.c
index aad1b93..2cd4fba 100644
--- a/board/freescale/common/fsl_chain_of_trust.c
+++ b/board/freescale/common/fsl_chain_of_trust.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <fsl_validate.h>
 #include <fsl_secboot_err.h>
 #include <fsl_sfp.h>
diff --git a/board/freescale/common/fsl_validate.c b/board/freescale/common/fsl_validate.c
index ed48c5c..ef93407 100644
--- a/board/freescale/common/fsl_validate.c
+++ b/board/freescale/common/fsl_validate.c
@@ -5,13 +5,13 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <fsl_validate.h>
 #include <fsl_secboot_err.h>
 #include <fsl_sfp.h>
 #include <fsl_sec.h>
 #include <command.h>
 #include <malloc.h>
-#include <dm/uclass.h>
 #include <u-boot/rsa-mod-exp.h>
 #include <hash.h>
 #include <fsl_secboot_err.h>
diff --git a/board/netgear/cg3100d/Kconfig b/board/netgear/cg3100d/Kconfig
new file mode 100644
index 0000000..632c22d
--- /dev/null
+++ b/board/netgear/cg3100d/Kconfig
@@ -0,0 +1,12 @@
+if BOARD_NETGEAR_CG3100D
+
+config SYS_BOARD
+	default "cg3100d"
+
+config SYS_VENDOR
+	default "netgear"
+
+config SYS_CONFIG_NAME
+	default "netgear_cg3100d"
+
+endif
diff --git a/board/netgear/cg3100d/MAINTAINERS b/board/netgear/cg3100d/MAINTAINERS
new file mode 100644
index 0000000..f1dcb1f
--- /dev/null
+++ b/board/netgear/cg3100d/MAINTAINERS
@@ -0,0 +1,6 @@
+NETGEAR CG3100D BOARD
+M:	Álvaro Fernández Rojas <noltari@gmail.com>
+S:	Maintained
+F:	board/netgear/cg3100d/
+F:	include/configs/netgear_cg3100d.h
+F:	configs/netgear_cg3100d_ram_defconfig
diff --git a/board/netgear/cg3100d/Makefile b/board/netgear/cg3100d/Makefile
new file mode 100644
index 0000000..b82e59e
--- /dev/null
+++ b/board/netgear/cg3100d/Makefile
@@ -0,0 +1,5 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += cg3100d.o
diff --git a/board/netgear/cg3100d/cg3100d.c b/board/netgear/cg3100d/cg3100d.c
new file mode 100644
index 0000000..d181ca6
--- /dev/null
+++ b/board/netgear/cg3100d/cg3100d.c
@@ -0,0 +1,7 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
diff --git a/board/qualcomm/dragonboard410c/dragonboard410c.c b/board/qualcomm/dragonboard410c/dragonboard410c.c
index e923ddc..37d0b85 100644
--- a/board/qualcomm/dragonboard410c/dragonboard410c.c
+++ b/board/qualcomm/dragonboard410c/dragonboard410c.c
@@ -53,8 +53,8 @@
 			printf("Failed to find usb_hub_reset_pm dt node.\n");
 			return node;
 		}
-		ret = gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0,
-						 &hub_reset, 0);
+		ret = gpio_request_by_name_nodev(offset_to_ofnode(node),
+						 "gpios", 0, &hub_reset, 0);
 		if (ret < 0) {
 			printf("Failed to request usb_hub_reset_pm gpio.\n");
 			return ret;
@@ -69,8 +69,8 @@
 			printf("Failed to find usb_sw_sel_pm dt node.\n");
 			return 0;
 		}
-		ret = gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0,
-						 &usb_sel, 0);
+		ret = gpio_request_by_name_nodev(offset_to_ofnode(node),
+						 "gpios", 0, &usb_sel, 0);
 		if (ret < 0) {
 			printf("Failed to request usb_sw_sel_pm gpio.\n");
 			return ret;
@@ -121,8 +121,8 @@
 		return 0;
 	}
 
-	if (gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0, &resin,
-				       0)) {
+	if (gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0,
+				       &resin, 0)) {
 		printf("Failed to request key_vol_down button.\n");
 		return 0;
 	}
diff --git a/board/sagem/f@st1704/Kconfig b/board/sagem/f@st1704/Kconfig
new file mode 100644
index 0000000..4566fcc
--- /dev/null
+++ b/board/sagem/f@st1704/Kconfig
@@ -0,0 +1,12 @@
+if BOARD_SAGEM_FAST1704
+
+config SYS_BOARD
+	default "f@st1704"
+
+config SYS_VENDOR
+	default "sagem"
+
+config SYS_CONFIG_NAME
+	default "sagem_f@st1704"
+
+endif
diff --git a/board/sagem/f@st1704/MAINTAINERS b/board/sagem/f@st1704/MAINTAINERS
new file mode 100644
index 0000000..72e1c5c
--- /dev/null
+++ b/board/sagem/f@st1704/MAINTAINERS
@@ -0,0 +1,6 @@
+SAGEM F@ST1704 BOARD
+M:	Álvaro Fernández Rojas <noltari@gmail.com>
+S:	Maintained
+F:	board/sagem/f@st1704/
+F:	include/configs/sagem_f@st1704.h
+F:	configs/sagem_f@st1704_ram_defconfig
diff --git a/board/sagem/f@st1704/Makefile b/board/sagem/f@st1704/Makefile
new file mode 100644
index 0000000..a5f97f8
--- /dev/null
+++ b/board/sagem/f@st1704/Makefile
@@ -0,0 +1,5 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += f@st1704.o
diff --git a/board/sagem/f@st1704/f@st1704.c b/board/sagem/f@st1704/f@st1704.c
new file mode 100644
index 0000000..d181ca6
--- /dev/null
+++ b/board/sagem/f@st1704/f@st1704.c
@@ -0,0 +1,7 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
diff --git a/board/samsung/common/board.c b/board/samsung/common/board.c
index 1762696..88299f1 100644
--- a/board/samsung/common/board.c
+++ b/board/samsung/common/board.c
@@ -351,8 +351,8 @@
 	if (node < 0)
 		return;
 
-	gpio_request_by_name_nodev(gd->fdt_blob, node, "reset-gpio", 0, &gpio,
-				   GPIOD_IS_OUT);
+	gpio_request_by_name_nodev(offset_to_ofnode(node), "reset-gpio", 0,
+				   &gpio, GPIOD_IS_OUT);
 
 	if (dm_gpio_is_valid(&gpio)) {
 		/*
diff --git a/board/samsung/common/exynos5-dt.c b/board/samsung/common/exynos5-dt.c
index aec1f39..44f412d 100644
--- a/board/samsung/common/exynos5-dt.c
+++ b/board/samsung/common/exynos5-dt.c
@@ -45,7 +45,7 @@
 	if (node <= 0)
 		return;
 
-	ret = gpio_request_by_name_nodev(gd->fdt_blob, node,
+	ret = gpio_request_by_name_nodev(offset_to_ofnode(node),
 					 "codec-enable-gpio", 0, &en_gpio,
 					 GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
 	if (ret == -FDT_ERR_NOTFOUND)
diff --git a/board/samsung/common/misc.c b/board/samsung/common/misc.c
index dc4dead..b18eed2 100644
--- a/board/samsung/common/misc.c
+++ b/board/samsung/common/misc.c
@@ -18,6 +18,19 @@
 #include <asm/gpio.h>
 #include <linux/input.h>
 #include <dm.h>
+/*
+ * Use #ifdef to work around conflicting headers while we wait for this to be
+ * converted to driver model.
+ */
+#ifdef CONFIG_DM_PMIC_MAX77686
+#include <power/max77686_pmic.h>
+#endif
+#ifdef CONFIG_DM_PMIC_MAX8998
+#include <power/max8998_pmic.h>
+#endif
+#ifdef CONFIG_PMIC_MAX8997
+#include <power/max8997_pmic.h>
+#endif
 #include <power/pmic.h>
 #include <mmc.h>
 
diff --git a/board/sandbox/MAINTAINERS b/board/sandbox/MAINTAINERS
index 4dcbf4b..6d0790c 100644
--- a/board/sandbox/MAINTAINERS
+++ b/board/sandbox/MAINTAINERS
@@ -18,3 +18,10 @@
 F:	board/sandbox/
 F:	include/configs/sandbox_spl.h
 F:	configs/sandbox_spl_defconfig
+
+SANDBOX FLAT TREE BOARD
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	board/sandbox/
+F:	include/configs/sandbox.h
+F:	configs/sandbox_flattree_defconfig
diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c
index 2773f59..3a8257c 100644
--- a/board/solidrun/clearfog/clearfog.c
+++ b/board/solidrun/clearfog/clearfog.c
@@ -131,8 +131,12 @@
 	/* Toggle GPIO41 to reset onboard switch and phy */
 	clrbits_le32(MVEBU_GPIO1_BASE + 0x0, BIT(9));
 	clrbits_le32(MVEBU_GPIO1_BASE + 0x4, BIT(9));
+	/* GPIO 19 on ClearFog rev 2.1 controls the uSOM onboard phy reset */
+	clrbits_le32(MVEBU_GPIO0_BASE + 0x0, BIT(19));
+	clrbits_le32(MVEBU_GPIO0_BASE + 0x4, BIT(19));
 	mdelay(1);
 	setbits_le32(MVEBU_GPIO1_BASE + 0x0, BIT(9));
+	setbits_le32(MVEBU_GPIO0_BASE + 0x0, BIT(19));
 	mdelay(10);
 
 	/* Init I2C IO expanders */
diff --git a/board/st/stm32f429-discovery/stm32f429-discovery.c b/board/st/stm32f429-discovery/stm32f429-discovery.c
index d16d73f..8c8abf6 100644
--- a/board/st/stm32f429-discovery/stm32f429-discovery.c
+++ b/board/st/stm32f429-discovery/stm32f429-discovery.c
@@ -12,12 +12,12 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/io.h>
 #include <asm/armv7m.h>
 #include <asm/arch/stm32.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/fmc.h>
-#include <dm/platdata.h>
 #include <dm/platform_data/serial_stm32.h>
 #include <asm/arch/stm32_periph.h>
 #include <asm/arch/stm32_defs.h>
diff --git a/board/st/stm32f746-disco/stm32f746-disco.c b/board/st/stm32f746-disco/stm32f746-disco.c
index dc3a9dc..7a6d93c 100644
--- a/board/st/stm32f746-disco/stm32f746-disco.c
+++ b/board/st/stm32f746-disco/stm32f746-disco.c
@@ -12,7 +12,7 @@
 #include <asm/armv7m.h>
 #include <asm/arch/stm32.h>
 #include <asm/arch/gpio.h>
-#include <dm/platdata.h>
+#include <asm/arch/fmc.h>
 #include <dm/platform_data/serial_stm32x7.h>
 #include <asm/arch/stm32_periph.h>
 #include <asm/arch/stm32_defs.h>
@@ -101,7 +101,7 @@
 	if (node < 0)
 		return -1;
 
-	gpio_request_by_name_nodev(gd->fdt_blob, node, "led-gpio", 0, &gpio,
+	gpio_request_by_name_nodev(offset_to_ofnode(node), "led-gpio", 0, &gpio,
 				   GPIOD_IS_OUT);
 
 	if (dm_gpio_is_valid(&gpio)) {
@@ -115,8 +115,8 @@
 	if (node < 0)
 		return -1;
 
-	gpio_request_by_name_nodev(gd->fdt_blob, node, "button-gpio", 0, &gpio,
-				   GPIOD_IS_IN);
+	gpio_request_by_name_nodev(offset_to_ofnode(node), "button-gpio", 0,
+				   &gpio, GPIOD_IS_IN);
 
 	if (dm_gpio_is_valid(&gpio)) {
 		if (dm_gpio_get_value(&gpio))
diff --git a/board/st/stv0991/stv0991.c b/board/st/stv0991/stv0991.c
index 6a19730..85ac66e 100644
--- a/board/st/stv0991/stv0991.c
+++ b/board/st/stv0991/stv0991.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <miiphy.h>
 #include <asm/arch/stv0991_periph.h>
 #include <asm/arch/stv0991_defs.h>
@@ -13,7 +14,6 @@
 #include <asm/arch/gpio.h>
 #include <netdev.h>
 #include <asm/io.h>
-#include <dm/platdata.h>
 #include <dm/platform_data/serial_pl01x.h>
 
 DECLARE_GLOBAL_DATA_PTR;
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index a512a20..0f1290a 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -114,6 +114,11 @@
 F:	configs/Bananapi_M2_Ultra_defconfig
 F:	arch/arm/dts/sun8i-r40-bananapi-m2-ultra.dts
 
+BANANAPI M64
+M:	Jagan Teki <jagan@amarulasolutions.com>
+S:	Maintained
+F:	configs/bananapi_m64_defconfig
+
 COLOMBUS BOARD
 M:	Maxime Ripard <maxime.ripard@free-electrons.com>
 S:	Maintained
@@ -237,6 +242,11 @@
 S:	Maintained
 F:	configs/MSI_Primo81_defconfig
 
+NANOPI-M1 BOARD
+M:	Mylène Josserand <mylene.josserand@free-electrons.com>
+S:	Maintained
+F:	configs/nanopi_m1_defconfig
+
 NANOPI-NEO BOARD
 M:	Jelle van der Waa <jelle@vdwaa.nl>
 S:	Maintained
@@ -262,6 +272,11 @@
 S:	Maintained
 F:	configs/orangepi_pc2_defconfig
 
+ORANGEPI PRIME BOARD
+M:	Jagan Teki <jagan@amarulasolutions.com>
+S:	Maintained
+F:	configs/orangepi_prime_defconfig
+
 PINE64 BOARDS
 M:	Andre Przywara <andre.przywara@arm.com>
 S:	Maintained
diff --git a/board/ti/common/Kconfig b/board/ti/common/Kconfig
index 1187cf5..c21eb8c 100644
--- a/board/ti/common/Kconfig
+++ b/board/ti/common/Kconfig
@@ -18,6 +18,7 @@
 	bool "Enable cmd options on TI platforms"
 	imply CMD_ASKENV
 	imply CMD_BOOTZ
+	imply CRC32_VERIFY if ARCH_KEYSTONE
 	imply CMD_DFU if USB_GADGET_DOWNLOAD
 	imply CMD_DHCP
 	imply CMD_EEPROM
@@ -26,6 +27,7 @@
 	imply CMD_EXT4_WRITE
 	imply CMD_FASTBOOT if FASTBOOT
 	imply CMD_FAT
+	imply FAT_WRITE if CMD_FAT
 	imply CMD_FS_GENERIC
 	imply CMD_GPIO
 	imply CMD_GPT
diff --git a/board/toradex/apalis_imx6/apalis_imx6.c b/board/toradex/apalis_imx6/apalis_imx6.c
index 45f1d5d..7c49ddf 100644
--- a/board/toradex/apalis_imx6/apalis_imx6.c
+++ b/board/toradex/apalis_imx6/apalis_imx6.c
@@ -8,6 +8,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/crm_regs.h>
 #include <asm/arch/mxc_hdmi.h>
diff --git a/board/toradex/colibri_imx6/colibri_imx6.c b/board/toradex/colibri_imx6/colibri_imx6.c
index d070677..69467ca 100644
--- a/board/toradex/colibri_imx6/colibri_imx6.c
+++ b/board/toradex/colibri_imx6/colibri_imx6.c
@@ -8,6 +8,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/crm_regs.h>
 #include <asm/arch/imx-regs.h>
diff --git a/board/toradex/colibri_pxa270/colibri_pxa270.c b/board/toradex/colibri_pxa270/colibri_pxa270.c
index 8e94854..5d62e66 100644
--- a/board/toradex/colibri_pxa270/colibri_pxa270.c
+++ b/board/toradex/colibri_pxa270/colibri_pxa270.c
@@ -8,6 +8,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/pxa.h>
 #include <asm/arch/regs-mmc.h>
diff --git a/board/toradex/common/tdx-cfg-block.c b/board/toradex/common/tdx-cfg-block.c
index 0014ce8..2a810c8 100644
--- a/board/toradex/common/tdx-cfg-block.c
+++ b/board/toradex/common/tdx-cfg-block.c
@@ -110,7 +110,7 @@
 		ret = -ENODEV;
 		goto out;
 	}
-	if (part != mmc->block_dev.hwpart) {
+	if (part != mmc_get_blk_desc(mmc)->hwpart) {
 		if (blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part)) {
 			puts("MMC partition switch failed\n");
 			ret = -ENODEV;
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 5ee52f6..270cff6 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -355,6 +355,12 @@
 	help
 	  Compute CRC32.
 
+config CRC32_VERIFY
+	bool "crc32 -v"
+	depends on CMD_CRC32
+	help
+	  Add -v option to verify data against a crc32 checksum.
+
 config CMD_EEPROM
 	bool "eeprom - EEPROM subsystem"
 	help
@@ -410,13 +416,25 @@
 	help
 	  Compute MD5 checksum.
 
-config MD5SUM_VERFIY
+config MD5SUM_VERIFY
 	bool "md5sum -v"
 	default n
 	depends on CMD_MD5SUM
 	help
 	  Add -v option to verify data against an MD5 checksum.
 
+config CMD_SHA1SUM
+	bool "sha1sum"
+	select SHA1
+	help
+	  Compute SHA1 checksum.
+
+config SHA1SUM_VERIFY
+	bool "sha1sum -v"
+	depends on CMD_SHA1SUM
+	help
+	  Add -v option to verify data against a SHA1 checksum.
+
 config LOOPW
 	bool "loopw"
 	help
@@ -1068,6 +1086,12 @@
 	  saved to memory or to an environment variable. It is also possible
 	  to verify a hash against data in memory.
 
+config HASH_VERIFY
+	bool "hash -v"
+	depends on CMD_HASH
+	help
+	  Add -v option to verify data against a hash.
+
 config CMD_TPM
 	bool "Enable the 'tpm' command"
 	depends on TPM
@@ -1142,6 +1166,7 @@
 
 config CMD_FAT
 	bool "FAT command support"
+	select FS_FAT
 	help
 	  Support for the FAT fs
 
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 3b77705..a0a5434 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -8,7 +8,7 @@
 
 #include <common.h>
 #include <command.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <efi_loader.h>
 #include <errno.h>
 #include <libfdt.h>
diff --git a/cmd/mem.c b/cmd/mem.c
index b6e200b..27075e5 100644
--- a/cmd/mem.c
+++ b/cmd/mem.c
@@ -1160,7 +1160,7 @@
 
 	av = argv + 1;
 	ac = argc - 1;
-#ifdef CONFIG_HASH_VERIFY
+#ifdef CONFIG_CRC32_VERIFY
 	if (strcmp(*av, "-v") == 0) {
 		flags |= HASH_FLAG_VERIFY | HASH_FLAG_ENV;
 		av++;
@@ -1238,7 +1238,7 @@
 
 #ifdef CONFIG_CMD_CRC32
 
-#ifndef CONFIG_HASH_VERIFY
+#ifndef CONFIG_CRC32_VERIFY
 
 U_BOOT_CMD(
 	crc32,	4,	1,	do_mem_crc,
@@ -1246,7 +1246,7 @@
 	"address count [addr]\n    - compute CRC32 checksum [save at addr]"
 );
 
-#else	/* CONFIG_HASH_VERIFY */
+#else	/* CONFIG_CRC32_VERIFY */
 
 U_BOOT_CMD(
 	crc32,	5,	1,	do_mem_crc,
@@ -1255,7 +1255,7 @@
 	"-v address count crc\n    - verify crc of memory area"
 );
 
-#endif	/* CONFIG_HASH_VERIFY */
+#endif	/* CONFIG_CRC32_VERIFY */
 
 #endif
 
diff --git a/common/board_r.c b/common/board_r.c
index fe7a70b..00ba319 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -40,6 +40,7 @@
 #endif
 #include <mmc.h>
 #include <nand.h>
+#include <of_live.h>
 #include <onenand_uboot.h>
 #include <scsi.h>
 #include <serial.h>
@@ -292,6 +293,14 @@
 }
 #endif
 
+#ifdef CONFIG_OF_LIVE
+static int initr_of_live(void)
+{
+	return of_live_build(gd->fdt_blob,
+			      (struct device_node **)&gd->of_root);
+}
+#endif
+
 #ifdef CONFIG_DM
 static int initr_dm(void)
 {
@@ -722,6 +731,9 @@
 	initr_noncached,
 #endif
 	bootstage_relocate,
+#ifdef CONFIG_OF_LIVE
+	initr_of_live,
+#endif
 #ifdef CONFIG_DM
 	initr_dm,
 #endif
diff --git a/common/env_mmc.c b/common/env_mmc.c
index a5d14d4..404de85 100644
--- a/common/env_mmc.c
+++ b/common/env_mmc.c
@@ -10,6 +10,7 @@
 
 #include <command.h>
 #include <environment.h>
+#include <fdtdec.h>
 #include <linux/stddef.h>
 #include <malloc.h>
 #include <memalign.h>
@@ -36,15 +37,37 @@
 #define CONFIG_ENV_OFFSET 0
 #endif
 
-__weak int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr)
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static inline s64 mmc_offset(int copy)
 {
-	s64 offset;
+	const char *propname = "u-boot,mmc-env-offset";
+	s64 defvalue = CONFIG_ENV_OFFSET;
 
-	offset = CONFIG_ENV_OFFSET;
-#ifdef CONFIG_ENV_OFFSET_REDUND
+#if defined(CONFIG_ENV_OFFSET_REDUND)
+	if (copy) {
+		propname = "u-boot,mmc-env-offset-redundant";
+		defvalue = CONFIG_ENV_OFFSET_REDUND;
+	}
+#endif
+
+	return fdtdec_get_config_int(gd->fdt_blob, propname, defvalue);
+}
+#else
+static inline s64 mmc_offset(int copy)
+{
+	s64 offset = CONFIG_ENV_OFFSET;
+
+#if defined(CONFIG_ENV_OFFSET_REDUND)
 	if (copy)
 		offset = CONFIG_ENV_OFFSET_REDUND;
 #endif
+	return offset;
+}
+#endif
+
+__weak int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr)
+{
+	s64 offset = mmc_offset(copy);
 
 	if (offset < 0)
 		offset += mmc->capacity;
@@ -98,9 +121,10 @@
 	if (!mmc)
 		return "!No MMC card found";
 
+#ifndef CONFIG_BLK
 	if (mmc_init(mmc))
 		return "!MMC init failed";
-
+#endif
 	if (mmc_set_env_part(mmc))
 		return "!MMC partition switch failed";
 
diff --git a/common/env_sf.c b/common/env_sf.c
index 9944602..45f441a 100644
--- a/common/env_sf.c
+++ b/common/env_sf.c
@@ -10,6 +10,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 #include <common.h>
+#include <dm.h>
 #include <environment.h>
 #include <malloc.h>
 #include <spi.h>
diff --git a/common/fdt_support.c b/common/fdt_support.c
index c6a76b7..dfdc04d 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1008,7 +1008,7 @@
 };
 
 /* Default translator (generic bus) */
-void of_bus_default_count_cells(const void *blob, int parentoffset,
+void fdt_support_default_count_cells(const void *blob, int parentoffset,
 					int *addrc, int *sizec)
 {
 	const fdt32_t *prop;
@@ -1030,9 +1030,9 @@
 {
 	u64 cp, s, da;
 
-	cp = of_read_number(range, na);
-	s  = of_read_number(range + na + pna, ns);
-	da = of_read_number(addr, na);
+	cp = fdt_read_number(range, na);
+	s  = fdt_read_number(range + na + pna, ns);
+	da = fdt_read_number(addr, na);
 
 	debug("OF: default map, cp=%" PRIu64 ", s=%" PRIu64
 	      ", da=%" PRIu64 "\n", cp, s, da);
@@ -1044,7 +1044,7 @@
 
 static int of_bus_default_translate(fdt32_t *addr, u64 offset, int na)
 {
-	u64 a = of_read_number(addr, na);
+	u64 a = fdt_read_number(addr, na);
 	memset(addr, 0, na * 4);
 	a += offset;
 	if (na > 1)
@@ -1086,9 +1086,9 @@
 	if ((addr[0] ^ range[0]) & cpu_to_be32(1))
 		return OF_BAD_ADDR;
 
-	cp = of_read_number(range + 1, na - 1);
-	s  = of_read_number(range + na + pna, ns);
-	da = of_read_number(addr + 1, na - 1);
+	cp = fdt_read_number(range + 1, na - 1);
+	s  = fdt_read_number(range + na + pna, ns);
+	da = fdt_read_number(addr + 1, na - 1);
 
 	debug("OF: ISA map, cp=%" PRIu64 ", s=%" PRIu64
 	      ", da=%" PRIu64 "\n", cp, s, da);
@@ -1122,7 +1122,7 @@
 	{
 		.name = "default",
 		.addresses = "reg",
-		.count_cells = of_bus_default_count_cells,
+		.count_cells = fdt_support_default_count_cells,
 		.map = of_bus_default_map,
 		.translate = of_bus_default_translate,
 	},
@@ -1173,7 +1173,7 @@
 	 */
 	ranges = fdt_getprop(blob, parent, rprop, &rlen);
 	if (ranges == NULL || rlen == 0) {
-		offset = of_read_number(addr, na);
+		offset = fdt_read_number(addr, na);
 		memset(addr, 0, pna * 4);
 		debug("OF: no ranges, 1:1 translation\n");
 		goto finish;
@@ -1253,7 +1253,7 @@
 		/* If root, we have finished */
 		if (parent < 0) {
 			debug("OF: reached root node\n");
-			result = of_read_number(addr, na);
+			result = fdt_read_number(addr, na);
 			break;
 		}
 
@@ -1539,7 +1539,7 @@
 /*
  * Returns the base address of an SOC or PCI node
  */
-u64 fdt_get_base_address(void *fdt, int node)
+u64 fdt_get_base_address(const void *fdt, int node)
 {
 	int size;
 	u32 naddr;
@@ -1666,8 +1666,8 @@
 	fdt32_t cells[4];
 	int i, addrc, sizec, ret;
 
-	of_bus_default_count_cells(fdt, fdt_parent_offset(fdt, node),
-				   &addrc, &sizec);
+	fdt_support_default_count_cells(fdt, fdt_parent_offset(fdt, node),
+					&addrc, &sizec);
 	i = 0;
 	if (addrc == 2)
 		cells[i++] = cpu_to_fdt32(base_address >> 32);
diff --git a/common/hash.c b/common/hash.c
index a0eded9..771d8fa 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -178,16 +178,9 @@
 	},
 };
 
-#if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM)
-#define MULTI_HASH
-#endif
-
-#if defined(CONFIG_HASH_VERIFY) || defined(CONFIG_CMD_HASH)
-#define MULTI_HASH
-#endif
-
 /* Try to minimize code size for boards that don't want much hashing */
-#ifdef MULTI_HASH
+#if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM) || \
+	defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_CMD_HASH)
 #define multi_hash()	1
 #else
 #define multi_hash()	0
@@ -424,7 +417,8 @@
 		unmap_sysmem(buf);
 
 		/* Try to avoid code bloat when verify is not needed */
-#ifdef CONFIG_HASH_VERIFY
+#if defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_SHA1SUM_VERIFY) || \
+	defined(CONFIG_HASH_VERIFY)
 		if (flags & HASH_FLAG_VERIFY) {
 #else
 		if (0) {
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index eabb2d0..48a0fad 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -306,6 +306,7 @@
 config SPL_FAT_SUPPORT
 	bool "Support FAT filesystems"
 	depends on SPL
+	select FS_FAT
 	help
 	  Enable support for FAT and VFAT filesystems with SPL. This
 	  permits U-Boot (or Linux in Falcon mode) to be loaded from a FAT
diff --git a/configs/Sinlinx_SinA33_defconfig b/configs/Sinlinx_SinA33_defconfig
index 8a51bf3..d1b5b22 100644
--- a/configs/Sinlinx_SinA33_defconfig
+++ b/configs/Sinlinx_SinA33_defconfig
@@ -1,5 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_SUNXI=y
+CONFIG_CONS_INDEX=1
 CONFIG_MACH_SUN8I_A33=y
 CONFIG_DRAM_CLK=552
 CONFIG_DRAM_ZQ=15291
diff --git a/configs/am335x_baltos_defconfig b/configs/am335x_baltos_defconfig
index 590673b..f210cca 100644
--- a/configs/am335x_baltos_defconfig
+++ b/configs/am335x_baltos_defconfig
@@ -60,4 +60,5 @@
 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/am335x_evm_nor_defconfig b/configs/am335x_evm_nor_defconfig
index 55ed8f3..31019e3 100644
--- a/configs/am335x_evm_nor_defconfig
+++ b/configs/am335x_evm_nor_defconfig
@@ -44,4 +44,5 @@
 CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
 CONFIG_G_DNL_VENDOR_NUM=0x0451
 CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/am335x_igep003x_defconfig b/configs/am335x_igep003x_defconfig
index fa468f0..651e194 100644
--- a/configs/am335x_igep003x_defconfig
+++ b/configs/am335x_igep003x_defconfig
@@ -49,6 +49,7 @@
 CONFIG_MMC_OMAP_HS=y
 CONFIG_MTD_UBI_FASTMAP=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 CONFIG_FDT_FIXUP_PARTITIONS=y
 # CONFIG_GENERATE_SMBIOS_TABLE is not set
diff --git a/configs/am335x_shc_defconfig b/configs/am335x_shc_defconfig
index 1068678..ab912bb 100644
--- a/configs/am335x_shc_defconfig
+++ b/configs/am335x_shc_defconfig
@@ -39,4 +39,5 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/am335x_shc_ict_defconfig b/configs/am335x_shc_ict_defconfig
index 85b24a5..7d75c5c 100644
--- a/configs/am335x_shc_ict_defconfig
+++ b/configs/am335x_shc_ict_defconfig
@@ -39,4 +39,5 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/am335x_shc_netboot_defconfig b/configs/am335x_shc_netboot_defconfig
index 9117407..322a070 100644
--- a/configs/am335x_shc_netboot_defconfig
+++ b/configs/am335x_shc_netboot_defconfig
@@ -40,4 +40,5 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/am335x_shc_prompt_defconfig b/configs/am335x_shc_prompt_defconfig
index e71e54b..c5d8dca 100644
--- a/configs/am335x_shc_prompt_defconfig
+++ b/configs/am335x_shc_prompt_defconfig
@@ -37,4 +37,5 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/am335x_shc_sdboot_defconfig b/configs/am335x_shc_sdboot_defconfig
index bd66fbc..185258d 100644
--- a/configs/am335x_shc_sdboot_defconfig
+++ b/configs/am335x_shc_sdboot_defconfig
@@ -39,4 +39,5 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/am335x_shc_sdboot_prompt_defconfig b/configs/am335x_shc_sdboot_prompt_defconfig
index bd66fbc..185258d 100644
--- a/configs/am335x_shc_sdboot_prompt_defconfig
+++ b/configs/am335x_shc_sdboot_prompt_defconfig
@@ -39,4 +39,5 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/am335x_sl50_defconfig b/configs/am335x_sl50_defconfig
index bae1dfe..86035d2 100644
--- a/configs/am335x_sl50_defconfig
+++ b/configs/am335x_sl50_defconfig
@@ -37,4 +37,5 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/am43xx_evm_ethboot_defconfig b/configs/am43xx_evm_ethboot_defconfig
index 6a30706..20874dd 100644
--- a/configs/am43xx_evm_ethboot_defconfig
+++ b/configs/am43xx_evm_ethboot_defconfig
@@ -58,4 +58,5 @@
 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_qspiboot_defconfig b/configs/am43xx_evm_qspiboot_defconfig
index 84766e8..c0d0bcc 100644
--- a/configs/am43xx_evm_qspiboot_defconfig
+++ b/configs/am43xx_evm_qspiboot_defconfig
@@ -55,4 +55,5 @@
 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 a98a97f..870ed0f 100644
--- a/configs/am43xx_evm_usbhost_boot_defconfig
+++ b/configs/am43xx_evm_usbhost_boot_defconfig
@@ -72,3 +72,4 @@
 CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
 CONFIG_G_DNL_VENDOR_NUM=0x0403
 CONFIG_G_DNL_PRODUCT_NUM=0xbd00
+CONFIG_FAT_WRITE=y
diff --git a/configs/am57xx_evm_nodt_defconfig b/configs/am57xx_evm_nodt_defconfig
index 33e7f91..6048e6c 100644
--- a/configs/am57xx_evm_nodt_defconfig
+++ b/configs/am57xx_evm_nodt_defconfig
@@ -62,4 +62,5 @@
 CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
 CONFIG_G_DNL_VENDOR_NUM=0x0451
 CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/apalis-tk1_defconfig b/configs/apalis-tk1_defconfig
index 74cea31..9179aaf 100644
--- a/configs/apalis-tk1_defconfig
+++ b/configs/apalis-tk1_defconfig
@@ -24,10 +24,8 @@
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_TEGRA124_MMC_DISABLE_EXT_LOOPBACK=y
 CONFIG_E1000=y
 CONFIG_PCI=y
diff --git a/configs/apalis_imx6_defconfig b/configs/apalis_imx6_defconfig
index f586773..d171cf0 100644
--- a/configs/apalis_imx6_defconfig
+++ b/configs/apalis_imx6_defconfig
@@ -24,6 +24,7 @@
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_XIMG is not set
 CONFIG_CMD_ASKENV=y
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
@@ -48,6 +49,7 @@
 CONFIG_G_DNL_MANUFACTURER="Toradex"
 CONFIG_G_DNL_VENDOR_NUM=0x1b67
 CONFIG_G_DNL_PRODUCT_NUM=0x4000
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 CONFIG_OF_LIBFDT_OVERLAY=y
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/apalis_imx6_nospl_com_defconfig b/configs/apalis_imx6_nospl_com_defconfig
index 42abbbd..6611c43 100644
--- a/configs/apalis_imx6_nospl_com_defconfig
+++ b/configs/apalis_imx6_nospl_com_defconfig
@@ -17,6 +17,7 @@
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_XIMG is not set
 CONFIG_CMD_ASKENV=y
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
@@ -41,5 +42,6 @@
 CONFIG_G_DNL_MANUFACTURER="Toradex"
 CONFIG_G_DNL_VENDOR_NUM=0x1b67
 CONFIG_G_DNL_PRODUCT_NUM=0x4020
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/apalis_imx6_nospl_it_defconfig b/configs/apalis_imx6_nospl_it_defconfig
index 18f0d02..dba0a7c 100644
--- a/configs/apalis_imx6_nospl_it_defconfig
+++ b/configs/apalis_imx6_nospl_it_defconfig
@@ -17,6 +17,7 @@
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_XIMG is not set
 CONFIG_CMD_ASKENV=y
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
@@ -41,5 +42,6 @@
 CONFIG_G_DNL_MANUFACTURER="Toradex"
 CONFIG_G_DNL_VENDOR_NUM=0x1b67
 CONFIG_G_DNL_PRODUCT_NUM=0x4020
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/apalis_t30_defconfig b/configs/apalis_t30_defconfig
index 8557df9..aaf1bfb 100644
--- a/configs/apalis_t30_defconfig
+++ b/configs/apalis_t30_defconfig
@@ -25,10 +25,8 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_E1000=y
 CONFIG_PCI=y
 CONFIG_DM_PCI=y
diff --git a/configs/at91sam9m10g45ek_mmc_defconfig b/configs/at91sam9m10g45ek_mmc_defconfig
index 18b6ddf7..d8ba087 100644
--- a/configs/at91sam9m10g45ek_mmc_defconfig
+++ b/configs/at91sam9m10g45ek_mmc_defconfig
@@ -49,3 +49,4 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_LCD=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/at91sam9n12ek_mmc_defconfig b/configs/at91sam9n12ek_mmc_defconfig
index e7e8a01..d13eed0 100644
--- a/configs/at91sam9n12ek_mmc_defconfig
+++ b/configs/at91sam9n12ek_mmc_defconfig
@@ -48,3 +48,4 @@
 CONFIG_DM_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_LCD=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/at91sam9rlek_mmc_defconfig b/configs/at91sam9rlek_mmc_defconfig
index 9a40c41..edf9881 100644
--- a/configs/at91sam9rlek_mmc_defconfig
+++ b/configs/at91sam9rlek_mmc_defconfig
@@ -42,3 +42,4 @@
 CONFIG_DEBUG_UART_ANNOUNCE=y
 CONFIG_ATMEL_USART=y
 CONFIG_LCD=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/at91sam9x5ek_mmc_defconfig b/configs/at91sam9x5ek_mmc_defconfig
index ddeeeef..fbe11ef 100644
--- a/configs/at91sam9x5ek_mmc_defconfig
+++ b/configs/at91sam9x5ek_mmc_defconfig
@@ -54,3 +54,4 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_LCD=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/bananapi_m64_defconfig b/configs/bananapi_m64_defconfig
new file mode 100644
index 0000000..3908d42
--- /dev/null
+++ b/configs/bananapi_m64_defconfig
@@ -0,0 +1,17 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_MACH_SUN50I=y
+CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
+CONFIG_MMC0_CD_PIN="PH13"
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-bananapi-m64"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL=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_SUN8I_EMAC=y
+CONFIG_USB_EHCI_HCD=y
diff --git a/configs/bcm958622hr_defconfig b/configs/bcm958622hr_defconfig
index c2713c6..62e50b6 100644
--- a/configs/bcm958622hr_defconfig
+++ b/configs/bcm958622hr_defconfig
@@ -13,10 +13,13 @@
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_HASH=y
+CONFIG_HASH_VERIFY=y
 CONFIG_CMD_FAT=y
 # CONFIG_MMC is not set
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_SHA1=y
 CONFIG_SHA256=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/beaver_defconfig b/configs/beaver_defconfig
index 76359c9..71d6cd5 100644
--- a/configs/beaver_defconfig
+++ b/configs/beaver_defconfig
@@ -26,11 +26,9 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_RTL8169=y
diff --git a/configs/birdland_bav335a_defconfig b/configs/birdland_bav335a_defconfig
index 7811273..d866b60 100644
--- a/configs/birdland_bav335a_defconfig
+++ b/configs/birdland_bav335a_defconfig
@@ -63,4 +63,5 @@
 CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
 CONFIG_G_DNL_VENDOR_NUM=0x0451
 CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/birdland_bav335b_defconfig b/configs/birdland_bav335b_defconfig
index 1765ec4..ef73fbf 100644
--- a/configs/birdland_bav335b_defconfig
+++ b/configs/birdland_bav335b_defconfig
@@ -54,6 +54,7 @@
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
diff --git a/configs/brppt1_mmc_defconfig b/configs/brppt1_mmc_defconfig
index 1bdbf90..3566223 100644
--- a/configs/brppt1_mmc_defconfig
+++ b/configs/brppt1_mmc_defconfig
@@ -58,4 +58,5 @@
 CONFIG_SYS_WHITE_ON_BLACK=y
 CONFIG_LCD=y
 CONFIG_OMAP_WATCHDOG=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/brppt1_nand_defconfig b/configs/brppt1_nand_defconfig
index ed7432d..f07a46b 100644
--- a/configs/brppt1_nand_defconfig
+++ b/configs/brppt1_nand_defconfig
@@ -58,4 +58,5 @@
 CONFIG_SYS_WHITE_ON_BLACK=y
 CONFIG_LCD=y
 CONFIG_OMAP_WATCHDOG=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/brppt1_spi_defconfig b/configs/brppt1_spi_defconfig
index 02b5ff6..333e204 100644
--- a/configs/brppt1_spi_defconfig
+++ b/configs/brppt1_spi_defconfig
@@ -66,4 +66,5 @@
 CONFIG_SYS_WHITE_ON_BLACK=y
 CONFIG_LCD=y
 CONFIG_OMAP_WATCHDOG=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/brxre1_defconfig b/configs/brxre1_defconfig
index 940793b..f558886 100644
--- a/configs/brxre1_defconfig
+++ b/configs/brxre1_defconfig
@@ -57,5 +57,6 @@
 CONFIG_USB_STORAGE=y
 CONFIG_SYS_WHITE_ON_BLACK=y
 CONFIG_LCD=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/cairo_defconfig b/configs/cairo_defconfig
index da28e13..d96a71a 100644
--- a/configs/cairo_defconfig
+++ b/configs/cairo_defconfig
@@ -34,4 +34,5 @@
 CONFIG_EFI_PARTITION=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/calimain_defconfig b/configs/calimain_defconfig
index 489d85f..48422dd 100644
--- a/configs/calimain_defconfig
+++ b/configs/calimain_defconfig
@@ -10,6 +10,7 @@
 CONFIG_AUTOBOOT_KEYED=y
 CONFIG_AUTOBOOT_STOP_STR="\x0b"
 CONFIG_CMD_ASKENV=y
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
diff --git a/configs/cardhu_defconfig b/configs/cardhu_defconfig
index 76e861a..f771a05 100644
--- a/configs/cardhu_defconfig
+++ b/configs/cardhu_defconfig
@@ -24,8 +24,6 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_RTL8169=y
diff --git a/configs/cei-tk1-som_defconfig b/configs/cei-tk1-som_defconfig
index c1b4486..1a5e47d 100644
--- a/configs/cei-tk1-som_defconfig
+++ b/configs/cei-tk1-som_defconfig
@@ -26,11 +26,9 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_RTL8169=y
diff --git a/configs/chiliboard_defconfig b/configs/chiliboard_defconfig
index 2f4c694..579df94 100644
--- a/configs/chiliboard_defconfig
+++ b/configs/chiliboard_defconfig
@@ -41,4 +41,5 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_STORAGE=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/cl-som-am57x_defconfig b/configs/cl-som-am57x_defconfig
index ef76033..8485137 100644
--- a/configs/cl-som-am57x_defconfig
+++ b/configs/cl-som-am57x_defconfig
@@ -53,4 +53,5 @@
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_STORAGE=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/clearfog_defconfig b/configs/clearfog_defconfig
index 1264871..0975068 100644
--- a/configs/clearfog_defconfig
+++ b/configs/clearfog_defconfig
@@ -8,14 +8,13 @@
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="armada-388-clearfog"
+CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BOOTDELAY=3
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SPL=y
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x141
 CONFIG_SPL_I2C_SUPPORT=y
-CONFIG_HUSH_PARSER=y
-CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_MMC=y
@@ -25,15 +24,8 @@
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TFTPPUT=y
-CONFIG_CMD_DHCP=y
-CONFIG_CMD_MII=y
-CONFIG_CMD_PING=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
-CONFIG_CMD_EXT2=y
-CONFIG_CMD_EXT4=y
-CONFIG_CMD_FAT=y
-CONFIG_CMD_FS_GENERIC=y
 CONFIG_EFI_PARTITION=y
 # CONFIG_PARTITION_UUIDS is not set
 # CONFIG_SPL_PARTITION_UUIDS is not set
diff --git a/configs/cm_t335_defconfig b/configs/cm_t335_defconfig
index dbb1c3b..876e332 100644
--- a/configs/cm_t335_defconfig
+++ b/configs/cm_t335_defconfig
@@ -50,4 +50,5 @@
 CONFIG_LED_STATUS_BOOT=0
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/cm_t43_defconfig b/configs/cm_t43_defconfig
index bec96ae..d813cc5 100644
--- a/configs/cm_t43_defconfig
+++ b/configs/cm_t43_defconfig
@@ -68,4 +68,5 @@
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_STORAGE=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/cm_t54_defconfig b/configs/cm_t54_defconfig
index eef2f89..ec26f99 100644
--- a/configs/cm_t54_defconfig
+++ b/configs/cm_t54_defconfig
@@ -43,4 +43,5 @@
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/colibri_imx6_defconfig b/configs/colibri_imx6_defconfig
index 6c10576..d8307b0 100644
--- a/configs/colibri_imx6_defconfig
+++ b/configs/colibri_imx6_defconfig
@@ -24,6 +24,7 @@
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_XIMG is not set
 CONFIG_CMD_ASKENV=y
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
@@ -48,6 +49,7 @@
 CONFIG_G_DNL_MANUFACTURER="Toradex"
 CONFIG_G_DNL_VENDOR_NUM=0x1b67
 CONFIG_G_DNL_PRODUCT_NUM=0x4000
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 CONFIG_OF_LIBFDT_OVERLAY=y
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/colibri_imx6_nospl_defconfig b/configs/colibri_imx6_nospl_defconfig
index bd2ac24..df24f17 100644
--- a/configs/colibri_imx6_nospl_defconfig
+++ b/configs/colibri_imx6_nospl_defconfig
@@ -17,6 +17,7 @@
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_XIMG is not set
 CONFIG_CMD_ASKENV=y
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
@@ -41,5 +42,6 @@
 CONFIG_G_DNL_MANUFACTURER="Toradex"
 CONFIG_G_DNL_VENDOR_NUM=0x1b67
 CONFIG_G_DNL_PRODUCT_NUM=0x4000
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/colibri_t20_defconfig b/configs/colibri_t20_defconfig
index db0224b..1d00055 100644
--- a/configs/colibri_t20_defconfig
+++ b/configs/colibri_t20_defconfig
@@ -29,10 +29,8 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_MTD_UBI_FASTMAP=y
 CONFIG_DM_PMIC=y
 CONFIG_DM_REGULATOR=y
diff --git a/configs/colibri_t30_defconfig b/configs/colibri_t30_defconfig
index 41cc0ed..4c5a248 100644
--- a/configs/colibri_t30_defconfig
+++ b/configs/colibri_t30_defconfig
@@ -25,10 +25,8 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
diff --git a/configs/comtrend_ct5361_ram_defconfig b/configs/comtrend_ct5361_ram_defconfig
new file mode 100644
index 0000000..9ec0c41
--- /dev/null
+++ b/configs/comtrend_ct5361_ram_defconfig
@@ -0,0 +1,57 @@
+CONFIG_ARCH_BMIPS=y
+CONFIG_BAUDRATE=115200
+CONFIG_BCM6345_CLK=y
+CONFIG_BCM6345_GPIO=y
+CONFIG_BCM6345_SERIAL=y
+CONFIG_BMIPS_BOOT_RAM=y
+CONFIG_BOARD_COMTREND_CT5361=y
+CONFIG_CFI_FLASH=y
+# CONFIG_CMD_BOOTD is not set
+CONFIG_CMD_BOOTM=y
+CONFIG_CMD_CPU=y
+# CONFIG_CMD_CRC32 is not set
+# CONFIG_CMD_EDITENV is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_ENV_EXISTS is not set
+# CONFIG_CMD_EXPORTENV is not set
+CONFIG_CMD_FLASH=y
+# CONFIG_CMD_FPGA is not set
+# CONFIG_CMD_GPIO is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_IMPORTENV is not set
+CONFIG_CMD_LED=y
+CONFIG_CMD_LICENSE=y
+CONFIG_CMD_LOADB=y
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MEMINFO=y
+# CONFIG_CMD_MISC is not set
+# CONFIG_CMD_NET is not set
+# CONFIG_CMD_NFS is not set
+# CONFIG_CMD_SAVEENV is not set
+# CONFIG_CMD_XIMG is not set
+CONFIG_DEFAULT_DEVICE_TREE="comtrend,ct-5361"
+CONFIG_DISPLAY_CPUINFO=y
+# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_DM_GPIO=y
+CONFIG_DM_RESET=y
+CONFIG_DM_SERIAL=y
+CONFIG_HUSH_PARSER=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_MIPS=y
+# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
+# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_MTD=y
+CONFIG_MTD_DEVICE=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_RESET=y
+CONFIG_RESET_BCM6345=y
+CONFIG_SOC_BMIPS_BCM6348=y
+# CONFIG_SPL_SERIAL_PRESENT is not set
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SYS_PROMPT="CT-5361 # "
+CONFIG_SYS_TEXT_BASE=0x80010000
+CONFIG_WDT=y
+CONFIG_WDT_BCM6345=y
diff --git a/configs/da850_am18xxevm_defconfig b/configs/da850_am18xxevm_defconfig
index bb92c43..74b3f03 100644
--- a/configs/da850_am18xxevm_defconfig
+++ b/configs/da850_am18xxevm_defconfig
@@ -17,6 +17,7 @@
 CONFIG_HUSH_PARSER=y
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_ASKENV=y
+CONFIG_CRC32_VERIFY=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/da850evm_defconfig b/configs/da850evm_defconfig
index 1120182..3745b85 100644
--- a/configs/da850evm_defconfig
+++ b/configs/da850evm_defconfig
@@ -19,6 +19,7 @@
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_ASKENV=y
+CONFIG_CRC32_VERIFY=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/da850evm_direct_nor_defconfig b/configs/da850evm_direct_nor_defconfig
index 1e17ce7..99543d3 100644
--- a/configs/da850evm_direct_nor_defconfig
+++ b/configs/da850evm_direct_nor_defconfig
@@ -10,6 +10,7 @@
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="U-Boot > "
 CONFIG_CMD_ASKENV=y
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_SF=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
diff --git a/configs/dalmore_defconfig b/configs/dalmore_defconfig
index 739cfa9..02fceaa 100644
--- a/configs/dalmore_defconfig
+++ b/configs/dalmore_defconfig
@@ -26,11 +26,9 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SYS_NS16550=y
diff --git a/configs/ds109_defconfig b/configs/ds109_defconfig
index 46ac567..d8f373b 100644
--- a/configs/ds109_defconfig
+++ b/configs/ds109_defconfig
@@ -12,7 +12,7 @@
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_PING=y
 CONFIG_CMD_DATE=y
-CONFIG_DOS_PARTITION=y
+CONFIG_CMD_FAT=y
 CONFIG_ISO_PARTITION=y
 # CONFIG_MMC is not set
 CONFIG_SPI_FLASH=y
diff --git a/configs/duovero_defconfig b/configs/duovero_defconfig
index 9e0ac20..b945875 100644
--- a/configs/duovero_defconfig
+++ b/configs/duovero_defconfig
@@ -28,4 +28,5 @@
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/e2220-1170_defconfig b/configs/e2220-1170_defconfig
index 7c51cc4..2e264bc 100644
--- a/configs/e2220-1170_defconfig
+++ b/configs/e2220-1170_defconfig
@@ -21,11 +21,9 @@
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_EXT4_WRITE=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SYS_NS16550=y
diff --git a/configs/ea20_defconfig b/configs/ea20_defconfig
index be48626..4ee7d5a 100644
--- a/configs/ea20_defconfig
+++ b/configs/ea20_defconfig
@@ -15,6 +15,7 @@
 CONFIG_SYS_PROMPT="ea20 > "
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_ASKENV=y
+CONFIG_CRC32_VERIFY=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
diff --git a/configs/gurnard_defconfig b/configs/gurnard_defconfig
index 2c6f524..d43fd14 100644
--- a/configs/gurnard_defconfig
+++ b/configs/gurnard_defconfig
@@ -18,6 +18,7 @@
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_SOURCE is not set
 # CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_FAT=y
 CONFIG_OF_CONTROL=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/configs/harmony_defconfig b/configs/harmony_defconfig
index e9b8ac2..fce3eee 100644
--- a/configs/harmony_defconfig
+++ b/configs/harmony_defconfig
@@ -22,8 +22,6 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_PCI=y
 CONFIG_DM_PCI=y
 CONFIG_DM_PCI_COMPAT=y
diff --git a/configs/hikey_defconfig b/configs/hikey_defconfig
index b112be2..5981d2f 100644
--- a/configs/hikey_defconfig
+++ b/configs/hikey_defconfig
@@ -16,3 +16,4 @@
 CONFIG_MMC_DW_K3=y
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/igep0020_defconfig b/configs/igep0020_defconfig
index c81dfdf..6e0a5e9 100644
--- a/configs/igep0020_defconfig
+++ b/configs/igep0020_defconfig
@@ -47,5 +47,6 @@
 CONFIG_LED_STATUS_BOOT=0
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 CONFIG_FDT_FIXUP_PARTITIONS=y
diff --git a/configs/igep0030_defconfig b/configs/igep0030_defconfig
index 9098451..5908a35 100644
--- a/configs/igep0030_defconfig
+++ b/configs/igep0030_defconfig
@@ -36,5 +36,6 @@
 CONFIG_LED_STATUS_BOOT=0
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 CONFIG_FDT_FIXUP_PARTITIONS=y
diff --git a/configs/igep0032_defconfig b/configs/igep0032_defconfig
index 56be1a1..53399e7 100644
--- a/configs/igep0032_defconfig
+++ b/configs/igep0032_defconfig
@@ -28,5 +28,6 @@
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 CONFIG_FDT_FIXUP_PARTITIONS=y
diff --git a/configs/imx6qdl_icore_mmc_defconfig b/configs/imx6qdl_icore_mmc_defconfig
index b6b1b4b..851dba2 100644
--- a/configs/imx6qdl_icore_mmc_defconfig
+++ b/configs/imx6qdl_icore_mmc_defconfig
@@ -21,6 +21,7 @@
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="icorem6qdl> "
 # CONFIG_CMD_IMLS is not set
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
diff --git a/configs/imx6qdl_icore_rqs_mmc_defconfig b/configs/imx6qdl_icore_rqs_mmc_defconfig
index 08e6784..b6a43ae 100644
--- a/configs/imx6qdl_icore_rqs_mmc_defconfig
+++ b/configs/imx6qdl_icore_rqs_mmc_defconfig
@@ -20,6 +20,7 @@
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="icorem6qdl-rqs> "
 # CONFIG_CMD_IMLS is not set
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
diff --git a/configs/imx6ul_geam_mmc_defconfig b/configs/imx6ul_geam_mmc_defconfig
index 8751a36..acaed60 100644
--- a/configs/imx6ul_geam_mmc_defconfig
+++ b/configs/imx6ul_geam_mmc_defconfig
@@ -19,6 +19,7 @@
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="geam6ul> "
 # CONFIG_CMD_IMLS is not set
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
diff --git a/configs/imx6ul_geam_nand_defconfig b/configs/imx6ul_geam_nand_defconfig
index 704c0c0..baf1a739 100644
--- a/configs/imx6ul_geam_nand_defconfig
+++ b/configs/imx6ul_geam_nand_defconfig
@@ -18,6 +18,7 @@
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="geam6ul> "
 # CONFIG_CMD_IMLS is not set
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_NAND=y
diff --git a/configs/imx6ul_isiot_emmc_defconfig b/configs/imx6ul_isiot_emmc_defconfig
index 1f501cb..4b429c2 100644
--- a/configs/imx6ul_isiot_emmc_defconfig
+++ b/configs/imx6ul_isiot_emmc_defconfig
@@ -19,6 +19,7 @@
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="isiotmx6ul> "
 # CONFIG_CMD_IMLS is not set
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_GPIO=y
diff --git a/configs/imx6ul_isiot_mmc_defconfig b/configs/imx6ul_isiot_mmc_defconfig
index 5214479..424089c 100644
--- a/configs/imx6ul_isiot_mmc_defconfig
+++ b/configs/imx6ul_isiot_mmc_defconfig
@@ -19,6 +19,7 @@
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="isiotmx6ul> "
 # CONFIG_CMD_IMLS is not set
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
diff --git a/configs/imx6ul_isiot_nand_defconfig b/configs/imx6ul_isiot_nand_defconfig
index 1b28336..fb2bef9 100644
--- a/configs/imx6ul_isiot_nand_defconfig
+++ b/configs/imx6ul_isiot_nand_defconfig
@@ -18,6 +18,7 @@
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="isiotmx6ul> "
 # CONFIG_CMD_IMLS is not set
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_NAND=y
diff --git a/configs/ipam390_defconfig b/configs/ipam390_defconfig
index 705236e..3c32a6b 100644
--- a/configs/ipam390_defconfig
+++ b/configs/ipam390_defconfig
@@ -17,6 +17,7 @@
 CONFIG_SYS_PROMPT="U-Boot > "
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_ASKENV=y
+CONFIG_CRC32_VERIFY=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
diff --git a/configs/jetson-tk1_defconfig b/configs/jetson-tk1_defconfig
index 982aec4..65a5832 100644
--- a/configs/jetson-tk1_defconfig
+++ b/configs/jetson-tk1_defconfig
@@ -26,11 +26,9 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_RTL8169=y
diff --git a/configs/kzm9g_defconfig b/configs/kzm9g_defconfig
index bc3e5d9..a884e5a 100644
--- a/configs/kzm9g_defconfig
+++ b/configs/kzm9g_defconfig
@@ -13,4 +13,5 @@
 CONFIG_CMD_FAT=y
 # CONFIG_MMC is not set
 CONFIG_MTD_NOR_FLASH=y
+# CONFIG_FAT_WRITE is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/legoev3_defconfig b/configs/legoev3_defconfig
index 86ff6a1..589e8cf 100644
--- a/configs/legoev3_defconfig
+++ b/configs/legoev3_defconfig
@@ -12,6 +12,7 @@
 CONFIG_AUTOBOOT_STOP_STR="l"
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_ASKENV=y
+CONFIG_CRC32_VERIFY=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
diff --git a/configs/ls1021aiot_qspi_defconfig b/configs/ls1021aiot_qspi_defconfig
index 3deda48..3628367 100644
--- a/configs/ls1021aiot_qspi_defconfig
+++ b/configs/ls1021aiot_qspi_defconfig
@@ -4,7 +4,7 @@
 CONFIG_SYS_EXTRA_OPTIONS="QSPI_BOOT"
 CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_CMD_GPT=y
-CONFIG_DOS_PARTITION=y
+CONFIG_CMD_FAT=y
 CONFIG_OF_CONTROL=y
 CONFIG_DM=y
 CONFIG_FSL_CAAM=y
diff --git a/configs/ls1021aiot_sdcard_defconfig b/configs/ls1021aiot_sdcard_defconfig
index 089ea34..e412024 100644
--- a/configs/ls1021aiot_sdcard_defconfig
+++ b/configs/ls1021aiot_sdcard_defconfig
@@ -7,7 +7,7 @@
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0xe8
 CONFIG_CMD_GPT=y
-CONFIG_DOS_PARTITION=y
+CONFIG_CMD_FAT=y
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_OF_CONTROL=y
 CONFIG_DM=y
diff --git a/configs/m28evk_defconfig b/configs/m28evk_defconfig
index fbd106e..944e39d 100644
--- a/configs/m28evk_defconfig
+++ b/configs/m28evk_defconfig
@@ -41,4 +41,5 @@
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/m53evk_defconfig b/configs/m53evk_defconfig
index a7bf297..a33a601 100644
--- a/configs/m53evk_defconfig
+++ b/configs/m53evk_defconfig
@@ -37,4 +37,5 @@
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
 # CONFIG_VIDEO_SW_CURSOR is not set
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/ma5d4evk_defconfig b/configs/ma5d4evk_defconfig
index a267c9a5..eca10d3 100644
--- a/configs/ma5d4evk_defconfig
+++ b/configs/ma5d4evk_defconfig
@@ -40,5 +40,6 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_ATMEL_USBA=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/medcom-wide_defconfig b/configs/medcom-wide_defconfig
index e30ac75..80e3ed8 100644
--- a/configs/medcom-wide_defconfig
+++ b/configs/medcom-wide_defconfig
@@ -23,8 +23,6 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_DM_PMIC=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
diff --git a/configs/mvebu_db-88f3720_defconfig b/configs/mvebu_db-88f3720_defconfig
index 4ea142c..349c2ce 100644
--- a/configs/mvebu_db-88f3720_defconfig
+++ b/configs/mvebu_db-88f3720_defconfig
@@ -19,6 +19,7 @@
 CONFIG_CMD_I2C=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPIO=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_DHCP=y
@@ -35,6 +36,8 @@
 CONFIG_ISO_PARTITION=y
 CONFIG_EFI_PARTITION=y
 CONFIG_BLOCK_CACHE=y
+CONFIG_DM_GPIO=y
+# CONFIG_MVEBU_GPIO is not set
 CONFIG_DM_I2C=y
 CONFIG_MISC=y
 CONFIG_DM_MMC=y
@@ -47,6 +50,8 @@
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_PHYLIB=y
 CONFIG_MVEBU_COMPHY_SUPPORT=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_ARMADA_37XX=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DEBUG_UART=y
 CONFIG_DEBUG_MVEBU_A3700_UART=y
diff --git a/configs/mvebu_db-88f7040-nand_defconfig b/configs/mvebu_db-88f7040-nand_defconfig
index d86c18e..8d48cb6 100644
--- a/configs/mvebu_db-88f7040-nand_defconfig
+++ b/configs/mvebu_db-88f7040-nand_defconfig
@@ -7,7 +7,6 @@
 CONFIG_AHCI=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
-CONFIG_BOARD_LATE_INIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_ARCH_EARLY_INIT_R=y
@@ -16,12 +15,12 @@
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_MMC=y
+CONFIG_CMD_NAND=y
 CONFIG_CMD_PART=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_USB=y
-CONFIG_CMD_NAND=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TFTPPUT=y
@@ -31,6 +30,7 @@
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_MVEBU_BUBT=y
+CONFIG_MVEBU_NAND_BOOT=y
 CONFIG_CMD_EXT4=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
@@ -45,18 +45,18 @@
 CONFIG_DM_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_XENON=y
+CONFIG_NAND_PXA3XX=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_SPANSION=y
 CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_MVEBU_NAND_BOOT=y
-CONFIG_NAND_PXA3XX=y
 CONFIG_PHYLIB=y
 CONFIG_PCI=y
 CONFIG_DM_PCI=y
 CONFIG_PCIE_DW_MVEBU=y
 CONFIG_MVEBU_COMPHY_SUPPORT=y
 CONFIG_PINCTRL=y
+CONFIG_PINCTRL_ARMADA_8K=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DEBUG_UART=y
 CONFIG_DEBUG_UART_BASE=0xf0512000
diff --git a/configs/mvebu_db-88f7040_defconfig b/configs/mvebu_db-88f7040_defconfig
index 797eabb..9f7b2c4 100644
--- a/configs/mvebu_db-88f7040_defconfig
+++ b/configs/mvebu_db-88f7040_defconfig
@@ -54,6 +54,7 @@
 CONFIG_PCIE_DW_MVEBU=y
 CONFIG_MVEBU_COMPHY_SUPPORT=y
 CONFIG_PINCTRL=y
+CONFIG_PINCTRL_ARMADA_8K=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DEBUG_UART=y
 CONFIG_DEBUG_UART_BASE=0xf0512000
diff --git a/configs/mvebu_db-88f8040_defconfig b/configs/mvebu_db-88f8040_defconfig
index 046da09..c21c977 100644
--- a/configs/mvebu_db-88f8040_defconfig
+++ b/configs/mvebu_db-88f8040_defconfig
@@ -54,6 +54,7 @@
 CONFIG_PCIE_DW_MVEBU=y
 CONFIG_MVEBU_COMPHY_SUPPORT=y
 CONFIG_PINCTRL=y
+CONFIG_PINCTRL_ARMADA_8K=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DEBUG_UART=y
 CONFIG_DEBUG_UART_BASE=0xf0512000
diff --git a/configs/mvebu_mcbin-88f8040_defconfig b/configs/mvebu_mcbin-88f8040_defconfig
index 7254920..4a7c592 100644
--- a/configs/mvebu_mcbin-88f8040_defconfig
+++ b/configs/mvebu_mcbin-88f8040_defconfig
@@ -57,6 +57,7 @@
 CONFIG_PCIE_DW_MVEBU=y
 CONFIG_MVEBU_COMPHY_SUPPORT=y
 CONFIG_PINCTRL=y
+CONFIG_PINCTRL_ARMADA_8K=y
 CONFIG_DM_REGULATOR_FIXED=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
 CONFIG_DEBUG_UART=y
diff --git a/configs/mx7ulp_evk_defconfig b/configs/mx7ulp_evk_defconfig
index c457d34..6ab7cb7 100644
--- a/configs/mx7ulp_evk_defconfig
+++ b/configs/mx7ulp_evk_defconfig
@@ -7,6 +7,7 @@
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_GPIO=y
+CONFIG_CMD_FAT=y
 CONFIG_OF_CONTROL=y
 CONFIG_DM=y
 # CONFIG_BLK is not set
diff --git a/configs/mx7ulp_evk_plugin_defconfig b/configs/mx7ulp_evk_plugin_defconfig
index c457d34..6ab7cb7 100644
--- a/configs/mx7ulp_evk_plugin_defconfig
+++ b/configs/mx7ulp_evk_plugin_defconfig
@@ -7,6 +7,7 @@
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_GPIO=y
+CONFIG_CMD_FAT=y
 CONFIG_OF_CONTROL=y
 CONFIG_DM=y
 # CONFIG_BLK is not set
diff --git a/configs/nanopi_m1_defconfig b/configs/nanopi_m1_defconfig
new file mode 100644
index 0000000..498496b
--- /dev/null
+++ b/configs/nanopi_m1_defconfig
@@ -0,0 +1,16 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_MACH_SUN8I_H3=y
+CONFIG_DRAM_CLK=408
+CONFIG_DRAM_ZQ=3881979
+CONFIG_DRAM_ODT_EN=y
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-m1"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL=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_USB_EHCI_HCD=y
diff --git a/configs/netgear_cg3100d_ram_defconfig b/configs/netgear_cg3100d_ram_defconfig
new file mode 100644
index 0000000..a6eff10
--- /dev/null
+++ b/configs/netgear_cg3100d_ram_defconfig
@@ -0,0 +1,56 @@
+CONFIG_ARCH_BMIPS=y
+CONFIG_BAUDRATE=115200
+CONFIG_BCM6345_CLK=y
+CONFIG_BCM6345_GPIO=y
+CONFIG_BCM6345_SERIAL=y
+CONFIG_BMIPS_BOOT_RAM=y
+CONFIG_BOARD_NETGEAR_CG3100D=y
+# CONFIG_CMD_BOOTD is not set
+CONFIG_CMD_BOOTM=y
+CONFIG_CMD_CPU=y
+# CONFIG_CMD_CRC32 is not set
+# CONFIG_CMD_EDITENV is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_ENV_EXISTS is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_CMD_GPIO is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_IMPORTENV is not set
+CONFIG_CMD_LED=y
+CONFIG_CMD_LICENSE=y
+CONFIG_CMD_LOADB=y
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MEMINFO=y
+# CONFIG_CMD_MISC is not set
+# CONFIG_CMD_NET is not set
+# CONFIG_CMD_NFS is not set
+# CONFIG_CMD_SAVEENV is not set
+# CONFIG_CMD_XIMG is not set
+CONFIG_DEFAULT_DEVICE_TREE="netgear,cg3100d"
+CONFIG_DISPLAY_CPUINFO=y
+# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_DM_GPIO=y
+CONFIG_DM_RESET=y
+CONFIG_DM_SERIAL=y
+CONFIG_HUSH_PARSER=y
+CONFIG_LED=y
+CONFIG_LED_BCM6328=y
+CONFIG_LED_BLINK=y
+CONFIG_LED_GPIO=y
+CONFIG_MIPS=y
+# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
+# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_RESET=y
+CONFIG_RESET_BCM6345=y
+CONFIG_SOC_BMIPS_BCM3380=y
+# CONFIG_SPL_SERIAL_PRESENT is not set
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SYS_NO_FLASH=y
+CONFIG_SYS_PROMPT="CG3100D # "
+CONFIG_SYS_TEXT_BASE=0x80010000
+CONFIG_WDT=y
+CONFIG_WDT_BCM6345=y
diff --git a/configs/novena_defconfig b/configs/novena_defconfig
index 49b963c..3c7589b 100644
--- a/configs/novena_defconfig
+++ b/configs/novena_defconfig
@@ -39,4 +39,5 @@
 CONFIG_USB_GADGET=y
 CONFIG_CI_UDC=y
 # CONFIG_VIDEO_SW_CURSOR is not set
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig
index c01d5f5..f0fad3e 100644
--- a/configs/nyan-big_defconfig
+++ b/configs/nyan-big_defconfig
@@ -32,14 +32,12 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
 CONFIG_CROS_EC_KEYB=y
 CONFIG_CROS_EC=y
 CONFIG_CROS_EC_SPI=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_DM_PMIC=y
diff --git a/configs/omap3_beagle_defconfig b/configs/omap3_beagle_defconfig
index 64971c1..eb780ab 100644
--- a/configs/omap3_beagle_defconfig
+++ b/configs/omap3_beagle_defconfig
@@ -42,4 +42,5 @@
 CONFIG_G_DNL_MANUFACTURER="TI"
 CONFIG_G_DNL_VENDOR_NUM=0x0451
 CONFIG_G_DNL_PRODUCT_NUM=0xd022
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/omap3_overo_defconfig b/configs/omap3_overo_defconfig
index 3be4a1d..e360780 100644
--- a/configs/omap3_overo_defconfig
+++ b/configs/omap3_overo_defconfig
@@ -44,4 +44,5 @@
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/omap3_pandora_defconfig b/configs/omap3_pandora_defconfig
index 3aa7ba3..d219ad0 100644
--- a/configs/omap3_pandora_defconfig
+++ b/configs/omap3_pandora_defconfig
@@ -24,4 +24,5 @@
 CONFIG_CMD_UBI=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/omap3_zoom1_defconfig b/configs/omap3_zoom1_defconfig
index c985c86..8c0e830 100644
--- a/configs/omap3_zoom1_defconfig
+++ b/configs/omap3_zoom1_defconfig
@@ -30,4 +30,5 @@
 CONFIG_EFI_PARTITION=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/omap4_panda_defconfig b/configs/omap4_panda_defconfig
index 8fdf7607..3d91f13 100644
--- a/configs/omap4_panda_defconfig
+++ b/configs/omap4_panda_defconfig
@@ -27,4 +27,5 @@
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/omap4_sdp4430_defconfig b/configs/omap4_sdp4430_defconfig
index 7229142..dda4030 100644
--- a/configs/omap4_sdp4430_defconfig
+++ b/configs/omap4_sdp4430_defconfig
@@ -25,4 +25,5 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/omap5_uevm_defconfig b/configs/omap5_uevm_defconfig
index bd799b7..f5ac38b 100644
--- a/configs/omap5_uevm_defconfig
+++ b/configs/omap5_uevm_defconfig
@@ -48,4 +48,5 @@
 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/omapl138_lcdk_defconfig b/configs/omapl138_lcdk_defconfig
index ff5e06d..cb351e4 100644
--- a/configs/omapl138_lcdk_defconfig
+++ b/configs/omapl138_lcdk_defconfig
@@ -17,6 +17,7 @@
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0xb5
 CONFIG_HUSH_PARSER=y
 # 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
@@ -29,4 +30,5 @@
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SYS_NS16550=y
+# CONFIG_FAT_WRITE is not set
 CONFIG_OF_LIBFDT=y
diff --git a/configs/orangepi_prime_defconfig b/configs/orangepi_prime_defconfig
new file mode 100644
index 0000000..dc8d59e
--- /dev/null
+++ b/configs/orangepi_prime_defconfig
@@ -0,0 +1,16 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_MACH_SUN50I_H5=y
+CONFIG_DRAM_CLK=672
+CONFIG_DRAM_ZQ=3881977
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-orangepi-prime"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL=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_SUN8I_EMAC=y
+CONFIG_USB_EHCI_HCD=y
diff --git a/configs/p2371-0000_defconfig b/configs/p2371-0000_defconfig
index d78f445..0dbcef9 100644
--- a/configs/p2371-0000_defconfig
+++ b/configs/p2371-0000_defconfig
@@ -22,11 +22,9 @@
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_EXT4_WRITE=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SYS_NS16550=y
diff --git a/configs/p2371-2180_defconfig b/configs/p2371-2180_defconfig
index e409a39..d04f052 100644
--- a/configs/p2371-2180_defconfig
+++ b/configs/p2371-2180_defconfig
@@ -22,11 +22,9 @@
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_EXT4_WRITE=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_RTL8169=y
diff --git a/configs/p2571_defconfig b/configs/p2571_defconfig
index daf9165..a268f38 100644
--- a/configs/p2571_defconfig
+++ b/configs/p2571_defconfig
@@ -22,11 +22,9 @@
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_EXT4_WRITE=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SYS_NS16550=y
diff --git a/configs/p2771-0000-000_defconfig b/configs/p2771-0000-000_defconfig
index b4daa12..edf6ce4 100644
--- a/configs/p2771-0000-000_defconfig
+++ b/configs/p2771-0000-000_defconfig
@@ -19,9 +19,7 @@
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_EXT4_WRITE=y
-# CONFIG_BLK is not set
 CONFIG_TEGRA186_BPMP_I2C=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_DWC_ETH_QOS=y
 CONFIG_E1000=y
 CONFIG_RTL8169=y
diff --git a/configs/p2771-0000-500_defconfig b/configs/p2771-0000-500_defconfig
index 02e974d..c3870c3 100644
--- a/configs/p2771-0000-500_defconfig
+++ b/configs/p2771-0000-500_defconfig
@@ -19,9 +19,7 @@
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_EXT4_WRITE=y
-# CONFIG_BLK is not set
 CONFIG_TEGRA186_BPMP_I2C=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_DWC_ETH_QOS=y
 CONFIG_E1000=y
 CONFIG_RTL8169=y
diff --git a/configs/paz00_defconfig b/configs/paz00_defconfig
index 9386df8..3fd1713 100644
--- a/configs/paz00_defconfig
+++ b/configs/paz00_defconfig
@@ -22,8 +22,6 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_DM_PMIC=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
diff --git a/configs/pcm051_rev1_defconfig b/configs/pcm051_rev1_defconfig
index f278075..6b4e229 100644
--- a/configs/pcm051_rev1_defconfig
+++ b/configs/pcm051_rev1_defconfig
@@ -57,4 +57,5 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/pcm051_rev3_defconfig b/configs/pcm051_rev3_defconfig
index 5fa60b7..6baca96 100644
--- a/configs/pcm051_rev3_defconfig
+++ b/configs/pcm051_rev3_defconfig
@@ -57,4 +57,5 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/pengwyn_defconfig b/configs/pengwyn_defconfig
index 6d4d8ad..8693dea 100644
--- a/configs/pengwyn_defconfig
+++ b/configs/pengwyn_defconfig
@@ -56,4 +56,5 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/pepper_defconfig b/configs/pepper_defconfig
index a7d67bf..4b122d6 100644
--- a/configs/pepper_defconfig
+++ b/configs/pepper_defconfig
@@ -40,4 +40,5 @@
 CONFIG_EFI_PARTITION=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/pic32mzdask_defconfig b/configs/pic32mzdask_defconfig
index 9eb8076..688b989 100644
--- a/configs/pic32mzdask_defconfig
+++ b/configs/pic32mzdask_defconfig
@@ -42,5 +42,6 @@
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_PIC32=y
 CONFIG_USB_STORAGE=y
+CONFIG_FAT_WRITE=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
diff --git a/configs/picosam9g45_defconfig b/configs/picosam9g45_defconfig
index f34dfe9..aa61e4b 100644
--- a/configs/picosam9g45_defconfig
+++ b/configs/picosam9g45_defconfig
@@ -35,4 +35,5 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_LCD=y
+CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/plutux_defconfig b/configs/plutux_defconfig
index f0fdde7..46d30fd 100644
--- a/configs/plutux_defconfig
+++ b/configs/plutux_defconfig
@@ -22,8 +22,6 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
diff --git a/configs/r8a7795_salvator-x_defconfig b/configs/r8a7795_salvator-x_defconfig
index 60e0b72..1eba299 100644
--- a/configs/r8a7795_salvator-x_defconfig
+++ b/configs/r8a7795_salvator-x_defconfig
@@ -16,6 +16,7 @@
 CONFIG_CMD_NFS=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
+CONFIG_CMD_FAT=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_USB=y
 CONFIG_USB=y
diff --git a/configs/r8a7796_salvator-x_defconfig b/configs/r8a7796_salvator-x_defconfig
index d6f1840..5bd762d 100644
--- a/configs/r8a7796_salvator-x_defconfig
+++ b/configs/r8a7796_salvator-x_defconfig
@@ -16,6 +16,7 @@
 CONFIG_CMD_NFS=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
+CONFIG_CMD_FAT=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_USB=y
 CONFIG_USB=y
diff --git a/configs/s5p_goni_defconfig b/configs/s5p_goni_defconfig
index c3e0457..8aeab15 100644
--- a/configs/s5p_goni_defconfig
+++ b/configs/s5p_goni_defconfig
@@ -35,3 +35,4 @@
 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/sagem_f@st1704_ram_defconfig b/configs/sagem_f@st1704_ram_defconfig
new file mode 100644
index 0000000..8e89c15
--- /dev/null
+++ b/configs/sagem_f@st1704_ram_defconfig
@@ -0,0 +1,52 @@
+CONFIG_ARCH_BMIPS=y
+CONFIG_BAUDRATE=115200
+CONFIG_BCM6345_CLK=y
+CONFIG_BCM6345_GPIO=y
+CONFIG_BCM6345_SERIAL=y
+CONFIG_BMIPS_BOOT_RAM=y
+CONFIG_BOARD_SAGEM_FAST1704=y
+# CONFIG_CMD_BOOTD is not set
+CONFIG_CMD_BOOTM=y
+CONFIG_CMD_CPU=y
+# CONFIG_CMD_CRC32 is not set
+# CONFIG_CMD_EDITENV is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_ENV_EXISTS is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_CMD_GPIO is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_IMPORTENV is not set
+CONFIG_CMD_LED=y
+CONFIG_CMD_LICENSE=y
+CONFIG_CMD_LOADB=y
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MEMINFO=y
+# CONFIG_CMD_MISC is not set
+# CONFIG_CMD_NET is not set
+# CONFIG_CMD_NFS is not set
+# CONFIG_CMD_SAVEENV is not set
+# CONFIG_CMD_XIMG is not set
+CONFIG_DEFAULT_DEVICE_TREE="sagem,f@st1704"
+CONFIG_DISPLAY_CPUINFO=y
+# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_DM_GPIO=y
+CONFIG_DM_RESET=y
+CONFIG_DM_SERIAL=y
+CONFIG_HUSH_PARSER=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_MIPS=y
+# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
+# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_RESET=y
+CONFIG_RESET_BCM6345=y
+CONFIG_SOC_BMIPS_BCM6338=y
+# CONFIG_SPL_SERIAL_PRESENT is not set
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SYS_NO_FLASH=y
+CONFIG_SYS_PROMPT="F@ST1704 # "
+CONFIG_SYS_TEXT_BASE=0x80010000
diff --git a/configs/sama5d2_ptc_nandflash_defconfig b/configs/sama5d2_ptc_nandflash_defconfig
index 239bfdd..66edd31 100644
--- a/configs/sama5d2_ptc_nandflash_defconfig
+++ b/configs/sama5d2_ptc_nandflash_defconfig
@@ -16,6 +16,7 @@
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_SF=y
 # CONFIG_CMD_FPGA is not set
+CONFIG_CMD_FAT=y
 # CONFIG_MMC is not set
 CONFIG_SPI_FLASH=y
 CONFIG_USB=y
diff --git a/configs/sama5d2_ptc_spiflash_defconfig b/configs/sama5d2_ptc_spiflash_defconfig
index 21014b9..8771e08 100644
--- a/configs/sama5d2_ptc_spiflash_defconfig
+++ b/configs/sama5d2_ptc_spiflash_defconfig
@@ -17,6 +17,7 @@
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_SF=y
 # CONFIG_CMD_FPGA is not set
+CONFIG_CMD_FAT=y
 # CONFIG_MMC is not set
 CONFIG_SPI_FLASH=y
 CONFIG_USB=y
diff --git a/configs/sama5d2_xplained_mmc_defconfig b/configs/sama5d2_xplained_mmc_defconfig
index f064a43..b60e00c 100644
--- a/configs/sama5d2_xplained_mmc_defconfig
+++ b/configs/sama5d2_xplained_mmc_defconfig
@@ -74,3 +74,4 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_ATMEL_USBA=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/sama5d36ek_cmp_mmc_defconfig b/configs/sama5d36ek_cmp_mmc_defconfig
index 32a21f9..8c34e64 100644
--- a/configs/sama5d36ek_cmp_mmc_defconfig
+++ b/configs/sama5d36ek_cmp_mmc_defconfig
@@ -49,3 +49,4 @@
 CONFIG_DM_SPI=y
 CONFIG_ATMEL_SPI=y
 CONFIG_LCD=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/sama5d36ek_cmp_nandflash_defconfig b/configs/sama5d36ek_cmp_nandflash_defconfig
index 34c4de1..9c72a67 100644
--- a/configs/sama5d36ek_cmp_nandflash_defconfig
+++ b/configs/sama5d36ek_cmp_nandflash_defconfig
@@ -49,3 +49,4 @@
 CONFIG_DM_SPI=y
 CONFIG_ATMEL_SPI=y
 CONFIG_LCD=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/sama5d36ek_cmp_spiflash_defconfig b/configs/sama5d36ek_cmp_spiflash_defconfig
index 42c3111..10db9c9 100644
--- a/configs/sama5d36ek_cmp_spiflash_defconfig
+++ b/configs/sama5d36ek_cmp_spiflash_defconfig
@@ -49,3 +49,4 @@
 CONFIG_DM_SPI=y
 CONFIG_ATMEL_SPI=y
 CONFIG_LCD=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/sama5d3_xplained_mmc_defconfig b/configs/sama5d3_xplained_mmc_defconfig
index d28d1d9..533dbcd 100644
--- a/configs/sama5d3_xplained_mmc_defconfig
+++ b/configs/sama5d3_xplained_mmc_defconfig
@@ -65,3 +65,4 @@
 CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/sama5d3_xplained_nandflash_defconfig b/configs/sama5d3_xplained_nandflash_defconfig
index 6f24324..d00ef6a 100644
--- a/configs/sama5d3_xplained_nandflash_defconfig
+++ b/configs/sama5d3_xplained_nandflash_defconfig
@@ -62,3 +62,4 @@
 CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/sama5d3xek_mmc_defconfig b/configs/sama5d3xek_mmc_defconfig
index 994bc04..7471985 100644
--- a/configs/sama5d3xek_mmc_defconfig
+++ b/configs/sama5d3xek_mmc_defconfig
@@ -74,3 +74,4 @@
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_ATMEL_USBA=y
 CONFIG_LCD=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/sama5d3xek_nandflash_defconfig b/configs/sama5d3xek_nandflash_defconfig
index dd0263c..a75767b 100644
--- a/configs/sama5d3xek_nandflash_defconfig
+++ b/configs/sama5d3xek_nandflash_defconfig
@@ -69,3 +69,4 @@
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_ATMEL_USBA=y
 CONFIG_LCD=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/sama5d3xek_spiflash_defconfig b/configs/sama5d3xek_spiflash_defconfig
index 069fbcc..1d8491c 100644
--- a/configs/sama5d3xek_spiflash_defconfig
+++ b/configs/sama5d3xek_spiflash_defconfig
@@ -70,3 +70,4 @@
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_ATMEL_USBA=y
 CONFIG_LCD=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/sama5d4_xplained_mmc_defconfig b/configs/sama5d4_xplained_mmc_defconfig
index 4fc44e5..e23df47 100644
--- a/configs/sama5d4_xplained_mmc_defconfig
+++ b/configs/sama5d4_xplained_mmc_defconfig
@@ -68,3 +68,4 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_ATMEL_USBA=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/sama5d4ek_mmc_defconfig b/configs/sama5d4ek_mmc_defconfig
index 204d128..68da5f9 100644
--- a/configs/sama5d4ek_mmc_defconfig
+++ b/configs/sama5d4ek_mmc_defconfig
@@ -72,3 +72,4 @@
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_ATMEL_USBA=y
 CONFIG_LCD=y
+CONFIG_FAT_WRITE=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index f39d03e..662606c 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -62,6 +62,7 @@
 CONFIG_MAC_PARTITION=y
 CONFIG_AMIGA_PARTITION=y
 CONFIG_OF_CONTROL=y
+CONFIG_OF_LIVE=y
 CONFIG_OF_HOSTFILE=y
 CONFIG_NETCONSOLE=y
 CONFIG_REGMAP=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
new file mode 100644
index 0000000..83efb23
--- /dev/null
+++ b/configs/sandbox_flattree_defconfig
@@ -0,0 +1,179 @@
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_DEFAULT_DEVICE_TREE="sandbox"
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_BOOTSTAGE_USER_COUNT=0x20
+CONFIG_BOOTSTAGE_FDT=y
+CONFIG_BOOTSTAGE_STASH=y
+CONFIG_BOOTSTAGE_STASH_ADDR=0x0
+CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
+CONFIG_CONSOLE_RECORD=y
+CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
+CONFIG_SILENT_CONSOLE=y
+CONFIG_CMD_CPU=y
+CONFIG_CMD_LICENSE=y
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_ASKENV=y
+CONFIG_CMD_GREPENV=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_LOOPW=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MX_CYCLIC=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_DEMO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_REMOTEPROC=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_TFTPSRV=y
+CONFIG_CMD_RARP=y
+CONFIG_CMD_CDP=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_LINK_LOCAL=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_SOUND=y
+CONFIG_CMD_QFW=y
+CONFIG_CMD_BOOTSTAGE=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_TPM=y
+CONFIG_CMD_TPM_TEST=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_MAC_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_HOSTFILE=y
+CONFIG_NETCONSOLE=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_DEVRES=y
+CONFIG_DEBUG_DEVRES=y
+CONFIG_ADC=y
+CONFIG_ADC_SANDBOX=y
+CONFIG_CLK=y
+CONFIG_CPU=y
+CONFIG_DM_DEMO=y
+CONFIG_DM_DEMO_SIMPLE=y
+CONFIG_DM_DEMO_SHAPE=y
+CONFIG_PM8916_GPIO=y
+CONFIG_SANDBOX_GPIO=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_I2C_CROS_EC_TUNNEL=y
+CONFIG_I2C_CROS_EC_LDO=y
+CONFIG_DM_I2C_GPIO=y
+CONFIG_SYS_I2C_SANDBOX=y
+CONFIG_I2C_MUX=y
+CONFIG_SPL_I2C_MUX=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=y
+CONFIG_CROS_EC_KEYB=y
+CONFIG_I8042_KEYB=y
+CONFIG_LED=y
+CONFIG_LED_BLINK=y
+CONFIG_LED_GPIO=y
+CONFIG_DM_MAILBOX=y
+CONFIG_SANDBOX_MBOX=y
+CONFIG_MISC=y
+CONFIG_CROS_EC=y
+CONFIG_CROS_EC_I2C=y
+CONFIG_CROS_EC_LPC=y
+CONFIG_CROS_EC_SANDBOX=y
+CONFIG_CROS_EC_SPI=y
+CONFIG_PWRSEQ=y
+CONFIG_SPL_PWRSEQ=y
+CONFIG_I2C_EEPROM=y
+CONFIG_MMC_SANDBOX=y
+CONFIG_SPI_FLASH_SANDBOX=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_SST=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_ETH=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_PCI_SANDBOX=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_ROCKCHIP_RK3036=y
+CONFIG_PINCTRL_ROCKCHIP_RK3288=y
+CONFIG_PINCTRL_SANDBOX=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_SANDBOX_POWER_DOMAIN=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_ACT8846=y
+CONFIG_DM_PMIC_PFUZE100=y
+CONFIG_DM_PMIC_MAX77686=y
+CONFIG_PMIC_PM8916=y
+CONFIG_PMIC_RK808=y
+CONFIG_PMIC_S2MPS11=y
+CONFIG_DM_PMIC_SANDBOX=y
+CONFIG_PMIC_S5M8767=y
+CONFIG_PMIC_TPS65090=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_ACT8846=y
+CONFIG_DM_REGULATOR_PFUZE100=y
+CONFIG_DM_REGULATOR_MAX77686=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK808=y
+CONFIG_REGULATOR_S5M8767=y
+CONFIG_DM_REGULATOR_SANDBOX=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_RAM=y
+CONFIG_REMOTEPROC_SANDBOX=y
+CONFIG_DM_RESET=y
+CONFIG_SANDBOX_RESET=y
+CONFIG_DM_RTC=y
+CONFIG_SANDBOX_SERIAL=y
+CONFIG_SOUND=y
+CONFIG_SOUND_SANDBOX=y
+CONFIG_SANDBOX_SPI=y
+CONFIG_SPMI=y
+CONFIG_SPMI_SANDBOX=y
+CONFIG_SYSRESET=y
+CONFIG_TIMER=y
+CONFIG_TIMER_EARLY=y
+CONFIG_SANDBOX_TIMER=y
+CONFIG_TPM_TIS_SANDBOX=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EMUL=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_SYS_USB_EVENT_POLL=y
+CONFIG_DM_VIDEO=y
+CONFIG_CONSOLE_ROTATION=y
+CONFIG_CONSOLE_TRUETYPE=y
+CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y
+CONFIG_VIDEO_SANDBOX_SDL=y
+CONFIG_PHY=y
+CONFIG_PHY_SANDBOX=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_TPM=y
+CONFIG_LZ4=y
+CONFIG_ERRNO_STR=y
+CONFIG_UNIT_TEST=y
+CONFIG_UT_TIME=y
+CONFIG_UT_DM=y
+CONFIG_UT_ENV=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_SANDBOX=y
diff --git a/configs/seaboard_defconfig b/configs/seaboard_defconfig
index 00fc117..6900b77 100644
--- a/configs/seaboard_defconfig
+++ b/configs/seaboard_defconfig
@@ -22,8 +22,6 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_DM_PMIC=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
diff --git a/configs/tec-ng_defconfig b/configs/tec-ng_defconfig
index 91fd3d5..f6ab7a2 100644
--- a/configs/tec-ng_defconfig
+++ b/configs/tec-ng_defconfig
@@ -25,8 +25,6 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SYS_NS16550=y
diff --git a/configs/tec_defconfig b/configs/tec_defconfig
index 5c394b7..6d1bde8 100644
--- a/configs/tec_defconfig
+++ b/configs/tec_defconfig
@@ -23,8 +23,6 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_DM_PMIC=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
diff --git a/configs/trimslice_defconfig b/configs/trimslice_defconfig
index e4074a0..cb42ac5 100644
--- a/configs/trimslice_defconfig
+++ b/configs/trimslice_defconfig
@@ -24,8 +24,6 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_RTL8169=y
diff --git a/configs/venice2_defconfig b/configs/venice2_defconfig
index 97960e7..e4a48ec 100644
--- a/configs/venice2_defconfig
+++ b/configs/venice2_defconfig
@@ -26,11 +26,9 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SYS_NS16550=y
diff --git a/configs/ventana_defconfig b/configs/ventana_defconfig
index 8d3e54e..5b88b20 100644
--- a/configs/ventana_defconfig
+++ b/configs/ventana_defconfig
@@ -21,8 +21,6 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_DM_PMIC=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
diff --git a/configs/whistler_defconfig b/configs/whistler_defconfig
index 3ebfb79..9d60509 100644
--- a/configs/whistler_defconfig
+++ b/configs/whistler_defconfig
@@ -22,8 +22,6 @@
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_SPL_DM=y
-# CONFIG_BLK is not set
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
diff --git a/configs/xtfpga_defconfig b/configs/xtfpga_defconfig
index c797c25..9f85d63 100644
--- a/configs/xtfpga_defconfig
+++ b/configs/xtfpga_defconfig
@@ -8,6 +8,7 @@
 CONFIG_AUTOBOOT_PROMPT="Autobooting in %d seconds, press <SPACE> to stop\n"
 CONFIG_AUTOBOOT_STOP_STR=" "
 CONFIG_CMD_ASKENV=y
+CONFIG_CRC32_VERIFY=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_PING=y
 CONFIG_CMD_DIAG=y
diff --git a/configs/zynq_zc770_xm011_defconfig b/configs/zynq_zc770_xm011_defconfig
index dc49372..148f703 100644
--- a/configs/zynq_zc770_xm011_defconfig
+++ b/configs/zynq_zc770_xm011_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ZYNQ=y
 CONFIG_SYS_TEXT_BASE=0x4000000
+# CONFIG_SPL_FAT_SUPPORT is not set
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm011"
 CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
diff --git a/configs/zynq_zc770_xm012_defconfig b/configs/zynq_zc770_xm012_defconfig
index 16cd613..943efdb 100644
--- a/configs/zynq_zc770_xm012_defconfig
+++ b/configs/zynq_zc770_xm012_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ZYNQ=y
 CONFIG_SYS_TEXT_BASE=0x4000000
+# CONFIG_SPL_FAT_SUPPORT is not set
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm012"
 CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
diff --git a/configs/zynq_zc770_xm013_defconfig b/configs/zynq_zc770_xm013_defconfig
index 4396db0..5c02910 100644
--- a/configs/zynq_zc770_xm013_defconfig
+++ b/configs/zynq_zc770_xm013_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARCH_ZYNQ=y
 CONFIG_SYS_TEXT_BASE=0x4000000
+# CONFIG_SPL_FAT_SUPPORT is not set
 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm013"
 CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
diff --git a/doc/device-tree-bindings/config.txt b/doc/device-tree-bindings/config.txt
index d4bc1df..fe0e04a 100644
--- a/doc/device-tree-bindings/config.txt
+++ b/doc/device-tree-bindings/config.txt
@@ -21,6 +21,18 @@
 
 	This setting will override any values configured via Kconfig.
 
+u-boot,mmc-env-offset
+u-boot,mmc-env-offset-redundant
+	If present, the values of the 'u-boot,mmc-env-offset' and/or
+	of the u-boot,mmc-env-offset-redundant' properties overrides
+	CONFIG_ENV_OFFSET and CONFIG_ENV_OFFSET_REDUND, respectively,
+	for SD/MMC devices.
+
+	Values are interpreted as the offset from the start of the
+	device, specified in bytes.  It is assumed that the setting
+	will point at the beginning of a LBA and values that are not
+	LBA-aligned will be rounded up to the next LBA address.
+
 u-boot,spl-payload-offset
 	If present (and SPL is controlled by the device-tree), this allows
 	to override the CONFIG_SYS_SPI_U_BOOT_OFFS setting using a value
diff --git a/drivers/adc/adc-uclass.c b/drivers/adc/adc-uclass.c
index 3e28a56..a5ef722 100644
--- a/drivers/adc/adc-uclass.c
+++ b/drivers/adc/adc-uclass.c
@@ -345,12 +345,11 @@
 static int adc_vdd_platdata_set(struct udevice *dev)
 {
 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
-	int ret, offset = dev_of_offset(dev);
-	const void *fdt = gd->fdt_blob;
+	int ret;
 	char *prop;
 
 	prop = "vdd-polarity-negative";
-	uc_pdata->vdd_polarity_negative = fdtdec_get_bool(fdt, offset, prop);
+	uc_pdata->vdd_polarity_negative = dev_read_bool(dev, prop);
 
 	ret = adc_vdd_platdata_update(dev);
 	if (ret != -ENOENT)
@@ -358,7 +357,7 @@
 
 	/* No vdd-supply phandle. */
 	prop  = "vdd-microvolts";
-	uc_pdata->vdd_microvolts = fdtdec_get_int(fdt, offset, prop, -ENODATA);
+	uc_pdata->vdd_microvolts = dev_read_u32_default(dev, prop, -ENODATA);
 
 	return 0;
 }
@@ -366,12 +365,11 @@
 static int adc_vss_platdata_set(struct udevice *dev)
 {
 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
-	int ret, offset = dev_of_offset(dev);
-	const void *fdt = gd->fdt_blob;
+	int ret;
 	char *prop;
 
 	prop = "vss-polarity-negative";
-	uc_pdata->vss_polarity_negative = fdtdec_get_bool(fdt, offset, prop);
+	uc_pdata->vss_polarity_negative = dev_read_bool(dev, prop);
 
 	ret = adc_vss_platdata_update(dev);
 	if (ret != -ENOENT)
@@ -379,7 +377,7 @@
 
 	/* No vss-supply phandle. */
 	prop = "vss-microvolts";
-	uc_pdata->vss_microvolts = fdtdec_get_int(fdt, offset, prop, -ENODATA);
+	uc_pdata->vss_microvolts = dev_read_u32_default(dev, prop, -ENODATA);
 
 	return 0;
 }
diff --git a/drivers/adc/exynos-adc.c b/drivers/adc/exynos-adc.c
index 534e68d..324d72f 100644
--- a/drivers/adc/exynos-adc.c
+++ b/drivers/adc/exynos-adc.c
@@ -107,7 +107,7 @@
 	struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
 	struct exynos_adc_priv *priv = dev_get_priv(dev);
 
-	priv->regs = (struct exynos_adc_v2 *)dev_get_addr(dev);
+	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);
 		return -ENODATA;
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index af3c35f..6145675 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -363,7 +363,7 @@
 	} while (1);
 }
 
-int blk_get_device(int if_type, int devnum, struct udevice **devp)
+int blk_find_device(int if_type, int devnum, struct udevice **devp)
 {
 	struct uclass *uc;
 	struct udevice *dev;
@@ -379,13 +379,24 @@
 		      if_type, devnum, dev->name, desc->if_type, desc->devnum);
 		if (desc->if_type == if_type && desc->devnum == devnum) {
 			*devp = dev;
-			return device_probe(dev);
+			return 0;
 		}
 	}
 
 	return -ENODEV;
 }
 
+int blk_get_device(int if_type, int devnum, struct udevice **devp)
+{
+	int ret;
+
+	ret = blk_find_device(if_type, devnum, devp);
+	if (ret)
+		return ret;
+
+	return device_probe(*devp);
+}
+
 unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start,
 			lbaint_t blkcnt, void *buffer)
 {
@@ -462,6 +473,44 @@
 	return max_devnum;
 }
 
+static int blk_next_free_devnum(enum if_type if_type)
+{
+	int ret;
+
+	ret = blk_find_max_devnum(if_type);
+	if (ret == -ENODEV)
+		return 0;
+	if (ret < 0)
+		return ret;
+
+	return ret + 1;
+}
+
+static int blk_claim_devnum(enum if_type if_type, int devnum)
+{
+	struct udevice *dev;
+	struct uclass *uc;
+	int ret;
+
+	ret = uclass_get(UCLASS_BLK, &uc);
+	if (ret)
+		return ret;
+	uclass_foreach_dev(dev, uc) {
+		struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+		if (desc->if_type == if_type && desc->devnum == devnum) {
+			int next = blk_next_free_devnum(if_type);
+
+			if (next < 0)
+				return next;
+			desc->devnum = next;
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
 int blk_create_device(struct udevice *parent, const char *drv_name,
 		      const char *name, int if_type, int devnum, int blksz,
 		      lbaint_t size, struct udevice **devp)
@@ -471,14 +520,14 @@
 	int ret;
 
 	if (devnum == -1) {
-		ret = blk_find_max_devnum(if_type);
-		if (ret == -ENODEV)
-			devnum = 0;
-		else if (ret < 0)
+		devnum = blk_next_free_devnum(if_type);
+	} else {
+		ret = blk_claim_devnum(if_type, devnum);
+		if (ret < 0 && ret != -ENOENT)
 			return ret;
-		else
-			devnum = ret + 1;
 	}
+	if (devnum < 0)
+		return devnum;
 	ret = device_bind_driver(parent, drv_name, name, &dev);
 	if (ret)
 		return ret;
diff --git a/drivers/block/dwc_ahci.c b/drivers/block/dwc_ahci.c
index d5bb0b8..3f839bf 100644
--- a/drivers/block/dwc_ahci.c
+++ b/drivers/block/dwc_ahci.c
@@ -31,15 +31,15 @@
 	struct scsi_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	plat->max_id = fdtdec_get_uint(gd->fdt_blob, dev->of_offset, "max-id",
-				       CONFIG_SYS_SCSI_MAX_SCSI_ID);
-	plat->max_lun = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
+	plat->max_id = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+				       "max-id", CONFIG_SYS_SCSI_MAX_SCSI_ID);
+	plat->max_lun = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
 					"max-lun", CONFIG_SYS_SCSI_MAX_LUN);
 
-	priv->base = map_physmem(dev_get_addr(dev), sizeof(void *),
+	priv->base = map_physmem(devfdt_get_addr(dev), sizeof(void *),
 				 MAP_NOCACHE);
 
-	addr = dev_get_addr_index(dev, 1);
+	addr = devfdt_get_addr_index(dev, 1);
 	if (addr != FDT_ADDR_T_NONE) {
 		priv->wrapper_base = map_physmem(addr, sizeof(void *),
 						 MAP_NOCACHE);
diff --git a/drivers/block/sata_ceva.c b/drivers/block/sata_ceva.c
index 9b54664..65a4bb2 100644
--- a/drivers/block/sata_ceva.c
+++ b/drivers/block/sata_ceva.c
@@ -129,7 +129,7 @@
 {
 	struct scsi_platdata *plat = dev_get_platdata(dev);
 
-	plat->base = dev_get_addr(dev);
+	plat->base = devfdt_get_addr(dev);
 	if (plat->base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index ccf47a1..c2efdda 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -429,7 +429,7 @@
 {
 	struct ast2500_clk_priv *priv = dev_get_priv(dev);
 
-	priv->scu = dev_get_addr_ptr(dev);
+	priv->scu = devfdt_get_addr_ptr(dev);
 	if (IS_ERR(priv->scu))
 		return PTR_ERR(priv->scu);
 
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
index ac27d3e..8c9a3cb 100644
--- a/drivers/clk/at91/clk-generated.c
+++ b/drivers/clk/at91/clk-generated.c
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <clk-uclass.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <linux/io.h>
 #include <mach/at91_pmc.h>
 #include "pmc.h"
diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c
index 1a304ba..dcc64fb 100644
--- a/drivers/clk/at91/clk-h32mx.c
+++ b/drivers/clk/at91/clk-h32mx.c
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <clk-uclass.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <dm/util.h>
 #include <linux/io.h>
 #include <mach/at91_pmc.h>
diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
index 252d076..a234ce8 100644
--- a/drivers/clk/at91/clk-main.c
+++ b/drivers/clk/at91/clk-main.c
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <clk-uclass.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <linux/io.h>
 #include <mach/at91_pmc.h>
 #include "pmc.h"
diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
index 72d0a73..6bc78ba 100644
--- a/drivers/clk/at91/clk-master.c
+++ b/drivers/clk/at91/clk-master.c
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <clk-uclass.h>
-#include <dm/device.h>
+#include <dm.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c
index 62fabe3..212a30b 100644
--- a/drivers/clk/at91/clk-peripheral.c
+++ b/drivers/clk/at91/clk-peripheral.c
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <clk-uclass.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <linux/io.h>
 #include <mach/at91_pmc.h>
 #include "pmc.h"
diff --git a/drivers/clk/at91/clk-plla.c b/drivers/clk/at91/clk-plla.c
index 2a71399..f5b2ca1 100644
--- a/drivers/clk/at91/clk-plla.c
+++ b/drivers/clk/at91/clk-plla.c
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <clk-uclass.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <linux/io.h>
 #include <mach/at91_pmc.h>
 #include "pmc.h"
diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c
index f7666b4..f18f002 100644
--- a/drivers/clk/at91/clk-slow.c
+++ b/drivers/clk/at91/clk-slow.c
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <clk-uclass.h>
-#include <dm/device.h>
+#include <dm.h>
 
 static int at91_slow_clk_enable(struct clk *clk)
 {
diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c
index 5b59a0c..24b271a 100644
--- a/drivers/clk/at91/clk-system.c
+++ b/drivers/clk/at91/clk-system.c
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <clk-uclass.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <linux/io.h>
 #include <mach/at91_pmc.h>
 #include "pmc.h"
diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c
index 369a687..af5362d 100644
--- a/drivers/clk/at91/clk-utmi.c
+++ b/drivers/clk/at91/clk-utmi.c
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <clk-uclass.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <linux/io.h>
 #include <mach/at91_pmc.h>
 #include "pmc.h"
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 72d52c5..be1d11e 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -7,9 +7,8 @@
 
 #include <common.h>
 #include <clk-uclass.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <dm/lists.h>
-#include <dm/root.h>
 #include <dm/util.h>
 #include "pmc.h"
 
@@ -40,7 +39,7 @@
 
 	dev = dev_get_parent(dev);
 
-	plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev);
+	plat->reg_base = (struct at91_pmc *)devfdt_get_addr_ptr(dev);
 
 	return 0;
 }
@@ -80,7 +79,7 @@
 		if (!name)
 			return -EINVAL;
 		ret = device_bind_driver_to_node(dev, drv_name, name,
-						 offset, NULL);
+					offset_to_ofnode(offset), NULL);
 		if (ret)
 			return ret;
 	}
@@ -88,7 +87,7 @@
 	return 0;
 }
 
-int at91_clk_of_xlate(struct clk *clk, struct fdtdec_phandle_args *args)
+int at91_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
 {
 	int periph;
 
@@ -115,7 +114,7 @@
 	dev_periph_container = dev_get_parent(dev);
 	dev_pmc = dev_get_parent(dev_periph_container);
 
-	plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev_pmc);
+	plat->reg_base = (struct at91_pmc *)devfdt_get_addr_ptr(dev_pmc);
 
 	return 0;
 }
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
index f222fce..bd3caba 100644
--- a/drivers/clk/at91/pmc.h
+++ b/drivers/clk/at91/pmc.h
@@ -15,7 +15,7 @@
 int at91_pmc_core_probe(struct udevice *dev);
 int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name);
 
-int at91_clk_of_xlate(struct clk *clk, struct fdtdec_phandle_args *args);
+int at91_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args);
 int at91_clk_probe(struct udevice *dev);
 
 #endif
diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c
index 6035e20..0c08812 100644
--- a/drivers/clk/at91/sckc.c
+++ b/drivers/clk/at91/sckc.c
@@ -6,8 +6,7 @@
  */
 
 #include <common.h>
-#include <dm/device.h>
-#include <dm/root.h>
+#include <dm.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 6fcfd69..83b6328 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -38,7 +38,7 @@
 }
 # else
 static int clk_of_xlate_default(struct clk *clk,
-				struct fdtdec_phandle_args *args)
+				struct ofnode_phandle_args *args)
 {
 	debug("%s(clk=%p)\n", __func__, clk);
 
@@ -58,23 +58,22 @@
 int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
 {
 	int ret;
-	struct fdtdec_phandle_args args;
+	struct ofnode_phandle_args args;
 	struct udevice *dev_clk;
 	struct clk_ops *ops;
 
 	debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk);
 
 	assert(clk);
-	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
-					     "clocks", "#clock-cells", 0, index,
-					     &args);
+	ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0,
+					  index, &args);
 	if (ret) {
 		debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
 		      __func__, ret);
 		return ret;
 	}
 
-	ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &dev_clk);
+	ret = uclass_get_device_by_ofnode(UCLASS_CLK, args.node, &dev_clk);
 	if (ret) {
 		debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
 		      __func__, ret);
@@ -104,8 +103,7 @@
 
 	debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk);
 
-	index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
-				      "clock-names", name);
+	index = dev_read_stringlist_search(dev, "clock-names", name);
 	if (index < 0) {
 		debug("fdt_stringlist_search() failed: %d\n", index);
 		return index;
diff --git a/drivers/clk/clk_bcm6345.c b/drivers/clk/clk_bcm6345.c
index 4c7a2df..93603fa 100644
--- a/drivers/clk/clk_bcm6345.c
+++ b/drivers/clk/clk_bcm6345.c
@@ -59,7 +59,7 @@
 	fdt_addr_t addr;
 	fdt_size_t size;
 
-	addr = dev_get_addr_size_index(dev, 0, &size);
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c
index 3911bf6..63565b6 100644
--- a/drivers/clk/clk_fixed_rate.c
+++ b/drivers/clk/clk_fixed_rate.c
@@ -6,7 +6,7 @@
 
 #include <common.h>
 #include <clk-uclass.h>
-#include <dm/device.h>
+#include <dm.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -31,9 +31,8 @@
 static int clk_fixed_rate_ofdata_to_platdata(struct udevice *dev)
 {
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
-	to_clk_fixed_rate(dev)->fixed_rate =
-				fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-					       "clock-frequency", 0);
+	to_clk_fixed_rate(dev)->fixed_rate = dev_read_u32_default(dev,
+							"clock-frequency", 0);
 #endif
 
 	return 0;
diff --git a/drivers/clk/clk_stm32f7.c b/drivers/clk/clk_stm32f7.c
index da3c204..fcdc3c0 100644
--- a/drivers/clk/clk_stm32f7.c
+++ b/drivers/clk/clk_stm32f7.c
@@ -252,8 +252,7 @@
 	return 0;
 }
 
-static int stm32_clk_of_xlate(struct clk *clk,
-			struct fdtdec_phandle_args *args)
+static int stm32_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
 {
 	debug("%s(clk=%p)\n", __func__, clk);
 
diff --git a/drivers/clk/clk_zynq.c b/drivers/clk/clk_zynq.c
index 6edc4dc..50f2a65 100644
--- a/drivers/clk/clk_zynq.c
+++ b/drivers/clk/clk_zynq.c
@@ -459,14 +459,14 @@
 	for (i = 0; i < 2; i++) {
 		sprintf(name, "gem%d_emio_clk", i);
 		ret = clk_get_by_name(dev, name, &priv->gem_emio_clk[i]);
-		if (ret < 0 && ret != -FDT_ERR_NOTFOUND) {
+		if (ret < 0 && ret != -ENODATA) {
 			dev_err(dev, "failed to get %s clock\n", name);
 			return ret;
 		}
 	}
 #endif
 
-	priv->ps_clk_freq = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
+	priv->ps_clk_freq = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
 					    "ps-clk-frequency", 33333333UL);
 
 	return 0;
diff --git a/drivers/clk/clk_zynqmp.c b/drivers/clk/clk_zynqmp.c
index 694274d..50eaf31 100644
--- a/drivers/clk/clk_zynqmp.c
+++ b/drivers/clk/clk_zynqmp.c
@@ -9,8 +9,8 @@
 #include <common.h>
 #include <linux/bitops.h>
 #include <clk-uclass.h>
-#include <dm/device.h>
 #include <clk.h>
+#include <dm.h>
 
 #define ZYNQMP_GEM0_REF_CTRL		0xFF5E0050
 #define ZYNQMP_IOPLL_CTRL		0xFF5E0020
diff --git a/drivers/clk/exynos/clk-exynos7420.c b/drivers/clk/exynos/clk-exynos7420.c
index 1f017a3..e34945d 100644
--- a/drivers/clk/exynos/clk-exynos7420.c
+++ b/drivers/clk/exynos/clk-exynos7420.c
@@ -98,7 +98,7 @@
 	fdt_addr_t base;
 	int ret;
 
-	base = dev_get_addr(dev);
+	base = devfdt_get_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
@@ -152,7 +152,7 @@
 	if (!priv)
 		return -EINVAL;
 
-	base = dev_get_addr(dev);
+	base = devfdt_get_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/clk/rockchip/clk_rk3036.c b/drivers/clk/rockchip/clk_rk3036.c
index d866d0b..0bee5db 100644
--- a/drivers/clk/rockchip/clk_rk3036.c
+++ b/drivers/clk/rockchip/clk_rk3036.c
@@ -331,7 +331,7 @@
 {
 	struct rk3036_clk_priv *priv = dev_get_priv(dev);
 
-	priv->cru = (struct rk3036_cru *)dev_get_addr(dev);
+	priv->cru = (struct rk3036_cru *)devfdt_get_addr(dev);
 	rkclk_init(priv->cru);
 
 	return 0;
diff --git a/drivers/clk/rockchip/clk_rk3188.c b/drivers/clk/rockchip/clk_rk3188.c
index b32491d..6f30332 100644
--- a/drivers/clk/rockchip/clk_rk3188.c
+++ b/drivers/clk/rockchip/clk_rk3188.c
@@ -542,7 +542,7 @@
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct rk3188_clk_priv *priv = dev_get_priv(dev);
 
-	priv->cru = (struct rk3188_cru *)dev_get_addr(dev);
+	priv->cru = (struct rk3188_cru *)devfdt_get_addr(dev);
 #endif
 
 	return 0;
diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c
index fc369dd..14851ca 100644
--- a/drivers/clk/rockchip/clk_rk3288.c
+++ b/drivers/clk/rockchip/clk_rk3288.c
@@ -794,7 +794,7 @@
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct rk3288_clk_priv *priv = dev_get_priv(dev);
 
-	priv->cru = (struct rk3288_cru *)dev_get_addr(dev);
+	priv->cru = (struct rk3288_cru *)devfdt_get_addr(dev);
 #endif
 
 	return 0;
diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c
index 8ec1574..2065a8a 100644
--- a/drivers/clk/rockchip/clk_rk3328.c
+++ b/drivers/clk/rockchip/clk_rk3328.c
@@ -555,7 +555,7 @@
 {
 	struct rk3328_clk_priv *priv = dev_get_priv(dev);
 
-	priv->cru = (struct rk3328_cru *)dev_get_addr(dev);
+	priv->cru = (struct rk3328_cru *)devfdt_get_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index 026ed4d..53d2a3f 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -970,7 +970,7 @@
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct rk3399_clk_priv *priv = dev_get_priv(dev);
 
-	priv->cru = (struct rk3399_cru *)dev_get_addr(dev);
+	priv->cru = (struct rk3399_cru *)devfdt_get_addr(dev);
 #endif
 	return 0;
 }
@@ -1154,7 +1154,7 @@
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct rk3399_pmuclk_priv *priv = dev_get_priv(dev);
 
-	priv->pmucru = (struct rk3399_pmucru *)dev_get_addr(dev);
+	priv->pmucru = (struct rk3399_pmucru *)devfdt_get_addr(dev);
 #endif
 	return 0;
 }
diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c
index bcb2d2e..d88bd62 100644
--- a/drivers/clk/uniphier/clk-uniphier-core.c
+++ b/drivers/clk/uniphier/clk-uniphier-core.c
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <clk-uclass.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
@@ -132,7 +132,7 @@
 	struct uniphier_clk_priv *priv = dev_get_priv(dev);
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev->parent);
+	addr = devfdt_get_addr(dev->parent);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 405e9ad..fb5c4e8 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -215,4 +215,8 @@
 	  mistranslation of device addresses, so ensure that this is
 	  enabled if your board does include an ISA bus.
 
+config DM_DEV_READ_INLINE
+	bool
+	default y if !OF_LIVE
+
 endmenu
diff --git a/drivers/core/Makefile b/drivers/core/Makefile
index 07adb61..435cf98 100644
--- a/drivers/core/Makefile
+++ b/drivers/core/Makefile
@@ -4,10 +4,15 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y	+= device.o lists.o root.o uclass.o util.o
+obj-y	+= device.o fdtaddr.o lists.o root.o uclass.o util.o
 obj-$(CONFIG_DEVRES) += devres.o
 obj-$(CONFIG_$(SPL_)DM_DEVICE_REMOVE)	+= device-remove.o
 obj-$(CONFIG_$(SPL_)SIMPLE_BUS)	+= simple-bus.o
 obj-$(CONFIG_DM)	+= dump.o
 obj-$(CONFIG_$(SPL_)REGMAP)	+= regmap.o
 obj-$(CONFIG_$(SPL_)SYSCON)	+= syscon-uclass.o
+obj-$(CONFIG_OF_LIVE) += of_access.o of_addr.o
+ifndef CONFIG_DM_DEV_READ_INLINE
+obj-$(CONFIG_OF_CONTROL) += read.o
+endif
+obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 09a115f..5463d1f 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -19,6 +19,7 @@
 #include <dm/lists.h>
 #include <dm/pinctrl.h>
 #include <dm/platdata.h>
+#include <dm/read.h>
 #include <dm/uclass.h>
 #include <dm/uclass-internal.h>
 #include <dm/util.h>
@@ -29,7 +30,7 @@
 
 static int device_bind_common(struct udevice *parent, const struct driver *drv,
 			      const char *name, void *platdata,
-			      ulong driver_data, int of_offset,
+			      ulong driver_data, ofnode node,
 			      uint of_platdata_size, struct udevice **devp)
 {
 	struct udevice *dev;
@@ -60,7 +61,7 @@
 	dev->platdata = platdata;
 	dev->driver_data = driver_data;
 	dev->name = name;
-	dev->of_offset = of_offset;
+	dev->node = node;
 	dev->parent = parent;
 	dev->driver = drv;
 	dev->uclass = uc;
@@ -76,10 +77,8 @@
 		 * resolved (and ->seq updated) when the device is probed.
 		 */
 		if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {
-			if (uc->uc_drv->name && of_offset != -1) {
-				fdtdec_get_alias_seq(gd->fdt_blob,
-						uc->uc_drv->name, of_offset,
-						&dev->req_seq);
+			if (uc->uc_drv->name && ofnode_valid(node)) {
+				dev_read_alias_seq(dev, &dev->req_seq);
 			}
 		}
 	}
@@ -215,19 +214,19 @@
 
 int device_bind_with_driver_data(struct udevice *parent,
 				 const struct driver *drv, const char *name,
-				 ulong driver_data, int of_offset,
+				 ulong driver_data, ofnode node,
 				 struct udevice **devp)
 {
-	return device_bind_common(parent, drv, name, NULL, driver_data,
-				  of_offset, 0, devp);
+	return device_bind_common(parent, drv, name, NULL, driver_data, node,
+				  0, devp);
 }
 
 int device_bind(struct udevice *parent, const struct driver *drv,
 		const char *name, void *platdata, int of_offset,
 		struct udevice **devp)
 {
-	return device_bind_common(parent, drv, name, platdata, 0, of_offset, 0,
-				  devp);
+	return device_bind_common(parent, drv, name, platdata, 0,
+				  offset_to_ofnode(of_offset), 0, devp);
 }
 
 int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
@@ -246,7 +245,8 @@
 	platdata_size = info->platdata_size;
 #endif
 	return device_bind_common(parent, drv, info->name,
-			(void *)info->platdata, 0, -1, platdata_size, devp);
+			(void *)info->platdata, 0, ofnode_null(), platdata_size,
+			devp);
 }
 
 static void *alloc_priv(int size, uint flags)
@@ -383,7 +383,7 @@
 			goto fail;
 	}
 
-	if (drv->ofdata_to_platdata && dev_of_offset(dev) >= 0) {
+	if (drv->ofdata_to_platdata && dev_has_of_node(dev)) {
 		ret = drv->ofdata_to_platdata(dev);
 		if (ret)
 			goto fail;
@@ -655,131 +655,6 @@
 	return dev->uclass->uc_drv->name;
 }
 
-fdt_addr_t dev_get_addr_index(struct udevice *dev, int index)
-{
-#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
-	fdt_addr_t addr;
-
-	if (CONFIG_IS_ENABLED(OF_TRANSLATE)) {
-		const fdt32_t *reg;
-		int len = 0;
-		int na, ns;
-
-		na = fdt_address_cells(gd->fdt_blob,
-				       dev_of_offset(dev->parent));
-		if (na < 1) {
-			debug("bad #address-cells\n");
-			return FDT_ADDR_T_NONE;
-		}
-
-		ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent));
-		if (ns < 0) {
-			debug("bad #size-cells\n");
-			return FDT_ADDR_T_NONE;
-		}
-
-		reg = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "reg",
-				  &len);
-		if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns)))) {
-			debug("Req index out of range\n");
-			return FDT_ADDR_T_NONE;
-		}
-
-		reg += index * (na + ns);
-
-		/*
-		 * Use the full-fledged translate function for complex
-		 * bus setups.
-		 */
-		addr = fdt_translate_address((void *)gd->fdt_blob,
-					     dev_of_offset(dev), reg);
-	} else {
-		/*
-		 * Use the "simple" translate function for less complex
-		 * bus setups.
-		 */
-		addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
-				dev_of_offset(dev->parent), dev_of_offset(dev),
-				"reg", index, NULL, false);
-		if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) {
-			if (device_get_uclass_id(dev->parent) ==
-			    UCLASS_SIMPLE_BUS)
-				addr = simple_bus_translate(dev->parent, addr);
-		}
-	}
-
-	/*
-	 * Some platforms need a special address translation. Those
-	 * platforms (e.g. mvebu in SPL) can configure a translation
-	 * offset in the DM by calling dm_set_translation_offset() that
-	 * will get added to all addresses returned by dev_get_addr().
-	 */
-	addr += dm_get_translation_offset();
-
-	return addr;
-#else
-	return FDT_ADDR_T_NONE;
-#endif
-}
-
-fdt_addr_t dev_get_addr_size_index(struct udevice *dev, int index,
-				   fdt_size_t *size)
-{
-#if CONFIG_IS_ENABLED(OF_CONTROL)
-	/*
-	 * Only get the size in this first call. We'll get the addr in the
-	 * next call to the exisiting dev_get_xxx function which handles
-	 * all config options.
-	 */
-	fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev_of_offset(dev),
-					   "reg", index, size, false);
-
-	/*
-	 * Get the base address via the existing function which handles
-	 * all Kconfig cases
-	 */
-	return dev_get_addr_index(dev, index);
-#else
-	return FDT_ADDR_T_NONE;
-#endif
-}
-
-fdt_addr_t dev_get_addr_name(struct udevice *dev, const char *name)
-{
-#if CONFIG_IS_ENABLED(OF_CONTROL)
-	int index;
-
-	index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
-				      "reg-names", name);
-	if (index < 0)
-		return index;
-
-	return dev_get_addr_index(dev, index);
-#else
-	return FDT_ADDR_T_NONE;
-#endif
-}
-
-fdt_addr_t dev_get_addr(struct udevice *dev)
-{
-	return dev_get_addr_index(dev, 0);
-}
-
-void *dev_get_addr_ptr(struct udevice *dev)
-{
-	return (void *)(uintptr_t)dev_get_addr_index(dev, 0);
-}
-
-void *dev_map_physmem(struct udevice *dev, unsigned long size)
-{
-	fdt_addr_t addr = dev_get_addr(dev);
-
-	if (addr == FDT_ADDR_T_NONE)
-		return NULL;
-
-	return map_physmem(addr, size, MAP_NOCACHE);
-}
-
 bool device_has_children(struct udevice *dev)
 {
 	return !list_empty(&dev->child_head);
@@ -824,7 +699,7 @@
 	return 0;
 }
 
-bool of_device_is_compatible(struct udevice *dev, const char *compat)
+bool device_is_compatible(struct udevice *dev, const char *compat)
 {
 	const void *fdt = gd->fdt_blob;
 
diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c
new file mode 100644
index 0000000..3847dd8
--- /dev/null
+++ b/drivers/core/fdtaddr.c
@@ -0,0 +1,143 @@
+/*
+ * Device addresses
+ *
+ * Copyright (c) 2017 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdt_support.h>
+#include <asm/io.h>
+#include <dm/device-internal.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+fdt_addr_t devfdt_get_addr_index(struct udevice *dev, int index)
+{
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+	fdt_addr_t addr;
+
+	if (CONFIG_IS_ENABLED(OF_TRANSLATE)) {
+		const fdt32_t *reg;
+		int len = 0;
+		int na, ns;
+
+		na = fdt_address_cells(gd->fdt_blob,
+				       dev_of_offset(dev->parent));
+		if (na < 1) {
+			debug("bad #address-cells\n");
+			return FDT_ADDR_T_NONE;
+		}
+
+		ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent));
+		if (ns < 0) {
+			debug("bad #size-cells\n");
+			return FDT_ADDR_T_NONE;
+		}
+
+		reg = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "reg",
+				  &len);
+		if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns)))) {
+			debug("Req index out of range\n");
+			return FDT_ADDR_T_NONE;
+		}
+
+		reg += index * (na + ns);
+
+		/*
+		 * Use the full-fledged translate function for complex
+		 * bus setups.
+		 */
+		addr = fdt_translate_address((void *)gd->fdt_blob,
+					     dev_of_offset(dev), reg);
+	} else {
+		/*
+		 * Use the "simple" translate function for less complex
+		 * bus setups.
+		 */
+		addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
+				dev_of_offset(dev->parent), dev_of_offset(dev),
+				"reg", index, NULL, false);
+		if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) {
+			if (device_get_uclass_id(dev->parent) ==
+			    UCLASS_SIMPLE_BUS)
+				addr = simple_bus_translate(dev->parent, addr);
+		}
+	}
+
+	/*
+	 * Some platforms need a special address translation. Those
+	 * platforms (e.g. mvebu in SPL) can configure a translation
+	 * offset in the DM by calling dm_set_translation_offset() that
+	 * will get added to all addresses returned by devfdt_get_addr().
+	 */
+	addr += dm_get_translation_offset();
+
+	return addr;
+#else
+	return FDT_ADDR_T_NONE;
+#endif
+}
+
+fdt_addr_t devfdt_get_addr_size_index(struct udevice *dev, int index,
+				   fdt_size_t *size)
+{
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	/*
+	 * Only get the size in this first call. We'll get the addr in the
+	 * next call to the exisiting dev_get_xxx function which handles
+	 * all config options.
+	 */
+	fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev_of_offset(dev),
+					   "reg", index, size, false);
+
+	/*
+	 * Get the base address via the existing function which handles
+	 * all Kconfig cases
+	 */
+	return devfdt_get_addr_index(dev, index);
+#else
+	return FDT_ADDR_T_NONE;
+#endif
+}
+
+fdt_addr_t devfdt_get_addr_name(struct udevice *dev, const char *name)
+{
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	int index;
+
+	index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
+				      "reg-names", name);
+	if (index < 0)
+		return index;
+
+	return devfdt_get_addr_index(dev, index);
+#else
+	return FDT_ADDR_T_NONE;
+#endif
+}
+
+fdt_addr_t devfdt_get_addr(struct udevice *dev)
+{
+	return devfdt_get_addr_index(dev, 0);
+}
+
+void *devfdt_get_addr_ptr(struct udevice *dev)
+{
+	return (void *)(uintptr_t)devfdt_get_addr_index(dev, 0);
+}
+
+void *devfdt_map_physmem(struct udevice *dev, unsigned long size)
+{
+	fdt_addr_t addr = devfdt_get_addr(dev);
+
+	if (addr == FDT_ADDR_T_NONE)
+		return NULL;
+
+	return map_physmem(addr, size, MAP_NOCACHE);
+}
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index 23b6ba7..b79f26d 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -74,11 +74,12 @@
 int device_bind_driver(struct udevice *parent, const char *drv_name,
 		       const char *dev_name, struct udevice **devp)
 {
-	return device_bind_driver_to_node(parent, drv_name, dev_name, -1, devp);
+	return device_bind_driver_to_node(parent, drv_name, dev_name,
+					  ofnode_null(), devp);
 }
 
 int device_bind_driver_to_node(struct udevice *parent, const char *drv_name,
-			       const char *dev_name, int node,
+			       const char *dev_name, ofnode node,
 			       struct udevice **devp)
 {
 	struct driver *drv;
@@ -89,14 +90,10 @@
 		debug("Cannot find driver '%s'\n", drv_name);
 		return -ENOENT;
 	}
-	ret = device_bind(parent, drv, dev_name, NULL, node, devp);
-	if (ret) {
-		debug("Cannot create device named '%s' (err=%d)\n",
-		      dev_name, ret);
-		return ret;
-	}
+	ret = device_bind_with_driver_data(parent, drv, dev_name, 0 /* data */,
+					   node, devp);
 
-	return 0;
+	return ret;
 }
 
 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
@@ -126,8 +123,7 @@
 	return -ENOENT;
 }
 
-int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
-		   struct udevice **devp)
+int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp)
 {
 	struct driver *driver = ll_entry_start(struct driver, driver);
 	const int n_ents = ll_entry_count(struct driver, driver);
@@ -140,19 +136,20 @@
 	int result = 0;
 	int ret = 0;
 
-	name = fdt_get_name(blob, offset, NULL);
-	dm_dbg("bind node %s\n", name);
 	if (devp)
 		*devp = NULL;
+	name = ofnode_get_name(node);
+	dm_dbg("bind node %s\n", name);
 
-	compat_list = fdt_getprop(blob, offset, "compatible", &compat_length);
+	compat_list = (const char *)ofnode_read_prop(node, "compatible",
+						     &compat_length);
 	if (!compat_list) {
 		if (compat_length == -FDT_ERR_NOTFOUND) {
 			dm_dbg("Device '%s' has no compatible string\n", name);
 			return 0;
 		}
 
-		dm_warn("Device tree error at offset %d\n", offset);
+		dm_warn("Device tree error at node '%s'\n", name);
 		return compat_length;
 	}
 
@@ -177,7 +174,7 @@
 
 		dm_dbg("   - found match at '%s'\n", entry->name);
 		ret = device_bind_with_driver_data(parent, entry, name,
-						   id->data, offset, &dev);
+						   id->data, node, &dev);
 		if (ret == -ENODEV) {
 			dm_dbg("Driver '%s' refuses to bind\n", entry->name);
 			continue;
diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c
new file mode 100644
index 0000000..94ef3cc
--- /dev/null
+++ b/drivers/core/of_access.c
@@ -0,0 +1,735 @@
+/*
+ * Originally from Linux v4.9
+ * Paul Mackerras	August 1996.
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ *   {engebret|bergner}@us.ibm.com
+ *
+ * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net
+ *
+ * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
+ * Grant Likely.
+ *
+ * Modified for U-Boot
+ * Copyright (c) 2017 Google, Inc
+ *
+ * This file follows drivers/of/base.c with functions in the same order as the
+ * Linux version.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <dm/of_access.h>
+#include <linux/ctype.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* list of struct alias_prop aliases */
+LIST_HEAD(aliases_lookup);
+
+/* "/aliaes" node */
+static struct device_node *of_aliases;
+
+/* "/chosen" node */
+static struct device_node *of_chosen;
+
+/* node pointed to by the stdout-path alias */
+static struct device_node *of_stdout;
+
+/* pointer to options given after the alias (separated by :) or NULL if none */
+static const char *of_stdout_options;
+
+/**
+ * struct alias_prop - Alias property in 'aliases' node
+ *
+ * The structure represents one alias property of 'aliases' node as
+ * an entry in aliases_lookup list.
+ *
+ * @link:	List node to link the structure in aliases_lookup list
+ * @alias:	Alias property name
+ * @np:		Pointer to device_node that the alias stands for
+ * @id:		Index value from end of alias name
+ * @stem:	Alias string without the index
+ */
+struct alias_prop {
+	struct list_head link;
+	const char *alias;
+	struct device_node *np;
+	int id;
+	char stem[0];
+};
+
+int of_n_addr_cells(const struct device_node *np)
+{
+	const __be32 *ip;
+
+	do {
+		if (np->parent)
+			np = np->parent;
+		ip = of_get_property(np, "#address-cells", NULL);
+		if (ip)
+			return be32_to_cpup(ip);
+	} while (np->parent);
+
+	/* No #address-cells property for the root node */
+	return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
+}
+
+int of_n_size_cells(const struct device_node *np)
+{
+	const __be32 *ip;
+
+	do {
+		if (np->parent)
+			np = np->parent;
+		ip = of_get_property(np, "#size-cells", NULL);
+		if (ip)
+			return be32_to_cpup(ip);
+	} while (np->parent);
+
+	/* No #size-cells property for the root node */
+	return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
+}
+
+struct property *of_find_property(const struct device_node *np,
+				  const char *name, int *lenp)
+{
+	struct property *pp;
+
+	if (!np)
+		return NULL;
+
+	for (pp = np->properties; pp; pp = pp->next) {
+		if (strcmp(pp->name, name) == 0) {
+			if (lenp)
+				*lenp = pp->length;
+			break;
+		}
+	}
+	if (!pp && lenp)
+		*lenp = -FDT_ERR_NOTFOUND;
+
+	return pp;
+}
+
+struct device_node *of_find_all_nodes(struct device_node *prev)
+{
+	struct device_node *np;
+
+	if (!prev) {
+		np = gd->of_root;
+	} else if (prev->child) {
+		np = prev->child;
+	} else {
+		/*
+		 * Walk back up looking for a sibling, or the end of the
+		 * structure
+		 */
+		np = prev;
+		while (np->parent && !np->sibling)
+			np = np->parent;
+		np = np->sibling; /* Might be null at the end of the tree */
+	}
+
+	return np;
+}
+
+const void *of_get_property(const struct device_node *np, const char *name,
+			    int *lenp)
+{
+	struct property *pp = of_find_property(np, name, lenp);
+
+	return pp ? pp->value : NULL;
+}
+
+static const char *of_prop_next_string(struct property *prop, const char *cur)
+{
+	const void *curv = cur;
+
+	if (!prop)
+		return NULL;
+
+	if (!cur)
+		return prop->value;
+
+	curv += strlen(cur) + 1;
+	if (curv >= prop->value + prop->length)
+		return NULL;
+
+	return curv;
+}
+
+int of_device_is_compatible(const struct device_node *device,
+			    const char *compat, const char *type,
+			    const char *name)
+{
+	struct property *prop;
+	const char *cp;
+	int index = 0, score = 0;
+
+	/* Compatible match has highest priority */
+	if (compat && compat[0]) {
+		prop = of_find_property(device, "compatible", NULL);
+		for (cp = of_prop_next_string(prop, NULL); cp;
+		     cp = of_prop_next_string(prop, cp), index++) {
+			if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {
+				score = INT_MAX/2 - (index << 2);
+				break;
+			}
+		}
+		if (!score)
+			return 0;
+	}
+
+	/* Matching type is better than matching name */
+	if (type && type[0]) {
+		if (!device->type || of_node_cmp(type, device->type))
+			return 0;
+		score += 2;
+	}
+
+	/* Matching name is a bit better than not */
+	if (name && name[0]) {
+		if (!device->name || of_node_cmp(name, device->name))
+			return 0;
+		score++;
+	}
+
+	return score;
+}
+
+bool of_device_is_available(const struct device_node *device)
+{
+	const char *status;
+	int statlen;
+
+	if (!device)
+		return false;
+
+	status = of_get_property(device, "status", &statlen);
+	if (status == NULL)
+		return true;
+
+	if (statlen > 0) {
+		if (!strcmp(status, "okay"))
+			return true;
+	}
+
+	return false;
+}
+
+struct device_node *of_get_parent(const struct device_node *node)
+{
+	const struct device_node *np;
+
+	if (!node)
+		return NULL;
+
+	np = of_node_get(node->parent);
+
+	return (struct device_node *)np;
+}
+
+static struct device_node *__of_get_next_child(const struct device_node *node,
+					       struct device_node *prev)
+{
+	struct device_node *next;
+
+	if (!node)
+		return NULL;
+
+	next = prev ? prev->sibling : node->child;
+	for (; next; next = next->sibling)
+		if (of_node_get(next))
+			break;
+	of_node_put(prev);
+	return next;
+}
+
+#define __for_each_child_of_node(parent, child) \
+	for (child = __of_get_next_child(parent, NULL); child != NULL; \
+	     child = __of_get_next_child(parent, child))
+
+static struct device_node *__of_find_node_by_path(struct device_node *parent,
+						  const char *path)
+{
+	struct device_node *child;
+	int len;
+
+	len = strcspn(path, "/:");
+	if (!len)
+		return NULL;
+
+	__for_each_child_of_node(parent, child) {
+		const char *name = strrchr(child->full_name, '/');
+
+		name++;
+		if (strncmp(path, name, len) == 0 && (strlen(name) == len))
+			return child;
+	}
+	return NULL;
+}
+
+#define for_each_property_of_node(dn, pp) \
+	for (pp = dn->properties; pp != NULL; pp = pp->next)
+
+struct device_node *of_find_node_opts_by_path(const char *path,
+					      const char **opts)
+{
+	struct device_node *np = NULL;
+	struct property *pp;
+	const char *separator = strchr(path, ':');
+
+	if (opts)
+		*opts = separator ? separator + 1 : NULL;
+
+	if (strcmp(path, "/") == 0)
+		return of_node_get(gd->of_root);
+
+	/* The path could begin with an alias */
+	if (*path != '/') {
+		int len;
+		const char *p = separator;
+
+		if (!p)
+			p = strchrnul(path, '/');
+		len = p - path;
+
+		/* of_aliases must not be NULL */
+		if (!of_aliases)
+			return NULL;
+
+		for_each_property_of_node(of_aliases, pp) {
+			if (strlen(pp->name) == len && !strncmp(pp->name, path,
+								len)) {
+				np = of_find_node_by_path(pp->value);
+				break;
+			}
+		}
+		if (!np)
+			return NULL;
+		path = p;
+	}
+
+	/* Step down the tree matching path components */
+	if (!np)
+		np = of_node_get(gd->of_root);
+	while (np && *path == '/') {
+		struct device_node *tmp = np;
+
+		path++; /* Increment past '/' delimiter */
+		np = __of_find_node_by_path(np, path);
+		of_node_put(tmp);
+		path = strchrnul(path, '/');
+		if (separator && separator < path)
+			break;
+	}
+
+	return np;
+}
+
+struct device_node *of_find_compatible_node(struct device_node *from,
+		const char *type, const char *compatible)
+{
+	struct device_node *np;
+
+	for_each_of_allnodes_from(from, np)
+		if (of_device_is_compatible(np, compatible, type, NULL) &&
+		    of_node_get(np))
+			break;
+	of_node_put(from);
+
+	return np;
+}
+
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+	struct device_node *np;
+
+	if (!handle)
+		return NULL;
+
+	for_each_of_allnodes(np)
+		if (np->phandle == handle)
+			break;
+	(void)of_node_get(np);
+
+	return np;
+}
+
+/**
+ * of_find_property_value_of_size() - find property of given size
+ *
+ * Search for a property in a device node and validate the requested size.
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @len:	requested length of property value
+ *
+ * @return the property value on success, -EINVAL if the property does not
+ * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ */
+static void *of_find_property_value_of_size(const struct device_node *np,
+					    const char *propname, u32 len)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+
+	if (!prop)
+		return ERR_PTR(-EINVAL);
+	if (!prop->value)
+		return ERR_PTR(-ENODATA);
+	if (len > prop->length)
+		return ERR_PTR(-EOVERFLOW);
+
+	return prop->value;
+}
+
+int of_read_u32(const struct device_node *np, const char *propname, u32 *outp)
+{
+	const __be32 *val;
+
+	debug("%s: %s: ", __func__, propname);
+	if (!np)
+		return -EINVAL;
+	val = of_find_property_value_of_size(np, propname, sizeof(*outp));
+	if (IS_ERR(val)) {
+		debug("(not found)\n");
+		return PTR_ERR(val);
+	}
+
+	*outp = be32_to_cpup(val);
+	debug("%#x (%d)\n", *outp, *outp);
+
+	return 0;
+}
+
+int of_read_u32_array(const struct device_node *np, const char *propname,
+		      u32 *out_values, size_t sz)
+{
+	const __be32 *val;
+
+	debug("%s: %s: ", __func__, propname);
+	val = of_find_property_value_of_size(np, propname,
+					     sz * sizeof(*out_values));
+
+	if (IS_ERR(val))
+		return PTR_ERR(val);
+
+	debug("size %zd\n", sz);
+	while (sz--)
+		*out_values++ = be32_to_cpup(val++);
+
+	return 0;
+}
+
+int of_property_match_string(const struct device_node *np, const char *propname,
+			     const char *string)
+{
+	const struct property *prop = of_find_property(np, propname, NULL);
+	size_t l;
+	int i;
+	const char *p, *end;
+
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+
+	p = prop->value;
+	end = p + prop->length;
+
+	for (i = 0; p < end; i++, p += l) {
+		l = strnlen(p, end - p) + 1;
+		if (p + l > end)
+			return -EILSEQ;
+		debug("comparing %s with %s\n", string, p);
+		if (strcmp(string, p) == 0)
+			return i; /* Found it; return index */
+	}
+	return -ENODATA;
+}
+
+/**
+ * of_property_read_string_helper() - Utility helper for parsing string properties
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @out_strs:	output array of string pointers.
+ * @sz:		number of array elements to read.
+ * @skip:	Number of strings to skip over at beginning of list.
+ *
+ * Don't call this function directly. It is a utility helper for the
+ * of_property_read_string*() family of functions.
+ */
+int of_property_read_string_helper(const struct device_node *np,
+				   const char *propname, const char **out_strs,
+				   size_t sz, int skip)
+{
+	const struct property *prop = of_find_property(np, propname, NULL);
+	int l = 0, i = 0;
+	const char *p, *end;
+
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+	p = prop->value;
+	end = p + prop->length;
+
+	for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) {
+		l = strnlen(p, end - p) + 1;
+		if (p + l > end)
+			return -EILSEQ;
+		if (out_strs && i >= skip)
+			*out_strs++ = p;
+	}
+	i -= skip;
+	return i <= 0 ? -ENODATA : i;
+}
+
+static int __of_parse_phandle_with_args(const struct device_node *np,
+					const char *list_name,
+					const char *cells_name,
+					int cell_count, int index,
+					struct of_phandle_args *out_args)
+{
+	const __be32 *list, *list_end;
+	int rc = 0, cur_index = 0;
+	uint32_t count = 0;
+	struct device_node *node = NULL;
+	phandle phandle;
+	int size;
+
+	/* Retrieve the phandle list property */
+	list = of_get_property(np, list_name, &size);
+	if (!list)
+		return -ENOENT;
+	list_end = list + size / sizeof(*list);
+
+	/* Loop over the phandles until all the requested entry is found */
+	while (list < list_end) {
+		rc = -EINVAL;
+		count = 0;
+
+		/*
+		 * If phandle is 0, then it is an empty entry with no
+		 * arguments.  Skip forward to the next entry.
+		 */
+		phandle = be32_to_cpup(list++);
+		if (phandle) {
+			/*
+			 * Find the provider node and parse the #*-cells
+			 * property to determine the argument length.
+			 *
+			 * This is not needed if the cell count is hard-coded
+			 * (i.e. cells_name not set, but cell_count is set),
+			 * except when we're going to return the found node
+			 * below.
+			 */
+			if (cells_name || cur_index == index) {
+				node = of_find_node_by_phandle(phandle);
+				if (!node) {
+					debug("%s: could not find phandle\n",
+					      np->full_name);
+					goto err;
+				}
+			}
+
+			if (cells_name) {
+				if (of_read_u32(node, cells_name, &count)) {
+					debug("%s: could not get %s for %s\n",
+					      np->full_name, cells_name,
+					      node->full_name);
+					goto err;
+				}
+			} else {
+				count = cell_count;
+			}
+
+			/*
+			 * Make sure that the arguments actually fit in the
+			 * remaining property data length
+			 */
+			if (list + count > list_end) {
+				debug("%s: arguments longer than property\n",
+				      np->full_name);
+				goto err;
+			}
+		}
+
+		/*
+		 * All of the error cases above bail out of the loop, so at
+		 * this point, the parsing is successful. If the requested
+		 * index matches, then fill the out_args structure and return,
+		 * or return -ENOENT for an empty entry.
+		 */
+		rc = -ENOENT;
+		if (cur_index == index) {
+			if (!phandle)
+				goto err;
+
+			if (out_args) {
+				int i;
+				if (WARN_ON(count > OF_MAX_PHANDLE_ARGS))
+					count = OF_MAX_PHANDLE_ARGS;
+				out_args->np = node;
+				out_args->args_count = count;
+				for (i = 0; i < count; i++)
+					out_args->args[i] =
+							be32_to_cpup(list++);
+			} else {
+				of_node_put(node);
+			}
+
+			/* Found it! return success */
+			return 0;
+		}
+
+		of_node_put(node);
+		node = NULL;
+		list += count;
+		cur_index++;
+	}
+
+	/*
+	 * Unlock node before returning result; will be one of:
+	 * -ENOENT : index is for empty phandle
+	 * -EINVAL : parsing error on data
+	 * [1..n]  : Number of phandle (count mode; when index = -1)
+	 */
+	rc = index < 0 ? cur_index : -ENOENT;
+ err:
+	if (node)
+		of_node_put(node);
+	return rc;
+}
+
+struct device_node *of_parse_phandle(const struct device_node *np,
+				     const char *phandle_name, int index)
+{
+	struct of_phandle_args args;
+
+	if (index < 0)
+		return NULL;
+
+	if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0, index,
+					 &args))
+		return NULL;
+
+	return args.np;
+}
+
+int of_parse_phandle_with_args(const struct device_node *np,
+			       const char *list_name, const char *cells_name,
+			       int index, struct of_phandle_args *out_args)
+{
+	if (index < 0)
+		return -EINVAL;
+
+	return __of_parse_phandle_with_args(np, list_name, cells_name, 0,
+					    index, out_args);
+}
+
+static void of_alias_add(struct alias_prop *ap, struct device_node *np,
+			 int id, const char *stem, int stem_len)
+{
+	ap->np = np;
+	ap->id = id;
+	strncpy(ap->stem, stem, stem_len);
+	ap->stem[stem_len] = 0;
+	list_add_tail(&ap->link, &aliases_lookup);
+	debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
+	      ap->alias, ap->stem, ap->id, of_node_full_name(np));
+}
+
+int of_alias_scan(void)
+{
+	struct property *pp;
+
+	of_aliases = of_find_node_by_path("/aliases");
+	of_chosen = of_find_node_by_path("/chosen");
+	if (of_chosen == NULL)
+		of_chosen = of_find_node_by_path("/chosen@0");
+
+	if (of_chosen) {
+		const char *name;
+
+		name = of_get_property(of_chosen, "stdout-path", NULL);
+		if (name)
+			of_stdout = of_find_node_opts_by_path(name,
+							&of_stdout_options);
+	}
+
+	if (!of_aliases)
+		return 0;
+
+	for_each_property_of_node(of_aliases, pp) {
+		const char *start = pp->name;
+		const char *end = start + strlen(start);
+		struct device_node *np;
+		struct alias_prop *ap;
+		ulong id;
+		int len;
+
+		/* Skip those we do not want to proceed */
+		if (!strcmp(pp->name, "name") ||
+		    !strcmp(pp->name, "phandle") ||
+		    !strcmp(pp->name, "linux,phandle"))
+			continue;
+
+		np = of_find_node_by_path(pp->value);
+		if (!np)
+			continue;
+
+		/*
+		 * walk the alias backwards to extract the id and work out
+		 * the 'stem' string
+		 */
+		while (isdigit(*(end-1)) && end > start)
+			end--;
+		len = end - start;
+
+		if (strict_strtoul(end, 10, &id) < 0)
+			continue;
+
+		/* Allocate an alias_prop with enough space for the stem */
+		ap = malloc(sizeof(*ap) + len + 1);
+		if (!ap)
+			return -ENOMEM;
+		memset(ap, 0, sizeof(*ap) + len + 1);
+		ap->alias = start;
+		of_alias_add(ap, np, id, start, len);
+	}
+
+	return 0;
+}
+
+int of_alias_get_id(const struct device_node *np, const char *stem)
+{
+	struct alias_prop *app;
+	int id = -ENODEV;
+
+	mutex_lock(&of_mutex);
+	list_for_each_entry(app, &aliases_lookup, link) {
+		if (strcmp(app->stem, stem) != 0)
+			continue;
+
+		if (np == app->np) {
+			id = app->id;
+			break;
+		}
+	}
+	mutex_unlock(&of_mutex);
+
+	return id;
+}
+
+struct device_node *of_get_stdout(void)
+{
+	return of_stdout;
+}
diff --git a/drivers/core/of_addr.c b/drivers/core/of_addr.c
new file mode 100644
index 0000000..4757066
--- /dev/null
+++ b/drivers/core/of_addr.c
@@ -0,0 +1,359 @@
+/*
+ * Taken from Linux v4.9 drivers/of/address.c
+ *
+ * Modified for U-Boot
+ * Copyright (c) 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <dm/of_access.h>
+#include <dm/of_addr.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
+
+/* Max address size we deal with */
+#define OF_MAX_ADDR_CELLS	4
+#define OF_CHECK_ADDR_COUNT(na)	((na) > 0 && (na) <= OF_MAX_ADDR_CELLS)
+#define OF_CHECK_COUNTS(na, ns)	(OF_CHECK_ADDR_COUNT(na) && (ns) > 0)
+
+static struct of_bus *of_match_bus(struct device_node *np);
+
+/* Debug utility */
+#ifdef DEBUG
+static void of_dump_addr(const char *s, const __be32 *addr, int na)
+{
+	debug("%s", s);
+	while (na--)
+		pr_cont(" %08x", be32_to_cpu(*(addr++)));
+	pr_cont("\n");
+}
+#else
+static void of_dump_addr(const char *s, const __be32 *addr, int na) { }
+#endif
+
+/* Callbacks for bus specific translators */
+struct of_bus {
+	const char *name;
+	const char *addresses;
+	int (*match)(struct device_node *parent);
+	void (*count_cells)(const struct device_node *child, int *addrc,
+			    int *sizec);
+	u64 (*map)(__be32 *addr, const __be32 *range, int na, int ns, int pna);
+	int (*translate)(__be32 *addr, u64 offset, int na);
+	unsigned int (*get_flags)(const __be32 *addr);
+};
+
+static void of_bus_default_count_cells(const struct device_node *np,
+				       int *addrc, int *sizec)
+{
+	if (addrc)
+		*addrc = of_n_addr_cells(np);
+	if (sizec)
+		*sizec = of_n_size_cells(np);
+}
+
+static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
+		int na, int ns, int pna)
+{
+	u64 cp, s, da;
+
+	cp = of_read_number(range, na);
+	s  = of_read_number(range + na + pna, ns);
+	da = of_read_number(addr, na);
+
+	debug("default map, cp=%llx, s=%llx, da=%llx\n",
+	      (unsigned long long)cp, (unsigned long long)s,
+	      (unsigned long long)da);
+
+	if (da < cp || da >= (cp + s))
+		return OF_BAD_ADDR;
+	return da - cp;
+}
+
+static int of_bus_default_translate(__be32 *addr, u64 offset, int na)
+{
+	u64 a = of_read_number(addr, na);
+	memset(addr, 0, na * 4);
+	a += offset;
+	if (na > 1)
+		addr[na - 2] = cpu_to_be32(a >> 32);
+	addr[na - 1] = cpu_to_be32(a & 0xffffffffu);
+
+	return 0;
+}
+
+static unsigned int of_bus_default_get_flags(const __be32 *addr)
+{
+	return IORESOURCE_MEM;
+}
+
+/*
+ * Array of bus-specific translators
+ */
+static struct of_bus of_busses[] = {
+	/* Default */
+	{
+		.name = "default",
+		.addresses = "reg",
+		.match = NULL,
+		.count_cells = of_bus_default_count_cells,
+		.map = of_bus_default_map,
+		.translate = of_bus_default_translate,
+		.get_flags = of_bus_default_get_flags,
+	},
+};
+
+static struct of_bus *of_match_bus(struct device_node *np)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(of_busses); i++)
+		if (!of_busses[i].match || of_busses[i].match(np))
+			return &of_busses[i];
+	BUG();
+	return NULL;
+}
+
+static void dev_count_cells(const struct device_node *np, int *nap, int *nsp)
+{
+	of_bus_default_count_cells(np, nap, nsp);
+}
+
+const __be32 *of_get_address(const struct device_node *dev, int index,
+			     u64 *size, unsigned int *flags)
+{
+	const __be32 *prop;
+	int psize;
+	struct device_node *parent;
+	struct of_bus *bus;
+	int onesize, i, na, ns;
+
+	/* Get parent & match bus type */
+	parent = of_get_parent(dev);
+	if (parent == NULL)
+		return NULL;
+	dev_count_cells(dev, &na, &ns);
+	bus = of_match_bus(parent);
+	bus->count_cells(dev, &na, &ns);
+	of_node_put(parent);
+	if (!OF_CHECK_ADDR_COUNT(na))
+		return NULL;
+
+	/* Get "reg" or "assigned-addresses" property */
+	prop = of_get_property(dev, "reg", &psize);
+	if (prop == NULL)
+		return NULL;
+	psize /= 4;
+
+	onesize = na + ns;
+	for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
+		if (i == index) {
+			if (size)
+				*size = of_read_number(prop + na, ns);
+			if (flags)
+				*flags = bus->get_flags(prop);
+			return prop;
+		}
+	return NULL;
+}
+EXPORT_SYMBOL(of_get_address);
+
+static int of_empty_ranges_quirk(const struct device_node *np)
+{
+	return false;
+}
+
+static int of_translate_one(const struct device_node *parent,
+			    struct of_bus *bus, struct of_bus *pbus,
+			    __be32 *addr, int na, int ns, int pna,
+			    const char *rprop)
+{
+	const __be32 *ranges;
+	int rlen;
+	int rone;
+	u64 offset = OF_BAD_ADDR;
+
+	/*
+	 * Normally, an absence of a "ranges" property means we are
+	 * crossing a non-translatable boundary, and thus the addresses
+	 * below the current cannot be converted to CPU physical ones.
+	 * Unfortunately, while this is very clear in the spec, it's not
+	 * what Apple understood, and they do have things like /uni-n or
+	 * /ht nodes with no "ranges" property and a lot of perfectly
+	 * useable mapped devices below them. Thus we treat the absence of
+	 * "ranges" as equivalent to an empty "ranges" property which means
+	 * a 1:1 translation at that level. It's up to the caller not to try
+	 * to translate addresses that aren't supposed to be translated in
+	 * the first place. --BenH.
+	 *
+	 * As far as we know, this damage only exists on Apple machines, so
+	 * This code is only enabled on powerpc. --gcl
+	 */
+	ranges = of_get_property(parent, rprop, &rlen);
+	if (ranges == NULL && !of_empty_ranges_quirk(parent)) {
+		debug("no ranges; cannot translate\n");
+		return 1;
+	}
+	if (ranges == NULL || rlen == 0) {
+		offset = of_read_number(addr, na);
+		memset(addr, 0, pna * 4);
+		debug("empty ranges; 1:1 translation\n");
+		goto finish;
+	}
+
+	debug("walking ranges...\n");
+
+	/* Now walk through the ranges */
+	rlen /= 4;
+	rone = na + pna + ns;
+	for (; rlen >= rone; rlen -= rone, ranges += rone) {
+		offset = bus->map(addr, ranges, na, ns, pna);
+		if (offset != OF_BAD_ADDR)
+			break;
+	}
+	if (offset == OF_BAD_ADDR) {
+		debug("not found !\n");
+		return 1;
+	}
+	memcpy(addr, ranges + na, 4 * pna);
+
+ finish:
+	of_dump_addr("parent translation for:", addr, pna);
+	debug("with offset: %llx\n", (unsigned long long)offset);
+
+	/* Translate it into parent bus space */
+	return pbus->translate(addr, offset, pna);
+}
+
+/*
+ * Translate an address from the device-tree into a CPU physical address,
+ * this walks up the tree and applies the various bus mappings on the
+ * way.
+ *
+ * Note: We consider that crossing any level with #size-cells == 0 to mean
+ * that translation is impossible (that is we are not dealing with a value
+ * that can be mapped to a cpu physical address). This is not really specified
+ * that way, but this is traditionally the way IBM at least do things
+ */
+static u64 __of_translate_address(const struct device_node *dev,
+				  const __be32 *in_addr, const char *rprop)
+{
+	struct device_node *parent = NULL;
+	struct of_bus *bus, *pbus;
+	__be32 addr[OF_MAX_ADDR_CELLS];
+	int na, ns, pna, pns;
+	u64 result = OF_BAD_ADDR;
+
+	debug("** translation for device %s **\n", of_node_full_name(dev));
+
+	/* Increase refcount at current level */
+	(void)of_node_get(dev);
+
+	/* Get parent & match bus type */
+	parent = of_get_parent(dev);
+	if (parent == NULL)
+		goto bail;
+	bus = of_match_bus(parent);
+
+	/* Count address cells & copy address locally */
+	bus->count_cells(dev, &na, &ns);
+	if (!OF_CHECK_COUNTS(na, ns)) {
+		debug("Bad cell count for %s\n", of_node_full_name(dev));
+		goto bail;
+	}
+	memcpy(addr, in_addr, na * 4);
+
+	debug("bus is %s (na=%d, ns=%d) on %s\n", bus->name, na, ns,
+	      of_node_full_name(parent));
+	of_dump_addr("translating address:", addr, na);
+
+	/* Translate */
+	for (;;) {
+		/* Switch to parent bus */
+		of_node_put(dev);
+		dev = parent;
+		parent = of_get_parent(dev);
+
+		/* If root, we have finished */
+		if (parent == NULL) {
+			debug("reached root node\n");
+			result = of_read_number(addr, na);
+			break;
+		}
+
+		/* Get new parent bus and counts */
+		pbus = of_match_bus(parent);
+		pbus->count_cells(dev, &pna, &pns);
+		if (!OF_CHECK_COUNTS(pna, pns)) {
+			debug("Bad cell count for %s\n",
+			      of_node_full_name(dev));
+			break;
+		}
+
+		debug("parent bus is %s (na=%d, ns=%d) on %s\n", pbus->name,
+		      pna, pns, of_node_full_name(parent));
+
+		/* Apply bus translation */
+		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
+			break;
+
+		/* Complete the move up one level */
+		na = pna;
+		ns = pns;
+		bus = pbus;
+
+		of_dump_addr("one level translation:", addr, na);
+	}
+ bail:
+	of_node_put(parent);
+	of_node_put(dev);
+
+	return result;
+}
+
+u64 of_translate_address(const struct device_node *dev, const __be32 *in_addr)
+{
+	return __of_translate_address(dev, in_addr, "ranges");
+}
+
+
+static int __of_address_to_resource(const struct device_node *dev,
+		const __be32 *addrp, u64 size, unsigned int flags,
+		const char *name, struct resource *r)
+{
+	u64 taddr;
+
+	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
+		return -EINVAL;
+	taddr = of_translate_address(dev, addrp);
+	if (taddr == OF_BAD_ADDR)
+		return -EINVAL;
+	memset(r, 0, sizeof(struct resource));
+	r->start = taddr;
+	r->end = taddr + size - 1;
+	r->flags = flags;
+	r->name = name ? name : dev->full_name;
+
+	return 0;
+}
+
+int of_address_to_resource(const struct device_node *dev, int index,
+			   struct resource *r)
+{
+	const __be32	*addrp;
+	u64		size;
+	unsigned int	flags;
+	const char	*name = NULL;
+
+	addrp = of_get_address(dev, index, &size, &flags);
+	if (addrp == NULL)
+		return -EINVAL;
+
+	/* Get optional "reg-names" property to add a name to a resource */
+	of_property_read_string_index(dev, "reg-names", index, &name);
+
+	return __of_address_to_resource(dev, addrp, size, flags, name, r);
+}
diff --git a/drivers/core/of_extra.c b/drivers/core/of_extra.c
new file mode 100644
index 0000000..0381909
--- /dev/null
+++ b/drivers/core/of_extra.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <dm/of_access.h>
+#include <dm/of_extra.h>
+#include <dm/ofnode.h>
+
+int of_read_fmap_entry(ofnode node, const char *name,
+		       struct fmap_entry *entry)
+{
+	const char *prop;
+	u32 reg[2];
+
+	if (ofnode_read_u32_array(node, "reg", reg, 2)) {
+		debug("Node '%s' has bad/missing 'reg' property\n", name);
+		return -FDT_ERR_NOTFOUND;
+	}
+	entry->offset = reg[0];
+	entry->length = reg[1];
+	entry->used = ofnode_read_s32_default(node, "used", entry->length);
+	prop = ofnode_read_string(node, "compress");
+	entry->compress_algo = prop && !strcmp(prop, "lzo") ?
+		FMAP_COMPRESS_LZO : FMAP_COMPRESS_NONE;
+	prop = ofnode_read_string(node, "hash");
+	if (prop)
+		entry->hash_size = strlen(prop);
+	entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE;
+	entry->hash = (uint8_t *)prop;
+
+	return 0;
+}
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
new file mode 100644
index 0000000..ac312d6
--- /dev/null
+++ b/drivers/core/ofnode.c
@@ -0,0 +1,579 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <fdt_support.h>
+#include <libfdt.h>
+#include <dm/of_access.h>
+#include <dm/of_addr.h>
+#include <dm/ofnode.h>
+#include <linux/err.h>
+
+int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
+{
+	assert(ofnode_valid(node));
+	debug("%s: %s: ", __func__, propname);
+
+	if (ofnode_is_np(node)) {
+		return of_read_u32(ofnode_to_np(node), propname, outp);
+	} else {
+		const int *cell;
+		int len;
+
+		cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
+				   propname, &len);
+		if (!cell || len < sizeof(int)) {
+			debug("(not found)\n");
+			return -EINVAL;
+		}
+		*outp = fdt32_to_cpu(cell[0]);
+	}
+	debug("%#x (%d)\n", *outp, *outp);
+
+	return 0;
+}
+
+int ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
+{
+	assert(ofnode_valid(node));
+	ofnode_read_u32(node, propname, &def);
+
+	return def;
+}
+
+int ofnode_read_s32_default(ofnode node, const char *propname, s32 def)
+{
+	assert(ofnode_valid(node));
+	ofnode_read_u32(node, propname, (u32 *)&def);
+
+	return def;
+}
+
+bool ofnode_read_bool(ofnode node, const char *propname)
+{
+	bool val;
+
+	assert(ofnode_valid(node));
+	debug("%s: %s: ", __func__, propname);
+
+	if (ofnode_is_np(node)) {
+		val = !!of_find_property(ofnode_to_np(node), propname, NULL);
+	} else {
+		val = !!fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
+				    propname, NULL);
+	}
+	debug("%s\n", val ? "true" : "false");
+
+	return val;
+}
+
+const char *ofnode_read_string(ofnode node, const char *propname)
+{
+	const char *str = NULL;
+	int len = -1;
+
+	assert(ofnode_valid(node));
+	debug("%s: %s: ", __func__, propname);
+
+	if (ofnode_is_np(node)) {
+		struct property *prop = of_find_property(
+				ofnode_to_np(node), propname, NULL);
+
+		if (prop) {
+			str = prop->value;
+			len = prop->length;
+		}
+	} else {
+		str = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
+				  propname, &len);
+	}
+	if (!str) {
+		debug("<not found>\n");
+		return NULL;
+	}
+	if (strnlen(str, len) >= len) {
+		debug("<invalid>\n");
+		return NULL;
+	}
+	debug("%s\n", str);
+
+	return str;
+}
+
+ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
+{
+	ofnode subnode;
+
+	assert(ofnode_valid(node));
+	debug("%s: %s: ", __func__, subnode_name);
+
+	if (ofnode_is_np(node)) {
+		const struct device_node *np = ofnode_to_np(node);
+
+		for (np = np->child; np; np = np->sibling) {
+			if (!strcmp(subnode_name, np->name))
+				break;
+		}
+		subnode = np_to_ofnode(np);
+	} else {
+		int ooffset = fdt_subnode_offset(gd->fdt_blob,
+				ofnode_to_offset(node), subnode_name);
+		subnode = offset_to_ofnode(ooffset);
+	}
+	debug("%s\n", ofnode_valid(subnode) ?
+	      ofnode_get_name(subnode) : "<none>");
+
+	return subnode;
+}
+
+int ofnode_read_u32_array(ofnode node, const char *propname,
+			  u32 *out_values, size_t sz)
+{
+	assert(ofnode_valid(node));
+	debug("%s: %s: ", __func__, propname);
+
+	if (ofnode_is_np(node)) {
+		return of_read_u32_array(ofnode_to_np(node), propname,
+					 out_values, sz);
+	} else {
+		return fdtdec_get_int_array(gd->fdt_blob,
+					    ofnode_to_offset(node), propname,
+					    out_values, sz);
+	}
+}
+
+ofnode ofnode_first_subnode(ofnode node)
+{
+	assert(ofnode_valid(node));
+	if (ofnode_is_np(node))
+		return np_to_ofnode(node.np->child);
+
+	return offset_to_ofnode(
+		fdt_first_subnode(gd->fdt_blob, ofnode_to_offset(node)));
+}
+
+ofnode ofnode_next_subnode(ofnode node)
+{
+	assert(ofnode_valid(node));
+	if (ofnode_is_np(node))
+		return np_to_ofnode(node.np->sibling);
+
+	return offset_to_ofnode(
+		fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node)));
+}
+
+const char *ofnode_get_name(ofnode node)
+{
+	assert(ofnode_valid(node));
+	if (ofnode_is_np(node))
+		return strrchr(node.np->full_name, '/') + 1;
+
+	return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL);
+}
+
+int ofnode_read_size(ofnode node, const char *propname)
+{
+	int len;
+
+	if (ofnode_is_np(node)) {
+		struct property *prop = of_find_property(
+				ofnode_to_np(node), propname, NULL);
+
+		if (prop)
+			return prop->length;
+	} else {
+		if (fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
+				&len))
+			return len;
+	}
+
+	return -EINVAL;
+}
+
+fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
+{
+	if (ofnode_is_np(node)) {
+		const __be32 *prop_val;
+		uint flags;
+		u64 size;
+
+		prop_val = of_get_address(
+			(struct device_node *)ofnode_to_np(node), index,
+			&size, &flags);
+		if (!prop_val)
+			return FDT_ADDR_T_NONE;
+		return  be32_to_cpup(prop_val);
+	} else {
+		return fdt_get_base_address(gd->fdt_blob,
+					    ofnode_to_offset(node));
+	}
+
+	return FDT_ADDR_T_NONE;
+}
+
+fdt_addr_t ofnode_get_addr(ofnode node)
+{
+	return ofnode_get_addr_index(node, 0);
+}
+
+int ofnode_stringlist_search(ofnode node, const char *property,
+			     const char *string)
+{
+	if (ofnode_is_np(node)) {
+		return of_property_match_string(ofnode_to_np(node),
+						property, string);
+	} else {
+		int ret;
+
+		ret = fdt_stringlist_search(gd->fdt_blob,
+					    ofnode_to_offset(node), property,
+					    string);
+		if (ret == -FDT_ERR_NOTFOUND)
+			return -ENODATA;
+		else if (ret < 0)
+			return -EINVAL;
+
+		return ret;
+	}
+}
+
+int ofnode_read_string_index(ofnode node, const char *property, int index,
+			     const char **outp)
+{
+	if (ofnode_is_np(node)) {
+		return of_property_read_string_index(ofnode_to_np(node),
+						     property, index, outp);
+	} else {
+		int len;
+
+		*outp = fdt_stringlist_get(gd->fdt_blob, ofnode_to_offset(node),
+					   property, index, &len);
+		if (len < 0)
+			return -EINVAL;
+		return 0;
+	}
+}
+
+static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in,
+					    struct ofnode_phandle_args *out)
+{
+	assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
+	out->node = offset_to_ofnode(in->node);
+	out->args_count = in->args_count;
+	memcpy(out->args, in->args, sizeof(out->args));
+}
+
+static void ofnode_from_of_phandle_args(struct of_phandle_args *in,
+					struct ofnode_phandle_args *out)
+{
+	assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
+	out->node = np_to_ofnode(in->np);
+	out->args_count = in->args_count;
+	memcpy(out->args, in->args, sizeof(out->args));
+}
+
+int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
+				   const char *cells_name, int cell_count,
+				   int index,
+				   struct ofnode_phandle_args *out_args)
+{
+	if (ofnode_is_np(node)) {
+		struct of_phandle_args args;
+		int ret;
+
+		ret = of_parse_phandle_with_args(ofnode_to_np(node),
+				list_name, cells_name, index, &args);
+		if (ret)
+			return ret;
+		ofnode_from_of_phandle_args(&args, out_args);
+	} else {
+		struct fdtdec_phandle_args args;
+		int ret;
+
+		ret = fdtdec_parse_phandle_with_args(gd->fdt_blob,
+				ofnode_to_offset(node), list_name, cells_name,
+				cell_count, index, &args);
+		if (ret)
+			return ret;
+		ofnode_from_fdtdec_phandle_args(&args, out_args);
+	}
+
+	return 0;
+}
+
+ofnode ofnode_path(const char *path)
+{
+	if (of_live_active())
+		return np_to_ofnode(of_find_node_by_path(path));
+	else
+		return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
+}
+
+const char *ofnode_get_chosen_prop(const char *name)
+{
+	ofnode chosen_node;
+
+	chosen_node = ofnode_path("/chosen");
+
+	return ofnode_read_string(chosen_node, name);
+}
+
+ofnode ofnode_get_chosen_node(const char *name)
+{
+	const char *prop;
+
+	prop = ofnode_get_chosen_prop(name);
+	if (!prop)
+		return ofnode_null();
+
+	return ofnode_path(prop);
+}
+
+static int decode_timing_property(ofnode node, const char *name,
+				  struct timing_entry *result)
+{
+	int length, ret = 0;
+
+	length = ofnode_read_size(node, name);
+	if (length < 0) {
+		debug("%s: could not find property %s\n",
+		      ofnode_get_name(node), name);
+		return length;
+	}
+
+	if (length == sizeof(u32)) {
+		result->typ = ofnode_read_u32_default(node, name, 0);
+		result->min = result->typ;
+		result->max = result->typ;
+	} else {
+		ret = ofnode_read_u32_array(node, name, &result->min, 3);
+	}
+
+	return ret;
+}
+
+int ofnode_decode_display_timing(ofnode parent, int index,
+				 struct display_timing *dt)
+{
+	int i;
+	ofnode timings, node;
+	u32 val = 0;
+	int ret = 0;
+
+	timings = ofnode_find_subnode(parent, "display-timings");
+	if (!ofnode_valid(timings))
+		return -EINVAL;
+
+	for (i = 0, node = ofnode_first_subnode(timings);
+	     ofnode_valid(node) && i != index;
+	     node = ofnode_first_subnode(node))
+		i++;
+
+	if (!ofnode_valid(node))
+		return -EINVAL;
+
+	memset(dt, 0, sizeof(*dt));
+
+	ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch);
+	ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch);
+	ret |= decode_timing_property(node, "hactive", &dt->hactive);
+	ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len);
+	ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch);
+	ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch);
+	ret |= decode_timing_property(node, "vactive", &dt->vactive);
+	ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len);
+	ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock);
+
+	dt->flags = 0;
+	val = ofnode_read_u32_default(node, "vsync-active", -1);
+	if (val != -1) {
+		dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
+				DISPLAY_FLAGS_VSYNC_LOW;
+	}
+	val = ofnode_read_u32_default(node, "hsync-active", -1);
+	if (val != -1) {
+		dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
+				DISPLAY_FLAGS_HSYNC_LOW;
+	}
+	val = ofnode_read_u32_default(node, "de-active", -1);
+	if (val != -1) {
+		dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
+				DISPLAY_FLAGS_DE_LOW;
+	}
+	val = ofnode_read_u32_default(node, "pixelclk-active", -1);
+	if (val != -1) {
+		dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
+				DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+	}
+
+	if (ofnode_read_bool(node, "interlaced"))
+		dt->flags |= DISPLAY_FLAGS_INTERLACED;
+	if (ofnode_read_bool(node, "doublescan"))
+		dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
+	if (ofnode_read_bool(node, "doubleclk"))
+		dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
+
+	return ret;
+}
+
+const u32 *ofnode_read_prop(ofnode node, const char *propname, int *lenp)
+{
+	if (ofnode_is_np(node)) {
+		struct property *prop;
+
+		prop = of_find_property(ofnode_to_np(node), propname, lenp);
+		if (!prop)
+			return NULL;
+		return prop->value;
+	} else {
+		return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
+				   propname, lenp);
+	}
+}
+
+bool ofnode_is_available(ofnode node)
+{
+	if (ofnode_is_np(node))
+		return of_device_is_available(ofnode_to_np(node));
+	else
+		return fdtdec_get_is_enabled(gd->fdt_blob,
+					     ofnode_to_offset(node));
+}
+
+fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
+				fdt_size_t *sizep)
+{
+	if (ofnode_is_np(node)) {
+		int na, ns;
+		int psize;
+		const struct device_node *np = ofnode_to_np(node);
+		const __be32 *prop = of_get_property(np, "reg", &psize);
+
+		na = of_n_addr_cells(np);
+		ns = of_n_addr_cells(np);
+		*sizep = of_read_number(prop + na, ns);
+		return of_read_number(prop, na);
+	} else {
+		return fdtdec_get_addr_size(gd->fdt_blob,
+					    ofnode_to_offset(node), property,
+					    sizep);
+	}
+}
+
+const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
+					size_t sz)
+{
+	if (ofnode_is_np(node)) {
+		const struct device_node *np = ofnode_to_np(node);
+		int psize;
+		const __be32 *prop = of_get_property(np, propname, &psize);
+
+		if (!prop || sz != psize)
+			return NULL;
+		return (uint8_t *)prop;
+
+	} else {
+		return fdtdec_locate_byte_array(gd->fdt_blob,
+				ofnode_to_offset(node), propname, sz);
+	}
+}
+
+int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
+			 const char *propname, struct fdt_pci_addr *addr)
+{
+	const u32 *cell;
+	int len;
+	int ret = -ENOENT;
+
+	debug("%s: %s: ", __func__, propname);
+
+	/*
+	 * If we follow the pci bus bindings strictly, we should check
+	 * the value of the node's parent node's #address-cells and
+	 * #size-cells. They need to be 3 and 2 accordingly. However,
+	 * for simplicity we skip the check here.
+	 */
+	cell = ofnode_read_prop(node, propname, &len);
+	if (!cell)
+		goto fail;
+
+	if ((len % FDT_PCI_REG_SIZE) == 0) {
+		int num = len / FDT_PCI_REG_SIZE;
+		int i;
+
+		for (i = 0; i < num; i++) {
+			debug("pci address #%d: %08lx %08lx %08lx\n", i,
+			      (ulong)fdt32_to_cpu(cell[0]),
+			      (ulong)fdt32_to_cpu(cell[1]),
+			      (ulong)fdt32_to_cpu(cell[2]));
+			if ((fdt32_to_cpu(*cell) & type) == type) {
+				addr->phys_hi = fdt32_to_cpu(cell[0]);
+				addr->phys_mid = fdt32_to_cpu(cell[1]);
+				addr->phys_lo = fdt32_to_cpu(cell[1]);
+				break;
+			} else {
+				cell += (FDT_PCI_ADDR_CELLS +
+					 FDT_PCI_SIZE_CELLS);
+			}
+		}
+
+		if (i == num) {
+			ret = -ENXIO;
+			goto fail;
+		}
+
+		return 0;
+	} else {
+		ret = -EINVAL;
+	}
+
+fail:
+	debug("(not found)\n");
+	return ret;
+}
+
+int ofnode_read_addr_cells(ofnode node)
+{
+	if (ofnode_is_np(node))
+		return of_n_addr_cells(ofnode_to_np(node));
+	else
+		return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node));
+}
+
+int ofnode_read_size_cells(ofnode node)
+{
+	if (ofnode_is_np(node))
+		return of_n_size_cells(ofnode_to_np(node));
+	else
+		return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node));
+}
+
+bool ofnode_pre_reloc(ofnode node)
+{
+	if (ofnode_read_prop(node, "u-boot,dm-pre-reloc", NULL))
+		return true;
+
+#ifdef CONFIG_TPL_BUILD
+	if (ofnode_read_prop(node, "u-boot,dm-tpl", NULL))
+		return true;
+#elif defined(CONFIG_SPL_BUILD)
+	if (ofnode_read_prop(node, "u-boot,dm-spl", NULL))
+		return true;
+#else
+	/*
+	 * In regular builds individual spl and tpl handling both
+	 * count as handled pre-relocation for later second init.
+	 */
+	if (ofnode_read_prop(node, "u-boot,dm-spl", NULL) ||
+	    ofnode_read_prop(node, "u-boot,dm-tpl", NULL))
+		return true;
+#endif
+
+	return false;
+}
diff --git a/drivers/core/read.c b/drivers/core/read.c
new file mode 100644
index 0000000..3131e53
--- /dev/null
+++ b/drivers/core/read.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/of_access.h>
+
+int dev_read_u32_default(struct udevice *dev, const char *propname, int def)
+{
+	return ofnode_read_u32_default(dev_ofnode(dev), propname, def);
+}
+
+const char *dev_read_string(struct udevice *dev, const char *propname)
+{
+	return ofnode_read_string(dev_ofnode(dev), propname);
+}
+
+bool dev_read_bool(struct udevice *dev, const char *propname)
+{
+	return ofnode_read_bool(dev_ofnode(dev), propname);
+}
+
+ofnode dev_read_subnode(struct udevice *dev, const char *subnode_name)
+{
+	return ofnode_find_subnode(dev_ofnode(dev), subnode_name);
+}
+
+ofnode dev_read_first_subnode(struct udevice *dev)
+{
+	return ofnode_first_subnode(dev_ofnode(dev));
+}
+
+ofnode dev_read_next_subnode(ofnode node)
+{
+	return ofnode_next_subnode(node);
+}
+
+int dev_read_size(struct udevice *dev, const char *propname)
+{
+	return ofnode_read_size(dev_ofnode(dev), propname);
+}
+
+fdt_addr_t dev_read_addr_index(struct udevice *dev, int index)
+{
+	if (ofnode_is_np(dev_ofnode(dev)))
+		return ofnode_get_addr_index(dev_ofnode(dev), index);
+	else
+		return devfdt_get_addr_index(dev, index);
+}
+
+fdt_addr_t dev_read_addr(struct udevice *dev)
+{
+	return dev_read_addr_index(dev, 0);
+}
+
+fdt_addr_t dev_read_addr_size(struct udevice *dev, const char *property,
+				fdt_size_t *sizep)
+{
+	return ofnode_get_addr_size(dev_ofnode(dev), property, sizep);
+}
+
+const char *dev_read_name(struct udevice *dev)
+{
+	return ofnode_get_name(dev_ofnode(dev));
+}
+
+int dev_read_stringlist_search(struct udevice *dev, const char *property,
+			  const char *string)
+{
+	return ofnode_stringlist_search(dev_ofnode(dev), property, string);
+}
+
+int dev_read_phandle_with_args(struct udevice *dev, const char *list_name,
+				const char *cells_name, int cell_count,
+				int index,
+				struct ofnode_phandle_args *out_args)
+{
+	return ofnode_parse_phandle_with_args(dev_ofnode(dev), list_name,
+					      cells_name, cell_count, index,
+					      out_args);
+}
+
+int dev_read_addr_cells(struct udevice *dev)
+{
+	return ofnode_read_addr_cells(dev_ofnode(dev));
+}
+
+int dev_read_size_cells(struct udevice *dev)
+{
+	return ofnode_read_size_cells(dev_ofnode(dev));
+}
+
+int dev_read_phandle(struct udevice *dev)
+{
+	ofnode node = dev_ofnode(dev);
+
+	if (ofnode_is_np(node))
+		return ofnode_to_np(node)->phandle;
+	else
+		return fdt_get_phandle(gd->fdt_blob, ofnode_to_offset(node));
+}
+
+const u32 *dev_read_prop(struct udevice *dev, const char *propname, int *lenp)
+{
+	return ofnode_read_prop(dev_ofnode(dev), propname, lenp);
+}
+
+int dev_read_alias_seq(struct udevice *dev, int *devnump)
+{
+	ofnode node = dev_ofnode(dev);
+	const char *uc_name = dev->uclass->uc_drv->name;
+	int ret;
+
+	if (ofnode_is_np(node)) {
+		ret = of_alias_get_id(ofnode_to_np(node), uc_name);
+		if (ret >= 0)
+			*devnump = ret;
+	} else {
+		ret = fdtdec_get_alias_seq(gd->fdt_blob, uc_name,
+					   ofnode_to_offset(node), devnump);
+	}
+
+	return ret;
+}
+
+int dev_read_u32_array(struct udevice *dev, const char *propname,
+		       u32 *out_values, size_t sz)
+{
+	return ofnode_read_u32_array(dev_ofnode(dev), propname, out_values, sz);
+}
+
+const uint8_t *dev_read_u8_array_ptr(struct udevice *dev, const char *propname,
+				     size_t sz)
+{
+	return ofnode_read_u8_array_ptr(dev_ofnode(dev), propname, sz);
+}
diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index 3bec3df..749d913 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -12,8 +12,9 @@
 #include <malloc.h>
 #include <mapmem.h>
 #include <regmap.h>
-
 #include <asm/io.h>
+#include <dm/of_addr.h>
+#include <linux/ioport.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -62,25 +63,25 @@
 #else
 int regmap_init_mem(struct udevice *dev, struct regmap **mapp)
 {
-	const void *blob = gd->fdt_blob;
 	struct regmap_range *range;
-	const fdt32_t *cell;
 	struct regmap *map;
 	int count;
 	int addr_len, size_len, both_len;
-	int parent;
 	int len;
 	int index;
+	ofnode node = dev_ofnode(dev);
+	struct resource r;
 
-	parent = dev_of_offset(dev->parent);
-	addr_len = fdt_address_cells(blob, parent);
-	size_len = fdt_size_cells(blob, parent);
+	addr_len = dev_read_addr_cells(dev->parent);
+	size_len = dev_read_size_cells(dev->parent);
 	both_len = addr_len + size_len;
 
-	cell = fdt_getprop(blob, dev_of_offset(dev), "reg", &len);
-	len /= sizeof(*cell);
+	len = dev_read_size(dev, "reg");
+	if (len < 0)
+		return len;
+	len /= sizeof(fdt32_t);
 	count = len / both_len;
-	if (!cell || !count)
+	if (!count)
 		return -EINVAL;
 
 	map = regmap_alloc_count(count);
@@ -88,11 +89,18 @@
 		return -ENOMEM;
 
 	for (range = map->range, index = 0; count > 0;
-	     count--, cell += both_len, range++, index++) {
+	     count--, range++, index++) {
 		fdt_size_t sz;
-		range->start = fdtdec_get_addr_size_fixed(blob, dev->of_offset,
-				"reg", index, addr_len, size_len, &sz, true);
-		range->size = sz;
+		if (of_live_active()) {
+			of_address_to_resource(ofnode_to_np(node), index, &r);
+			range->start = r.start;
+			range->size = r.end - r.start + 1;
+		} else {
+			range->start = fdtdec_get_addr_size_fixed(gd->fdt_blob,
+					dev_of_offset(dev), "reg", index,
+					addr_len, size_len, &sz, true);
+			range->size = sz;
+		}
 	}
 	map->base = map->range[0].start;
 
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 42679d0..d691d6f 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -15,7 +15,10 @@
 #include <dm/device.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
+#include <dm/of.h>
+#include <dm/of_access.h>
 #include <dm/platdata.h>
+#include <dm/read.h>
 #include <dm/root.h>
 #include <dm/uclass.h>
 #include <dm/util.h>
@@ -147,7 +150,7 @@
 
 #endif
 
-int dm_init(void)
+int dm_init(bool of_live)
 {
 	int ret;
 
@@ -167,7 +170,12 @@
 	if (ret)
 		return ret;
 #if CONFIG_IS_ENABLED(OF_CONTROL)
-	DM_ROOT_NON_CONST->of_offset = 0;
+# if CONFIG_IS_ENABLED(OF_LIVE)
+	if (of_live)
+		DM_ROOT_NON_CONST->node = np_to_ofnode(gd->of_root);
+	else
+#endif
+		DM_ROOT_NON_CONST->node = offset_to_ofnode(0);
 #endif
 	ret = device_probe(DM_ROOT_NON_CONST);
 	if (ret)
@@ -206,9 +214,52 @@
 	return ret;
 }
 
+#if CONFIG_IS_ENABLED(OF_LIVE)
+static int dm_scan_fdt_live(struct udevice *parent,
+			    const struct device_node *node_parent,
+			    bool pre_reloc_only)
+{
+	struct device_node *np;
+	int ret = 0, err;
+
+	for (np = node_parent->child; np; np = np->sibling) {
+		if (pre_reloc_only &&
+		    !of_find_property(np, "u-boot,dm-pre-reloc", NULL))
+			continue;
+		if (!of_device_is_available(np)) {
+			dm_dbg("   - ignoring disabled device\n");
+			continue;
+		}
+		err = lists_bind_fdt(parent, np_to_ofnode(np), NULL);
+		if (err && !ret) {
+			ret = err;
+			debug("%s: ret=%d\n", np->name, ret);
+		}
+	}
+
+	if (ret)
+		dm_warn("Some drivers failed to bind\n");
+
+	return ret;
+}
+#endif /* CONFIG_IS_ENABLED(OF_LIVE) */
+
 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
-int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
-		     bool pre_reloc_only)
+/**
+ * dm_scan_fdt_node() - Scan the device tree and bind drivers for a node
+ *
+ * This scans the subnodes of a device tree node and and creates a driver
+ * for each one.
+ *
+ * @parent: Parent device for the devices that will be created
+ * @blob: Pointer to device tree blob
+ * @offset: Offset of node to scan
+ * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC
+ * flag. If false bind all drivers.
+ * @return 0 if OK, -ve on error
+ */
+static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
+			    int offset, bool pre_reloc_only)
 {
 	int ret = 0, err;
 
@@ -222,7 +273,7 @@
 			dm_dbg("   - ignoring disabled device\n");
 			continue;
 		}
-		err = lists_bind_fdt(parent, blob, offset, NULL);
+		err = lists_bind_fdt(parent, offset_to_ofnode(offset), NULL);
 		if (err && !ret) {
 			ret = err;
 			debug("%s: ret=%d\n", fdt_get_name(blob, offset, NULL),
@@ -238,15 +289,27 @@
 
 int dm_scan_fdt_dev(struct udevice *dev)
 {
-	if (dev_of_offset(dev) == -1)
+	if (!dev_of_valid(dev))
 		return 0;
 
+#if CONFIG_IS_ENABLED(OF_LIVE)
+	if (of_live_active())
+		return dm_scan_fdt_live(dev, dev_np(dev),
+				gd->flags & GD_FLG_RELOC ? false : true);
+	else
+#endif
 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev_of_offset(dev),
 				gd->flags & GD_FLG_RELOC ? false : true);
 }
 
 int dm_scan_fdt(const void *blob, bool pre_reloc_only)
 {
+#if CONFIG_IS_ENABLED(OF_LIVE)
+	if (of_live_active())
+		return dm_scan_fdt_live(gd->dm_root, gd->of_root,
+					pre_reloc_only);
+	else
+#endif
 	return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
 }
 #endif
@@ -260,7 +323,7 @@
 {
 	int ret;
 
-	ret = dm_init();
+	ret = dm_init(IS_ENABLED(CONFIG_OF_LIVE));
 	if (ret) {
 		debug("dm_init() failed: %d\n", ret);
 		return ret;
diff --git a/drivers/core/simple-bus.c b/drivers/core/simple-bus.c
index a300217..14803e3 100644
--- a/drivers/core/simple-bus.c
+++ b/drivers/core/simple-bus.c
@@ -33,8 +33,7 @@
 	u32 cell[3];
 	int ret;
 
-	ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "ranges",
-				   cell, ARRAY_SIZE(cell));
+	ret = dev_read_u32_array(dev, "ranges", cell, ARRAY_SIZE(cell));
 	if (!ret) {
 		struct simple_bus_plat *plat = dev_get_uclass_platdata(dev);
 
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 04fb45b..21dc696 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -8,6 +8,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <malloc.h>
 #include <dm/device.h>
@@ -287,6 +288,30 @@
 	return -ENODEV;
 }
 
+int uclass_find_device_by_ofnode(enum uclass_id id, ofnode node,
+				 struct udevice **devp)
+{
+	struct uclass *uc;
+	struct udevice *dev;
+	int ret;
+
+	*devp = NULL;
+	if (!ofnode_valid(node))
+		return -ENODEV;
+	ret = uclass_get(id, &uc);
+	if (ret)
+		return ret;
+
+	list_for_each_entry(dev, &uc->dev_head, uclass_node) {
+		if (ofnode_equal(dev_ofnode(dev), node)) {
+			*devp = dev;
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
 #if CONFIG_IS_ENABLED(OF_CONTROL)
 static int uclass_find_device_by_phandle(enum uclass_id id,
 					 struct udevice *parent,
@@ -299,8 +324,7 @@
 	int ret;
 
 	*devp = NULL;
-	find_phandle = fdtdec_get_int(gd->fdt_blob, dev_of_offset(parent), name,
-				      -1);
+	find_phandle = dev_read_u32_default(parent, name, -1);
 	if (find_phandle <= 0)
 		return -ENOENT;
 	ret = uclass_get(id, &uc);
@@ -310,7 +334,7 @@
 	list_for_each_entry(dev, &uc->dev_head, uclass_node) {
 		uint phandle;
 
-		phandle = fdt_get_phandle(gd->fdt_blob, dev_of_offset(dev));
+		phandle = dev_read_phandle(dev);
 
 		if (phandle == find_phandle) {
 			*devp = dev;
@@ -407,6 +431,18 @@
 	return uclass_get_device_tail(dev, ret, devp);
 }
 
+int uclass_get_device_by_ofnode(enum uclass_id id, ofnode node,
+				struct udevice **devp)
+{
+	struct udevice *dev;
+	int ret;
+
+	*devp = NULL;
+	ret = uclass_find_device_by_ofnode(id, node, &dev);
+
+	return uclass_get_device_tail(dev, ret, devp);
+}
+
 #if CONFIG_IS_ENABLED(OF_CONTROL)
 int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent,
 				 const char *name, struct udevice **devp)
diff --git a/drivers/cpu/bmips_cpu.c b/drivers/cpu/bmips_cpu.c
index 379acf2..1eb744a 100644
--- a/drivers/cpu/bmips_cpu.c
+++ b/drivers/cpu/bmips_cpu.c
@@ -30,6 +30,14 @@
 #define STRAPBUS_6328_FCVO_SHIFT	7
 #define STRAPBUS_6328_FCVO_MASK		(0x1f << STRAPBUS_6328_FCVO_SHIFT)
 
+#define REG_BCM6348_PERF_MIPSPLLCFG	0x34
+#define MIPSPLLCFG_6348_M1CPU_SHIFT	6
+#define MIPSPLLCFG_6348_M1CPU_MASK	(0x7 << MIPSPLLCFG_6348_M1CPU_SHIFT)
+#define MIPSPLLCFG_6348_N2_SHIFT	15
+#define MIPSPLLCFG_6348_N2_MASK		(0x1F << MIPSPLLCFG_6348_N2_SHIFT)
+#define MIPSPLLCFG_6348_N1_SHIFT	20
+#define MIPSPLLCFG_6348_N1_MASK		(0x7 << MIPSPLLCFG_6348_N1_SHIFT)
+
 #define REG_BCM6358_DDR_DMIPSPLLCFG	0x12b8
 #define DMIPSPLLCFG_6358_M1_SHIFT	0
 #define DMIPSPLLCFG_6358_M1_MASK	(0xff << DMIPSPLLCFG_6358_M1_SHIFT)
@@ -56,7 +64,7 @@
 };
 
 /* Specific CPU Ops */
-static int bcm6358_get_cpu_desc(struct bmips_cpu_priv *priv, char *buf,
+static int bmips_short_cpu_desc(struct bmips_cpu_priv *priv, char *buf,
 				int size)
 {
 	unsigned short cpu_id;
@@ -72,7 +80,7 @@
 	return 0;
 }
 
-static int bcm6328_get_cpu_desc(struct bmips_cpu_priv *priv, char *buf,
+static int bmips_long_cpu_desc(struct bmips_cpu_priv *priv, char *buf,
 				int size)
 {
 	unsigned int cpu_id;
@@ -88,6 +96,11 @@
 	return 0;
 }
 
+static ulong bcm3380_get_cpu_freq(struct bmips_cpu_priv *priv)
+{
+	return 333000000;
+}
+
 static ulong bcm6328_get_cpu_freq(struct bmips_cpu_priv *priv)
 {
 	unsigned int mips_pll_fcvo;
@@ -115,6 +128,23 @@
 	}
 }
 
+static ulong bcm6338_get_cpu_freq(struct bmips_cpu_priv *priv)
+{
+	return 240000000;
+}
+
+static ulong bcm6348_get_cpu_freq(struct bmips_cpu_priv *priv)
+{
+	unsigned int tmp, n1, n2, m1;
+
+	tmp = readl_be(priv->regs + REG_BCM6348_PERF_MIPSPLLCFG);
+	n1 = (tmp & MIPSPLLCFG_6348_N1_MASK) >> MIPSPLLCFG_6348_N1_SHIFT;
+	n2 = (tmp & MIPSPLLCFG_6348_N2_MASK) >> MIPSPLLCFG_6348_N2_SHIFT;
+	m1 = (tmp & MIPSPLLCFG_6348_M1CPU_MASK) >> MIPSPLLCFG_6348_M1CPU_SHIFT;
+
+	return (16 * 1000000 * (n1 + 1) * (n2 + 2)) / (m1 + 1);
+}
+
 static ulong bcm6358_get_cpu_freq(struct bmips_cpu_priv *priv)
 {
 	unsigned int tmp, n1, n2, m1;
@@ -160,25 +190,48 @@
 		return 2;
 }
 
+static int bcm6345_get_cpu_count(struct bmips_cpu_priv *priv)
+{
+	return 1;
+}
+
 static int bcm6358_get_cpu_count(struct bmips_cpu_priv *priv)
 {
 	return 2;
 }
 
+static const struct bmips_cpu_hw bmips_cpu_bcm3380 = {
+	.get_cpu_desc = bmips_short_cpu_desc,
+	.get_cpu_freq = bcm3380_get_cpu_freq,
+	.get_cpu_count = bcm6358_get_cpu_count,
+};
+
 static const struct bmips_cpu_hw bmips_cpu_bcm6328 = {
-	.get_cpu_desc = bcm6328_get_cpu_desc,
+	.get_cpu_desc = bmips_long_cpu_desc,
 	.get_cpu_freq = bcm6328_get_cpu_freq,
 	.get_cpu_count = bcm6328_get_cpu_count,
 };
 
+static const struct bmips_cpu_hw bmips_cpu_bcm6338 = {
+	.get_cpu_desc = bmips_short_cpu_desc,
+	.get_cpu_freq = bcm6338_get_cpu_freq,
+	.get_cpu_count = bcm6345_get_cpu_count,
+};
+
+static const struct bmips_cpu_hw bmips_cpu_bcm6348 = {
+	.get_cpu_desc = bmips_short_cpu_desc,
+	.get_cpu_freq = bcm6348_get_cpu_freq,
+	.get_cpu_count = bcm6345_get_cpu_count,
+};
+
 static const struct bmips_cpu_hw bmips_cpu_bcm6358 = {
-	.get_cpu_desc = bcm6358_get_cpu_desc,
+	.get_cpu_desc = bmips_short_cpu_desc,
 	.get_cpu_freq = bcm6358_get_cpu_freq,
 	.get_cpu_count = bcm6358_get_cpu_count,
 };
 
 static const struct bmips_cpu_hw bmips_cpu_bcm63268 = {
-	.get_cpu_desc = bcm6328_get_cpu_desc,
+	.get_cpu_desc = bmips_long_cpu_desc,
 	.get_cpu_freq = bcm63268_get_cpu_freq,
 	.get_cpu_count = bcm6358_get_cpu_count,
 };
@@ -247,7 +300,7 @@
 	fdt_addr_t addr;
 	fdt_size_t size;
 
-	addr = dev_get_addr_size_index(dev_get_parent(dev), 0, &size);
+	addr = devfdt_get_addr_size_index(dev_get_parent(dev), 0, &size);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
@@ -259,9 +312,18 @@
 
 static const struct udevice_id bmips_cpu_ids[] = {
 	{
+		.compatible = "brcm,bcm3380-cpu",
+		.data = (ulong)&bmips_cpu_bcm3380,
+	}, {
 		.compatible = "brcm,bcm6328-cpu",
 		.data = (ulong)&bmips_cpu_bcm6328,
 	}, {
+		.compatible = "brcm,bcm6338-cpu",
+		.data = (ulong)&bmips_cpu_bcm6338,
+	}, {
+		.compatible = "brcm,bcm6348-cpu",
+		.data = (ulong)&bmips_cpu_bcm6348,
+	}, {
 		.compatible = "brcm,bcm6358-cpu",
 		.data = (ulong)&bmips_cpu_bcm6358,
 	}, {
diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c
index c57ac16..73e4853 100644
--- a/drivers/cpu/cpu-uclass.c
+++ b/drivers/cpu/cpu-uclass.c
@@ -63,11 +63,11 @@
 static int uclass_cpu_init(struct uclass *uc)
 {
 	struct udevice *dev;
-	int node;
+	ofnode node;
 	int ret;
 
-	node = fdt_path_offset(gd->fdt_blob, "/cpus");
-	if (node < 0)
+	node = ofnode_path("/cpus");
+	if (!ofnode_valid(node))
 		return 0;
 
 	ret = device_bind_driver_to_node(dm_root(), "cpu_bus", "cpus", node,
diff --git a/drivers/dma/ti-edma3.c b/drivers/dma/ti-edma3.c
index 2478438..39e9793 100644
--- a/drivers/dma/ti-edma3.c
+++ b/drivers/dma/ti-edma3.c
@@ -11,8 +11,8 @@
 
 #include <asm/io.h>
 #include <common.h>
+#include <dm.h>
 #include <dma.h>
-#include <dm/device.h>
 #include <asm/omap_common.h>
 #include <asm/ti-common/ti-edma3.h>
 
@@ -505,7 +505,7 @@
 {
 	struct ti_edma3_priv *priv = dev_get_priv(dev);
 
-	priv->base = dev_get_addr(dev);
+	priv->base = devfdt_get_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/firmware/firmware-uclass.c b/drivers/firmware/firmware-uclass.c
index 01b6a44..af781b5 100644
--- a/drivers/firmware/firmware-uclass.c
+++ b/drivers/firmware/firmware-uclass.c
@@ -2,7 +2,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/uclass.h>
+#include <common.h>
+#include <dm.h>
 
 /* Firmware access is platform-dependent.  No generic code in uclass */
 UCLASS_DRIVER(firmware) = {
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 40fba64..451fbde 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -8,7 +8,7 @@
  */
 
 #include <common.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <dm/lists.h>
 #include <libfdt.h>
 #include <linux/arm-smccc.h>
@@ -40,8 +40,8 @@
 static int psci_bind(struct udevice *dev)
 {
 	/* No SYSTEM_RESET support for PSCI 0.1 */
-	if (of_device_is_compatible(dev, "arm,psci-0.2") ||
-	    of_device_is_compatible(dev, "arm,psci-1.0")) {
+	if (device_is_compatible(dev, "arm,psci-0.2") ||
+	    device_is_compatible(dev, "arm,psci-1.0")) {
 		int ret;
 
 		/* bind psci-sysreset optionally */
@@ -59,8 +59,8 @@
 	DECLARE_GLOBAL_DATA_PTR;
 	const char *method;
 
-	method = fdt_stringlist_get(gd->fdt_blob, dev->of_offset, "method", 0,
-				    NULL);
+	method = fdt_stringlist_get(gd->fdt_blob, dev_of_offset(dev), "method",
+				    0, NULL);
 	if (!method) {
 		printf("missing \"method\" property\n");
 		return -ENXIO;
diff --git a/drivers/gpio/74x164_gpio.c b/drivers/gpio/74x164_gpio.c
index 53a639a..eb2c0b6 100644
--- a/drivers/gpio/74x164_gpio.c
+++ b/drivers/gpio/74x164_gpio.c
@@ -106,7 +106,7 @@
 }
 
 static int gen_74x164_xlate(struct udevice *dev, struct gpio_desc *desc,
-			    struct fdtdec_phandle_args *args)
+			    struct ofnode_phandle_args *args)
 {
 	desc->offset = args->args[0];
 	desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
diff --git a/drivers/gpio/altera_pio.c b/drivers/gpio/altera_pio.c
index 92849c5..d17245a 100644
--- a/drivers/gpio/altera_pio.c
+++ b/drivers/gpio/altera_pio.c
@@ -89,7 +89,7 @@
 {
 	struct altera_pio_platdata *plat = dev_get_platdata(dev);
 
-	plat->regs = map_physmem(dev_get_addr(dev),
+	plat->regs = map_physmem(devfdt_get_addr(dev),
 				 sizeof(struct altera_pio_regs),
 				 MAP_NOCACHE);
 	plat->gpio_count = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c
index 98dbd82..174d561 100644
--- a/drivers/gpio/at91_gpio.c
+++ b/drivers/gpio/at91_gpio.c
@@ -587,7 +587,7 @@
 	uc_priv->gpio_count = GPIO_PER_BANK;
 
 #if CONFIG_IS_ENABLED(OF_CONTROL)
-	plat->base_addr = (uint32_t)dev_get_addr_ptr(dev);
+	plat->base_addr = (uint32_t)devfdt_get_addr_ptr(dev);
 #endif
 	port->regs = (struct at91_port *)plat->base_addr;
 
diff --git a/drivers/gpio/atmel_pio4.c b/drivers/gpio/atmel_pio4.c
index 81c3047..f368946 100644
--- a/drivers/gpio/atmel_pio4.c
+++ b/drivers/gpio/atmel_pio4.c
@@ -10,7 +10,6 @@
 #include <clk.h>
 #include <dm.h>
 #include <fdtdec.h>
-#include <dm/root.h>
 #include <asm/arch/hardware.h>
 #include <asm/gpio.h>
 #include <mach/gpio.h>
@@ -276,7 +275,7 @@
 
 static int atmel_pio4_bind(struct udevice *dev)
 {
-	return dm_scan_fdt_node(dev, gd->fdt_blob, dev_of_offset(dev), false);
+	return dm_scan_fdt_dev(dev);
 }
 
 static int atmel_pio4_probe(struct udevice *dev)
@@ -299,7 +298,7 @@
 
 	clk_free(&clk);
 
-	addr_base = dev_get_addr(dev);
+	addr_base = devfdt_get_addr(dev);
 	if (addr_base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/bcm2835_gpio.c b/drivers/gpio/bcm2835_gpio.c
index cd5480e..beaa218 100644
--- a/drivers/gpio/bcm2835_gpio.c
+++ b/drivers/gpio/bcm2835_gpio.c
@@ -130,7 +130,7 @@
 	struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/bcm6345_gpio.c b/drivers/gpio/bcm6345_gpio.c
index 1c46020..009e2fc 100644
--- a/drivers/gpio/bcm6345_gpio.c
+++ b/drivers/gpio/bcm6345_gpio.c
@@ -9,10 +9,10 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
-#include <dm/device.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -92,11 +92,11 @@
 	fdt_addr_t data_addr, dirout_addr;
 	fdt_size_t data_size, dirout_size;
 
-	dirout_addr = dev_get_addr_size_index(dev, 0, &dirout_size);
+	dirout_addr = devfdt_get_addr_size_index(dev, 0, &dirout_size);
 	if (dirout_addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
-	data_addr = dev_get_addr_size_index(dev, 1, &data_size);
+	data_addr = devfdt_get_addr_size_index(dev, 1, &data_size);
 	if (data_addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index ba48040..f611996 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -114,9 +114,8 @@
 	return 0;
 }
 
-int gpio_xlate_offs_flags(struct udevice *dev,
-					 struct gpio_desc *desc,
-					 struct fdtdec_phandle_args *args)
+int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc,
+			  struct ofnode_phandle_args *args)
 {
 	if (args->args_count < 1)
 		return -EINVAL;
@@ -133,7 +132,7 @@
 }
 
 static int gpio_find_and_xlate(struct gpio_desc *desc,
-			       struct fdtdec_phandle_args *args)
+			       struct ofnode_phandle_args *args)
 {
 	struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
 
@@ -642,37 +641,30 @@
 	return vector;
 }
 
-static int _gpio_request_by_name_nodev(const void *blob, int node,
-				       const char *list_name, int index,
-				       struct gpio_desc *desc, int flags,
-				       bool add_index)
+static int gpio_request_tail(int ret, ofnode node,
+			     struct ofnode_phandle_args *args,
+			     const char *list_name, int index,
+			     struct gpio_desc *desc, int flags, bool add_index)
 {
-	struct fdtdec_phandle_args args;
-	int ret;
-
 	desc->dev = NULL;
 	desc->offset = 0;
 	desc->flags = 0;
-	ret = fdtdec_parse_phandle_with_args(blob, node, list_name,
-					     "#gpio-cells", 0, index, &args);
-	if (ret) {
-		debug("%s: fdtdec_parse_phandle_with_args failed\n", __func__);
+	if (ret)
 		goto err;
-	}
 
-	ret = uclass_get_device_by_of_offset(UCLASS_GPIO, args.node,
-					     &desc->dev);
+	ret = uclass_get_device_by_ofnode(UCLASS_GPIO, args->node,
+					  &desc->dev);
 	if (ret) {
 		debug("%s: uclass_get_device_by_of_offset failed\n", __func__);
 		goto err;
 	}
-	ret = gpio_find_and_xlate(desc, &args);
+	ret = gpio_find_and_xlate(desc, args);
 	if (ret) {
 		debug("%s: gpio_find_and_xlate failed\n", __func__);
 		goto err;
 	}
 	ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s",
-			       fdt_get_name(blob, node, NULL),
+			       ofnode_get_name(node),
 			       list_name, index);
 	if (ret) {
 		debug("%s: dm_gpio_requestf failed\n", __func__);
@@ -687,32 +679,45 @@
 	return 0;
 err:
 	debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n",
-	      __func__, fdt_get_name(blob, node, NULL), list_name, index, ret);
+	      __func__, ofnode_get_name(node), list_name, index, ret);
 	return ret;
 }
 
-int gpio_request_by_name_nodev(const void *blob, int node,
-			       const char *list_name, int index,
+static int _gpio_request_by_name_nodev(ofnode node, const char *list_name,
+				       int index, struct gpio_desc *desc,
+				       int flags, bool add_index)
+{
+	struct ofnode_phandle_args args;
+	int ret;
+
+	ret = ofnode_parse_phandle_with_args(node, list_name, "#gpio-cells", 0,
+					     index, &args);
+
+	return gpio_request_tail(ret, node, &args, list_name, index, desc,
+				 flags, add_index);
+}
+
+int gpio_request_by_name_nodev(ofnode node, const char *list_name, int index,
 			       struct gpio_desc *desc, int flags)
 {
-	return _gpio_request_by_name_nodev(blob, node, list_name, index, desc,
-					   flags, index > 0);
+	return _gpio_request_by_name_nodev(node, list_name, index, desc, flags,
+					   index > 0);
 }
 
-int gpio_request_by_name(struct udevice *dev,  const char *list_name, int index,
+int gpio_request_by_name(struct udevice *dev, const char *list_name, int index,
 			 struct gpio_desc *desc, int flags)
 {
-	/*
-	 * This isn't ideal since we don't use dev->name in the debug()
-	 * calls in gpio_request_by_name(), but we can do this until
-	 * gpio_request_by_name_nodev() can be dropped.
-	 */
-	return gpio_request_by_name_nodev(gd->fdt_blob, dev_of_offset(dev),
-					  list_name, index, desc, flags);
+	struct ofnode_phandle_args args;
+	int ret;
+
+	ret = dev_read_phandle_with_args(dev, list_name, "#gpio-cells", 0,
+					 index, &args);
+
+	return gpio_request_tail(ret, dev_ofnode(dev), &args, list_name,
+				 index, desc, flags, index > 0);
 }
 
-int gpio_request_list_by_name_nodev(const void *blob, int node,
-				    const char *list_name,
+int gpio_request_list_by_name_nodev(ofnode node, const char *list_name,
 				    struct gpio_desc *desc, int max_count,
 				    int flags)
 {
@@ -720,7 +725,7 @@
 	int ret;
 
 	for (count = 0; count < max_count; count++) {
-		ret = _gpio_request_by_name_nodev(blob, node, list_name, count,
+		ret = _gpio_request_by_name_nodev(node, list_name, count,
 						  &desc[count], flags, true);
 		if (ret == -ENOENT)
 			break;
@@ -746,9 +751,8 @@
 	 * calls in gpio_request_by_name(), but we can do this until
 	 * gpio_request_list_by_name_nodev() can be dropped.
 	 */
-	return gpio_request_list_by_name_nodev(gd->fdt_blob, dev_of_offset(dev),
-					       list_name, desc, max_count,
-					       flags);
+	return gpio_request_list_by_name_nodev(dev_ofnode(dev), list_name, desc,
+					       max_count, flags);
 }
 
 int gpio_get_list_count(struct udevice *dev, const char *list_name)
diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c
index ad11764..c11e953 100644
--- a/drivers/gpio/gpio-uniphier.c
+++ b/drivers/gpio/gpio-uniphier.c
@@ -6,7 +6,7 @@
  */
 
 #include <common.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
@@ -95,7 +95,7 @@
 	fdt_addr_t addr;
 	unsigned int tmp;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/imx_rgpio2p.c b/drivers/gpio/imx_rgpio2p.c
index 886b161..5abc88b 100644
--- a/drivers/gpio/imx_rgpio2p.c
+++ b/drivers/gpio/imx_rgpio2p.c
@@ -166,7 +166,7 @@
 	if (plat)
 		return 0;
 
-	addr = dev_get_addr_index(dev, 1);
+	addr = devfdt_get_addr_index(dev, 1);
 	if (addr == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 0a9eb03..ffc3ccb 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -129,7 +129,7 @@
 	bank->io_sel = plat->base_addr + 4;
 	bank->lvl = plat->base_addr + 8;
 
-	prop = fdt_getprop(gd->fdt_blob, dev->of_offset,
+	prop = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
 			   "use-lvl-write-cache", NULL);
 	if (prop)
 		bank->use_lvl_write_cache = true;
diff --git a/drivers/gpio/lpc32xx_gpio.c b/drivers/gpio/lpc32xx_gpio.c
index 1bf945a..292fc74 100644
--- a/drivers/gpio/lpc32xx_gpio.c
+++ b/drivers/gpio/lpc32xx_gpio.c
@@ -7,6 +7,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#include <common.h>
 #include <asm/io.h>
 #include <asm/arch-lpc32xx/cpu.h>
 #include <asm/arch-lpc32xx/gpio.h>
diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c
index 01ce1d6..ff38fc5 100644
--- a/drivers/gpio/msm_gpio.c
+++ b/drivers/gpio/msm_gpio.c
@@ -97,7 +97,7 @@
 {
 	struct msm_gpio_bank *priv = dev_get_priv(dev);
 
-	priv->base = dev_get_addr(dev);
+	priv->base = devfdt_get_addr(dev);
 
 	return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;
 }
diff --git a/drivers/gpio/mvebu_gpio.c b/drivers/gpio/mvebu_gpio.c
index 75dc73e..85dea14 100644
--- a/drivers/gpio/mvebu_gpio.c
+++ b/drivers/gpio/mvebu_gpio.c
@@ -92,7 +92,7 @@
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct mvebu_gpio_priv *priv = dev_get_priv(dev);
 
-	priv->regs = (struct mvebu_gpio_regs *)dev_get_addr(dev);
+	priv->regs = (struct mvebu_gpio_regs *)devfdt_get_addr(dev);
 	uc_priv->gpio_count = MVEBU_GPIOS_PER_BANK;
 	priv->name[0] = 'A' + dev->req_seq;
 	uc_priv->bank_name = priv->name;
diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c
index 70fe5b6..0eb6c60 100644
--- a/drivers/gpio/mxc_gpio.c
+++ b/drivers/gpio/mxc_gpio.c
@@ -302,7 +302,7 @@
 	if (plat)
 		return 0;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c
index 5338552..b423e34 100644
--- a/drivers/gpio/omap_gpio.c
+++ b/drivers/gpio/omap_gpio.c
@@ -305,7 +305,7 @@
 	if (plat)
 		return 0;
 
-	base_addr = dev_get_addr(dev);
+	base_addr = devfdt_get_addr(dev);
 	if (base_addr == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
diff --git a/drivers/gpio/pca953x_gpio.c b/drivers/gpio/pca953x_gpio.c
index b81f0fa..4962f25 100644
--- a/drivers/gpio/pca953x_gpio.c
+++ b/drivers/gpio/pca953x_gpio.c
@@ -228,7 +228,7 @@
 }
 
 static int pca953x_xlate(struct udevice *dev, struct gpio_desc *desc,
-			 struct fdtdec_phandle_args *args)
+			 struct ofnode_phandle_args *args)
 {
 	desc->offset = args->args[0];
 	desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
diff --git a/drivers/gpio/pm8916_gpio.c b/drivers/gpio/pm8916_gpio.c
index e38cee8..9ec2a24 100644
--- a/drivers/gpio/pm8916_gpio.c
+++ b/drivers/gpio/pm8916_gpio.c
@@ -173,7 +173,7 @@
 	struct pm8916_gpio_bank *priv = dev_get_priv(dev);
 	int reg;
 
-	priv->pid = dev_get_addr(dev);
+	priv->pid = dev_read_addr(dev);
 	if (priv->pid == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
@@ -193,10 +193,8 @@
 {
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 
-	uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-					     "gpio-count", 0);
-	uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
-					 "gpio-bank-name", NULL);
+	uc_priv->gpio_count = dev_read_u32_default(dev, "gpio-count", 0);
+	uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
 	if (uc_priv->bank_name == NULL)
 		uc_priv->bank_name = "pm8916";
 
@@ -259,7 +257,7 @@
 	struct pm8916_gpio_bank *priv = dev_get_priv(dev);
 	int reg;
 
-	priv->pid = dev_get_addr(dev);
+	priv->pid = devfdt_get_addr(dev);
 	if (priv->pid == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/rk_gpio.c b/drivers/gpio/rk_gpio.c
index 5dbd228..6f7366a 100644
--- a/drivers/gpio/rk_gpio.c
+++ b/drivers/gpio/rk_gpio.c
@@ -104,7 +104,7 @@
 	int ret;
 
 	/* This only supports RK3288 at present */
-	priv->regs = (struct rockchip_gpio_regs *)dev_get_addr(dev);
+	priv->regs = (struct rockchip_gpio_regs *)devfdt_get_addr(dev);
 	ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl);
 	if (ret)
 		return ret;
diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c
index 042996e..5c894a2 100644
--- a/drivers/gpio/s5p_gpio.c
+++ b/drivers/gpio/s5p_gpio.c
@@ -316,7 +316,7 @@
 	if (plat)
 		return 0;
 
-	base = (struct s5p_gpio_bank *)dev_get_addr(parent);
+	base = (struct s5p_gpio_bank *)devfdt_get_addr(parent);
 	for (node = fdt_first_subnode(blob, dev_of_offset(parent)), bank = base;
 	     node > 0;
 	     node = fdt_next_subnode(blob, node), bank++) {
@@ -339,7 +339,7 @@
 
 		dev_set_of_offset(dev, node);
 
-		reg = dev_get_addr(dev);
+		reg = devfdt_get_addr(dev);
 		if (reg != FDT_ADDR_T_NONE)
 			bank = (struct s5p_gpio_bank *)((ulong)base + reg);
 
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index ae6d930..4f7b62e 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -8,6 +8,7 @@
 #include <fdtdec.h>
 #include <malloc.h>
 #include <asm/gpio.h>
+#include <dm/of.h>
 #include <dt-bindings/gpio/gpio.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -165,7 +166,7 @@
 }
 
 static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
-			 struct fdtdec_phandle_args *args)
+			 struct ofnode_phandle_args *args)
 {
 	desc->offset = args->args[0];
 	if (args->args_count < 2)
@@ -197,10 +198,8 @@
 {
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 
-	uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-					     "num-gpios", 0);
-	uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
-					 "gpio-bank-name", NULL);
+	uc_priv->gpio_count = dev_read_u32_default(dev, "num-gpios", 0);
+	uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
 
 	return 0;
 }
@@ -209,10 +208,9 @@
 {
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 
-	if (dev_of_offset(dev) == -1) {
+	if (!dev_of_valid(dev))
 		/* Tell the uclass how many GPIOs we have */
 		uc_priv->gpio_count = CONFIG_SANDBOX_GPIO_COUNT;
-	}
 
 	dev->priv = calloc(sizeof(struct gpio_state), uc_priv->gpio_count);
 
diff --git a/drivers/gpio/stm32f7_gpio.c b/drivers/gpio/stm32f7_gpio.c
index 5e05463..653e9be 100644
--- a/drivers/gpio/stm32f7_gpio.c
+++ b/drivers/gpio/stm32f7_gpio.c
@@ -84,7 +84,7 @@
 	fdt_addr_t addr;
 	char *name;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index 3f40e83..b47cc66 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -217,7 +217,7 @@
 }
 
 static int sunxi_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
-			    struct fdtdec_phandle_args *args)
+			    struct ofnode_phandle_args *args)
 {
 	int ret;
 
@@ -296,7 +296,7 @@
 	if (plat)
 		return 0;
 
-	ctlr = (struct sunxi_gpio_reg *)dev_get_addr(parent);
+	ctlr = (struct sunxi_gpio_reg *)devfdt_get_addr(parent);
 	for (bank = 0; bank < soc_data->no_banks; bank++) {
 		struct sunxi_gpio_platdata *plat;
 		struct udevice *dev;
diff --git a/drivers/gpio/tegra186_gpio.c b/drivers/gpio/tegra186_gpio.c
index b0c22e5..c5a7e13 100644
--- a/drivers/gpio/tegra186_gpio.c
+++ b/drivers/gpio/tegra186_gpio.c
@@ -139,7 +139,7 @@
 }
 
 static int tegra186_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
-			    struct fdtdec_phandle_args *args)
+			       struct ofnode_phandle_args *args)
 {
 	int gpio, port, ret;
 
@@ -179,7 +179,7 @@
 	if (parent_plat)
 		return 0;
 
-	regs = (uint32_t *)dev_get_addr_name(parent, "gpio");
+	regs = (uint32_t *)devfdt_get_addr_name(parent, "gpio");
 	if (regs == (uint32_t *)FDT_ADDR_T_NONE)
 		return -ENODEV;
 
diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c
index b01968a..687cd74 100644
--- a/drivers/gpio/tegra_gpio.c
+++ b/drivers/gpio/tegra_gpio.c
@@ -236,7 +236,7 @@
 }
 
 static int tegra_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
-			    struct fdtdec_phandle_args *args)
+			    struct ofnode_phandle_args *args)
 {
 	int gpio, port, ret;
 
@@ -341,7 +341,7 @@
 			 &len))
 		return -EINVAL;
 	bank_count = len / 3 / sizeof(u32);
-	ctlr = (struct gpio_ctlr *)dev_get_addr(parent);
+	ctlr = (struct gpio_ctlr *)devfdt_get_addr(parent);
 	}
 #endif
 	for (bank = 0; bank < bank_count; bank++) {
diff --git a/drivers/gpio/vybrid_gpio.c b/drivers/gpio/vybrid_gpio.c
index 458104e..b7a1b6a 100644
--- a/drivers/gpio/vybrid_gpio.c
+++ b/drivers/gpio/vybrid_gpio.c
@@ -113,7 +113,7 @@
 	if (plat)
 		return 0;
 
-	base_addr = dev_get_addr(dev);
+	base_addr = devfdt_get_addr(dev);
 	if (base_addr == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
diff --git a/drivers/gpio/zynq_gpio.c b/drivers/gpio/zynq_gpio.c
index 64579a1..4cb75a8 100644
--- a/drivers/gpio/zynq_gpio.c
+++ b/drivers/gpio/zynq_gpio.c
@@ -375,7 +375,7 @@
 {
 	struct zynq_gpio_privdata *priv = dev_get_priv(dev);
 
-	priv->base = dev_get_addr(dev);
+	priv->base = devfdt_get_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index c58bc1e..8ac1cc6 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -134,7 +134,6 @@
 
 config SYS_I2C_IMX_LPI2C
 	bool "NXP i.MX LPI2C driver"
-	depends on ARCH_MX7ULP
 	help
 	  Add support for the NXP i.MX LPI2C driver.
 
diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c
index 16dfb57..7ed0c10 100644
--- a/drivers/i2c/ast_i2c.c
+++ b/drivers/i2c/ast_i2c.c
@@ -92,7 +92,7 @@
 	struct ast_i2c_priv *priv = dev_get_priv(dev);
 	int ret;
 
-	priv->regs = dev_get_addr_ptr(dev);
+	priv->regs = devfdt_get_addr_ptr(dev);
 	if (IS_ERR(priv->regs))
 		return PTR_ERR(priv->regs);
 
diff --git a/drivers/i2c/at91_i2c.c b/drivers/i2c/at91_i2c.c
index 5a63669..b7298cf 100644
--- a/drivers/i2c/at91_i2c.c
+++ b/drivers/i2c/at91_i2c.c
@@ -244,7 +244,7 @@
 	struct at91_i2c_bus *bus = dev_get_priv(dev);
 	int node = dev_of_offset(dev);
 
-	bus->regs = (struct at91_i2c_regs *)dev_get_addr(dev);
+	bus->regs = (struct at91_i2c_regs *)devfdt_get_addr(dev);
 	bus->pdata = (struct at91_i2c_pdata *)dev_get_driver_data(dev);
 	bus->clock_frequency = fdtdec_get_int(blob, node,
 					      "clock-frequency", 100000);
diff --git a/drivers/i2c/davinci_i2c.c b/drivers/i2c/davinci_i2c.c
index 4471193..2df07bb 100644
--- a/drivers/i2c/davinci_i2c.c
+++ b/drivers/i2c/davinci_i2c.c
@@ -470,7 +470,7 @@
 	struct i2c_bus *i2c_bus = dev_get_priv(dev);
 
 	i2c_bus->id = dev->seq;
-	i2c_bus->regs = (struct i2c_regs *)dev_get_addr(dev);
+	i2c_bus->regs = (struct i2c_regs *)devfdt_get_addr(dev);
 
 	i2c_bus->speed = 100000;
 	 _davinci_i2c_init(i2c_bus->regs, i2c_bus->speed, 0);
diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index c68ff64..d4df35a 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -545,7 +545,7 @@
 #endif
 #endif
 	} else {
-		priv->regs = (struct i2c_regs *)dev_get_addr_ptr(bus);
+		priv->regs = (struct i2c_regs *)devfdt_get_addr_ptr(bus);
 	}
 
 	__dw_i2c_init(priv->regs, 0, 0);
diff --git a/drivers/i2c/exynos_hs_i2c.c b/drivers/i2c/exynos_hs_i2c.c
index 2dd75fd..9f4ac2f 100644
--- a/drivers/i2c/exynos_hs_i2c.c
+++ b/drivers/i2c/exynos_hs_i2c.c
@@ -524,7 +524,7 @@
 
 	node = dev_of_offset(dev);
 
-	i2c_bus->hsregs = (struct exynos5_hsi2c *)dev_get_addr(dev);
+	i2c_bus->hsregs = (struct exynos5_hsi2c *)devfdt_get_addr(dev);
 
 	i2c_bus->id = pinmux_decode_periph_id(blob, node);
 
diff --git a/drivers/i2c/i2c-cdns.c b/drivers/i2c/i2c-cdns.c
index dec1820..8265ce3 100644
--- a/drivers/i2c/i2c-cdns.c
+++ b/drivers/i2c/i2c-cdns.c
@@ -9,10 +9,10 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/errno.h>
-#include <dm/device.h>
 #include <dm/root.h>
 #include <i2c.h>
 #include <fdtdec.h>
@@ -419,7 +419,7 @@
 	struct cdns_i2c_platform_data *pdata =
 		(struct cdns_i2c_platform_data *)dev_get_driver_data(dev);
 
-	i2c_bus->regs = (struct cdns_i2c_regs *)dev_get_addr(dev);
+	i2c_bus->regs = (struct cdns_i2c_regs *)devfdt_get_addr(dev);
 	if (!i2c_bus->regs)
 		return -ENOMEM;
 
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c
index f3184c7..1397f34 100644
--- a/drivers/i2c/i2c-uclass.c
+++ b/drivers/i2c/i2c-uclass.c
@@ -7,7 +7,6 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
-#include <fdtdec.h>
 #include <i2c.h>
 #include <malloc.h>
 #include <dm/device-internal.h>
@@ -467,18 +466,20 @@
 }
 
 #if CONFIG_IS_ENABLED(OF_CONTROL)
-int i2c_chip_ofdata_to_platdata(const void *blob, int node,
-				struct dm_i2c_chip *chip)
+int i2c_chip_ofdata_to_platdata(struct udevice *dev, struct dm_i2c_chip *chip)
 {
-	chip->offset_len = fdtdec_get_int(gd->fdt_blob, node,
-					  "u-boot,i2c-offset-len", 1);
+	int addr;
+
+	chip->offset_len = dev_read_u32_default(dev, "u-boot,i2c-offset-len",
+						1);
 	chip->flags = 0;
-	chip->chip_addr = fdtdec_get_int(gd->fdt_blob, node, "reg", -1);
-	if (chip->chip_addr == -1) {
-		debug("%s: I2C Node '%s' has no 'reg' property\n", __func__,
-		      fdt_get_name(blob, node, NULL));
+	addr = dev_read_u32_default(dev, "reg", -1);
+	if (addr == -1) {
+		debug("%s: I2C Node '%s' has no 'reg' property %s\n", __func__,
+		      dev_read_name(dev), dev->name);
 		return -EINVAL;
 	}
+	chip->chip_addr = addr;
 
 	return 0;
 }
@@ -489,8 +490,7 @@
 #if CONFIG_IS_ENABLED(OF_CONTROL)
 	struct dm_i2c_bus *i2c = dev_get_uclass_priv(dev);
 
-	i2c->speed_hz = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-				     "clock-frequency", 100000);
+	i2c->speed_hz = dev_read_u32_default(dev, "clock-frequency", 100000);
 
 	return dm_i2c_set_bus_speed(dev, i2c->speed_hz);
 #else
@@ -503,11 +503,9 @@
 #if CONFIG_IS_ENABLED(OF_CONTROL)
 	struct dm_i2c_chip *plat = dev_get_parent_platdata(dev);
 
-	if (dev_of_offset(dev) == -1)
+	if (!dev_of_valid(dev))
 		return 0;
-
-	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev_of_offset(dev),
-					   plat);
+	return i2c_chip_ofdata_to_platdata(dev, plat);
 #else
 	return 0;
 #endif
diff --git a/drivers/i2c/i2c-uniphier-f.c b/drivers/i2c/i2c-uniphier-f.c
index 9f0df59..e51537b 100644
--- a/drivers/i2c/i2c-uniphier-f.c
+++ b/drivers/i2c/i2c-uniphier-f.c
@@ -7,12 +7,12 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/sizes.h>
 #include <linux/errno.h>
-#include <dm/device.h>
 #include <i2c.h>
 #include <fdtdec.h>
 
@@ -104,7 +104,7 @@
 	struct uniphier_fi2c_dev *priv = dev_get_priv(dev);
 	int ret;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/i2c/i2c-uniphier.c b/drivers/i2c/i2c-uniphier.c
index 73575e9..3412e2a 100644
--- a/drivers/i2c/i2c-uniphier.c
+++ b/drivers/i2c/i2c-uniphier.c
@@ -7,11 +7,11 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
 #include <linux/errno.h>
-#include <dm/device.h>
 #include <i2c.h>
 #include <fdtdec.h>
 
@@ -49,7 +49,7 @@
 	fdt_addr_t addr;
 	struct uniphier_i2c_dev *priv = dev_get_priv(dev);
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/i2c/imx_lpi2c.c b/drivers/i2c/imx_lpi2c.c
index f792d44..aa97196 100644
--- a/drivers/i2c/imx_lpi2c.c
+++ b/drivers/i2c/imx_lpi2c.c
@@ -25,9 +25,8 @@
 	return 0;
 }
 
-static int imx_lpci2c_check_busy_bus(struct udevice *bus)
+static int imx_lpci2c_check_busy_bus(const struct imx_lpi2c_reg *regs)
 {
-	struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus);
 	lpi2c_status_t result = LPI2C_SUCESS;
 	u32 status;
 
@@ -39,9 +38,8 @@
 	return result;
 }
 
-static int imx_lpci2c_check_clear_error(struct udevice *bus)
+static int imx_lpci2c_check_clear_error(struct imx_lpi2c_reg *regs)
 {
-	struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus);
 	lpi2c_status_t result = LPI2C_SUCESS;
 	u32 val, status;
 
@@ -71,9 +69,8 @@
 	return result;
 }
 
-static int bus_i2c_wait_for_tx_ready(struct udevice *bus)
+static int bus_i2c_wait_for_tx_ready(struct imx_lpi2c_reg *regs)
 {
-	struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus);
 	lpi2c_status_t result = LPI2C_SUCESS;
 	u32 txcount = 0;
 	ulong start_time = get_timer(0);
@@ -81,7 +78,7 @@
 	do {
 		txcount = LPI2C_MFSR_TXCOUNT(readl(&regs->mfsr));
 		txcount = LPI2C_FIFO_SIZE - txcount;
-		result = imx_lpci2c_check_clear_error(bus);
+		result = imx_lpci2c_check_clear_error(regs);
 		if (result) {
 			debug("i2c: wait for tx ready: result 0x%x\n", result);
 			return result;
@@ -95,9 +92,8 @@
 	return result;
 }
 
-static int bus_i2c_send(struct udevice *bus, u8 *txbuf, int len)
+static int bus_i2c_send(struct imx_lpi2c_reg *regs, u8 *txbuf, int len)
 {
-	struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus);
 	lpi2c_status_t result = LPI2C_SUCESS;
 
 	/* empty tx */
@@ -105,7 +101,7 @@
 		return result;
 
 	while (len--) {
-		result = bus_i2c_wait_for_tx_ready(bus);
+		result = bus_i2c_wait_for_tx_ready(regs);
 		if (result) {
 			debug("i2c: send wait fot tx ready: %d\n", result);
 			return result;
@@ -116,9 +112,8 @@
 	return result;
 }
 
-static int bus_i2c_receive(struct udevice *bus, u8 *rxbuf, int len)
+static int bus_i2c_receive(struct imx_lpi2c_reg *regs, u8 *rxbuf, int len)
 {
-	struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus);
 	lpi2c_status_t result = LPI2C_SUCESS;
 	u32 val;
 	ulong start_time = get_timer(0);
@@ -127,7 +122,7 @@
 	if (!len)
 		return result;
 
-	result = bus_i2c_wait_for_tx_ready(bus);
+	result = bus_i2c_wait_for_tx_ready(regs);
 	if (result) {
 		debug("i2c: receive wait fot tx ready: %d\n", result);
 		return result;
@@ -141,9 +136,10 @@
 
 	while (len--) {
 		do {
-			result = imx_lpci2c_check_clear_error(bus);
+			result = imx_lpci2c_check_clear_error(regs);
 			if (result) {
-				debug("i2c: receive check clear error: %d\n", result);
+				debug("i2c: receive check clear error: %d\n",
+				      result);
 				return result;
 			}
 			if (get_timer(start_time) > LPI2C_TIMEOUT_MS) {
@@ -158,13 +154,12 @@
 	return result;
 }
 
-static int bus_i2c_start(struct udevice *bus, u8 addr, u8 dir)
+static int bus_i2c_start(struct imx_lpi2c_reg *regs, u8 addr, u8 dir)
 {
-	struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus);
 	lpi2c_status_t result = LPI2C_SUCESS;
 	u32 val;
 
-	result = imx_lpci2c_check_busy_bus(bus);
+	result = imx_lpci2c_check_busy_bus(regs);
 	if (result) {
 		debug("i2c: start check busy bus: 0x%x\n", result);
 		return result;
@@ -175,7 +170,7 @@
 	val = readl(&regs->mcfgr1) & ~LPI2C_MCFGR1_AUTOSTOP_MASK;
 	writel(val, &regs->mcfgr1);
 	/* wait tx fifo ready */
-	result = bus_i2c_wait_for_tx_ready(bus);
+	result = bus_i2c_wait_for_tx_ready(regs);
 	if (result) {
 		debug("i2c: start wait for tx ready: 0x%x\n", result);
 		return result;
@@ -186,13 +181,13 @@
 
 	return result;
 }
-static int bus_i2c_stop(struct udevice *bus)
+
+static int bus_i2c_stop(struct imx_lpi2c_reg *regs)
 {
-	struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus);
 	lpi2c_status_t result = LPI2C_SUCESS;
 	u32 status;
 
-	result = bus_i2c_wait_for_tx_ready(bus);
+	result = bus_i2c_wait_for_tx_ready(regs);
 	if (result) {
 		debug("i2c: stop wait for tx ready: 0x%x\n", result);
 		return result;
@@ -203,7 +198,7 @@
 
 	while (result == LPI2C_SUCESS) {
 		status = readl(&regs->msr);
-		result = imx_lpci2c_check_clear_error(bus);
+		result = imx_lpci2c_check_clear_error(regs);
 		/* stop detect flag */
 		if (status & LPI2C_MSR_SDF_MASK) {
 			/* clear stop flag */
@@ -216,34 +211,34 @@
 	return result;
 }
 
-static int bus_i2c_read(struct udevice *bus, u32 chip, u8 *buf, int len)
+static int bus_i2c_read(struct imx_lpi2c_reg *regs, u32 chip, u8 *buf, int len)
 {
 	lpi2c_status_t result = LPI2C_SUCESS;
 
-	result = bus_i2c_start(bus, chip, 1);
+	result = bus_i2c_start(regs, chip, 1);
 	if (result)
 		return result;
-	result = bus_i2c_receive(bus, buf, len);
+	result = bus_i2c_receive(regs, buf, len);
 	if (result)
 		return result;
-	result = bus_i2c_stop(bus);
+	result = bus_i2c_stop(regs);
 	if (result)
 		return result;
 
 	return result;
 }
 
-static int bus_i2c_write(struct udevice *bus, u32 chip, u8 *buf, int len)
+static int bus_i2c_write(struct imx_lpi2c_reg *regs, u32 chip, u8 *buf, int len)
 {
 	lpi2c_status_t result = LPI2C_SUCESS;
 
-	result = bus_i2c_start(bus, chip, 0);
+	result = bus_i2c_start(regs, chip, 0);
 	if (result)
 		return result;
-	result = bus_i2c_send(bus, buf, len);
+	result = bus_i2c_send(regs, buf, len);
 	if (result)
 		return result;
-	result = bus_i2c_stop(bus);
+	result = bus_i2c_stop(regs);
 	if (result)
 		return result;
 
@@ -253,7 +248,7 @@
 
 static int bus_i2c_set_bus_speed(struct udevice *bus, int speed)
 {
-	struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus);
+	struct imx_lpi2c_reg *regs;
 	u32 val;
 	u32 preescale = 0, best_pre = 0, clkhi = 0;
 	u32 best_clkhi = 0, abs_error = 0, rate;
@@ -262,6 +257,7 @@
 	bool mode;
 	int i;
 
+	regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
 	clock_rate = imx_get_i2cclk(bus->seq + 4);
 	if (!clock_rate)
 		return -EPERM;
@@ -320,10 +316,11 @@
 
 static int bus_i2c_init(struct udevice *bus, int speed)
 {
-	struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)dev_get_addr(bus);
+	struct imx_lpi2c_reg *regs;
 	u32 val;
 	int ret;
 
+	regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
 	/* reset peripheral */
 	writel(LPI2C_MCR_RST_MASK, &regs->mcr);
 	writel(0x0, &regs->mcr);
@@ -356,16 +353,18 @@
 static int imx_lpi2c_probe_chip(struct udevice *bus, u32 chip,
 				u32 chip_flags)
 {
+	struct imx_lpi2c_reg *regs;
 	lpi2c_status_t result = LPI2C_SUCESS;
 
-	result = bus_i2c_start(bus, chip, 0);
+	regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
+	result = bus_i2c_start(regs, chip, 0);
 	if (result) {
-		bus_i2c_stop(bus);
+		bus_i2c_stop(regs);
 		bus_i2c_init(bus, 100000);
 		return result;
 	}
 
-	result = bus_i2c_stop(bus);
+	result = bus_i2c_stop(regs);
 	if (result) {
 		bus_i2c_init(bus, 100000);
 		return -result;
@@ -376,15 +375,16 @@
 
 static int imx_lpi2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
 {
+	struct imx_lpi2c_reg *regs;
 	int ret = 0;
 
+	regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
 	for (; nmsgs > 0; nmsgs--, msg++) {
 		debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
 		if (msg->flags & I2C_M_RD)
-			ret = bus_i2c_read(bus, msg->addr, msg->buf,
-					   msg->len);
+			ret = bus_i2c_read(regs, msg->addr, msg->buf, msg->len);
 		else {
-			ret = bus_i2c_write(bus, msg->addr, msg->buf,
+			ret = bus_i2c_write(regs, msg->addr, msg->buf,
 					    msg->len);
 			if (ret)
 				break;
@@ -410,7 +410,7 @@
 
 	i2c_bus->driver_data = dev_get_driver_data(bus);
 
-	addr = dev_get_addr(bus);
+	addr = devfdt_get_addr(bus);
 	if (addr == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
diff --git a/drivers/i2c/muxes/i2c-mux-uclass.c b/drivers/i2c/muxes/i2c-mux-uclass.c
index d243b8e..187e8a7 100644
--- a/drivers/i2c/muxes/i2c-mux-uclass.c
+++ b/drivers/i2c/muxes/i2c-mux-uclass.c
@@ -51,24 +51,21 @@
 /* Find the I2C buses selected by this mux */
 static int i2c_mux_post_bind(struct udevice *mux)
 {
-	const void *blob = gd->fdt_blob;
+	ofnode node;
 	int ret;
-	int offset;
 
 	debug("%s: %s\n", __func__, mux->name);
 	/*
 	 * There is no compatible string in the sub-nodes, so we must manually
 	 * bind these
 	 */
-	for (offset = fdt_first_subnode(blob, dev_of_offset(mux));
-	     offset > 0;
-	     offset = fdt_next_subnode(blob, offset)) {
+	dev_for_each_subnode(node, mux) {
 		struct udevice *dev;
 		const char *name;
 
-		name = fdt_get_name(blob, offset, NULL);
+		name = ofnode_get_name(node);
 		ret = device_bind_driver_to_node(mux, "i2c_mux_bus_drv", name,
-						 offset, &dev);
+						 node, &dev);
 		debug("   - bind ret=%d, %s\n", ret, dev ? dev->name : NULL);
 		if (ret)
 			return ret;
diff --git a/drivers/i2c/mv_i2c.c b/drivers/i2c/mv_i2c.c
index c780272..913721b 100644
--- a/drivers/i2c/mv_i2c.c
+++ b/drivers/i2c/mv_i2c.c
@@ -579,7 +579,7 @@
 {
 	struct mv_i2c_priv *priv = dev_get_priv(bus);
 
-	priv->base = (void *)dev_get_addr_ptr(bus);
+	priv->base = (void *)devfdt_get_addr_ptr(bus);
 
 	return 0;
 }
diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c
index 3703519..dfbc4e0 100644
--- a/drivers/i2c/mvtwsi.c
+++ b/drivers/i2c/mvtwsi.c
@@ -778,7 +778,7 @@
 {
 	struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
 
-	dev->base = dev_get_addr_ptr(bus);
+	dev->base = devfdt_get_addr_ptr(bus);
 
 	if (!dev->base)
 		return -ENOMEM;
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index b68e827..110b9d6 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -752,7 +752,7 @@
 
 	i2c_bus->driver_data = dev_get_driver_data(bus);
 
-	addr = dev_get_addr(bus);
+	addr = devfdt_get_addr(bus);
 	if (addr == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
@@ -773,12 +773,12 @@
 	if (ret < 0) {
 		debug("i2c bus %d at 0x%2lx, no gpio pinctrl state.\n", bus->seq, i2c_bus->base);
 	} else {
-		ret = gpio_request_by_name_nodev(fdt, node, "scl-gpios",
-						 0, &i2c_bus->scl_gpio,
-						 GPIOD_IS_OUT);
-		ret2 = gpio_request_by_name_nodev(fdt, node, "sda-gpios",
-						 0, &i2c_bus->sda_gpio,
-						 GPIOD_IS_OUT);
+		ret = gpio_request_by_name_nodev(offset_to_ofnode(node),
+				"scl-gpios", 0, &i2c_bus->scl_gpio,
+				GPIOD_IS_OUT);
+		ret2 = gpio_request_by_name_nodev(offset_to_ofnode(node),
+				"sda-gpios", 0, &i2c_bus->sda_gpio,
+				GPIOD_IS_OUT);
 		if (!dm_gpio_is_valid(&i2c_bus->sda_gpio) |
 		    !dm_gpio_is_valid(&i2c_bus->scl_gpio) |
 		    ret | ret2) {
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 4b8397a..f71e0a5 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -896,7 +896,7 @@
 {
 	struct omap_i2c *priv = dev_get_priv(bus);
 
-	priv->regs = map_physmem(dev_get_addr(bus), sizeof(void *),
+	priv->regs = map_physmem(devfdt_get_addr(bus), sizeof(void *),
 				 MAP_NOCACHE);
 	priv->speed = CONFIG_SYS_OMAP24_I2C_SPEED;
 
diff --git a/drivers/i2c/rk_i2c.c b/drivers/i2c/rk_i2c.c
index 76f41f7..8bc045a 100644
--- a/drivers/i2c/rk_i2c.c
+++ b/drivers/i2c/rk_i2c.c
@@ -369,7 +369,7 @@
 {
 	struct rk_i2c *priv = dev_get_priv(bus);
 
-	priv->regs = (void *)dev_get_addr(bus);
+	priv->regs = (void *)devfdt_get_addr(bus);
 
 	return 0;
 }
diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
index 3c69dbf..06fe0a5 100644
--- a/drivers/i2c/s3c24x0_i2c.c
+++ b/drivers/i2c/s3c24x0_i2c.c
@@ -314,7 +314,7 @@
 
 	node = dev_of_offset(dev);
 
-	i2c_bus->regs = (struct s3c24x0_i2c *)dev_get_addr(dev);
+	i2c_bus->regs = (struct s3c24x0_i2c *)devfdt_get_addr(dev);
 
 	i2c_bus->id = pinmux_decode_periph_id(blob, node);
 
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c
index 4696a1a..f5978fd 100644
--- a/drivers/i2c/sandbox_i2c.c
+++ b/drivers/i2c/sandbox_i2c.c
@@ -9,7 +9,6 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
-#include <fdtdec.h>
 #include <i2c.h>
 #include <asm/test.h>
 #include <dm/lists.h>
diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c
index 898f12a..055f481 100644
--- a/drivers/i2c/tegra_i2c.c
+++ b/drivers/i2c/tegra_i2c.c
@@ -365,7 +365,7 @@
 
 	i2c_bus->id = dev->seq;
 	i2c_bus->type = dev_get_driver_data(dev);
-	i2c_bus->regs = (struct i2c_ctlr *)dev_get_addr(dev);
+	i2c_bus->regs = (struct i2c_ctlr *)devfdt_get_addr(dev);
 
 	ret = reset_get_by_name(dev, "i2c", &i2c_bus->reset_ctl);
 	if (ret) {
diff --git a/drivers/input/cros_ec_keyb.c b/drivers/input/cros_ec_keyb.c
index 00381dc..6fa35a6 100644
--- a/drivers/input/cros_ec_keyb.c
+++ b/drivers/input/cros_ec_keyb.c
@@ -10,7 +10,6 @@
 #include <cros_ec.h>
 #include <dm.h>
 #include <errno.h>
-#include <fdtdec.h>
 #include <input.h>
 #include <keyboard.h>
 #include <key_matrix.h>
@@ -161,15 +160,15 @@
  * @param config	Configuration data read from fdt
  * @return 0 if ok, -1 on error
  */
-static int cros_ec_keyb_decode_fdt(const void *blob, int node,
-				struct cros_ec_keyb_priv *config)
+static int cros_ec_keyb_decode_fdt(struct udevice *dev,
+				   struct cros_ec_keyb_priv *config)
 {
 	/*
 	 * Get keyboard rows and columns - at present we are limited to
 	 * 8 columns by the protocol (one byte per row scan)
 	 */
-	config->key_rows = fdtdec_get_int(blob, node, "keypad,num-rows", 0);
-	config->key_cols = fdtdec_get_int(blob, node, "keypad,num-columns", 0);
+	config->key_rows = dev_read_u32_default(dev, "keypad,num-rows", 0);
+	config->key_cols = dev_read_u32_default(dev, "keypad,num-columns", 0);
 	if (!config->key_rows || !config->key_cols ||
 			config->key_rows * config->key_cols / 8
 				> CROS_EC_KEYSCAN_COLS) {
@@ -177,8 +176,8 @@
 		      config->key_rows, config->key_cols);
 		return -1;
 	}
-	config->ghost_filter = fdtdec_get_bool(blob, node,
-					       "google,needs-ghost-filter");
+	config->ghost_filter = dev_read_bool(dev, "google,needs-ghost-filter");
+
 	return 0;
 }
 
@@ -188,12 +187,13 @@
 	struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct stdio_dev *sdev = &uc_priv->sdev;
 	struct input_config *input = &uc_priv->input;
-	const void *blob = gd->fdt_blob;
-	int node = dev_of_offset(dev);
 	int ret;
 
-	if (cros_ec_keyb_decode_fdt(blob, node, priv))
-		return -1;
+	ret = cros_ec_keyb_decode_fdt(dev, priv);
+	if (ret) {
+		debug("%s: Cannot decode node (ret=%d)\n", __func__, ret);
+		return -EINVAL;
+	}
 	input_set_delays(input, KBC_REPEAT_DELAY_MS, KBC_REPEAT_RATE_MS);
 	ret = key_matrix_init(&priv->matrix, priv->key_rows, priv->key_cols,
 			      priv->ghost_filter);
@@ -201,7 +201,7 @@
 		debug("%s: cannot init key matrix\n", __func__);
 		return ret;
 	}
-	ret = key_matrix_decode_fdt(&priv->matrix, gd->fdt_blob, node);
+	ret = key_matrix_decode_fdt(dev, &priv->matrix);
 	if (ret) {
 		debug("%s: Could not decode key matrix from fdt\n", __func__);
 		return ret;
diff --git a/drivers/input/key_matrix.c b/drivers/input/key_matrix.c
index 8867e49..cd5bce3 100644
--- a/drivers/input/key_matrix.c
+++ b/drivers/input/key_matrix.c
@@ -8,7 +8,7 @@
  */
 
 #include <common.h>
-#include <fdtdec.h>
+#include <dm.h>
 #include <key_matrix.h>
 #include <malloc.h>
 #include <linux/input.h>
@@ -105,7 +105,7 @@
  * @param pos           Returns position of map_keycode, if found, else -1
  * @return map  Pointer to allocated map
  */
-static uchar *create_keymap(struct key_matrix *config, u32 *data, int len,
+static uchar *create_keymap(struct key_matrix *config, const u32 *data, int len,
 			    int map_keycode, int *pos)
 {
 	uchar *map;
@@ -138,33 +138,32 @@
 	return map;
 }
 
-int key_matrix_decode_fdt(struct key_matrix *config, const void *blob, int node)
+int key_matrix_decode_fdt(struct udevice *dev, struct key_matrix *config)
 {
-	const struct fdt_property *prop;
+	const u32 *prop;
 	int proplen;
 	uchar *plain_keycode;
 
-	prop = fdt_get_property(blob, node, "linux,keymap", &proplen);
+	prop = dev_read_prop(dev, "linux,keymap", &proplen);
 	/* Basic keymap is required */
 	if (!prop) {
 		debug("%s: cannot find keycode-plain map\n", __func__);
 		return -1;
 	}
 
-	plain_keycode = create_keymap(config, (u32 *)prop->data,
-		proplen, KEY_FN, &config->fn_pos);
+	plain_keycode = create_keymap(config, prop, proplen, KEY_FN,
+				      &config->fn_pos);
 	config->plain_keycode = plain_keycode;
 	/* Conversion error -> fail */
 	if (!config->plain_keycode)
 		return -1;
 
-	prop = fdt_get_property(blob, node, "linux,fn-keymap", &proplen);
+	prop = dev_read_prop(dev, "linux,fn-keymap", &proplen);
 	/* fn keymap is optional */
 	if (!prop)
 		goto done;
 
-	config->fn_keycode = create_keymap(config, (u32 *)prop->data,
-		proplen, -1, NULL);
+	config->fn_keycode = create_keymap(config, prop, proplen, -1, NULL);
 	/* Conversion error -> fail */
 	if (!config->fn_keycode) {
 		free(plain_keycode);
diff --git a/drivers/input/tegra-kbc.c b/drivers/input/tegra-kbc.c
index d36f1a1..cb56957 100644
--- a/drivers/input/tegra-kbc.c
+++ b/drivers/input/tegra-kbc.c
@@ -290,10 +290,9 @@
 	struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct stdio_dev *sdev = &uc_priv->sdev;
 	struct input_config *input = &uc_priv->input;
-	int node = dev_of_offset(dev);
 	int ret;
 
-	priv->kbc = (struct kbc_tegra *)dev_get_addr(dev);
+	priv->kbc = (struct kbc_tegra *)devfdt_get_addr(dev);
 	if ((fdt_addr_t)priv->kbc == FDT_ADDR_T_NONE) {
 		debug("%s: No keyboard register found\n", __func__);
 		return -EINVAL;
@@ -306,7 +305,7 @@
 		debug("%s: Could not init key matrix: %d\n", __func__, ret);
 		return ret;
 	}
-	ret = key_matrix_decode_fdt(&priv->matrix, gd->fdt_blob, node);
+	ret = key_matrix_decode_fdt(dev, &priv->matrix);
 	if (ret) {
 		debug("%s: Could not decode key matrix from fdt: %d\n",
 		      __func__, ret);
diff --git a/drivers/led/led_bcm6328.c b/drivers/led/led_bcm6328.c
index ef8c6a7..5d545c5 100644
--- a/drivers/led/led_bcm6328.c
+++ b/drivers/led/led_bcm6328.c
@@ -158,7 +158,7 @@
 		void __iomem *regs;
 		u32 set_bits = 0;
 
-		addr = dev_get_addr_size_index(dev, 0, &size);
+		addr = devfdt_get_addr_size_index(dev, 0, &size);
 		if (addr == FDT_ADDR_T_NONE)
 			return -EINVAL;
 
@@ -185,7 +185,8 @@
 		struct bcm6328_led_priv *priv = dev_get_priv(dev);
 		unsigned int pin;
 
-		addr = dev_get_addr_size_index(dev_get_parent(dev), 0, &size);
+		addr = devfdt_get_addr_size_index(dev_get_parent(dev), 0,
+						  &size);
 		if (addr == FDT_ADDR_T_NONE)
 			return -EINVAL;
 
@@ -235,7 +236,7 @@
 
 		ret = device_bind_driver_to_node(parent, "bcm6328-led",
 						 fdt_get_name(blob, node, NULL),
-						 node, &dev);
+						 offset_to_ofnode(node), &dev);
 		if (ret)
 			return ret;
 
diff --git a/drivers/led/led_bcm6358.c b/drivers/led/led_bcm6358.c
index 11caecd..e8a3b64 100644
--- a/drivers/led/led_bcm6358.c
+++ b/drivers/led/led_bcm6358.c
@@ -124,7 +124,7 @@
 		unsigned int clk_div;
 		u32 set_bits = 0;
 
-		addr = dev_get_addr_size_index(dev, 0, &size);
+		addr = devfdt_get_addr_size_index(dev, 0, &size);
 		if (addr == FDT_ADDR_T_NONE)
 			return -EINVAL;
 
@@ -158,7 +158,8 @@
 		struct bcm6358_led_priv *priv = dev_get_priv(dev);
 		unsigned int pin;
 
-		addr = dev_get_addr_size_index(dev_get_parent(dev), 0, &size);
+		addr = devfdt_get_addr_size_index(dev_get_parent(dev), 0,
+						  &size);
 		if (addr == FDT_ADDR_T_NONE)
 			return -EINVAL;
 
@@ -200,7 +201,7 @@
 
 		ret = device_bind_driver_to_node(parent, "bcm6358-led",
 						 fdt_get_name(blob, node, NULL),
-						 node, &dev);
+						 offset_to_ofnode(node), &dev);
 		if (ret)
 			return ret;
 
diff --git a/drivers/led/led_gpio.c b/drivers/led/led_gpio.c
index 4106ecb..9976635 100644
--- a/drivers/led/led_gpio.c
+++ b/drivers/led/led_gpio.c
@@ -85,25 +85,22 @@
 
 static int led_gpio_bind(struct udevice *parent)
 {
-	const void *blob = gd->fdt_blob;
 	struct udevice *dev;
-	int node;
+	ofnode node;
 	int ret;
 
-	for (node = fdt_first_subnode(blob, dev_of_offset(parent));
-	     node > 0;
-	     node = fdt_next_subnode(blob, node)) {
+	dev_for_each_subnode(node, parent) {
 		struct led_uc_plat *uc_plat;
 		const char *label;
 
-		label = fdt_getprop(blob, node, "label", NULL);
+		label = ofnode_read_string(node, "label");
 		if (!label) {
 			debug("%s: node %s has no label\n", __func__,
-			      fdt_get_name(blob, node, NULL));
+			      ofnode_get_name(node));
 			return -EINVAL;
 		}
 		ret = device_bind_driver_to_node(parent, "gpio_led",
-						 fdt_get_name(blob, node, NULL),
+						 ofnode_get_name(node),
 						 node, &dev);
 		if (ret)
 			return ret;
diff --git a/drivers/mailbox/mailbox-uclass.c b/drivers/mailbox/mailbox-uclass.c
index 38448de..822ae5b 100644
--- a/drivers/mailbox/mailbox-uclass.c
+++ b/drivers/mailbox/mailbox-uclass.c
@@ -6,7 +6,6 @@
 
 #include <common.h>
 #include <dm.h>
-#include <fdtdec.h>
 #include <mailbox.h>
 #include <mailbox-uclass.h>
 
@@ -18,7 +17,7 @@
 }
 
 static int mbox_of_xlate_default(struct mbox_chan *chan,
-				 struct fdtdec_phandle_args *args)
+				 struct ofnode_phandle_args *args)
 {
 	debug("%s(chan=%p)\n", __func__, chan);
 
@@ -34,24 +33,22 @@
 
 int mbox_get_by_index(struct udevice *dev, int index, struct mbox_chan *chan)
 {
-	struct fdtdec_phandle_args args;
+	struct ofnode_phandle_args args;
 	int ret;
 	struct udevice *dev_mbox;
 	struct mbox_ops *ops;
 
 	debug("%s(dev=%p, index=%d, chan=%p)\n", __func__, dev, index, chan);
 
-	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
-					     "mboxes", "#mbox-cells", 0,
-					     index, &args);
+	ret = dev_read_phandle_with_args(dev, "mboxes", "#mbox-cells", 0, index,
+					 &args);
 	if (ret) {
-		debug("%s: fdtdec_parse_phandle_with_args failed: %d\n",
-		      __func__, ret);
+		debug("%s: dev_read_phandle_with_args failed: %d\n", __func__,
+		      ret);
 		return ret;
 	}
 
-	ret = uclass_get_device_by_of_offset(UCLASS_MAILBOX, args.node,
-					     &dev_mbox);
+	ret = uclass_get_device_by_ofnode(UCLASS_MAILBOX, args.node, &dev_mbox);
 	if (ret) {
 		debug("%s: uclass_get_device_by_of_offset failed: %d\n",
 		      __func__, ret);
@@ -85,8 +82,7 @@
 
 	debug("%s(dev=%p, name=%s, chan=%p)\n", __func__, dev, name, chan);
 
-	index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
-				      "mbox-names", name);
+	index = dev_read_stringlist_search(dev, "mbox-names", name);
 	if (index < 0) {
 		debug("fdt_stringlist_search() failed: %d\n", index);
 		return index;
diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index 3d0362d..bd2ec41 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -72,7 +72,7 @@
 }
 
 static int tegra_hsp_of_xlate(struct mbox_chan *chan,
-			      struct fdtdec_phandle_args *args)
+			      struct ofnode_phandle_args *args)
 {
 	debug("%s(chan=%p)\n", __func__, chan);
 
@@ -153,7 +153,7 @@
 
 	debug("%s(dev=%p)\n", __func__, dev);
 
-	thsp->regs = dev_get_addr(dev);
+	thsp->regs = devfdt_get_addr(dev);
 	if (thsp->regs == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
diff --git a/drivers/misc/altera_sysid.c b/drivers/misc/altera_sysid.c
index ed6d462..87aadaf 100644
--- a/drivers/misc/altera_sysid.c
+++ b/drivers/misc/altera_sysid.c
@@ -74,7 +74,7 @@
 {
 	struct altera_sysid_platdata *plat = dev_get_platdata(dev);
 
-	plat->regs = map_physmem(dev_get_addr(dev),
+	plat->regs = map_physmem(devfdt_get_addr(dev),
 				 sizeof(struct altera_sysid_regs),
 				 MAP_NOCACHE);
 
diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c
index 3d449b2..feaa5d8 100644
--- a/drivers/misc/cros_ec.c
+++ b/drivers/misc/cros_ec.c
@@ -26,6 +26,7 @@
 #include <asm/io.h>
 #include <asm-generic/gpio.h>
 #include <dm/device-internal.h>
+#include <dm/of_extra.h>
 #include <dm/uclass-internal.h>
 
 #ifdef DEBUG_TRACE
@@ -304,8 +305,7 @@
 				NULL, 0, &din, din_len);
 	}
 
-	debug("%s: len=%d, dinp=%p, *dinp=%p\n", __func__, len, dinp,
-	      dinp ? *dinp : NULL);
+	debug("%s: len=%d, din=%p\n", __func__, len, din);
 	if (dinp) {
 		/* If we have any data to return, it must be 64bit-aligned */
 		assert(len <= 0 || !((uintptr_t)din & 7));
@@ -997,15 +997,12 @@
 int cros_ec_register(struct udevice *dev)
 {
 	struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
-	const void *blob = gd->fdt_blob;
-	int node = dev_of_offset(dev);
 	char id[MSG_BYTES];
 
 	cdev->dev = dev;
 	gpio_request_by_name(dev, "ec-interrupt", 0, &cdev->ec_int,
 			     GPIOD_IS_IN);
-	cdev->optimise_flash_write = fdtdec_get_bool(blob, node,
-						     "optimise-flash-write");
+	cdev->optimise_flash_write = dev_read_bool(dev, "optimise-flash-write");
 
 	if (cros_ec_check_version(cdev)) {
 		debug("%s: Could not detect CROS-EC version\n", __func__);
@@ -1024,28 +1021,26 @@
 	return 0;
 }
 
-int cros_ec_decode_ec_flash(const void *blob, int node,
-			    struct fdt_cros_ec *config)
+int cros_ec_decode_ec_flash(struct udevice *dev, struct fdt_cros_ec *config)
 {
-	int flash_node;
+	ofnode flash_node, node;
 
-	flash_node = fdt_subnode_offset(blob, node, "flash");
-	if (flash_node < 0) {
+	flash_node = dev_read_subnode(dev, "flash");
+	if (!ofnode_valid(flash_node)) {
 		debug("Failed to find flash node\n");
 		return -1;
 	}
 
-	if (fdtdec_read_fmap_entry(blob, flash_node, "flash",
-				   &config->flash)) {
-		debug("Failed to decode flash node in chrome-ec'\n");
+	if (of_read_fmap_entry(flash_node, "flash", &config->flash)) {
+		debug("Failed to decode flash node in chrome-ec\n");
 		return -1;
 	}
 
-	config->flash_erase_value = fdtdec_get_int(blob, flash_node,
-						    "erase-value", -1);
-	for (node = fdt_first_subnode(blob, flash_node); node >= 0;
-	     node = fdt_next_subnode(blob, node)) {
-		const char *name = fdt_get_name(blob, node, NULL);
+	config->flash_erase_value = ofnode_read_s32_default(flash_node,
+							    "erase-value", -1);
+	for (node = ofnode_first_subnode(flash_node); ofnode_valid(node);
+	     node = ofnode_next_subnode(node)) {
+		const char *name = ofnode_get_name(node);
 		enum ec_flash_region region;
 
 		if (0 == strcmp(name, "ro")) {
@@ -1059,8 +1054,7 @@
 			return -1;
 		}
 
-		if (fdtdec_read_fmap_entry(blob, node, "reg",
-					   &config->region[region])) {
+		if (of_read_fmap_entry(node, "reg", &config->region[region])) {
 			debug("Failed to decode flash region in chrome-ec'\n");
 			return -1;
 		}
diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c
index 848c67b..c96e26e 100644
--- a/drivers/misc/cros_ec_sandbox.c
+++ b/drivers/misc/cros_ec_sandbox.c
@@ -188,18 +188,16 @@
  * RR=Row CC=Column KKKK=Key Code
  *
  * @param ec	Current emulated EC state
- * @param blob	Device tree blob containing keyscan information
  * @param node	Keyboard node of device tree containing keyscan information
  * @return 0 if ok, -1 on error
  */
-static int keyscan_read_fdt_matrix(struct ec_state *ec, const void *blob,
-				   int node)
+static int keyscan_read_fdt_matrix(struct ec_state *ec, ofnode node)
 {
 	const u32 *cell;
 	int upto;
 	int len;
 
-	cell = fdt_getprop(blob, node, "linux,keymap", &len);
+	cell = ofnode_read_prop(node, "linux,keymap", &len);
 	ec->matrix_count = len / 4;
 	ec->matrix = calloc(ec->matrix_count, sizeof(*ec->matrix));
 	if (!ec->matrix) {
@@ -516,28 +514,29 @@
 {
 	struct ec_state *ec = dev->priv;
 	struct cros_ec_dev *cdev = dev->uclass_priv;
-	const void *blob = gd->fdt_blob;
 	struct udevice *keyb_dev;
-	int node;
+	ofnode node;
 	int err;
 
 	memcpy(ec, &s_state, sizeof(*ec));
-	err = cros_ec_decode_ec_flash(blob, dev_of_offset(dev), &ec->ec_config);
-	if (err)
+	err = cros_ec_decode_ec_flash(dev, &ec->ec_config);
+	if (err) {
+		debug("%s: Cannot device EC flash\n", __func__);
 		return err;
+	}
 
-	node = -1;
+	node = ofnode_null();
 	for (device_find_first_child(dev, &keyb_dev);
 	     keyb_dev;
 	     device_find_next_child(&keyb_dev)) {
 		if (device_get_uclass_id(keyb_dev) == UCLASS_KEYBOARD) {
-			node = dev_of_offset(keyb_dev);
+			node = dev_ofnode(keyb_dev);
 			break;
 		}
 	}
-	if (node < 0) {
+	if (!ofnode_valid(node)) {
 		debug("%s: No cros_ec keyboard found\n", __func__);
-	} else if (keyscan_read_fdt_matrix(ec, blob, node)) {
+	} else if (keyscan_read_fdt_matrix(ec, node)) {
 		debug("%s: Could not read key matrix\n", __func__);
 		return -1;
 	}
diff --git a/drivers/misc/i2c_eeprom_emul.c b/drivers/misc/i2c_eeprom_emul.c
index 02de8d7..52aa7d6 100644
--- a/drivers/misc/i2c_eeprom_emul.c
+++ b/drivers/misc/i2c_eeprom_emul.c
@@ -9,7 +9,6 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
-#include <fdtdec.h>
 #include <i2c.h>
 #include <malloc.h>
 #include <asm/test.h>
@@ -115,10 +114,8 @@
 {
 	struct sandbox_i2c_flash_plat_data *plat = dev_get_platdata(dev);
 
-	plat->size = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-				    "sandbox,size", 32);
-	plat->filename = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
-				     "sandbox,filename", NULL);
+	plat->size = dev_read_u32_default(dev, "sandbox,size", 32);
+	plat->filename = dev_read_string(dev, "sandbox,filename");
 	if (!plat->filename) {
 		debug("%s: No filename for device '%s'\n", __func__,
 		      dev->name);
diff --git a/drivers/misc/tegra186_bpmp.c b/drivers/misc/tegra186_bpmp.c
index bd8b960..d61bacf 100644
--- a/drivers/misc/tegra186_bpmp.c
+++ b/drivers/misc/tegra186_bpmp.c
@@ -112,19 +112,19 @@
 	debug("%s(dev=%p)\n", __func__, dev);
 
 	ret = device_bind_driver_to_node(dev, "tegra186_clk", "tegra186_clk",
-					 dev_of_offset(dev), &child);
+					 dev_ofnode(dev), &child);
 	if (ret)
 		return ret;
 
 	ret = device_bind_driver_to_node(dev, "tegra186_reset",
-					 "tegra186_reset", dev_of_offset(dev),
+					 "tegra186_reset", dev_ofnode(dev),
 					 &child);
 	if (ret)
 		return ret;
 
 	ret = device_bind_driver_to_node(dev, "tegra186_power_domain",
 					 "tegra186_power_domain",
-					 dev_of_offset(dev), &child);
+					 dev_ofnode(dev), &child);
 	if (ret)
 		return ret;
 
diff --git a/drivers/misc/tegra_car.c b/drivers/misc/tegra_car.c
index 5db3c37..93639e1 100644
--- a/drivers/misc/tegra_car.c
+++ b/drivers/misc/tegra_car.c
@@ -22,12 +22,12 @@
 	debug("%s(dev=%p)\n", __func__, dev);
 
 	ret = device_bind_driver_to_node(dev, "tegra_car_clk", "tegra_car_clk",
-					 dev_of_offset(dev), &child);
+					 dev_ofnode(dev), &child);
 	if (ret)
 		return ret;
 
 	ret = device_bind_driver_to_node(dev, "tegra_car_reset",
-					 "tegra_car_reset", dev_of_offset(dev),
+					 "tegra_car_reset", dev_ofnode(dev),
 					 &child);
 	if (ret)
 		return ret;
diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c
index 86e36a9..c19a1f3 100644
--- a/drivers/mmc/atmel_sdhci.c
+++ b/drivers/mmc/atmel_sdhci.c
@@ -72,7 +72,7 @@
 		return ret;
 
 	host->name = dev->name;
-	host->ioaddr = (void *)dev_get_addr(dev);
+	host->ioaddr = (void *)devfdt_get_addr(dev);
 
 	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
 	host->bus_width	= fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c
index b6e2fc6..3157354 100644
--- a/drivers/mmc/bcm2835_sdhci.c
+++ b/drivers/mmc/bcm2835_sdhci.c
@@ -179,7 +179,7 @@
 	int emmc_freq;
 	int ret;
 
-	base = dev_get_addr(dev);
+	base = devfdt_get_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index f3c6358..5ee712f 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -963,7 +963,7 @@
 	unsigned int val;
 	int ret;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
@@ -983,15 +983,15 @@
 	 } else {
 		priv->non_removable = 0;
 #ifdef CONFIG_DM_GPIO
-		gpio_request_by_name_nodev(fdt, node, "cd-gpios", 0,
-					   &priv->cd_gpio, GPIOD_IS_IN);
+		gpio_request_by_name_nodev(offset_to_ofnode(node), "cd-gpios",
+					   0, &priv->cd_gpio, GPIOD_IS_IN);
 #endif
 	}
 
 	priv->wp_enable = 1;
 
 #ifdef CONFIG_DM_GPIO
-	ret = gpio_request_by_name_nodev(fdt, node, "wp-gpios", 0,
+	ret = gpio_request_by_name_nodev(offset_to_ofnode(node), "wp-gpios", 0,
 					 &priv->wp_gpio, GPIOD_IS_IN);
 	if (ret)
 		priv->wp_enable = 0;
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index c25d9ed..e9f061e 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -11,6 +11,7 @@
 
 #include <common.h>
 #include <clk.h>
+#include <dm.h>
 #include <mmc.h>
 #include <part.h>
 #include <malloc.h>
@@ -19,7 +20,6 @@
 #include <asm/byteorder.h>
 #include <asm/arch/clk.h>
 #include <asm/arch/hardware.h>
-#include <dm/device.h>
 #include "atmel_mci.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -576,7 +576,7 @@
 	if (ret)
 		return ret;
 
-	priv->mci = (struct atmel_mci *)dev_get_addr_ptr(dev);
+	priv->mci = (struct atmel_mci *)devfdt_get_addr_ptr(dev);
 
 	atmel_mci_setup_cfg(priv);
 
diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c
index 8e28ab7..4652fab 100644
--- a/drivers/mmc/meson_gx_mmc.c
+++ b/drivers/mmc/meson_gx_mmc.c
@@ -5,12 +5,12 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <fdtdec.h>
 #include <malloc.h>
 #include <mmc.h>
 #include <asm/io.h>
 #include <asm/arch/sd_emmc.h>
-#include <dm/device.h>
 #include <linux/log2.h>
 
 static inline void *get_regbase(const struct mmc *mmc)
@@ -221,7 +221,7 @@
 	struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
@@ -244,7 +244,7 @@
 			MMC_MODE_HS_52MHz | MMC_MODE_HS;
 	cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV);
 	cfg->f_max = 100000000; /* 100 MHz */
-	cfg->b_max = 256; /* max 256 blocks */
+	cfg->b_max = 511; /* max 512 - 1 blocks */
 	cfg->name = dev->name;
 
 	mmc->priv = pdata;
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 9c07871..4dc3925 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -196,9 +196,14 @@
 	struct udevice *bdev;
 	int ret, devnum = -1;
 
+#ifdef CONFIG_DM_MMC_OPS
+	if (!mmc_get_ops(dev))
+		return -ENOSYS;
+#endif
 #ifndef CONFIG_SPL_BUILD
 	/* Use the fixed index with aliase node's index */
-	fdtdec_get_alias_seq(gd->fdt_blob, "mmc", dev->of_offset, &devnum);
+	ret = dev_read_alias_seq(dev, &devnum);
+	debug("%s: alias ret=%d, devnum=%d\n", __func__, ret, devnum);
 #endif
 
 	ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC,
@@ -256,13 +261,18 @@
 
 static int mmc_blk_probe(struct udevice *dev)
 {
-	struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
-	int dev_num = block_dev->devnum;
-	struct mmc *mmc = find_mmc_device(dev_num);
+	struct udevice *mmc_dev = dev_get_parent(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc_dev);
+	struct mmc *mmc = upriv->mmc;
+	int ret;
 
-	if (!mmc)
-		return -ENODEV;
-	return mmc_init(mmc);
+	ret = mmc_init(mmc);
+	if (ret) {
+		debug("%s: mmc_init() failed (err=%d)\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
 }
 
 static const struct blk_ops mmc_blk_ops = {
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 72fc177..3cdf6a4 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1608,17 +1608,17 @@
 	return 0;
 }
 
+#ifndef CONFIG_DM_MMC
 /* board-specific MMC power initializations. */
 __weak void board_mmc_power_init(void)
 {
 }
+#endif
 
 static int mmc_power_init(struct mmc *mmc)
 {
-	board_mmc_power_init();
-
-#if defined(CONFIG_DM_MMC) && defined(CONFIG_DM_REGULATOR) && \
-	!defined(CONFIG_SPL_BUILD)
+#if defined(CONFIG_DM_MMC)
+#if defined(CONFIG_DM_REGULATOR) && !defined(CONFIG_SPL_BUILD)
 	struct udevice *vmmc_supply;
 	int ret;
 
@@ -1635,6 +1635,13 @@
 		return ret;
 	}
 #endif
+#else /* !CONFIG_DM_MMC */
+	/*
+	 * Driver model should use a regulator, as above, rather than calling
+	 * out to board code.
+	 */
+	board_mmc_power_init();
+#endif
 	return 0;
 }
 
diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c
index 7a7e67f..9117ab6 100644
--- a/drivers/mmc/msm_sdhci.c
+++ b/drivers/mmc/msm_sdhci.c
@@ -171,7 +171,7 @@
 	int node = dev_of_offset(dev);
 
 	host->name = strdup(dev->name);
-	host->ioaddr = (void *)dev_get_addr(dev);
+	host->ioaddr = (void *)devfdt_get_addr(dev);
 	host->bus_width = fdtdec_get_int(gd->fdt_blob, node, "bus-width", 4);
 	host->index = fdtdec_get_uint(gd->fdt_blob, node, "index", 0);
 	priv->base = (void *)fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 0b21ec6..bb10caa 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -808,7 +808,8 @@
 	int node = dev_of_offset(dev);
 	int val;
 
-	plat->base_addr = map_physmem(dev_get_addr(dev), sizeof(struct hsmmc *),
+	plat->base_addr = map_physmem(devfdt_get_addr(dev),
+				      sizeof(struct hsmmc *),
 				      MAP_NOCACHE) + data->reg_offset;
 
 	cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
diff --git a/drivers/mmc/pic32_sdhci.c b/drivers/mmc/pic32_sdhci.c
index 9d8a392..212e22e 100644
--- a/drivers/mmc/pic32_sdhci.c
+++ b/drivers/mmc/pic32_sdhci.c
@@ -7,8 +7,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm.h>
 #include <common.h>
+#include <dm.h>
 #include <sdhci.h>
 #include <linux/errno.h>
 #include <mach/pic32.h>
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index 2885ef2..25a21e2 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -58,7 +58,7 @@
 	struct dwmci_host *host = &priv->host;
 
 	host->name = dev->name;
-	host->ioaddr = (void *)dev_get_addr(dev);
+	host->ioaddr = (void *)devfdt_get_addr(dev);
 	host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 					"bus-width", 4);
 	host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk;
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index bdde831..8985878 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -83,7 +83,7 @@
 	struct sdhci_host *host = dev_get_priv(dev);
 
 	host->name = dev->name;
-	host->ioaddr = dev_get_addr_ptr(dev);
+	host->ioaddr = devfdt_get_addr_ptr(dev);
 #endif
 
 	return 0;
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
index 640ea02..62817a0 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -184,10 +184,10 @@
 	}
 	host->ioaddr = (void *)base;
 
-	gpio_request_by_name_nodev(blob, node, "pwr-gpios", 0, &host->pwr_gpio,
-				   GPIOD_IS_OUT);
-	gpio_request_by_name_nodev(blob, node, "cd-gpios", 0, &host->cd_gpio,
-				   GPIOD_IS_IN);
+	gpio_request_by_name_nodev(offset_to_ofnode(node), "pwr-gpios", 0,
+				   &host->pwr_gpio, GPIOD_IS_OUT);
+	gpio_request_by_name_nodev(offset_to_ofnode(node), "cd-gpios", 0,
+				   &host->cd_gpio, GPIOD_IS_IN);
 
 	return 0;
 }
diff --git a/drivers/mmc/sdhci-cadence.c b/drivers/mmc/sdhci-cadence.c
index dc86d10..4bd2623 100644
--- a/drivers/mmc/sdhci-cadence.c
+++ b/drivers/mmc/sdhci-cadence.c
@@ -6,10 +6,10 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/sizes.h>
-#include <dm/device.h>
 #include <libfdt.h>
 #include <mmc.h>
 #include <sdhci.h>
@@ -127,7 +127,7 @@
 	fdt_addr_t base;
 	int ret;
 
-	base = dev_get_addr(dev);
+	base = devfdt_get_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
@@ -139,7 +139,7 @@
 	host->ioaddr = plat->hrs_addr + SDHCI_CDNS_SRS_BASE;
 	host->quirks |= SDHCI_QUIRK_WAIT_SEND_CMD;
 
-	ret = sdhci_cdns_phy_init(plat, gd->fdt_blob, dev->of_offset);
+	ret = sdhci_cdns_phy_init(plat, gd->fdt_blob, dev_of_offset(dev));
 	if (ret)
 		return ret;
 
diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c
index d0c3c51..759686c 100644
--- a/drivers/mmc/socfpga_dw_mmc.c
+++ b/drivers/mmc/socfpga_dw_mmc.c
@@ -78,7 +78,7 @@
 	}
 
 	host->name = dev->name;
-	host->ioaddr = (void *)dev_get_addr(dev);
+	host->ioaddr = (void *)devfdt_get_addr(dev);
 	host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 					"bus-width", 4);
 	host->clksel = socfpga_dwmci_clksel;
diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c
index 2a07082..f85f6b4 100644
--- a/drivers/mmc/sti_sdhci.c
+++ b/drivers/mmc/sti_sdhci.c
@@ -108,7 +108,7 @@
 	struct sdhci_host *host = dev_get_priv(dev);
 
 	host->name = strdup(dev->name);
-	host->ioaddr = (void *)dev_get_addr(dev);
+	host->ioaddr = (void *)devfdt_get_addr(dev);
 
 	host->bus_width = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 					 "bus-width", 4);
diff --git a/drivers/mmc/tangier_sdhci.c b/drivers/mmc/tangier_sdhci.c
index 77b18e7..bafe85b 100644
--- a/drivers/mmc/tangier_sdhci.c
+++ b/drivers/mmc/tangier_sdhci.c
@@ -36,7 +36,7 @@
 	fdt_addr_t base;
 	int ret;
 
-	base = dev_get_addr(dev);
+	base = devfdt_get_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 6c6affb..338e42b 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -9,7 +9,7 @@
 
 #include <bouncebuf.h>
 #include <common.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <errno.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
@@ -18,6 +18,11 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+struct tegra_mmc_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
 struct tegra_mmc_priv {
 	struct tegra_mmc *reg;
 	struct reset_ctl reset_ctl;
@@ -27,8 +32,6 @@
 	struct gpio_desc wp_gpio;	/* Write Protect GPIO */
 	unsigned int version;	/* SDHCI spec. version */
 	unsigned int clock;	/* Current clock (MHz) */
-	struct mmc_config cfg;	/* mmc configuration */
-	struct mmc *mmc;
 };
 
 static void tegra_mmc_set_power(struct tegra_mmc_priv *priv,
@@ -151,11 +154,11 @@
 	return 0;
 }
 
-static int tegra_mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd,
+static int tegra_mmc_send_cmd_bounced(struct udevice *dev, struct mmc_cmd *cmd,
 				      struct mmc_data *data,
 				      struct bounce_buffer *bbstate)
 {
-	struct tegra_mmc_priv *priv = mmc->priv;
+	struct tegra_mmc_priv *priv = dev_get_priv(dev);
 	int flags, i;
 	int result;
 	unsigned int mask = 0;
@@ -324,7 +327,7 @@
 	return 0;
 }
 
-static int tegra_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+static int tegra_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 			      struct mmc_data *data)
 {
 	void *buf;
@@ -346,7 +349,7 @@
 		bounce_buffer_start(&bbstate, buf, len, bbflags);
 	}
 
-	ret = tegra_mmc_send_cmd_bounced(mmc, cmd, data, &bbstate);
+	ret = tegra_mmc_send_cmd_bounced(dev, cmd, data, &bbstate);
 
 	if (data)
 		bounce_buffer_stop(&bbstate);
@@ -408,9 +411,10 @@
 	priv->clock = clock;
 }
 
-static int tegra_mmc_set_ios(struct mmc *mmc)
+static int tegra_mmc_set_ios(struct udevice *dev)
 {
-	struct tegra_mmc_priv *priv = mmc->priv;
+	struct tegra_mmc_priv *priv = dev_get_priv(dev);
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
 	unsigned char ctrl;
 	debug(" mmc_set_ios called\n");
 
@@ -505,9 +509,10 @@
 	tegra_mmc_pad_init(priv);
 }
 
-static int tegra_mmc_init(struct mmc *mmc)
+static int tegra_mmc_init(struct udevice *dev)
 {
-	struct tegra_mmc_priv *priv = mmc->priv;
+	struct tegra_mmc_priv *priv = dev_get_priv(dev);
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
 	unsigned int mask;
 	debug(" tegra_mmc_init called\n");
 
@@ -566,9 +571,9 @@
 	return 0;
 }
 
-static int tegra_mmc_getcd(struct mmc *mmc)
+static int tegra_mmc_getcd(struct udevice *dev)
 {
-	struct tegra_mmc_priv *priv = mmc->priv;
+	struct tegra_mmc_priv *priv = dev_get_priv(dev);
 
 	debug("tegra_mmc_getcd called\n");
 
@@ -578,32 +583,32 @@
 	return 1;
 }
 
-static const struct mmc_ops tegra_mmc_ops = {
+static const struct dm_mmc_ops tegra_mmc_ops = {
 	.send_cmd	= tegra_mmc_send_cmd,
 	.set_ios	= tegra_mmc_set_ios,
-	.init		= tegra_mmc_init,
-	.getcd		= tegra_mmc_getcd,
+	.get_cd		= tegra_mmc_getcd,
 };
 
 static int tegra_mmc_probe(struct udevice *dev)
 {
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct tegra_mmc_plat *plat = dev_get_platdata(dev);
 	struct tegra_mmc_priv *priv = dev_get_priv(dev);
+	struct mmc_config *cfg = &plat->cfg;
 	int bus_width, ret;
 
-	priv->cfg.name = "Tegra SD/MMC";
-	priv->cfg.ops = &tegra_mmc_ops;
+	cfg->name = dev->name;
 
 	bus_width = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 				   "bus-width", 1);
 
-	priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
-	priv->cfg.host_caps = 0;
+	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+	cfg->host_caps = 0;
 	if (bus_width == 8)
-		priv->cfg.host_caps |= MMC_MODE_8BIT;
+		cfg->host_caps |= MMC_MODE_8BIT;
 	if (bus_width >= 4)
-		priv->cfg.host_caps |= MMC_MODE_4BIT;
-	priv->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
+		cfg->host_caps |= MMC_MODE_4BIT;
+	cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
 
 	/*
 	 * min freq is for card identification, and is the highest
@@ -611,12 +616,12 @@
 	 * max freq is highest HS eMMC clock as per the SD/MMC spec
 	 *  (actually 52MHz)
 	 */
-	priv->cfg.f_min = 375000;
-	priv->cfg.f_max = 48000000;
+	cfg->f_min = 375000;
+	cfg->f_max = 48000000;
 
-	priv->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
-	priv->reg = (void *)dev_get_addr(dev);
+	priv->reg = (void *)devfdt_get_addr(dev);
 
 	ret = reset_get_by_name(dev, "sdhci", &priv->reset_ctl);
 	if (ret) {
@@ -652,14 +657,16 @@
 	if (dm_gpio_is_valid(&priv->pwr_gpio))
 		dm_gpio_set_value(&priv->pwr_gpio, 1);
 
-	priv->mmc = mmc_create(&priv->cfg, priv);
-	if (priv->mmc == NULL)
-		return -1;
+	upriv->mmc = &plat->mmc;
 
-	priv->mmc->dev = dev;
-	upriv->mmc = priv->mmc;
+	return tegra_mmc_init(dev);
+}
 
-	return 0;
+static int tegra_mmc_bind(struct udevice *dev)
+{
+	struct tegra_mmc_plat *plat = dev_get_platdata(dev);
+
+	return mmc_bind(dev, &plat->mmc, &plat->cfg);
 }
 
 static const struct udevice_id tegra_mmc_ids[] = {
@@ -676,6 +683,9 @@
 	.name		= "tegra_mmc",
 	.id		= UCLASS_MMC,
 	.of_match	= tegra_mmc_ids,
+	.bind		= tegra_mmc_bind,
 	.probe		= tegra_mmc_probe,
+	.ops		= &tegra_mmc_ops,
+	.platdata_auto_alloc_size = sizeof(struct tegra_mmc_plat),
 	.priv_auto_alloc_size = sizeof(struct tegra_mmc_priv),
 };
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c
index 7f20ef1..3c462bd 100644
--- a/drivers/mmc/uniphier-sd.c
+++ b/drivers/mmc/uniphier-sd.c
@@ -9,7 +9,7 @@
 #include <clk.h>
 #include <fdtdec.h>
 #include <mmc.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <linux/compat.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
@@ -673,7 +673,7 @@
 	struct clk clk;
 	int ret;
 
-	base = dev_get_addr(dev);
+	base = devfdt_get_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/mmc/xenon_sdhci.c b/drivers/mmc/xenon_sdhci.c
index 2a0d8b4..2b7cb7f 100644
--- a/drivers/mmc/xenon_sdhci.c
+++ b/drivers/mmc/xenon_sdhci.c
@@ -452,10 +452,10 @@
 	const char *name;
 
 	host->name = dev->name;
-	host->ioaddr = (void *)dev_get_addr(dev);
+	host->ioaddr = (void *)devfdt_get_addr(dev);
 
-	if (of_device_is_compatible(dev, "marvell,armada-3700-sdhci"))
-		priv->pad_ctrl_reg = (void *)dev_get_addr_index(dev, 1);
+	if (device_is_compatible(dev, "marvell,armada-3700-sdhci"))
+		priv->pad_ctrl_reg = (void *)devfdt_get_addr_index(dev, 1);
 
 	name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "marvell,pad-type",
 			   NULL);
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 28cedf0..0fddb42 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -81,9 +81,9 @@
 	struct sdhci_host *host = dev_get_priv(dev);
 
 	host->name = dev->name;
-	host->ioaddr = (void *)dev_get_addr(dev);
+	host->ioaddr = (void *)devfdt_get_addr(dev);
 
-	plat->f_max = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+	plat->f_max = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 				"max-frequency", CONFIG_ZYNQ_SDHCI_MAX_FREQ);
 
 	return 0;
diff --git a/drivers/mtd/altera_qspi.c b/drivers/mtd/altera_qspi.c
index e04964b..fb33cef 100644
--- a/drivers/mtd/altera_qspi.c
+++ b/drivers/mtd/altera_qspi.c
@@ -362,7 +362,7 @@
 	 * match with reg-names.
 	 */
 	parent = fdt_parent_offset(blob, node);
-	of_bus_default_count_cells(blob, parent, &addrc, &sizec);
+	fdt_support_default_count_cells(blob, parent, &addrc, &sizec);
 	list = fdt_getprop(blob, node, "reg-names", &len);
 	if (!list)
 		return -ENOENT;
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index d440f5c..048a517 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -2448,7 +2448,7 @@
 	int len, idx;
 
 	parent = fdt_parent_offset(blob, node);
-	of_bus_default_count_cells(blob, parent, &addrc, &sizec);
+	fdt_support_default_count_cells(blob, parent, &addrc, &sizec);
 	/* decode regs, there may be multiple reg tuples. */
 	cell = fdt_getprop(blob, node, "reg", &len);
 	if (!cell)
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index c4e2cd7..8bc3828 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -1663,7 +1663,7 @@
 			chip->sels[i].rb.type = RB_NATIVE;
 			chip->sels[i].rb.info.nativeid = tmp;
 		} else {
-			ret = gpio_request_by_name_nodev(blob, node,
+			ret = gpio_request_by_name_nodev(offset_to_ofnode(node),
 						"rb-gpios", i,
 						&chip->sels[i].rb.info.gpio,
 						GPIOD_IS_IN);
diff --git a/drivers/mtd/nand/tegra_nand.c b/drivers/mtd/nand/tegra_nand.c
index 5c9b485..c03c9cb 100644
--- a/drivers/mtd/nand/tegra_nand.c
+++ b/drivers/mtd/nand/tegra_nand.c
@@ -894,8 +894,8 @@
 	config->reg = (struct nand_ctlr *)fdtdec_get_addr(blob, node, "reg");
 	config->enabled = fdtdec_get_is_enabled(blob, node);
 	config->width = fdtdec_get_int(blob, node, "nvidia,nand-width", 8);
-	err = gpio_request_by_name_nodev(blob, node, "nvidia,wp-gpios", 0,
-				 &config->wp_gpio, GPIOD_IS_OUT);
+	err = gpio_request_by_name_nodev(offset_to_ofnode(node),
+			"nvidia,wp-gpios", 0, &config->wp_gpio, GPIOD_IS_OUT);
 	if (err)
 		return err;
 	err = fdtdec_get_int_array(blob, node, "nvidia,timing",
diff --git a/drivers/mtd/pic32_flash.c b/drivers/mtd/pic32_flash.c
index 8ed7874..e1a8d3b 100644
--- a/drivers/mtd/pic32_flash.c
+++ b/drivers/mtd/pic32_flash.c
@@ -384,7 +384,7 @@
 	 * match with reg-names.
 	 */
 	parent = fdt_parent_offset(blob, node);
-	of_bus_default_count_cells(blob, parent, &addrc, &sizec);
+	fdt_support_default_count_cells(blob, parent, &addrc, &sizec);
 	list = fdt_getprop(blob, node, "reg-names", &len);
 	if (!list)
 		return -ENOENT;
diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c
index a53f4eb..1ba6815 100644
--- a/drivers/mtd/spi/sandbox.c
+++ b/drivers/mtd/spi/sandbox.c
@@ -515,11 +515,9 @@
 int sandbox_sf_ofdata_to_platdata(struct udevice *dev)
 {
 	struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev);
-	const void *blob = gd->fdt_blob;
-	int node = dev_of_offset(dev);
 
-	pdata->filename = fdt_getprop(blob, node, "sandbox,filename", NULL);
-	pdata->device_name = fdt_getprop(blob, node, "compatible", NULL);
+	pdata->filename = dev_read_string(dev, "sandbox,filename");
+	pdata->device_name = dev_read_string(dev, "compatible");
 	if (!pdata->filename || !pdata->device_name) {
 		debug("%s: Missing properties, filename=%s, device_name=%s\n",
 		      __func__, pdata->filename, pdata->device_name);
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index ab7910b..0034a28 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -914,14 +914,13 @@
 }
 
 #if CONFIG_IS_ENABLED(OF_CONTROL)
-int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
+int spi_flash_decode_fdt(struct spi_flash *flash)
 {
 #ifdef CONFIG_DM_SPI_FLASH
 	fdt_addr_t addr;
 	fdt_size_t size;
-	int node = dev_of_offset(flash->dev);
 
-	addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
+	addr = dev_read_addr_size(flash->dev, "memory-map", &size);
 	if (addr == FDT_ADDR_T_NONE) {
 		debug("%s: Cannot decode address\n", __func__);
 		return 0;
@@ -1081,7 +1080,7 @@
 #endif
 
 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
-	ret = spi_flash_decode_fdt(gd->fdt_blob, flash);
+	ret = spi_flash_decode_fdt(flash);
 	if (ret) {
 		debug("SF: FDT decode error\n");
 		return -EINVAL;
diff --git a/drivers/net/ag7xxx.c b/drivers/net/ag7xxx.c
index f8782bc..cf60d11 100644
--- a/drivers/net/ag7xxx.c
+++ b/drivers/net/ag7xxx.c
@@ -941,7 +941,7 @@
 	const char *phy_mode;
 	int ret;
 
-	pdata->iobase = dev_get_addr(dev);
+	pdata->iobase = devfdt_get_addr(dev);
 	pdata->phy_interface = -1;
 
 	/* Decoding of convoluted PHY wiring on Atheros MIPS. */
diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c
index d4d17dd..fb878d4 100644
--- a/drivers/net/altera_tse.c
+++ b/drivers/net/altera_tse.c
@@ -595,7 +595,7 @@
 	 * match with reg-names.
 	 */
 	parent = fdt_parent_offset(blob, node);
-	of_bus_default_count_cells(blob, parent, &addrc, &sizec);
+	fdt_support_default_count_cells(blob, parent, &addrc, &sizec);
 	list = fdt_getprop(blob, node, "reg-names", &len);
 	if (!list)
 		return -ENOENT;
diff --git a/drivers/net/cpsw-common.c b/drivers/net/cpsw-common.c
index 55f56d9..8970ee0 100644
--- a/drivers/net/cpsw-common.c
+++ b/drivers/net/cpsw-common.c
@@ -104,10 +104,10 @@
 	if (of_machine_is_compatible("ti,am33xx"))
 		return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);
 
-	if (of_device_is_compatible(dev, "ti,am3517-emac"))
+	if (device_is_compatible(dev, "ti,am3517-emac"))
 		return davinci_emac_3517_get_macid(dev, 0x110, slave, mac_addr);
 
-	if (of_device_is_compatible(dev, "ti,dm816-emac"))
+	if (device_is_compatible(dev, "ti,dm816-emac"))
 		return cpsw_am33xx_cm_get_macid(dev, 0x30, slave, mac_addr);
 
 	if (of_machine_is_compatible("ti,am43"))
diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index 5fbab9e..778d2f5 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/cpsw.c
@@ -1293,7 +1293,7 @@
 	int num_mode_gpios;
 	int ret;
 
-	pdata->iobase = dev_get_addr(dev);
+	pdata->iobase = devfdt_get_addr(dev);
 	priv->data.version = CPSW_CTRL_VERSION_2;
 	priv->data.bd_ram_ofs = CPSW_BD_OFFSET;
 	priv->data.ale_reg_ofs = CPSW_ALE_OFFSET;
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index f9fb8e0..e3a194c 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -726,7 +726,7 @@
 #endif
 	int ret = 0;
 
-	pdata->iobase = dev_get_addr(dev);
+	pdata->iobase = devfdt_get_addr(dev);
 	pdata->phy_interface = -1;
 	phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
 			       NULL);
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 81eeba2..5c4315f 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -1452,9 +1452,9 @@
 	eqos->dev = dev;
 	eqos->config = (void *)dev_get_driver_data(dev);
 
-	eqos->regs = dev_get_addr(dev);
+	eqos->regs = devfdt_get_addr(dev);
 	if (eqos->regs == FDT_ADDR_T_NONE) {
-		error("dev_get_addr() failed");
+		error("devfdt_get_addr() failed");
 		return -ENODEV;
 	}
 	eqos->mac_regs = (void *)(eqos->regs + EQOS_MAC_REGS_BASE);
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index ad8c462..a6df950 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -11,7 +11,7 @@
  */
 
 #include <common.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <dm/platform_data/net_ethoc.h>
 #include <linux/io.h>
 #include <malloc.h>
@@ -689,8 +689,8 @@
 	struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	pdata->eth_pdata.iobase = dev_get_addr(dev);
-	addr = dev_get_addr_index(dev, 1);
+	pdata->eth_pdata.iobase = devfdt_get_addr(dev);
+	addr = devfdt_get_addr_index(dev, 1);
 	if (addr != FDT_ADDR_T_NONE)
 		pdata->packet_base = addr;
 	return 0;
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 08bea8b..6840908 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -1279,7 +1279,7 @@
 	struct fec_priv *priv = dev_get_priv(dev);
 	const char *phy_mode;
 
-	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
+	pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
 	priv->eth = (struct ethernet_regs *)pdata->iobase;
 
 	pdata->phy_interface = -1;
diff --git a/drivers/net/ftmac100.c b/drivers/net/ftmac100.c
index b79c467..cd24a21 100644
--- a/drivers/net/ftmac100.c
+++ b/drivers/net/ftmac100.c
@@ -392,7 +392,7 @@
 	struct ftmac100_data *priv = dev_get_priv(dev);
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	const char *mac;
-	pdata->iobase = dev_get_addr(dev);
+	pdata->iobase = devfdt_get_addr(dev);
 	priv->iobase = pdata->iobase;
 	mac = dtbmacaddr(0);
 	if (mac)
diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c
index 1b781f4..72ef42c 100644
--- a/drivers/net/keystone_net.c
+++ b/drivers/net/keystone_net.c
@@ -1008,8 +1008,8 @@
 			slave_name = malloc(20);
 			snprintf(slave_name, 20, "netcp@slave-%d", slave_no);
 			ret = device_bind_driver_to_node(dev, "eth_ks2_sl",
-							 slave_name, slave,
-							 &sl_dev);
+					slave_name, offset_to_ofnode(slave),
+					&sl_dev);
 			if (ret) {
 				error("ks2_net - not able to bind slave interfaces\n");
 				return ret;
@@ -1029,7 +1029,7 @@
 		slave_name = malloc(20);
 		snprintf(slave_name, 20, "netcp@slave-%d", slave_no);
 		ret = device_bind_driver_to_node(dev, "eth_ks2_sl", slave_name,
-						 slave, &sl_dev);
+					offset_to_ofnode(slave), &sl_dev);
 		if (ret) {
 			error("ks2_net - not able to bind slave interfaces\n");
 			return ret;
@@ -1134,7 +1134,7 @@
 
 	ks2_eth_parse_slave_interface(dev_of_offset(dev), gbe_0, priv, pdata);
 
-	pdata->iobase = dev_get_addr(dev);
+	pdata->iobase = devfdt_get_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 21a620c..bbbdb74 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -1090,7 +1090,7 @@
 {
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 
-	pdata->iobase = dev_get_addr(dev);
+	pdata->iobase = devfdt_get_addr(dev);
 	return 0;
 }
 
diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
index 8881cc7..50577d7 100644
--- a/drivers/net/mvneta.c
+++ b/drivers/net/mvneta.c
@@ -1695,7 +1695,7 @@
 	pp->base = (void __iomem *)pdata->iobase;
 
 	/* Configure MBUS address windows */
-	if (of_device_is_compatible(dev, "marvell,armada-3700-neta"))
+	if (device_is_compatible(dev, "marvell,armada-3700-neta"))
 		mvneta_bypass_mbus_windows(pp);
 	else
 		mvneta_conf_mbus_windows(pp);
@@ -1756,7 +1756,7 @@
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	const char *phy_mode;
 
-	pdata->iobase = dev_get_addr(dev);
+	pdata->iobase = devfdt_get_addr(dev);
 
 	/* Get phy-mode / phy_interface from DT */
 	pdata->phy_interface = -1;
diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c
index 08adb68..6dc7239 100644
--- a/drivers/net/mvpp2.c
+++ b/drivers/net/mvpp2.c
@@ -5394,18 +5394,18 @@
 	memset(bd_space, 0, size);
 
 	/* Save base addresses for later use */
-	priv->base = (void *)dev_get_addr_index(dev, 0);
+	priv->base = (void *)devfdt_get_addr_index(dev, 0);
 	if (IS_ERR(priv->base))
 		return PTR_ERR(priv->base);
 
 	if (priv->hw_version == MVPP21) {
-		priv->lms_base = (void *)dev_get_addr_index(dev, 1);
+		priv->lms_base = (void *)devfdt_get_addr_index(dev, 1);
 		if (IS_ERR(priv->lms_base))
 			return PTR_ERR(priv->lms_base);
 
 		priv->mdio_base = priv->lms_base + MVPP21_SMI;
 	} else {
-		priv->iface_base = (void *)dev_get_addr_index(dev, 1);
+		priv->iface_base = (void *)devfdt_get_addr_index(dev, 1);
 		if (IS_ERR(priv->iface_base))
 			return PTR_ERR(priv->iface_base);
 
@@ -5463,7 +5463,7 @@
 	if (priv->hw_version == MVPP21) {
 		int priv_common_regs_num = 2;
 
-		port->base = (void __iomem *)dev_get_addr_index(
+		port->base = (void __iomem *)devfdt_get_addr_index(
 			dev->parent, priv_common_regs_num + port->id);
 		if (IS_ERR(port->base))
 			return PTR_ERR(port->base);
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 8bacd99..97e0bc0 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -860,7 +860,7 @@
 #ifdef CONFIG_PHY_FIXED
 	int sn;
 	const char *name;
-	sn = fdt_first_subnode(gd->fdt_blob, dev->of_offset);
+	sn = fdt_first_subnode(gd->fdt_blob, dev_of_offset(dev));
 	while (sn > 0) {
 		name = fdt_get_name(gd->fdt_blob, sn, NULL);
 		if (name != NULL && strcmp(name, "fixed-link") == 0) {
diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c
index 1d87080..6ad31a0 100644
--- a/drivers/net/phy/ti.c
+++ b/drivers/net/phy/ti.c
@@ -174,7 +174,7 @@
 {
 	struct dp83867_private *dp83867 = phydev->priv;
 	struct udevice *dev = phydev->dev;
-	int node = dev->of_offset;
+	int node = dev_of_offset(dev);
 	const void *fdt = gd->fdt_blob;
 
 	if (fdtdec_get_bool(fdt, node, "ti,max-output-impedance"))
diff --git a/drivers/net/pic32_eth.c b/drivers/net/pic32_eth.c
index 385aad5..0b89911 100644
--- a/drivers/net/pic32_eth.c
+++ b/drivers/net/pic32_eth.c
@@ -561,8 +561,7 @@
 		phy_addr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
 
 	/* phy reset gpio */
-	gpio_request_by_name_nodev(gd->fdt_blob, dev_of_offset(dev),
-				   "reset-gpios", 0,
+	gpio_request_by_name_nodev(dev_ofnode(dev), "reset-gpios", 0,
 				   &priv->rst_gpio, GPIOD_IS_OUT);
 
 	priv->phyif	= pdata->phy_interface;
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
index 9742c2c..f5fa0e8 100644
--- a/drivers/net/sandbox-raw.c
+++ b/drivers/net/sandbox-raw.c
@@ -145,7 +145,7 @@
 {
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 
-	pdata->iobase = dev_get_addr(dev);
+	pdata->iobase = devfdt_get_addr(dev);
 	return 0;
 }
 
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index 79d0ae6..59c57d1 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -205,7 +205,7 @@
 {
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 
-	pdata->iobase = dev_get_addr(dev);
+	pdata->iobase = devfdt_get_addr(dev);
 	return 0;
 }
 
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index a3dbe28..09bbb2c 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -776,8 +776,8 @@
 	int ret = 0;
 #endif
 
-	pdata->iobase = dev_get_addr_name(dev, "emac");
-	priv->sysctl_reg = dev_get_addr_name(dev, "syscon");
+	pdata->iobase = devfdt_get_addr_name(dev, "emac");
+	priv->sysctl_reg = devfdt_get_addr_name(dev, "syscon");
 
 	pdata->phy_interface = -1;
 	priv->phyaddr = -1;
@@ -820,7 +820,7 @@
 		parse_phy_pins(dev);
 
 #ifdef CONFIG_DM_GPIO
-	if (fdtdec_get_bool(gd->fdt_blob, dev->of_offset,
+	if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
 			    "snps,reset-active-low"))
 		reset_flags |= GPIOD_ACTIVE_LOW;
 
@@ -828,7 +828,7 @@
 				   &priv->reset_gpio, reset_flags);
 
 	if (ret == 0) {
-		ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
+		ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
 					   "snps,reset-delays-us",
 					   sun8i_pdata->reset_delays, 3);
 	} else if (ret == -ENOENT) {
diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
index 99339db..37685f3 100644
--- a/drivers/net/sunxi_emac.c
+++ b/drivers/net/sunxi_emac.c
@@ -576,7 +576,7 @@
 {
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 
-	pdata->iobase = dev_get_addr(dev);
+	pdata->iobase = devfdt_get_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index f2ce4e2..18e7a83 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -780,7 +780,7 @@
 	const char *phy_mode;
 	int ret;
 
-	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
+	pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
 	priv->regs = (struct tsec *)pdata->iobase;
 
 	offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev),
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index a6f24b3..25c66c6 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -686,7 +686,7 @@
 	int offset = 0;
 	const char *phy_mode;
 
-	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
+	pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
 	priv->iobase = (struct axi_regs *)pdata->iobase;
 
 	offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index 7d4e14f..e3e58ae 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -598,7 +598,7 @@
 	struct xemaclite *emaclite = dev_get_priv(dev);
 	int offset = 0;
 
-	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
+	pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
 	emaclite->regs = (struct emaclite_regs *)ioremap_nocache(pdata->iobase,
 								 0x10000);
 
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index 357f8c2..1bb7fa5 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -683,7 +683,7 @@
 	int node = dev_of_offset(dev);
 	const char *phy_mode;
 
-	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
+	pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
 	priv->iobase = (struct zynq_gem_regs *)pdata->iobase;
 	/* Hardcode for now */
 	priv->phyaddr = -1;
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 504d7e3..b36ef33 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -8,12 +8,11 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
-#include <fdtdec.h>
 #include <inttypes.h>
 #include <pci.h>
 #include <asm/io.h>
-#include <dm/lists.h>
 #include <dm/device-internal.h>
+#include <dm/lists.h>
 #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
 #include <asm/fsp/fsp_support.h>
 #endif
@@ -754,8 +753,8 @@
 	return ret;
 }
 
-static int decode_regions(struct pci_controller *hose, const void *blob,
-			  int parent_node, int node)
+static int decode_regions(struct pci_controller *hose, ofnode parent_node,
+			  ofnode node)
 {
 	int pci_addr_cells, addr_cells, size_cells;
 	phys_addr_t base = 0, size;
@@ -764,12 +763,12 @@
 	int len;
 	int i;
 
-	prop = fdt_getprop(blob, node, "ranges", &len);
+	prop = ofnode_read_prop(node, "ranges", &len);
 	if (!prop)
 		return -EINVAL;
-	pci_addr_cells = fdt_address_cells(blob, node);
-	addr_cells = fdt_address_cells(blob, parent_node);
-	size_cells = fdt_size_cells(blob, node);
+	pci_addr_cells = ofnode_read_addr_cells(node);
+	addr_cells = ofnode_read_addr_cells(parent_node);
+	size_cells = ofnode_read_size_cells(node);
 
 	/* PCI addresses are always 3-cells */
 	len /= sizeof(u32);
@@ -841,9 +840,8 @@
 	/* For bridges, use the top-level PCI controller */
 	if (!device_is_on_pci_bus(bus)) {
 		hose->ctlr = bus;
-		ret = decode_regions(hose, gd->fdt_blob,
-				     dev_of_offset(bus->parent),
-				     dev_of_offset(bus));
+		ret = decode_regions(hose, dev_ofnode(bus->parent),
+				     dev_ofnode(bus));
 		if (ret) {
 			debug("%s: Cannot decode regions\n", __func__);
 			return ret;
@@ -906,7 +904,7 @@
 	struct fdt_pci_addr addr;
 	int ret;
 
-	if (dev_of_offset(dev) == -1)
+	if (!dev_of_valid(dev))
 		return 0;
 
 	/*
@@ -914,8 +912,8 @@
 	 * just check the address.
 	 */
 	pplat = dev_get_parent_platdata(dev);
-	ret = fdtdec_get_pci_addr(gd->fdt_blob, dev_of_offset(dev),
-				  FDT_PCI_SPACE_CONFIG, "reg", &addr);
+	ret = ofnode_read_pci_addr(dev_ofnode(dev), FDT_PCI_SPACE_CONFIG, "reg",
+				   &addr);
 
 	if (ret) {
 		if (ret != -ENOENT)
diff --git a/drivers/pci/pcie_dw_mvebu.c b/drivers/pci/pcie_dw_mvebu.c
index 05a0660..202cfe9 100644
--- a/drivers/pci/pcie_dw_mvebu.c
+++ b/drivers/pci/pcie_dw_mvebu.c
@@ -521,12 +521,12 @@
 	struct pcie_dw_mvebu *pcie = dev_get_priv(dev);
 
 	/* Get the controller base address */
-	pcie->ctrl_base = (void *)dev_get_addr_index(dev, 0);
+	pcie->ctrl_base = (void *)devfdt_get_addr_index(dev, 0);
 	if ((fdt_addr_t)pcie->ctrl_base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
 	/* Get the config space base address and size */
-	pcie->cfg_base = (void *)dev_get_addr_size_index(dev, 1,
+	pcie->cfg_base = (void *)devfdt_get_addr_size_index(dev, 1,
 							 &pcie->cfg_size);
 	if ((fdt_addr_t)pcie->cfg_base == FDT_ADDR_T_NONE)
 		return -EINVAL;
diff --git a/drivers/phy/marvell/comphy_core.c b/drivers/phy/marvell/comphy_core.c
index 596921b..426db30 100644
--- a/drivers/phy/marvell/comphy_core.c
+++ b/drivers/phy/marvell/comphy_core.c
@@ -113,11 +113,11 @@
 	static int current_idx;
 
 	/* Save base addresses for later use */
-	chip_cfg->comphy_base_addr = (void *)dev_get_addr_index(dev, 0);
+	chip_cfg->comphy_base_addr = (void *)devfdt_get_addr_index(dev, 0);
 	if (IS_ERR(chip_cfg->comphy_base_addr))
 		return PTR_ERR(chip_cfg->comphy_base_addr);
 
-	chip_cfg->hpipe3_base_addr = (void *)dev_get_addr_index(dev, 1);
+	chip_cfg->hpipe3_base_addr = (void *)devfdt_get_addr_index(dev, 1);
 	if (IS_ERR(chip_cfg->hpipe3_base_addr))
 		return PTR_ERR(chip_cfg->hpipe3_base_addr);
 
@@ -135,10 +135,10 @@
 		return -EINVAL;
 	}
 
-	if (of_device_is_compatible(dev, "marvell,comphy-armada-3700"))
+	if (device_is_compatible(dev, "marvell,comphy-armada-3700"))
 		chip_cfg->ptr_comphy_chip_init = comphy_a3700_init;
 
-	if (of_device_is_compatible(dev, "marvell,comphy-cp110"))
+	if (device_is_compatible(dev, "marvell,comphy-cp110"))
 		chip_cfg->ptr_comphy_chip_init = comphy_cp110_init;
 
 	/*
diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c
index 0d8bef7..d8b8d58 100644
--- a/drivers/phy/phy-uclass.c
+++ b/drivers/phy/phy-uclass.c
@@ -17,7 +17,7 @@
 }
 
 static int generic_phy_xlate_offs_flags(struct phy *phy,
-				 struct fdtdec_phandle_args *args)
+					struct ofnode_phandle_args *args)
 {
 	debug("%s(phy=%p)\n", __func__, phy);
 
@@ -31,14 +31,13 @@
 	else
 		phy->id = 0;
 
-
 	return 0;
 }
 
 int generic_phy_get_by_index(struct udevice *dev, int index,
 			     struct phy *phy)
 {
-	struct fdtdec_phandle_args args;
+	struct ofnode_phandle_args args;
 	struct phy_ops *ops;
 	int ret;
 	struct udevice *phydev;
@@ -46,18 +45,17 @@
 	debug("%s(dev=%p, index=%d, phy=%p)\n", __func__, dev, index, phy);
 
 	assert(phy);
-	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
-					     "phys", "#phy-cells", 0, index,
-					     &args);
+	ret = dev_read_phandle_with_args(dev, "phys", "#phy-cells", 0, index,
+					 &args);
 	if (ret) {
-		debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
+		debug("%s: dev_read_phandle_with_args failed: err=%d\n",
 		      __func__, ret);
 		return ret;
 	}
 
-	ret = uclass_get_device_by_of_offset(UCLASS_PHY, args.node, &phydev);
+	ret = uclass_get_device_by_ofnode(UCLASS_PHY, args.node, &phydev);
 	if (ret) {
-		debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
+		debug("%s: uclass_get_device_by_ofnode failed: err=%d\n",
 		      __func__, ret);
 		return ret;
 	}
@@ -88,10 +86,9 @@
 
 	debug("%s(dev=%p, name=%s, phy=%p)\n", __func__, dev, phy_name, phy);
 
-	index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
-				      "phy-names", phy_name);
+	index = dev_read_stringlist_search(dev, "phy-names", phy_name);
 	if (index < 0) {
-		debug("fdt_stringlist_search() failed: %d\n", index);
+		debug("dev_read_stringlist_search() failed: %d\n", index);
 		return index;
 	}
 
diff --git a/drivers/phy/sandbox-phy.c b/drivers/phy/sandbox-phy.c
index 9ad820c..867c6fe 100644
--- a/drivers/phy/sandbox-phy.c
+++ b/drivers/phy/sandbox-phy.c
@@ -80,8 +80,7 @@
 
 	priv->initialized = false;
 	priv->on = false;
-	priv->broken = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
-				       "broken");
+	priv->broken = dev_read_bool(dev, "broken");
 
 	return 0;
 }
diff --git a/drivers/phy/ti-pipe3-phy.c b/drivers/phy/ti-pipe3-phy.c
index ed80f0f..680e32f 100644
--- a/drivers/phy/ti-pipe3-phy.c
+++ b/drivers/phy/ti-pipe3-phy.c
@@ -296,7 +296,7 @@
 		return NULL;
 	}
 
-	cell = fdt_getprop(gd->fdt_blob, dev->of_offset, name,
+	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);
@@ -316,7 +316,7 @@
 	fdt_size_t sz;
 	struct omap_pipe3 *pipe3 = dev_get_priv(dev);
 
-	addr = dev_get_addr_size_index(dev, 2, &sz);
+	addr = devfdt_get_addr_size_index(dev, 2, &sz);
 	if (addr == FDT_ADDR_T_NONE) {
 		error("missing pll ctrl address\n");
 		return -EINVAL;
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 1e5c425..64da7c6 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -17,7 +17,7 @@
 obj-$(CONFIG_PINCTRL_PIC32)	+= pinctrl_pic32.o
 obj-$(CONFIG_PINCTRL_EXYNOS)	+= exynos/
 obj-$(CONFIG_PINCTRL_MESON)	+= meson/
-obj-$(CONFIG_PINCTRL_MVEBU)	+= mvebu/
+obj-$(CONFIG_ARCH_MVEBU)	+= mvebu/
 obj-$(CONFIG_PINCTRL_SINGLE)	+= pinctrl-single.o
 obj-$(CONFIG_PINCTRL_STI)	+= pinctrl-sti.o
 obj-$(CONFIG_PINCTRL_STM32)	+= pinctrl_stm32.o
diff --git a/drivers/pinctrl/ath79/pinctrl_ar933x.c b/drivers/pinctrl/ath79/pinctrl_ar933x.c
index fccc7c4..83f4d53 100644
--- a/drivers/pinctrl/ath79/pinctrl_ar933x.c
+++ b/drivers/pinctrl/ath79/pinctrl_ar933x.c
@@ -111,7 +111,7 @@
 	struct ar933x_pinctrl_priv *priv = dev_get_priv(dev);
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/pinctrl/ath79/pinctrl_qca953x.c b/drivers/pinctrl/ath79/pinctrl_qca953x.c
index a7f8c70..abc0368 100644
--- a/drivers/pinctrl/ath79/pinctrl_qca953x.c
+++ b/drivers/pinctrl/ath79/pinctrl_qca953x.c
@@ -131,7 +131,7 @@
 	struct qca953x_pinctrl_priv *priv = dev_get_priv(dev);
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/pinctrl/exynos/pinctrl-exynos.c b/drivers/pinctrl/exynos/pinctrl-exynos.c
index 5b9a592..95610a7 100644
--- a/drivers/pinctrl/exynos/pinctrl-exynos.c
+++ b/drivers/pinctrl/exynos/pinctrl-exynos.c
@@ -128,7 +128,7 @@
 	if (!priv)
 		return -EINVAL;
 
-	base = dev_get_addr(dev);
+	base = devfdt_get_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index a0a7de5..2fa840c 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -7,7 +7,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 #include <dt-bindings/gpio/meson-gxbb-gpio.h>
 
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index b5486b8..6281f52 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -5,7 +5,7 @@
  */
 
 #include <common.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 #include <fdt_support.h>
 #include <linux/err.h>
diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig
index cf9c299..a9388ff 100644
--- a/drivers/pinctrl/mvebu/Kconfig
+++ b/drivers/pinctrl/mvebu/Kconfig
@@ -1,7 +1,17 @@
-config PINCTRL_MVEBU
-	depends on ARCH_MVEBU
-	bool
-	default y
+if ARCH_MVEBU
+
+config PINCTRL_ARMADA_37XX
+	depends on ARMADA_3700
+	bool "Armada 37xx pin control driver"
+	help
+	   Support pin multiplexing and pin configuration control on
+	   Marvell's Armada-37xx SoC.
+
+config PINCTRL_ARMADA_8K
+	depends on ARMADA_8K
+	bool "Armada 7k/8k pin control driver"
 	help
 	   Support pin multiplexing and pin configuration control on
 	   Marvell's Armada-8K SoC.
+
+endif
diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile
index f4f7864..13a38d5 100644
--- a/drivers/pinctrl/mvebu/Makefile
+++ b/drivers/pinctrl/mvebu/Makefile
@@ -4,4 +4,5 @@
 # SPDX-License-Identifier:	GPL-2.0
 # https://spdx.org/licenses
 
-obj-$(CONFIG_PINCTRL_MVEBU)	+= pinctrl-mvebu.o
+obj-$(CONFIG_PINCTRL_ARMADA_37XX) += pinctrl-armada-37xx.o
+obj-$(CONFIG_PINCTRL_ARMADA_8K)	+= pinctrl-mvebu.o
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
new file mode 100644
index 0000000..3bb4c43
--- /dev/null
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -0,0 +1,631 @@
+/*
+ * U-Boot Marvell 37xx SoC pinctrl driver
+ *
+ * Copyright (C) 2017 Stefan Roese <sr@denx.de>
+ *
+ * This driver is based on the Linux driver version, which is:
+ * Copyright (C) 2017 Marvell
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * Additionally parts are derived from the Meson U-Boot pinctrl driver,
+ * which is:
+ * (C) Copyright 2016 - Beniamino Galvani <b.galvani@gmail.com>
+ * Based on code from Linux kernel:
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ * https://spdx.org/licenses
+ */
+
+#include <common.h>
+#include <config.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <regmap.h>
+#include <asm/gpio.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define OUTPUT_EN	0x0
+#define INPUT_VAL	0x10
+#define OUTPUT_VAL	0x18
+#define OUTPUT_CTL	0x20
+#define SELECTION	0x30
+
+#define IRQ_EN		0x0
+#define IRQ_POL		0x08
+#define IRQ_STATUS	0x10
+#define IRQ_WKUP	0x18
+
+#define NB_FUNCS 2
+#define GPIO_PER_REG	32
+
+/**
+ * struct armada_37xx_pin_group: represents group of pins of a pinmux function.
+ * The pins of a pinmux groups are composed of one or two groups of contiguous
+ * pins.
+ * @name:	Name of the pin group, used to lookup the group.
+ * @start_pins:	Index of the first pin of the main range of pins belonging to
+ *		the group
+ * @npins:	Number of pins included in the first range
+ * @reg_mask:	Bit mask matching the group in the selection register
+ * @extra_pins:	Index of the first pin of the optional second range of pins
+ *		belonging to the group
+ * @npins:	Number of pins included in the second optional range
+ * @funcs:	A list of pinmux functions that can be selected for this group.
+ * @pins:	List of the pins included in the group
+ */
+struct armada_37xx_pin_group {
+	const char	*name;
+	unsigned int	start_pin;
+	unsigned int	npins;
+	u32		reg_mask;
+	u32		val[NB_FUNCS];
+	unsigned int	extra_pin;
+	unsigned int	extra_npins;
+	const char	*funcs[NB_FUNCS];
+	unsigned int	*pins;
+};
+
+struct armada_37xx_pin_data {
+	u8				nr_pins;
+	char				*name;
+	struct armada_37xx_pin_group	*groups;
+	int				ngroups;
+};
+
+struct armada_37xx_pmx_func {
+	const char		*name;
+	const char		**groups;
+	unsigned int		ngroups;
+};
+
+struct armada_37xx_pinctrl {
+	void __iomem			*base;
+	const struct armada_37xx_pin_data	*data;
+	struct udevice			*dev;
+	struct pinctrl_dev		*pctl_dev;
+	struct armada_37xx_pin_group	*groups;
+	unsigned int			ngroups;
+	struct armada_37xx_pmx_func	*funcs;
+	unsigned int			nfuncs;
+};
+
+#define PIN_GRP(_name, _start, _nr, _mask, _func1, _func2)	\
+	{					\
+		.name = _name,			\
+		.start_pin = _start,		\
+		.npins = _nr,			\
+		.reg_mask = _mask,		\
+		.val = {0, _mask},		\
+		.funcs = {_func1, _func2}	\
+	}
+
+#define PIN_GRP_GPIO(_name, _start, _nr, _mask, _func1)	\
+	{					\
+		.name = _name,			\
+		.start_pin = _start,		\
+		.npins = _nr,			\
+		.reg_mask = _mask,		\
+		.val = {0, _mask},		\
+		.funcs = {_func1, "gpio"}	\
+	}
+
+#define PIN_GRP_GPIO_2(_name, _start, _nr, _mask, _val1, _val2, _func1)   \
+	{					\
+		.name = _name,			\
+		.start_pin = _start,		\
+		.npins = _nr,			\
+		.reg_mask = _mask,		\
+		.val = {_val1, _val2},		\
+		.funcs = {_func1, "gpio"}	\
+	}
+
+#define PIN_GRP_EXTRA(_name, _start, _nr, _mask, _v1, _v2, _start2, _nr2, \
+		      _f1, _f2)				\
+	{						\
+		.name = _name,				\
+		.start_pin = _start,			\
+		.npins = _nr,				\
+		.reg_mask = _mask,			\
+		.val = {_v1, _v2},			\
+		.extra_pin = _start2,			\
+		.extra_npins = _nr2,			\
+		.funcs = {_f1, _f2}			\
+	}
+
+static struct armada_37xx_pin_group armada_37xx_nb_groups[] = {
+	PIN_GRP_GPIO("jtag", 20, 5, BIT(0), "jtag"),
+	PIN_GRP_GPIO("sdio0", 8, 3, BIT(1), "sdio"),
+	PIN_GRP_GPIO("emmc_nb", 27, 9, BIT(2), "emmc"),
+	PIN_GRP_GPIO("pwm0", 11, 1, BIT(3), "pwm"),
+	PIN_GRP_GPIO("pwm1", 12, 1, BIT(4), "pwm"),
+	PIN_GRP_GPIO("pwm2", 13, 1, BIT(5), "pwm"),
+	PIN_GRP_GPIO("pwm3", 14, 1, BIT(6), "pwm"),
+	PIN_GRP_GPIO("pmic1", 17, 1, BIT(7), "pmic"),
+	PIN_GRP_GPIO("pmic0", 16, 1, BIT(8), "pmic"),
+	PIN_GRP_GPIO("i2c2", 2, 2, BIT(9), "i2c"),
+	PIN_GRP_GPIO("i2c1", 0, 2, BIT(10), "i2c"),
+	PIN_GRP_GPIO("spi_cs1", 17, 1, BIT(12), "spi"),
+	PIN_GRP_GPIO_2("spi_cs2", 18, 1, BIT(13) | BIT(19), 0, BIT(13), "spi"),
+	PIN_GRP_GPIO_2("spi_cs3", 19, 1, BIT(14) | BIT(19), 0, BIT(14), "spi"),
+	PIN_GRP_GPIO("onewire", 4, 1, BIT(16), "onewire"),
+	PIN_GRP_GPIO("uart1", 25, 2, BIT(17), "uart"),
+	PIN_GRP_GPIO("spi_quad", 15, 2, BIT(18), "spi"),
+	PIN_GRP_EXTRA("uart2", 9, 2, BIT(13) | BIT(14) | BIT(19),
+		      BIT(13) | BIT(14), BIT(19), 18, 2, "gpio", "uart"),
+	PIN_GRP_GPIO("led0_od", 11, 1, BIT(20), "led"),
+	PIN_GRP_GPIO("led1_od", 12, 1, BIT(21), "led"),
+	PIN_GRP_GPIO("led2_od", 13, 1, BIT(22), "led"),
+	PIN_GRP_GPIO("led3_od", 14, 1, BIT(23), "led"),
+
+};
+
+static struct armada_37xx_pin_group armada_37xx_sb_groups[] = {
+	PIN_GRP_GPIO("usb32_drvvbus0", 0, 1, BIT(0), "drvbus"),
+	PIN_GRP_GPIO("usb2_drvvbus1", 1, 1, BIT(1), "drvbus"),
+	PIN_GRP_GPIO("sdio_sb", 24, 5, BIT(2), "sdio"),
+	PIN_GRP_EXTRA("rgmii", 6, 14, BIT(3), 0, BIT(3), 23, 1, "mii", "gpio"),
+	PIN_GRP_GPIO("pcie1", 3, 2, BIT(4), "pcie"),
+	PIN_GRP_GPIO("ptp", 20, 3, BIT(5), "ptp"),
+	PIN_GRP("ptp_clk", 21, 1, BIT(6), "ptp", "mii"),
+	PIN_GRP("ptp_trig", 22, 1, BIT(7), "ptp", "mii"),
+	PIN_GRP("mii_col", 23, 1, BIT(8), "mii", "mii_err"),
+};
+
+const struct armada_37xx_pin_data armada_37xx_pin_nb = {
+	.nr_pins = 36,
+	.name = "GPIO1",
+	.groups = armada_37xx_nb_groups,
+	.ngroups = ARRAY_SIZE(armada_37xx_nb_groups),
+};
+
+const struct armada_37xx_pin_data armada_37xx_pin_sb = {
+	.nr_pins = 29,
+	.name = "GPIO2",
+	.groups = armada_37xx_sb_groups,
+	.ngroups = ARRAY_SIZE(armada_37xx_sb_groups),
+};
+
+static inline void armada_37xx_update_reg(unsigned int *reg,
+					  unsigned int offset)
+{
+	/* We never have more than 2 registers */
+	if (offset >= GPIO_PER_REG) {
+		offset -= GPIO_PER_REG;
+		*reg += sizeof(u32);
+	}
+}
+
+static int armada_37xx_get_func_reg(struct armada_37xx_pin_group *grp,
+				    const char *func)
+{
+	int f;
+
+	for (f = 0; f < NB_FUNCS; f++)
+		if (!strcmp(grp->funcs[f], func))
+			return f;
+
+	return -ENOTSUPP;
+}
+
+static int armada_37xx_pmx_get_groups_count(struct udevice *dev)
+{
+	struct armada_37xx_pinctrl *info = dev_get_priv(dev);
+
+	return info->ngroups;
+}
+
+static const char *armada_37xx_pmx_dummy_name = "_dummy";
+
+static const char *armada_37xx_pmx_get_group_name(struct udevice *dev,
+						  unsigned selector)
+{
+	struct armada_37xx_pinctrl *info = dev_get_priv(dev);
+
+	if (!info->groups[selector].name)
+		return armada_37xx_pmx_dummy_name;
+
+	return info->groups[selector].name;
+}
+
+static int armada_37xx_pmx_get_funcs_count(struct udevice *dev)
+{
+	struct armada_37xx_pinctrl *info = dev_get_priv(dev);
+
+	return info->nfuncs;
+}
+
+static const char *armada_37xx_pmx_get_func_name(struct udevice *dev,
+						 unsigned selector)
+{
+	struct armada_37xx_pinctrl *info = dev_get_priv(dev);
+
+	return info->funcs[selector].name;
+}
+
+static int armada_37xx_pmx_set_by_name(struct udevice *dev,
+				       const char *name,
+				       struct armada_37xx_pin_group *grp)
+{
+	struct armada_37xx_pinctrl *info = dev_get_priv(dev);
+	unsigned int reg = SELECTION;
+	unsigned int mask = grp->reg_mask;
+	int func, val;
+
+	dev_dbg(info->dev, "enable function %s group %s\n",
+		name, grp->name);
+
+	func = armada_37xx_get_func_reg(grp, name);
+
+	if (func < 0)
+		return func;
+
+	val = grp->val[func];
+
+	clrsetbits_le32(info->base + reg, mask, val);
+
+	return 0;
+}
+
+static int armada_37xx_pmx_group_set(struct udevice *dev,
+				     unsigned group_selector,
+				     unsigned func_selector)
+{
+	struct armada_37xx_pinctrl *info = dev_get_priv(dev);
+	struct armada_37xx_pin_group *grp = &info->groups[group_selector];
+	const char *name = info->funcs[func_selector].name;
+
+	return armada_37xx_pmx_set_by_name(dev, name, grp);
+}
+
+/**
+ * armada_37xx_add_function() - Add a new function to the list
+ * @funcs: array of function to add the new one
+ * @funcsize: size of the remaining space for the function
+ * @name: name of the function to add
+ *
+ * If it is a new function then create it by adding its name else
+ * increment the number of group associated to this function.
+ */
+static int armada_37xx_add_function(struct armada_37xx_pmx_func *funcs,
+				    int *funcsize, const char *name)
+{
+	int i = 0;
+
+	if (*funcsize <= 0)
+		return -EOVERFLOW;
+
+	while (funcs->ngroups) {
+		/* function already there */
+		if (strcmp(funcs->name, name) == 0) {
+			funcs->ngroups++;
+
+			return -EEXIST;
+		}
+		funcs++;
+		i++;
+	}
+
+	/* append new unique function */
+	funcs->name = name;
+	funcs->ngroups = 1;
+	(*funcsize)--;
+
+	return 0;
+}
+
+/**
+ * armada_37xx_fill_group() - complete the group array
+ * @info: info driver instance
+ *
+ * Based on the data available from the armada_37xx_pin_group array
+ * completes the last member of the struct for each function: the list
+ * of the groups associated to this function.
+ *
+ */
+static int armada_37xx_fill_group(struct armada_37xx_pinctrl *info)
+{
+	int n, num = 0, funcsize = info->data->nr_pins;
+
+	for (n = 0; n < info->ngroups; n++) {
+		struct armada_37xx_pin_group *grp = &info->groups[n];
+		int i, j, f;
+
+		grp->pins = devm_kzalloc(info->dev,
+					 (grp->npins + grp->extra_npins) *
+					 sizeof(*grp->pins), GFP_KERNEL);
+		if (!grp->pins)
+			return -ENOMEM;
+
+		for (i = 0; i < grp->npins; i++)
+			grp->pins[i] = grp->start_pin + i;
+
+		for (j = 0; j < grp->extra_npins; j++)
+			grp->pins[i+j] = grp->extra_pin + j;
+
+		for (f = 0; f < NB_FUNCS; f++) {
+			int ret;
+			/* check for unique functions and count groups */
+			ret = armada_37xx_add_function(info->funcs, &funcsize,
+					    grp->funcs[f]);
+			if (ret == -EOVERFLOW)
+				dev_err(info->dev,
+					"More functions than pins(%d)\n",
+					info->data->nr_pins);
+			if (ret < 0)
+				continue;
+			num++;
+		}
+	}
+
+	info->nfuncs = num;
+
+	return 0;
+}
+
+/**
+ * armada_37xx_fill_funcs() - complete the funcs array
+ * @info: info driver instance
+ *
+ * Based on the data available from the armada_37xx_pin_group array
+ * completes the last two member of the struct for each group:
+ * - the list of the pins included in the group
+ * - the list of pinmux functions that can be selected for this group
+ *
+ */
+static int armada_37xx_fill_func(struct armada_37xx_pinctrl *info)
+{
+	struct armada_37xx_pmx_func *funcs = info->funcs;
+	int n;
+
+	for (n = 0; n < info->nfuncs; n++) {
+		const char *name = funcs[n].name;
+		const char **groups;
+		int g;
+
+		funcs[n].groups = devm_kzalloc(info->dev, funcs[n].ngroups *
+					       sizeof(*(funcs[n].groups)),
+					       GFP_KERNEL);
+		if (!funcs[n].groups)
+			return -ENOMEM;
+
+		groups = funcs[n].groups;
+
+		for (g = 0; g < info->ngroups; g++) {
+			struct armada_37xx_pin_group *gp = &info->groups[g];
+			int f;
+
+			for (f = 0; f < NB_FUNCS; f++) {
+				if (strcmp(gp->funcs[f], name) == 0) {
+					*groups = gp->name;
+					groups++;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+static int armada_37xx_gpio_get(struct udevice *dev, unsigned int offset)
+{
+	struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent);
+	unsigned int reg = INPUT_VAL;
+	unsigned int val, mask;
+
+	armada_37xx_update_reg(&reg, offset);
+	mask = BIT(offset);
+
+	val = readl(info->base + reg);
+
+	return (val & mask) != 0;
+}
+
+static int armada_37xx_gpio_set(struct udevice *dev, unsigned int offset,
+				int value)
+{
+	struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent);
+	unsigned int reg = OUTPUT_VAL;
+	unsigned int mask, val;
+
+	armada_37xx_update_reg(&reg, offset);
+	mask = BIT(offset);
+	val = value ? mask : 0;
+
+	clrsetbits_le32(info->base + reg, mask, val);
+
+	return 0;
+}
+
+static int armada_37xx_gpio_get_direction(struct udevice *dev,
+					  unsigned int offset)
+{
+	struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent);
+	unsigned int reg = OUTPUT_EN;
+	unsigned int val, mask;
+
+	armada_37xx_update_reg(&reg, offset);
+	mask = BIT(offset);
+	val = readl(info->base + reg);
+
+	if (val & mask)
+		return GPIOF_OUTPUT;
+	else
+		return GPIOF_INPUT;
+}
+
+static int armada_37xx_gpio_direction_input(struct udevice *dev,
+					    unsigned int offset)
+{
+	struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent);
+	unsigned int reg = OUTPUT_EN;
+	unsigned int mask;
+
+	armada_37xx_update_reg(&reg, offset);
+	mask = BIT(offset);
+
+	clrbits_le32(info->base + reg, mask);
+
+	return 0;
+}
+
+static int armada_37xx_gpio_direction_output(struct udevice *dev,
+					     unsigned int offset, int value)
+{
+	struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent);
+	unsigned int reg = OUTPUT_EN;
+	unsigned int mask;
+
+	armada_37xx_update_reg(&reg, offset);
+	mask = BIT(offset);
+
+	setbits_le32(info->base + reg, mask);
+
+	/* And set the requested value */
+	return armada_37xx_gpio_set(dev, offset, value);
+}
+
+static int armada_37xx_gpio_probe(struct udevice *dev)
+{
+	struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent);
+	struct gpio_dev_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+	uc_priv->bank_name = info->data->name;
+	uc_priv->gpio_count = info->data->nr_pins;
+
+	return 0;
+}
+
+static const struct dm_gpio_ops armada_37xx_gpio_ops = {
+	.set_value = armada_37xx_gpio_set,
+	.get_value = armada_37xx_gpio_get,
+	.get_function = armada_37xx_gpio_get_direction,
+	.direction_input = armada_37xx_gpio_direction_input,
+	.direction_output = armada_37xx_gpio_direction_output,
+};
+
+static struct driver armada_37xx_gpio_driver = {
+	.name	= "armada-37xx-gpio",
+	.id	= UCLASS_GPIO,
+	.probe	= armada_37xx_gpio_probe,
+	.ops	= &armada_37xx_gpio_ops,
+};
+
+static int armada_37xx_gpiochip_register(struct udevice *parent,
+					 struct armada_37xx_pinctrl *info)
+{
+	const void *blob = gd->fdt_blob;
+	int node = dev_of_offset(parent);
+	struct uclass_driver *drv;
+	struct udevice *dev;
+	int ret = -ENODEV;
+	int subnode;
+	char *name;
+
+	/* Lookup GPIO driver */
+	drv = lists_uclass_lookup(UCLASS_GPIO);
+	if (!drv) {
+		puts("Cannot find GPIO driver\n");
+		return -ENOENT;
+	}
+
+	fdt_for_each_subnode(subnode, blob, node) {
+		if (!fdtdec_get_bool(blob, subnode, "gpio-controller")) {
+			ret = 0;
+			break;
+		}
+	};
+	if (ret)
+		return ret;
+
+	name = calloc(1, 32);
+	sprintf(name, "armada-37xx-gpio");
+
+	/* Create child device UCLASS_GPIO and bind it */
+	device_bind(parent, &armada_37xx_gpio_driver, name, NULL, subnode,
+		    &dev);
+	dev_set_of_offset(dev, subnode);
+
+	return 0;
+}
+
+const struct pinctrl_ops armada_37xx_pinctrl_ops  = {
+	.get_groups_count = armada_37xx_pmx_get_groups_count,
+	.get_group_name = armada_37xx_pmx_get_group_name,
+	.get_functions_count = armada_37xx_pmx_get_funcs_count,
+	.get_function_name = armada_37xx_pmx_get_func_name,
+	.pinmux_group_set = armada_37xx_pmx_group_set,
+	.set_state = pinctrl_generic_set_state,
+};
+
+int armada_37xx_pinctrl_probe(struct udevice *dev)
+{
+	struct armada_37xx_pinctrl *info = dev_get_priv(dev);
+	const struct armada_37xx_pin_data *pin_data;
+	int ret;
+
+	info->data = (struct armada_37xx_pin_data *)dev_get_driver_data(dev);
+	pin_data = info->data;
+
+	info->base = (void __iomem *)devfdt_get_addr(dev);
+	if (!info->base) {
+		error("unable to find regmap\n");
+		return -ENODEV;
+	}
+
+	info->groups = pin_data->groups;
+	info->ngroups = pin_data->ngroups;
+
+	/*
+	 * we allocate functions for number of pins and hope there are
+	 * fewer unique functions than pins available
+	 */
+	info->funcs = devm_kzalloc(info->dev, pin_data->nr_pins *
+			   sizeof(struct armada_37xx_pmx_func), GFP_KERNEL);
+	if (!info->funcs)
+		return -ENOMEM;
+
+
+	ret = armada_37xx_fill_group(info);
+	if (ret)
+		return ret;
+
+	ret = armada_37xx_fill_func(info);
+	if (ret)
+		return ret;
+
+	ret = armada_37xx_gpiochip_register(dev, info);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct udevice_id armada_37xx_pinctrl_of_match[] = {
+	{
+		.compatible = "marvell,armada3710-sb-pinctrl",
+		.data = (ulong)&armada_37xx_pin_sb,
+	},
+	{
+		.compatible = "marvell,armada3710-nb-pinctrl",
+		.data = (ulong)&armada_37xx_pin_nb,
+	},
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(armada_37xx_pinctrl) = {
+	.name = "armada-37xx-pinctrl",
+	.id = UCLASS_PINCTRL,
+	.of_match = of_match_ptr(armada_37xx_pinctrl_of_match),
+	.probe = armada_37xx_pinctrl_probe,
+	.priv_auto_alloc_size = sizeof(struct armada_37xx_pinctrl),
+	.ops = &armada_37xx_pinctrl_ops,
+};
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index 80f0dfa..ec19583 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -137,7 +137,7 @@
 		return -EINVAL;
 	}
 
-	priv->base_reg = dev_get_addr_ptr(dev);
+	priv->base_reg = devfdt_get_addr_ptr(dev);
 	if (priv->base_reg == (void *)FDT_ADDR_T_NONE) {
 		debug("%s: Failed to get base address\n", __func__);
 		return -EINVAL;
diff --git a/drivers/pinctrl/nxp/pinctrl-imx.c b/drivers/pinctrl/nxp/pinctrl-imx.c
index ebc14a3..1b6107f 100644
--- a/drivers/pinctrl/nxp/pinctrl-imx.c
+++ b/drivers/pinctrl/nxp/pinctrl-imx.c
@@ -8,7 +8,7 @@
 #include <mapmem.h>
 #include <linux/io.h>
 #include <linux/err.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-imx.h"
diff --git a/drivers/pinctrl/nxp/pinctrl-imx5.c b/drivers/pinctrl/nxp/pinctrl-imx5.c
index 6942f39..f1c655f 100644
--- a/drivers/pinctrl/nxp/pinctrl-imx5.c
+++ b/drivers/pinctrl/nxp/pinctrl-imx5.c
@@ -5,7 +5,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-imx.h"
diff --git a/drivers/pinctrl/nxp/pinctrl-imx6.c b/drivers/pinctrl/nxp/pinctrl-imx6.c
index 4488b16..0f767d9 100644
--- a/drivers/pinctrl/nxp/pinctrl-imx6.c
+++ b/drivers/pinctrl/nxp/pinctrl-imx6.c
@@ -5,7 +5,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-imx.h"
diff --git a/drivers/pinctrl/nxp/pinctrl-imx7.c b/drivers/pinctrl/nxp/pinctrl-imx7.c
index eeb7942..1f3e423 100644
--- a/drivers/pinctrl/nxp/pinctrl-imx7.c
+++ b/drivers/pinctrl/nxp/pinctrl-imx7.c
@@ -4,7 +4,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-imx.h"
diff --git a/drivers/pinctrl/nxp/pinctrl-imx7ulp.c b/drivers/pinctrl/nxp/pinctrl-imx7ulp.c
index 5f01175..4a893e5 100644
--- a/drivers/pinctrl/nxp/pinctrl-imx7ulp.c
+++ b/drivers/pinctrl/nxp/pinctrl-imx7ulp.c
@@ -6,7 +6,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-imx.h"
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index 5c6bff5..1abfc50 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -8,7 +8,7 @@
  */
 
 #include <common.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 #include <linux/io.h>
 #include <linux/err.h>
@@ -158,7 +158,7 @@
 	fdt_addr_t addr_base;
 
 	dev = dev_get_parent(dev);
-	addr_base = dev_get_addr(dev);
+	addr_base = devfdt_get_addr(dev);
 	if (addr_base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 904e1bd..38c435e 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -8,7 +8,7 @@
  */
 
 #include <common.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 #include <linux/io.h>
 #include <linux/err.h>
@@ -364,7 +364,7 @@
 {
 	struct at91_pinctrl_priv *priv = dev_get_priv(dev);
 	const void *blob = gd->fdt_blob;
-	int node = config->of_offset;
+	int node = dev_of_offset(config);
 	u32 cells[MAX_PINMUX_ENTRIES];
 	const u32 *list = cells;
 	u32 bank, pin;
@@ -424,7 +424,7 @@
 	int index;
 
 	for (index = 0; index < MAX_GPIO_BANKS; index++) {
-		addr_base = dev_get_addr_index(dev, index);
+		addr_base = devfdt_get_addr_index(dev, index);
 		if (addr_base == FDT_ADDR_T_NONE)
 			break;
 
diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c
index 0272496..49e3648 100644
--- a/drivers/pinctrl/pinctrl-generic.c
+++ b/drivers/pinctrl/pinctrl-generic.c
@@ -5,8 +5,8 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <linux/compat.h>
-#include <dm/device.h>
 #include <dm/pinctrl.h>
 
 DECLARE_GLOBAL_DATA_PTR;
diff --git a/drivers/pinctrl/pinctrl-sandbox.c b/drivers/pinctrl/pinctrl-sandbox.c
index ab03d8b..e77b49c 100644
--- a/drivers/pinctrl/pinctrl-sandbox.c
+++ b/drivers/pinctrl/pinctrl-sandbox.c
@@ -7,7 +7,7 @@
 /* #define DEBUG */
 
 #include <common.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 static const char * const sandbox_pins[] = {
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index f19f779..a38d774 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -5,7 +5,7 @@
  */
 
 #include <common.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 #include <libfdt.h>
 #include <asm/io.h>
@@ -79,7 +79,8 @@
 	const struct single_fdt_pin_cfg *prop;
 	int len;
 
-	prop = fdt_getprop(fdt, config->of_offset, "pinctrl-single,pins", &len);
+	prop = fdt_getprop(fdt, dev_of_offset(config), "pinctrl-single,pins",
+			   &len);
 	if (prop) {
 		dev_dbg(dev, "configuring pins for %s\n", config->name);
 		if (len % sizeof(struct single_fdt_pin_cfg)) {
@@ -100,23 +101,23 @@
 	int res;
 	struct single_pdata *pdata = dev->platdata;
 
-	pdata->width = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+	pdata->width = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 				      "pinctrl-single,register-width", 0);
 
-	res = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
+	res = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
 				   "reg", of_reg, 2);
 	if (res)
 		return res;
 	pdata->offset = of_reg[1] - pdata->width / 8;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE) {
 		dev_dbg(dev, "no valid base register address\n");
 		return -EINVAL;
 	}
 	pdata->base = addr;
 
-	pdata->mask = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+	pdata->mask = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 				     "pinctrl-single,function-mask",
 				     0xffffffff);
 	return 0;
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c
index 9efad06..02e2690 100644
--- a/drivers/pinctrl/pinctrl-uclass.c
+++ b/drivers/pinctrl/pinctrl-uclass.c
@@ -8,10 +8,9 @@
 #include <libfdt.h>
 #include <linux/err.h>
 #include <linux/list.h>
-#include <dm/device.h>
+#include <dm.h>
 #include <dm/lists.h>
 #include <dm/pinctrl.h>
-#include <dm/uclass.h>
 #include <dm/util.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -122,34 +121,31 @@
  */
 static int pinconfig_post_bind(struct udevice *dev)
 {
-	const void *fdt = gd->fdt_blob;
-	int offset = dev_of_offset(dev);
 	bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC);
 	const char *name;
+	ofnode node;
 	int ret;
 
-	for (offset = fdt_first_subnode(fdt, offset);
-	     offset > 0;
-	     offset = fdt_next_subnode(fdt, offset)) {
+	dev_for_each_subnode(node, dev) {
 		if (pre_reloc_only &&
-		    !dm_fdt_pre_reloc(fdt, offset))
+		    !ofnode_pre_reloc(node))
 			continue;
 		/*
 		 * If this node has "compatible" property, this is not
 		 * a pin configuration node, but a normal device. skip.
 		 */
-		fdt_get_property(fdt, offset, "compatible", &ret);
+		ofnode_read_prop(node, "compatible", &ret);
 		if (ret >= 0)
 			continue;
 
 		if (ret != -FDT_ERR_NOTFOUND)
 			return ret;
 
-		name = fdt_get_name(fdt, offset, NULL);
+		name = ofnode_get_name(node);
 		if (!name)
 			return -EINVAL;
 		ret = device_bind_driver_to_node(dev, "pinconfig", name,
-						 offset, NULL);
+						 node, NULL);
 		if (ret)
 			return ret;
 	}
diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
index d7b5ea3..5bee7fb 100644
--- a/drivers/pinctrl/pinctrl_stm32.c
+++ b/drivers/pinctrl/pinctrl_stm32.c
@@ -101,7 +101,7 @@
 	int rv, len;
 
 	/* Get node pinctrl-0 */
-	rv = fdtdec_parse_phandle_with_args(gd->fdt_blob, periph->of_offset,
+	rv = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(periph),
 					   "pinctrl-0", 0, 0, 0, &args);
 	if (rv)
 		return rv;
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3188.c b/drivers/pinctrl/rockchip/pinctrl_rk3188.c
index ef94dab..65c1f66 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3188.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3188.c
@@ -370,7 +370,7 @@
 	u32 cell[3];
 	int ret;
 
-	ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset,
+	ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(periph),
 				   "interrupts", cell, ARRAY_SIZE(cell));
 	if (ret < 0)
 		return -EINVAL;
@@ -516,7 +516,7 @@
 	u32 cell[60], *ptr;
 
 	debug("%s: %s %s\n", __func__, dev->name, config->name);
-	ret = fdtdec_get_int_array_count(blob, config->of_offset,
+	ret = fdtdec_get_int_array_count(blob, dev_of_offset(config),
 					 "rockchip,pins", cell,
 					 ARRAY_SIZE(cell));
 	if (ret < 0) {
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3328.c b/drivers/pinctrl/rockchip/pinctrl_rk3328.c
index 5ca6782..b6beec5 100644
--- a/drivers/pinctrl/rockchip/pinctrl_rk3328.c
+++ b/drivers/pinctrl/rockchip/pinctrl_rk3328.c
@@ -347,7 +347,7 @@
 	u32 cell[3];
 	int ret;
 
-	ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset,
+	ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(periph),
 				   "interrupts", cell, ARRAY_SIZE(cell));
 	if (ret < 0)
 		return -EINVAL;
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index d8e9948..d314482 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -6,10 +6,10 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/sizes.h>
-#include <dm/device.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-uniphier.h"
@@ -299,7 +299,7 @@
 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev->parent);
+	addr = devfdt_get_addr(dev->parent);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c
index 53c37cd..9c2db1a 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c
@@ -5,7 +5,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-uniphier.h"
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c
index 5a7d142..0b0af1c 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c
@@ -5,7 +5,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-uniphier.h"
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
index 9b3db9d..709b005 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
@@ -5,7 +5,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-uniphier.h"
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
index b25c7ea..6ade131 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
@@ -5,7 +5,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-uniphier.h"
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
index f1624da..df5f2d8 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
@@ -5,7 +5,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-uniphier.h"
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
index 70c90ba..7b14662 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
@@ -5,7 +5,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-uniphier.h"
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
index 60777c3..90d6329 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
@@ -5,7 +5,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-uniphier.h"
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs3.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs3.c
index 65b56da..86752d9 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs3.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs3.c
@@ -5,7 +5,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-uniphier.h"
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld3.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld3.c
index d3a507e..e9cc9d2 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld3.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld3.c
@@ -5,7 +5,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-uniphier.h"
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
index 471fb67..897ce15 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
@@ -5,7 +5,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <dm/pinctrl.h>
 
 #include "pinctrl-uniphier.h"
diff --git a/drivers/power/domain/bcm6328-power-domain.c b/drivers/power/domain/bcm6328-power-domain.c
index 15638bf..776afa3 100644
--- a/drivers/power/domain/bcm6328-power-domain.c
+++ b/drivers/power/domain/bcm6328-power-domain.c
@@ -52,7 +52,7 @@
 	fdt_addr_t addr;
 	fdt_size_t size;
 
-	addr = dev_get_addr_size_index(dev, 0, &size);
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/power/domain/power-domain-uclass.c b/drivers/power/domain/power-domain-uclass.c
index 3dabbe4..1847a49 100644
--- a/drivers/power/domain/power-domain-uclass.c
+++ b/drivers/power/domain/power-domain-uclass.c
@@ -6,7 +6,6 @@
 
 #include <common.h>
 #include <dm.h>
-#include <fdtdec.h>
 #include <power-domain.h>
 #include <power-domain-uclass.h>
 
@@ -18,7 +17,7 @@
 }
 
 static int power_domain_of_xlate_default(struct power_domain *power_domain,
-				       struct fdtdec_phandle_args *args)
+					 struct ofnode_phandle_args *args)
 {
 	debug("%s(power_domain=%p)\n", __func__, power_domain);
 
@@ -34,27 +33,25 @@
 
 int power_domain_get(struct udevice *dev, struct power_domain *power_domain)
 {
-	struct fdtdec_phandle_args args;
+	struct ofnode_phandle_args args;
 	int ret;
 	struct udevice *dev_power_domain;
 	struct power_domain_ops *ops;
 
 	debug("%s(dev=%p, power_domain=%p)\n", __func__, dev, power_domain);
 
-	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
-					     "power-domains",
-					     "#power-domain-cells", 0, 0,
-					     &args);
+	ret = dev_read_phandle_with_args(dev, "power-domains",
+					 "#power-domain-cells", 0, 0, &args);
 	if (ret) {
-		debug("%s: fdtdec_parse_phandle_with_args failed: %d\n",
+		debug("%s: dev_read_phandle_with_args failed: %d\n",
 		      __func__, ret);
 		return ret;
 	}
 
-	ret = uclass_get_device_by_of_offset(UCLASS_POWER_DOMAIN, args.node,
-					     &dev_power_domain);
+	ret = uclass_get_device_by_ofnode(UCLASS_POWER_DOMAIN, args.node,
+					  &dev_power_domain);
 	if (ret) {
-		debug("%s: uclass_get_device_by_of_offset failed: %d\n",
+		debug("%s: uclass_get_device_by_ofnode failed: %d\n",
 		      __func__, ret);
 		return ret;
 	}
diff --git a/drivers/power/pmic/act8846.c b/drivers/power/pmic/act8846.c
index 15da12e..a6b0940 100644
--- a/drivers/power/pmic/act8846.c
+++ b/drivers/power/pmic/act8846.c
@@ -48,13 +48,11 @@
 
 static int act8846_bind(struct udevice *dev)
 {
-	const void *blob = gd->fdt_blob;
-	int regulators_node;
+	ofnode regulators_node;
 	int children;
 
-	regulators_node = fdt_subnode_offset(blob, dev_of_offset(dev),
-					     "regulators");
-	if (regulators_node <= 0) {
+	regulators_node = dev_read_subnode(dev, "regulators");
+	if (!ofnode_valid(regulators_node)) {
 		debug("%s: %s regulators subnode not found!", __func__,
 		      dev->name);
 		return -ENXIO;
diff --git a/drivers/power/pmic/i2c_pmic_emul.c b/drivers/power/pmic/i2c_pmic_emul.c
index 4f92e3d..2d35d09 100644
--- a/drivers/power/pmic/i2c_pmic_emul.c
+++ b/drivers/power/pmic/i2c_pmic_emul.c
@@ -6,7 +6,6 @@
  */
 
 #include <common.h>
-#include <fdtdec.h>
 #include <errno.h>
 #include <dm.h>
 #include <i2c.h>
@@ -108,9 +107,8 @@
 
 	debug("%s:%d Setting PMIC default registers\n", __func__, __LINE__);
 
-	reg_defaults = fdtdec_locate_byte_array(gd->fdt_blob,
-			dev_of_offset(emul), "reg-defaults",
-			SANDBOX_PMIC_REG_COUNT);
+	reg_defaults = dev_read_u8_array_ptr(emul, "reg-defaults",
+					     SANDBOX_PMIC_REG_COUNT);
 
 	if (!reg_defaults) {
 		error("Property \"reg-defaults\" not found for device: %s!",
diff --git a/drivers/power/pmic/lp873x.c b/drivers/power/pmic/lp873x.c
index d8f30df..f505468 100644
--- a/drivers/power/pmic/lp873x.c
+++ b/drivers/power/pmic/lp873x.c
@@ -46,15 +46,13 @@
 
 static int lp873x_bind(struct udevice *dev)
 {
-	int regulators_node;
-	const void *blob = gd->fdt_blob;
+	ofnode regulators_node;
 	int children;
-	int node = dev_of_offset(dev);
 
-	regulators_node = fdt_subnode_offset(blob, node, "regulators");
-
-	if (regulators_node <= 0) {
-		printf("%s: %s reg subnode not found!", __func__, dev->name);
+	regulators_node = dev_read_subnode(dev, "regulators");
+	if (!ofnode_valid(regulators_node)) {
+		debug("%s: %s regulators subnode not found!", __func__,
+		      dev->name);
 		return -ENXIO;
 	}
 
diff --git a/drivers/power/pmic/max77686.c b/drivers/power/pmic/max77686.c
index 8295fab..ceca9f9 100644
--- a/drivers/power/pmic/max77686.c
+++ b/drivers/power/pmic/max77686.c
@@ -50,13 +50,11 @@
 
 static int max77686_bind(struct udevice *dev)
 {
-	int regulators_node;
-	const void *blob = gd->fdt_blob;
+	ofnode regulators_node;
 	int children;
 
-	regulators_node = fdt_subnode_offset(blob, dev_of_offset(dev),
-					     "voltage-regulators");
-	if (regulators_node <= 0) {
+	regulators_node = dev_read_subnode(dev, "voltage-regulators");
+	if (!ofnode_valid(regulators_node)) {
 		debug("%s: %s regulators subnode not found!", __func__,
 							     dev->name);
 		return -ENXIO;
diff --git a/drivers/power/pmic/palmas.c b/drivers/power/pmic/palmas.c
index f5a2307..804c0d1 100644
--- a/drivers/power/pmic/palmas.c
+++ b/drivers/power/pmic/palmas.c
@@ -46,17 +46,15 @@
 
 static int palmas_bind(struct udevice *dev)
 {
-	int pmic_node = -1, regulators_node;
-	const void *blob = gd->fdt_blob;
+	ofnode pmic_node = ofnode_null(), regulators_node;
+	ofnode subnode;
 	int children;
-	int node = dev_of_offset(dev);
-	int subnode, len;
 
-	fdt_for_each_subnode(subnode, blob, node) {
+	dev_for_each_subnode(subnode, dev) {
 		const char *name;
 		char *temp;
 
-		name = fdt_get_name(blob, subnode, &len);
+		name = ofnode_get_name(subnode);
 		temp = strstr(name, "pmic");
 		if (temp) {
 			pmic_node = subnode;
@@ -64,14 +62,14 @@
 		}
 	}
 
-	if (pmic_node <= 0) {
+	if (!ofnode_valid(pmic_node)) {
 		debug("%s: %s pmic subnode not found!", __func__, dev->name);
 		return -ENXIO;
 	}
 
-	regulators_node = fdt_subnode_offset(blob, pmic_node, "regulators");
+	regulators_node = ofnode_find_subnode(pmic_node, "regulators");
 
-	if (regulators_node <= 0) {
+	if (!ofnode_valid(regulators_node)) {
 		debug("%s: %s reg subnode not found!", __func__, dev->name);
 		return -ENXIO;
 	}
diff --git a/drivers/power/pmic/pfuze100.c b/drivers/power/pmic/pfuze100.c
index 90a43f2..5f361c7 100644
--- a/drivers/power/pmic/pfuze100.c
+++ b/drivers/power/pmic/pfuze100.c
@@ -52,13 +52,11 @@
 
 static int pfuze100_bind(struct udevice *dev)
 {
+	ofnode regulators_node;
 	int children;
-	int regulators_node;
-	const void *blob = gd->fdt_blob;
 
-	regulators_node = fdt_subnode_offset(blob, dev_of_offset(dev),
-					     "regulators");
-	if (regulators_node <= 0) {
+	regulators_node = dev_read_subnode(dev, "regulators");
+	if (!ofnode_valid(regulators_node)) {
 		debug("%s: %s regulators subnode not found!", __func__,
 		      dev->name);
 		return -ENXIO;
diff --git a/drivers/power/pmic/pm8916.c b/drivers/power/pmic/pm8916.c
index 2b65c69..a048bbe 100644
--- a/drivers/power/pmic/pm8916.c
+++ b/drivers/power/pmic/pm8916.c
@@ -70,7 +70,7 @@
 {
 	struct pm8916_priv *priv = dev_get_priv(dev);
 
-	priv->usid = dev_get_addr(dev);
+	priv->usid = dev_read_addr(dev);
 
 	if (priv->usid == FDT_ADDR_T_NONE)
 		return -EINVAL;
diff --git a/drivers/power/pmic/pmic-uclass.c b/drivers/power/pmic/pmic-uclass.c
index 0f7fa51..953bbe5 100644
--- a/drivers/power/pmic/pmic-uclass.c
+++ b/drivers/power/pmic/pmic-uclass.c
@@ -19,29 +19,27 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
-int pmic_bind_children(struct udevice *pmic, int offset,
+int pmic_bind_children(struct udevice *pmic, ofnode parent,
 		       const struct pmic_child_info *child_info)
 {
 	const struct pmic_child_info *info;
-	const void *blob = gd->fdt_blob;
 	struct driver *drv;
 	struct udevice *child;
 	const char *node_name;
 	int bind_count = 0;
-	int node;
+	ofnode node;
 	int prefix_len;
 	int ret;
 
 	debug("%s for '%s' at node offset: %d\n", __func__, pmic->name,
 	      dev_of_offset(pmic));
 
-	for (node = fdt_first_subnode(blob, offset);
-	     node > 0;
-	     node = fdt_next_subnode(blob, node)) {
-		node_name = fdt_get_name(blob, node, NULL);
+	for (node = ofnode_first_subnode(parent);
+	     ofnode_valid(node);
+	     node = ofnode_next_subnode(node)) {
+		node_name = ofnode_get_name(node);
 
-		debug("* Found child node: '%s' at offset:%d\n", node_name,
-								 node);
+		debug("* Found child node: '%s'\n", node_name);
 
 		child = NULL;
 		for (info = child_info; info->prefix && info->driver; info++) {
@@ -60,8 +58,8 @@
 
 			debug("  - found child driver: '%s'\n", drv->name);
 
-			ret = device_bind(pmic, drv, node_name, NULL,
-					  node, &child);
+			ret = device_bind_with_driver_data(pmic, drv, node_name,
+							   0, node, &child);
 			if (ret) {
 				debug("  - child binding error: %d\n", ret);
 				continue;
@@ -82,7 +80,7 @@
 			debug("  - compatible prefix not found\n");
 	}
 
-	debug("Bound: %d childs for PMIC: '%s'\n", bind_count, pmic->name);
+	debug("Bound: %d children for PMIC: '%s'\n", bind_count, pmic->name);
 	return bind_count;
 }
 #endif
diff --git a/drivers/power/pmic/pmic_tps65218.c b/drivers/power/pmic/pmic_tps65218.c
index f32fa40..c5e768a 100644
--- a/drivers/power/pmic/pmic_tps65218.c
+++ b/drivers/power/pmic/pmic_tps65218.c
@@ -101,7 +101,7 @@
 
 	/* set voltage level */
 	if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
-			       TPS65218_MASK_ALL_BITS))
+			       TPS65218_DCDC_VSEL_MASK))
 		return 1;
 
 	/* set GO bit to initiate voltage transition */
diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
index 394e2ff..09b9b54 100644
--- a/drivers/power/pmic/rk8xx.c
+++ b/drivers/power/pmic/rk8xx.c
@@ -57,13 +57,11 @@
 #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
 static int rk8xx_bind(struct udevice *dev)
 {
-	const void *blob = gd->fdt_blob;
-	int regulators_node;
+	ofnode regulators_node;
 	int children;
 
-	regulators_node = fdt_subnode_offset(blob, dev_of_offset(dev),
-					     "regulators");
-	if (regulators_node <= 0) {
+	regulators_node = dev_read_subnode(dev, "regulators");
+	if (!ofnode_valid(regulators_node)) {
 		debug("%s: %s regulators subnode not found!", __func__,
 		      dev->name);
 		return -ENXIO;
diff --git a/drivers/power/pmic/s5m8767.c b/drivers/power/pmic/s5m8767.c
index 25d673b..f8ae5ea 100644
--- a/drivers/power/pmic/s5m8767.c
+++ b/drivers/power/pmic/s5m8767.c
@@ -54,12 +54,11 @@
 
 static int s5m8767_bind(struct udevice *dev)
 {
-	int node;
-	const void *blob = gd->fdt_blob;
 	int children;
+	ofnode node;
 
-	node = fdt_subnode_offset(blob, dev_of_offset(dev), "regulators");
-	if (node <= 0) {
+	node = dev_read_subnode(dev, "regulators");
+	if (!ofnode_valid(node)) {
 		debug("%s: %s regulators subnode not found!", __func__,
 		      dev->name);
 		return -ENXIO;
diff --git a/drivers/power/pmic/sandbox.c b/drivers/power/pmic/sandbox.c
index b4e412e..6763303 100644
--- a/drivers/power/pmic/sandbox.c
+++ b/drivers/power/pmic/sandbox.c
@@ -51,7 +51,7 @@
 
 static int sandbox_pmic_bind(struct udevice *dev)
 {
-	if (!pmic_bind_children(dev, dev_of_offset(dev), pmic_children_info))
+	if (!pmic_bind_children(dev, dev_ofnode(dev), pmic_children_info))
 		error("%s:%d PMIC: %s - no child found!", __func__, __LINE__,
 							  dev->name);
 
diff --git a/drivers/power/pmic/tps65090.c b/drivers/power/pmic/tps65090.c
index b30a7f0..4565e3b 100644
--- a/drivers/power/pmic/tps65090.c
+++ b/drivers/power/pmic/tps65090.c
@@ -52,13 +52,11 @@
 
 static int tps65090_bind(struct udevice *dev)
 {
-	int regulators_node;
-	const void *blob = gd->fdt_blob;
+	ofnode regulators_node;
 	int children;
 
-	regulators_node = fdt_subnode_offset(blob, dev_of_offset(dev),
-					     "regulators");
-	if (regulators_node <= 0) {
+	regulators_node = dev_read_subnode(dev, "regulators");
+	if (!ofnode_valid(regulators_node)) {
 		debug("%s: %s regulators subnode not found!", __func__,
 		      dev->name);
 		return -ENXIO;
diff --git a/drivers/power/regulator/fixed.c b/drivers/power/regulator/fixed.c
index cd52137..656371b 100644
--- a/drivers/power/regulator/fixed.c
+++ b/drivers/power/regulator/fixed.c
@@ -7,7 +7,6 @@
  */
 
 #include <common.h>
-#include <fdtdec.h>
 #include <errno.h>
 #include <dm.h>
 #include <i2c.h>
@@ -27,8 +26,7 @@
 	struct dm_regulator_uclass_platdata *uc_pdata;
 	struct fixed_regulator_platdata *dev_pdata;
 	struct gpio_desc *gpio;
-	const void *blob = gd->fdt_blob;
-	int node = dev_of_offset(dev), flags = GPIOD_IS_OUT;
+	int flags = GPIOD_IS_OUT;
 	int ret;
 
 	dev_pdata = dev_get_platdata(dev);
@@ -39,7 +37,7 @@
 	/* Set type to fixed */
 	uc_pdata->type = REGULATOR_TYPE_FIXED;
 
-	if (fdtdec_get_bool(blob, node, "enable-active-high"))
+	if (dev_read_bool(dev, "enable-active-high"))
 		flags |= GPIOD_IS_OUT_ACTIVE;
 
 	/* Get fixed regulator optional enable GPIO desc */
@@ -53,9 +51,8 @@
 	}
 
 	/* Get optional ramp up delay */
-	dev_pdata->startup_delay_us = fdtdec_get_uint(gd->fdt_blob,
-						      dev_of_offset(dev),
-						      "startup-delay-us", 0);
+	dev_pdata->startup_delay_us = dev_read_u32_default(dev,
+							"startup-delay-us", 0);
 
 	return 0;
 }
@@ -108,8 +105,11 @@
 	struct fixed_regulator_platdata *dev_pdata = dev_get_platdata(dev);
 	int ret;
 
+	debug("%s: dev='%s', enable=%d, delay=%d, has_gpio=%d\n", __func__,
+	      dev->name, enable, dev_pdata->startup_delay_us,
+	      dm_gpio_is_valid(&dev_pdata->gpio));
 	/* Enable GPIO is optional */
-	if (!dev_pdata->gpio.dev) {
+	if (!dm_gpio_is_valid(&dev_pdata->gpio)) {
 		if (!enable)
 			return -ENOSYS;
 		return 0;
@@ -124,6 +124,7 @@
 
 	if (enable && dev_pdata->startup_delay_us)
 		udelay(dev_pdata->startup_delay_us);
+	debug("%s: done\n", __func__);
 
 	return 0;
 }
diff --git a/drivers/power/regulator/max77686.c b/drivers/power/regulator/max77686.c
index 7479af7..5e5815f 100644
--- a/drivers/power/regulator/max77686.c
+++ b/drivers/power/regulator/max77686.c
@@ -71,8 +71,8 @@
 
 static int max77686_buck_volt2hex(int buck, int uV)
 {
-	unsigned int hex = 0;
-	unsigned int hex_max = 0;
+	int hex = 0;
+	int hex_max = 0;
 
 	switch (buck) {
 	case 2:
@@ -105,7 +105,7 @@
 static int max77686_buck_hex2volt(int buck, int hex)
 {
 	unsigned uV = 0;
-	unsigned int hex_max = 0;
+	int hex_max = 0;
 
 	if (hex < 0)
 		goto bad_hex;
@@ -140,7 +140,7 @@
 
 static int max77686_ldo_volt2hex(int ldo, int uV)
 {
-	unsigned int hex = 0;
+	int hex = 0;
 
 	switch (ldo) {
 	case 1:
@@ -319,9 +319,9 @@
 
 static int max77686_ldo_val(struct udevice *dev, int op, int *uV)
 {
-	unsigned int hex, adr;
+	unsigned int adr;
 	unsigned char val;
-	int ldo, ret;
+	int hex, ldo, ret;
 
 	if (op == PMIC_OP_GET)
 		*uV = 0;
@@ -360,9 +360,9 @@
 
 static int max77686_buck_val(struct udevice *dev, int op, int *uV)
 {
-	unsigned int hex, mask, adr;
+	unsigned int mask, adr;
 	unsigned char val;
-	int buck, ret;
+	int hex, buck, ret;
 
 	buck = dev->driver_data;
 	if (buck < 1 || buck > MAX77686_BUCK_NUM) {
diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c
index 2e0b5ed..a42f80b 100644
--- a/drivers/power/regulator/regulator-uclass.c
+++ b/drivers/power/regulator/regulator-uclass.c
@@ -4,8 +4,8 @@
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
+
 #include <common.h>
-#include <fdtdec.h>
 #include <errno.h>
 #include <dm.h>
 #include <dm/uclass-internal.h>
@@ -278,20 +278,16 @@
 static int regulator_post_bind(struct udevice *dev)
 {
 	struct dm_regulator_uclass_platdata *uc_pdata;
-	int offset = dev_of_offset(dev);
-	const void *blob = gd->fdt_blob;
 	const char *property = "regulator-name";
 
 	uc_pdata = dev_get_uclass_platdata(dev);
-	if (!uc_pdata)
-		return -ENXIO;
 
 	/* Regulator's mandatory constraint */
-	uc_pdata->name = fdt_getprop(blob, offset, property, NULL);
+	uc_pdata->name = dev_read_string(dev, property);
 	if (!uc_pdata->name) {
-		debug("%s: dev: %s has no property 'regulator-name'\n",
-		      __func__, dev->name);
-		uc_pdata->name = fdt_get_name(blob, offset, NULL);
+		debug("%s: dev '%s' has no property '%s'\n",
+		      __func__, dev->name, property);
+		uc_pdata->name = dev_read_name(dev);
 		if (!uc_pdata->name)
 			return -EINVAL;
 	}
@@ -299,7 +295,7 @@
 	if (regulator_name_is_unique(dev, uc_pdata->name))
 		return 0;
 
-	debug("\"%s\" of dev: \"%s\", has nonunique value: \"%s\"",
+	debug("'%s' of dev: '%s', has nonunique value: '%s\n",
 	      property, dev->name, uc_pdata->name);
 
 	return -EINVAL;
@@ -308,25 +304,22 @@
 static int regulator_pre_probe(struct udevice *dev)
 {
 	struct dm_regulator_uclass_platdata *uc_pdata;
-	int offset = dev_of_offset(dev);
 
 	uc_pdata = dev_get_uclass_platdata(dev);
 	if (!uc_pdata)
 		return -ENXIO;
 
 	/* Regulator's optional constraints */
-	uc_pdata->min_uV = fdtdec_get_int(gd->fdt_blob, offset,
-					  "regulator-min-microvolt", -ENODATA);
-	uc_pdata->max_uV = fdtdec_get_int(gd->fdt_blob, offset,
-					  "regulator-max-microvolt", -ENODATA);
-	uc_pdata->min_uA = fdtdec_get_int(gd->fdt_blob, offset,
-					  "regulator-min-microamp", -ENODATA);
-	uc_pdata->max_uA = fdtdec_get_int(gd->fdt_blob, offset,
-					  "regulator-max-microamp", -ENODATA);
-	uc_pdata->always_on = fdtdec_get_bool(gd->fdt_blob, offset,
-					      "regulator-always-on");
-	uc_pdata->boot_on = fdtdec_get_bool(gd->fdt_blob, offset,
-					    "regulator-boot-on");
+	uc_pdata->min_uV = dev_read_u32_default(dev, "regulator-min-microvolt",
+						-ENODATA);
+	uc_pdata->max_uV = dev_read_u32_default(dev, "regulator-max-microvolt",
+						-ENODATA);
+	uc_pdata->min_uA = dev_read_u32_default(dev, "regulator-min-microamp",
+						-ENODATA);
+	uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp",
+						-ENODATA);
+	uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
+	uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
 
 	/* Those values are optional (-ENODATA if unset) */
 	if ((uc_pdata->min_uV != -ENODATA) &&
diff --git a/drivers/pwm/exynos_pwm.c b/drivers/pwm/exynos_pwm.c
index a0edafc..9520a14 100644
--- a/drivers/pwm/exynos_pwm.c
+++ b/drivers/pwm/exynos_pwm.c
@@ -94,7 +94,7 @@
 {
 	struct exynos_pwm_priv *priv = dev_get_priv(dev);
 
-	priv->regs = (struct s5p_timer *)dev_get_addr(dev);
+	priv->regs = (struct s5p_timer *)devfdt_get_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/pwm/rk_pwm.c b/drivers/pwm/rk_pwm.c
index f3b2f76..59eae09 100644
--- a/drivers/pwm/rk_pwm.c
+++ b/drivers/pwm/rk_pwm.c
@@ -75,7 +75,7 @@
 {
 	struct rk_pwm_priv *priv = dev_get_priv(dev);
 
-	priv->regs = (struct rk3288_pwm *)dev_get_addr(dev);
+	priv->regs = (struct rk3288_pwm *)devfdt_get_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/pwm/tegra_pwm.c b/drivers/pwm/tegra_pwm.c
index 10e1fdc..d93ac28 100644
--- a/drivers/pwm/tegra_pwm.c
+++ b/drivers/pwm/tegra_pwm.c
@@ -59,7 +59,7 @@
 {
 	struct tegra_pwm_priv *priv = dev_get_priv(dev);
 
-	priv->regs = (struct pwm_ctlr *)dev_get_addr(dev);
+	priv->regs = (struct pwm_ctlr *)devfdt_get_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/ram/bmips_ram.c b/drivers/ram/bmips_ram.c
index d0f7cd7..3f9d9a8 100644
--- a/drivers/ram/bmips_ram.c
+++ b/drivers/ram/bmips_ram.c
@@ -9,10 +9,20 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <ram.h>
 #include <asm/io.h>
-#include <dm/device.h>
+
+#define SDRAM_CFG_REG		0x0
+#define SDRAM_CFG_COL_SHIFT	4
+#define SDRAM_CFG_COL_MASK	(0x3 << SDRAM_CFG_COL_SHIFT)
+#define SDRAM_CFG_ROW_SHIFT	6
+#define SDRAM_CFG_ROW_MASK	(0x3 << SDRAM_CFG_ROW_SHIFT)
+#define SDRAM_CFG_32B_SHIFT	10
+#define SDRAM_CFG_32B_MASK	(1 << SDRAM_CFG_32B_SHIFT)
+#define SDRAM_CFG_BANK_SHIFT	13
+#define SDRAM_CFG_BANK_MASK	(1 << SDRAM_CFG_BANK_SHIFT)
 
 #define MEMC_CFG_REG		0x4
 #define MEMC_CFG_32B_SHIFT	1
@@ -40,24 +50,41 @@
 	return readl_be(priv->regs + DDR_CSEND_REG) << 24;
 }
 
+static ulong bmips_dram_size(unsigned int cols, unsigned int rows,
+			     unsigned int is_32b, unsigned int banks)
+{
+	rows += 11; /* 0 => 11 address bits ... 2 => 13 address bits */
+	cols += 8; /* 0 => 8 address bits ... 2 => 10 address bits */
+	is_32b += 1;
+
+	return 1 << (cols + rows + is_32b + banks);
+}
+
+static ulong bcm6338_get_ram_size(struct bmips_ram_priv *priv)
+{
+	unsigned int cols = 0, rows = 0, is_32b = 0, banks = 0;
+	u32 val;
+
+	val = readl_be(priv->regs + SDRAM_CFG_REG);
+	rows = (val & SDRAM_CFG_ROW_MASK) >> SDRAM_CFG_ROW_SHIFT;
+	cols = (val & SDRAM_CFG_COL_MASK) >> SDRAM_CFG_COL_SHIFT;
+	is_32b = (val & SDRAM_CFG_32B_MASK) ? 1 : 0;
+	banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1;
+
+	return bmips_dram_size(cols, rows, is_32b, banks);
+}
+
 static ulong bcm6358_get_ram_size(struct bmips_ram_priv *priv)
 {
-	unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0;
+	unsigned int cols = 0, rows = 0, is_32b = 0;
 	u32 val;
 
 	val = readl_be(priv->regs + MEMC_CFG_REG);
 	rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT;
 	cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT;
-	is_32bits = (val & MEMC_CFG_32B_MASK) ? 0 : 1;
-	banks = 2;
+	is_32b = (val & MEMC_CFG_32B_MASK) ? 0 : 1;
 
-	/* 0 => 11 address bits ... 2 => 13 address bits */
-	rows += 11;
-
-	/* 0 => 8 address bits ... 2 => 10 address bits */
-	cols += 8;
-
-	return 1 << (cols + rows + (is_32bits + 1) + banks);
+	return bmips_dram_size(cols, rows, is_32b, 2);
 }
 
 static int bmips_ram_get_info(struct udevice *dev, struct ram_info *info)
@@ -79,6 +106,10 @@
 	.get_ram_size = bcm6328_get_ram_size,
 };
 
+static const struct bmips_ram_hw bmips_ram_bcm6338 = {
+	.get_ram_size = bcm6338_get_ram_size,
+};
+
 static const struct bmips_ram_hw bmips_ram_bcm6358 = {
 	.get_ram_size = bcm6358_get_ram_size,
 };
@@ -88,6 +119,9 @@
 		.compatible = "brcm,bcm6328-mc",
 		.data = (ulong)&bmips_ram_bcm6328,
 	}, {
+		.compatible = "brcm,bcm6338-mc",
+		.data = (ulong)&bmips_ram_bcm6338,
+	}, {
 		.compatible = "brcm,bcm6358-mc",
 		.data = (ulong)&bmips_ram_bcm6358,
 	}, { /* sentinel */ }
@@ -101,7 +135,7 @@
 	fdt_addr_t addr;
 	fdt_size_t size;
 
-	addr = dev_get_addr_size_index(dev, 0, &size);
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/ram/stm32_sdram.c b/drivers/ram/stm32_sdram.c
index 48b4979..b640519 100644
--- a/drivers/ram/stm32_sdram.c
+++ b/drivers/ram/stm32_sdram.c
@@ -104,7 +104,7 @@
 static int stm32_fmc_ofdata_to_platdata(struct udevice *dev)
 {
 	int ret;
-	int node = dev->of_offset;
+	int node = dev_of_offset(dev);
 	const void *blob = gd->fdt_blob;
 	struct stm32_sdram_params *params = dev_get_platdata(dev);
 
diff --git a/drivers/reset/reset-bcm6345.c b/drivers/reset/reset-bcm6345.c
index 774c2a7..ebf6bee 100644
--- a/drivers/reset/reset-bcm6345.c
+++ b/drivers/reset/reset-bcm6345.c
@@ -70,7 +70,7 @@
 	fdt_addr_t addr;
 	fdt_size_t size;
 
-	addr = dev_get_addr_size_index(dev, 0, &size);
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c
index e92b24f..de3695f 100644
--- a/drivers/reset/reset-uclass.c
+++ b/drivers/reset/reset-uclass.c
@@ -18,7 +18,7 @@
 }
 
 static int reset_of_xlate_default(struct reset_ctl *reset_ctl,
-				  struct fdtdec_phandle_args *args)
+				  struct ofnode_phandle_args *args)
 {
 	debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
 
@@ -35,7 +35,7 @@
 int reset_get_by_index(struct udevice *dev, int index,
 		       struct reset_ctl *reset_ctl)
 {
-	struct fdtdec_phandle_args args;
+	struct ofnode_phandle_args args;
 	int ret;
 	struct udevice *dev_reset;
 	struct reset_ops *ops;
@@ -43,20 +43,20 @@
 	debug("%s(dev=%p, index=%d, reset_ctl=%p)\n", __func__, dev, index,
 	      reset_ctl);
 
-	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
-					     "resets", "#reset-cells", 0,
-					     index, &args);
+	ret = dev_read_phandle_with_args(dev, "resets", "#reset-cells", 0,
+					  index, &args);
 	if (ret) {
-		debug("%s: fdtdec_parse_phandle_with_args failed: %d\n",
+		debug("%s: fdtdec_parse_phandle_with_args() failed: %d\n",
 		      __func__, ret);
 		return ret;
 	}
 
-	ret = uclass_get_device_by_of_offset(UCLASS_RESET, args.node,
-					     &dev_reset);
+	ret = uclass_get_device_by_ofnode(UCLASS_RESET, args.node,
+					  &dev_reset);
 	if (ret) {
-		debug("%s: uclass_get_device_by_of_offset failed: %d\n",
+		debug("%s: uclass_get_device_by_ofnode() failed: %d\n",
 		      __func__, ret);
+		debug("%s %d\n", ofnode_get_name(args.node), args.args[0]);
 		return ret;
 	}
 	ops = reset_dev_ops(dev_reset);
@@ -88,8 +88,7 @@
 	debug("%s(dev=%p, name=%s, reset_ctl=%p)\n", __func__, dev, name,
 	      reset_ctl);
 
-	index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
-				      "reset-names", name);
+	index = dev_read_stringlist_search(dev, "reset-names", name);
 	if (index < 0) {
 		debug("fdt_stringlist_search() failed: %d\n", index);
 		return index;
diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c
index 29c4d4d..e98df43 100644
--- a/drivers/reset/reset-uniphier.c
+++ b/drivers/reset/reset-uniphier.c
@@ -6,8 +6,8 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <reset-uclass.h>
-#include <dm/device.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
@@ -254,7 +254,7 @@
 	struct uniphier_reset_priv *priv = dev_get_priv(dev);
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev->parent);
+	addr = devfdt_get_addr(dev->parent);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/rtc/i2c_rtc_emul.c b/drivers/rtc/i2c_rtc_emul.c
index 20827fd..0e06c97 100644
--- a/drivers/rtc/i2c_rtc_emul.c
+++ b/drivers/rtc/i2c_rtc_emul.c
@@ -16,7 +16,6 @@
 
 #include <common.h>
 #include <dm.h>
-#include <fdtdec.h>
 #include <i2c.h>
 #include <os.h>
 #include <rtc.h>
diff --git a/drivers/serial/altera_jtag_uart.c b/drivers/serial/altera_jtag_uart.c
index cb11b31..4a6e60f 100644
--- a/drivers/serial/altera_jtag_uart.c
+++ b/drivers/serial/altera_jtag_uart.c
@@ -97,7 +97,7 @@
 {
 	struct altera_jtaguart_platdata *plat = dev_get_platdata(dev);
 
-	plat->regs = map_physmem(dev_get_addr(dev),
+	plat->regs = map_physmem(devfdt_get_addr(dev),
 				 sizeof(struct altera_jtaguart_regs),
 				 MAP_NOCACHE);
 
diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c
index 8344940..75c0352 100644
--- a/drivers/serial/altera_uart.c
+++ b/drivers/serial/altera_uart.c
@@ -89,7 +89,7 @@
 {
 	struct altera_uart_platdata *plat = dev_get_platdata(dev);
 
-	plat->regs = map_physmem(dev_get_addr(dev),
+	plat->regs = map_physmem(devfdt_get_addr(dev),
 				 sizeof(struct altera_uart_regs),
 				 MAP_NOCACHE);
 	plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c
index 453f8eb..bb294ff 100644
--- a/drivers/serial/atmel_usart.c
+++ b/drivers/serial/atmel_usart.c
@@ -255,7 +255,7 @@
 #if CONFIG_IS_ENABLED(OF_CONTROL)
 	fdt_addr_t addr_base;
 
-	addr_base = dev_get_addr(dev);
+	addr_base = devfdt_get_addr(dev);
 	if (addr_base == FDT_ADDR_T_NONE)
 		return -ENODEV;
 
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 0eb7c02..52c52c1 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -395,7 +395,7 @@
 	int err;
 
 	/* try Processor Local Bus device first */
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 #if defined(CONFIG_PCI) && defined(CONFIG_DM_PCI)
 	if (addr == FDT_ADDR_T_NONE) {
 		/* then try pci device */
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index c2b9c5f..a9c4f89 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -74,7 +74,8 @@
 		 * bind it anyway.
 		 */
 		if (node > 0 &&
-		    !lists_bind_fdt(gd->dm_root, blob, node, &dev)) {
+		    !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node),
+				    &dev)) {
 			if (!device_probe(dev)) {
 				gd->cur_serial_dev = dev;
 				return;
diff --git a/drivers/serial/serial_ar933x.c b/drivers/serial/serial_ar933x.c
index aae66dc..09d2efe 100644
--- a/drivers/serial/serial_ar933x.c
+++ b/drivers/serial/serial_ar933x.c
@@ -149,7 +149,7 @@
 	fdt_addr_t addr;
 	u32 val;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_arc.c b/drivers/serial/serial_arc.c
index fc91977..da4a07a 100644
--- a/drivers/serial/serial_arc.c
+++ b/drivers/serial/serial_arc.c
@@ -114,7 +114,7 @@
 	struct arc_serial_platdata *plat = dev_get_platdata(dev);
 	DECLARE_GLOBAL_DATA_PTR;
 
-	plat->reg = (struct arc_serial_regs *)dev_get_addr(dev);
+	plat->reg = (struct arc_serial_regs *)devfdt_get_addr(dev);
 	plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 				       "clock-frequency", 0);
 
diff --git a/drivers/serial/serial_bcm283x_mu.c b/drivers/serial/serial_bcm283x_mu.c
index e7ed899..41c26b3 100644
--- a/drivers/serial/serial_bcm283x_mu.c
+++ b/drivers/serial/serial_bcm283x_mu.c
@@ -159,7 +159,7 @@
 	struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_bcm6345.c b/drivers/serial/serial_bcm6345.c
index db270e3..20f67f4 100644
--- a/drivers/serial/serial_bcm6345.c
+++ b/drivers/serial/serial_bcm6345.c
@@ -8,12 +8,12 @@
  */
 
 #include <clk.h>
+#include <dm.h>
 #include <debug_uart.h>
 #include <errno.h>
 #include <serial.h>
 #include <asm/io.h>
 #include <asm/types.h>
-#include <dm/device.h>
 
 /* UART Control register */
 #define UART_CTL_REG			0x0
@@ -141,6 +141,8 @@
 			UART_CTL_RXTIMEOUT_5 |
 			/* set 8 bits/symbol */
 			UART_CTL_BITSPERSYM_8 |
+			/* set 1 stop bit */
+			UART_CTL_STOPBITS_1 |
 			/* set parity to even */
 			UART_CTL_RXPAREVEN_MASK |
 			UART_CTL_TXPAREVEN_MASK);
@@ -155,11 +157,11 @@
 			UART_FIFO_CFG_TX_4);
 
 	/* set baud rate */
-	val = (clk / baudrate) / 16;
+	val = ((clk / baudrate) >> 4);
 	if (val & 0x1)
-		val = val;
+		val = (val >> 1);
 	else
-		val = val / 2 - 1;
+		val = (val >> 1) - 1;
 	writel_be(val, base + UART_BAUD_REG);
 
 	/* clear interrupts */
@@ -231,7 +233,7 @@
 	int ret;
 
 	/* get address */
-	addr = dev_get_addr_size_index(dev, 0, &size);
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
@@ -241,7 +243,7 @@
 	ret = clk_get_by_index(dev, 0, &clk);
 	if (ret < 0)
 		return ret;
-	priv->uartclk = clk_get_rate(&clk) / 2;
+	priv->uartclk = clk_get_rate(&clk);
 	clk_free(&clk);
 
 	/* initialize serial */
diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c
index 95e002e..382f8ba 100644
--- a/drivers/serial/serial_lpuart.c
+++ b/drivers/serial/serial_lpuart.c
@@ -416,10 +416,10 @@
 {
 	struct lpuart_serial_platdata *plat = dev->platdata;
 	const void *blob = gd->fdt_blob;
-	int node = dev->of_offset;
+	int node = dev_of_offset(dev);
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_meson.c b/drivers/serial/serial_meson.c
index 1b49426..363affb 100644
--- a/drivers/serial/serial_meson.c
+++ b/drivers/serial/serial_meson.c
@@ -108,7 +108,7 @@
 	struct meson_serial_platdata *plat = dev->platdata;
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c
index 63b3006..7bed756 100644
--- a/drivers/serial/serial_msm.c
+++ b/drivers/serial/serial_msm.c
@@ -201,7 +201,7 @@
 {
 	struct msm_serial_data *priv = dev_get_priv(dev);
 
-	priv->base = dev_get_addr(dev);
+	priv->base = devfdt_get_addr(dev);
 	if (priv->base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_mvebu_a3700.c b/drivers/serial/serial_mvebu_a3700.c
index 192e79a..4f9de88 100644
--- a/drivers/serial/serial_mvebu_a3700.c
+++ b/drivers/serial/serial_mvebu_a3700.c
@@ -105,7 +105,7 @@
 {
 	struct mvebu_platdata *plat = dev_get_platdata(dev);
 
-	plat->base = dev_get_addr_ptr(dev);
+	plat->base = devfdt_get_addr_ptr(dev);
 
 	return 0;
 }
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c
index 64126e2..75264fb 100644
--- a/drivers/serial/serial_mxc.c
+++ b/drivers/serial/serial_mxc.c
@@ -353,7 +353,7 @@
 	struct mxc_serial_platdata *plat = dev->platdata;
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index 941b424..4ec0f29 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -349,7 +349,7 @@
 	struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c
index 96842de..a2f692b 100644
--- a/drivers/serial/serial_s5p.c
+++ b/drivers/serial/serial_s5p.c
@@ -182,7 +182,7 @@
 	struct s5p_serial_platdata *plat = dev->platdata;
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_sti_asc.c b/drivers/serial/serial_sti_asc.c
index ce26c94..8dcd4f8 100644
--- a/drivers/serial/serial_sti_asc.c
+++ b/drivers/serial/serial_sti_asc.c
@@ -170,7 +170,7 @@
 	unsigned long val;
 	fdt_addr_t base;
 
-	base = dev_get_addr(dev);
+	base = devfdt_get_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_stm32x7.c b/drivers/serial/serial_stm32x7.c
index 1907cef..bdabf87 100644
--- a/drivers/serial/serial_stm32x7.c
+++ b/drivers/serial/serial_stm32x7.c
@@ -110,7 +110,7 @@
 	struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_uniphier.c b/drivers/serial/serial_uniphier.c
index 0e25cba..68895bd 100644
--- a/drivers/serial/serial_uniphier.c
+++ b/drivers/serial/serial_uniphier.c
@@ -6,11 +6,12 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#include <common.h>
+#include <dm.h>
 #include <linux/io.h>
 #include <linux/serial_reg.h>
 #include <linux/sizes.h>
 #include <linux/errno.h>
-#include <dm/device.h>
 #include <serial.h>
 #include <fdtdec.h>
 
@@ -95,7 +96,7 @@
 	fdt_addr_t base;
 	u32 tmp;
 
-	base = dev_get_addr(dev);
+	base = devfdt_get_addr(dev);
 	if (base == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/serial/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c
index a2e9303..fedd2a9 100644
--- a/drivers/serial/serial_xuartlite.c
+++ b/drivers/serial/serial_xuartlite.c
@@ -87,7 +87,7 @@
 {
 	struct uartlite_platdata *plat = dev_get_platdata(dev);
 
-	plat->regs = (struct uartlite *)dev_get_addr(dev);
+	plat->regs = (struct uartlite *)devfdt_get_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c
index a2967c0..4e86e5c 100644
--- a/drivers/serial/serial_zynq.c
+++ b/drivers/serial/serial_zynq.c
@@ -179,7 +179,7 @@
 {
 	struct zynq_uart_priv *priv = dev_get_priv(dev);
 
-	priv->regs = (struct uart_zynq *)dev_get_addr(dev);
+	priv->regs = (struct uart_zynq *)devfdt_get_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/sound/max98095.c b/drivers/sound/max98095.c
index 35829f8..7c37bd0 100644
--- a/drivers/sound/max98095.c
+++ b/drivers/sound/max98095.c
@@ -9,6 +9,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#include <common.h>
 #include <asm/arch/clk.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/power.h>
diff --git a/drivers/sound/wm8994.c b/drivers/sound/wm8994.c
index d378442..b8208cd 100644
--- a/drivers/sound/wm8994.c
+++ b/drivers/sound/wm8994.c
@@ -4,11 +4,11 @@
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
+#include <common.h>
 #include <asm/arch/clk.h>
 #include <asm/arch/cpu.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
-#include <common.h>
 #include <div64.h>
 #include <fdtdec.h>
 #include <i2c.h>
diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c
index eb1ba27..c8dcb82 100644
--- a/drivers/spi/altera_spi.c
+++ b/drivers/spi/altera_spi.c
@@ -174,7 +174,7 @@
 {
 	struct altera_spi_platdata *plat = dev_get_platdata(bus);
 
-	plat->regs = map_physmem(dev_get_addr(bus),
+	plat->regs = map_physmem(devfdt_get_addr(bus),
 				 sizeof(struct altera_spi_regs),
 				 MAP_NOCACHE);
 
diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c
index b18c733..f4b92aa 100644
--- a/drivers/spi/ath79_spi.c
+++ b/drivers/spi/ath79_spi.c
@@ -177,7 +177,7 @@
 	struct ath79_spi_priv *priv = dev_get_priv(bus);
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(bus);
+	addr = devfdt_get_addr(bus);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 4701b79..e2f8342 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -469,7 +469,7 @@
 	if (ret)
 		return ret;
 
-	bus_plat->regs = (struct at91_spi *)dev_get_addr(bus);
+	bus_plat->regs = (struct at91_spi *)devfdt_get_addr(bus);
 
 	ret = gpio_request_list_by_name(bus, "cs-gpios", priv->cs_gpios,
 					ARRAY_SIZE(priv->cs_gpios), 0);
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index 65d37b0..291ef95 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -542,7 +542,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
-	ds->regs = dev_map_physmem(bus, sizeof(struct davinci_spi_regs));
+	ds->regs = devfdt_map_physmem(bus, sizeof(struct davinci_spi_regs));
 	if (!ds->regs) {
 		printf("%s: could not map device address\n", __func__);
 		return -EINVAL;
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 9d5e29c..5aa507b 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -134,7 +134,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
-	plat->regs = (struct dw_spi *)dev_get_addr(bus);
+	plat->regs = (struct dw_spi *)devfdt_get_addr(bus);
 
 	/* Use 500KHz as a suitable default */
 	plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
index aa0784c..89490f7 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -255,7 +255,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
-	plat->regs = (struct exynos_spi *)dev_get_addr(bus);
+	plat->regs = (struct exynos_spi *)devfdt_get_addr(bus);
 	plat->periph_id = pinmux_decode_periph_id(blob, node);
 
 	if (plat->periph_id == PERIPH_ID_NONE) {
diff --git a/drivers/spi/fsl_dspi.c b/drivers/spi/fsl_dspi.c
index e09985e..4208619 100644
--- a/drivers/spi/fsl_dspi.c
+++ b/drivers/spi/fsl_dspi.c
@@ -9,6 +9,8 @@
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
+
+#include <common.h>
 #include <dm.h>
 #include <errno.h>
 #include <common.h>
@@ -654,7 +656,7 @@
 	plat->num_chipselect =
 		fdtdec_get_int(blob, node, "num-cs", FSL_DSPI_MAX_CHIPSELECT);
 
-	addr = dev_get_addr(bus);
+	addr = devfdt_get_addr(bus);
 	if (addr == FDT_ADDR_T_NONE) {
 		debug("DSPI: Can't get base address or size\n");
 		return -ENOMEM;
diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c
index 791f3e8..0c6bd29 100644
--- a/drivers/spi/kirkwood_spi.c
+++ b/drivers/spi/kirkwood_spi.c
@@ -327,7 +327,7 @@
 {
 	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
 
-	plat->spireg = (struct kwspi_registers *)dev_get_addr(bus);
+	plat->spireg = (struct kwspi_registers *)devfdt_get_addr(bus);
 
 	return 0;
 }
diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
index ee847e4..ec49073 100644
--- a/drivers/spi/mvebu_a3700_spi.c
+++ b/drivers/spi/mvebu_a3700_spi.c
@@ -251,7 +251,7 @@
 {
 	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
 
-	plat->spireg = (struct spi_reg *)dev_get_addr(bus);
+	plat->spireg = (struct spi_reg *)devfdt_get_addr(bus);
 
 	/*
 	 * FIXME
diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c
index 3caea15..ebbdcaf 100644
--- a/drivers/spi/omap3_spi.c
+++ b/drivers/spi/omap3_spi.c
@@ -633,7 +633,7 @@
 	struct omap2_mcspi_platform_config* data =
 		(struct omap2_mcspi_platform_config*)dev_get_driver_data(dev);
 
-	priv->regs = (struct mcspi *)(dev_get_addr(dev) + data->regs_offset);
+	priv->regs = (struct mcspi *)(devfdt_get_addr(dev) + data->regs_offset);
 	priv->pin_dir = fdtdec_get_uint(blob, node, "ti,pindir-d0-out-d1-in",
 					    MCSPI_PINDIR_D0_IN_D1_OUT);
 	priv->wordlen = SPI_DEFAULT_WORDLEN;
diff --git a/drivers/spi/pic32_spi.c b/drivers/spi/pic32_spi.c
index 78d78bc..15266b0 100644
--- a/drivers/spi/pic32_spi.c
+++ b/drivers/spi/pic32_spi.c
@@ -414,7 +414,7 @@
 	 * of the ongoing transfer. To avoid this sort of error we will drive
 	 * /CS manually by toggling cs-gpio pins.
 	 */
-	ret = gpio_request_by_name_nodev(gd->fdt_blob, node, "cs-gpios", 0,
+	ret = gpio_request_by_name_nodev(offset_to_ofnode(node), "cs-gpios", 0,
 					 &priv->cs_gpio, GPIOD_IS_OUT);
 	if (ret) {
 		printf("pic32-spi: error, cs-gpios not found\n");
diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c
index ea20980..a8f0eb0 100644
--- a/drivers/spi/rk_spi.c
+++ b/drivers/spi/rk_spi.c
@@ -186,7 +186,7 @@
 	int node = dev_of_offset(bus);
 	int ret;
 
-	plat->base = dev_get_addr(bus);
+	plat->base = devfdt_get_addr(bus);
 
 	ret = clk_get_by_index(bus, 0, &priv->clk);
 	if (ret < 0) {
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index c061c05..e06a603 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -7,7 +7,6 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
-#include <fdtdec.h>
 #include <malloc.h>
 #include <spi.h>
 #include <dm/device-internal.h>
@@ -113,11 +112,10 @@
 {
 	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
 
-	if (dev_of_offset(dev) == -1)
+	if (!dev_of_valid(dev))
 		return 0;
 
-	return spi_slave_ofdata_to_platdata(gd->fdt_blob, dev_of_offset(dev),
-					    plat);
+	return spi_slave_ofdata_to_platdata(dev, plat);
 }
 #endif
 
@@ -126,8 +124,7 @@
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	struct dm_spi_bus *spi = dev_get_uclass_priv(bus);
 
-	spi->max_hz = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus),
-				     "spi-max-frequency", 0);
+	spi->max_hz = dev_read_u32_default(bus, "spi-max-frequency", 0);
 #endif
 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
 	struct dm_spi_ops *ops = spi_get_ops(bus);
@@ -375,7 +372,7 @@
 	int ret;
 
 	ret = spi_get_bus_and_cs(busnum, cs, speed, mode, NULL, 0, &dev,
-				  &slave);
+				 &slave);
 	if (ret)
 		return NULL;
 
@@ -388,27 +385,27 @@
 	slave->dev = NULL;
 }
 
-int spi_slave_ofdata_to_platdata(const void *blob, int node,
+int spi_slave_ofdata_to_platdata(struct udevice *dev,
 				 struct dm_spi_slave_platdata *plat)
 {
 	int mode = 0;
 	int value;
 
-	plat->cs = fdtdec_get_int(blob, node, "reg", -1);
-	plat->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", 0);
-	if (fdtdec_get_bool(blob, node, "spi-cpol"))
+	plat->cs = dev_read_u32_default(dev, "reg", -1);
+	plat->max_hz = dev_read_u32_default(dev, "spi-max-frequency", 0);
+	if (dev_read_bool(dev, "spi-cpol"))
 		mode |= SPI_CPOL;
-	if (fdtdec_get_bool(blob, node, "spi-cpha"))
+	if (dev_read_bool(dev, "spi-cpha"))
 		mode |= SPI_CPHA;
-	if (fdtdec_get_bool(blob, node, "spi-cs-high"))
+	if (dev_read_bool(dev, "spi-cs-high"))
 		mode |= SPI_CS_HIGH;
-	if (fdtdec_get_bool(blob, node, "spi-3wire"))
+	if (dev_read_bool(dev, "spi-3wire"))
 		mode |= SPI_3WIRE;
-	if (fdtdec_get_bool(blob, node, "spi-half-duplex"))
+	if (dev_read_bool(dev, "spi-half-duplex"))
 		mode |= SPI_PREAMBLE;
 
 	/* Device DUAL/QUAD mode */
-	value = fdtdec_get_uint(blob, node, "spi-tx-bus-width", 1);
+	value = dev_read_u32_default(dev, "spi-tx-bus-width", 1);
 	switch (value) {
 	case 1:
 		break;
@@ -423,7 +420,7 @@
 		break;
 	}
 
-	value = fdtdec_get_uint(blob, node, "spi-rx-bus-width", 1);
+	value = dev_read_u32_default(dev, "spi-rx-bus-width", 1);
 	switch (value) {
 	case 1:
 		break;
diff --git a/drivers/spi/tegra114_spi.c b/drivers/spi/tegra114_spi.c
index 897409c..802117e 100644
--- a/drivers/spi/tegra114_spi.c
+++ b/drivers/spi/tegra114_spi.c
@@ -103,7 +103,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
-	plat->base = dev_get_addr(bus);
+	plat->base = devfdt_get_addr(bus);
 	plat->periph_id = clock_decode_periph_id(blob, node);
 
 	if (plat->periph_id == PERIPH_ID_NONE) {
diff --git a/drivers/spi/tegra20_sflash.c b/drivers/spi/tegra20_sflash.c
index ecbf4c1..299e1b4 100644
--- a/drivers/spi/tegra20_sflash.c
+++ b/drivers/spi/tegra20_sflash.c
@@ -90,7 +90,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
-	plat->base = dev_get_addr(bus);
+	plat->base = devfdt_get_addr(bus);
 	plat->periph_id = clock_decode_periph_id(blob, node);
 
 	if (plat->periph_id == PERIPH_ID_NONE) {
diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c
index 1d99a1e..4cbde7b 100644
--- a/drivers/spi/tegra20_slink.c
+++ b/drivers/spi/tegra20_slink.c
@@ -96,7 +96,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
-	plat->base = dev_get_addr(bus);
+	plat->base = devfdt_get_addr(bus);
 	plat->periph_id = clock_decode_periph_id(blob, node);
 
 	if (plat->periph_id == PERIPH_ID_NONE) {
diff --git a/drivers/spi/tegra210_qspi.c b/drivers/spi/tegra210_qspi.c
index 1e094cb..6d0b5da 100644
--- a/drivers/spi/tegra210_qspi.c
+++ b/drivers/spi/tegra210_qspi.c
@@ -99,7 +99,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
-	plat->base = dev_get_addr(bus);
+	plat->base = devfdt_get_addr(bus);
 	plat->periph_id = clock_decode_periph_id(blob, node);
 
 	if (plat->periph_id == PERIPH_ID_NONE) {
diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c
index 3c4c9dd..bea3aff 100644
--- a/drivers/spi/ti_qspi.c
+++ b/drivers/spi/ti_qspi.c
@@ -574,8 +574,8 @@
 		return NULL;
 	}
 
-	cell = fdt_getprop(gd->fdt_blob, bus->of_offset, "syscon-chipselects",
-			   &len);
+	cell = fdt_getprop(gd->fdt_blob, dev_of_offset(bus),
+			   "syscon-chipselects", &len);
 	if (len < 2*sizeof(fdt32_t)) {
 		debug("%s: offset not available\n", __func__);
 		return NULL;
@@ -584,7 +584,7 @@
 	return fdtdec_get_number(cell + 1, 1) + regmap_get_range(regmap, 0);
 #else
 	fdt_addr_t addr;
-	addr = dev_get_addr_index(bus, 2);
+	addr = devfdt_get_addr_index(bus, 2);
 	return (addr == FDT_ADDR_T_NONE) ? NULL :
 		map_physmem(addr, 0, MAP_NOCACHE);
 #endif
@@ -597,9 +597,9 @@
 	int node = dev_of_offset(bus);
 
 	priv->ctrl_mod_mmap = map_syscon_chipselects(bus);
-	priv->base = map_physmem(dev_get_addr(bus), sizeof(struct ti_qspi_regs),
-				 MAP_NOCACHE);
-	priv->memory_map = map_physmem(dev_get_addr_index(bus, 1), 0,
+	priv->base = map_physmem(devfdt_get_addr(bus),
+				 sizeof(struct ti_qspi_regs), MAP_NOCACHE);
+	priv->memory_map = map_physmem(devfdt_get_addr_index(bus, 1), 0,
 				       MAP_NOCACHE);
 
 	priv->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", -1);
diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c
index 2b77f1c..ed2b8cb 100644
--- a/drivers/spi/zynq_spi.c
+++ b/drivers/spi/zynq_spi.c
@@ -76,7 +76,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(bus);
 
-	plat->regs = (struct zynq_spi_regs *)dev_get_addr(bus);
+	plat->regs = (struct zynq_spi_regs *)devfdt_get_addr(bus);
 
 	/* FIXME: Use 250MHz as a suitable default */
 	plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c
index 605683f..ca27ee5 100644
--- a/drivers/spmi/spmi-msm.c
+++ b/drivers/spmi/spmi-msm.c
@@ -150,7 +150,7 @@
 	int node = dev_of_offset(dev);
 	int i;
 
-	priv->arb_chnl = dev_get_addr(dev);
+	priv->arb_chnl = devfdt_get_addr(dev);
 	priv->spmi_core = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
 			dev_of_offset(parent), node, "reg", 1, NULL, false);
 	priv->spmi_obs = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig
index b2f7464..a6d48e8 100644
--- a/drivers/sysreset/Kconfig
+++ b/drivers/sysreset/Kconfig
@@ -31,4 +31,10 @@
 	help
 	  Reboot support for generic SYSCON mapped register reset.
 
+config SYSRESET_WATCHDOG
+	bool "Enable support for watchdog reboot driver"
+	select WDT
+	help
+	  Reboot support for generic watchdog reset.
+
 endmenu
diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile
index bd352e7..b683811 100644
--- a/drivers/sysreset/Makefile
+++ b/drivers/sysreset/Makefile
@@ -7,6 +7,7 @@
 obj-$(CONFIG_SYSRESET) += sysreset-uclass.o
 obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o
 obj-$(CONFIG_SYSRESET_SYSCON) += sysreset_syscon.o
+obj-$(CONFIG_SYSRESET_WATCHDOG) += sysreset_watchdog.o
 
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ROCKCHIP_RK3036) += sysreset_rk3036.o
diff --git a/drivers/sysreset/sysreset_psci.c b/drivers/sysreset/sysreset_psci.c
index a4911b7..4656d27 100644
--- a/drivers/sysreset/sysreset_psci.c
+++ b/drivers/sysreset/sysreset_psci.c
@@ -4,7 +4,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <dm/device.h>
+#include <common.h>
+#include <dm.h>
 #include <sysreset.h>
 #include <linux/errno.h>
 #include <linux/psci.h>
diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c
index 0c4e2e1..12b3e5f 100644
--- a/drivers/sysreset/sysreset_sandbox.c
+++ b/drivers/sysreset/sysreset_sandbox.c
@@ -41,7 +41,7 @@
 	 * (see the U_BOOT_DEVICE() declaration below) should not do anything.
 	 * If we are that device, return an error.
 	 */
-	if (state->fdt_fname && dev_of_offset(dev) == -1)
+	if (state->fdt_fname && !dev_of_valid(dev))
 		return -ENODEV;
 
 	switch (type) {
diff --git a/drivers/sysreset/sysreset_snapdragon.c b/drivers/sysreset/sysreset_snapdragon.c
index a6cabfb..9869813 100644
--- a/drivers/sysreset/sysreset_snapdragon.c
+++ b/drivers/sysreset/sysreset_snapdragon.c
@@ -16,7 +16,7 @@
 
 static int msm_sysreset_request(struct udevice *dev, enum sysreset_t type)
 {
-	phys_addr_t addr = dev_get_addr(dev);
+	phys_addr_t addr = devfdt_get_addr(dev);
 	if (!addr)
 		return -EINVAL;
 	writel(0, addr);
diff --git a/drivers/sysreset/sysreset_watchdog.c b/drivers/sysreset/sysreset_watchdog.c
new file mode 100644
index 0000000..304ed05
--- /dev/null
+++ b/drivers/sysreset/sysreset_watchdog.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <sysreset.h>
+#include <wdt.h>
+
+struct wdt_reboot_priv {
+	struct udevice *wdt;
+};
+
+static int wdt_reboot_request(struct udevice *dev, enum sysreset_t type)
+{
+	struct wdt_reboot_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = wdt_expire_now(priv->wdt, 0);
+	if (ret)
+		return ret;
+
+	return -EINPROGRESS;
+}
+
+static struct sysreset_ops wdt_reboot_ops = {
+	.request = wdt_reboot_request,
+};
+
+int wdt_reboot_probe(struct udevice *dev)
+{
+	struct wdt_reboot_priv *priv = dev_get_priv(dev);
+	int err;
+
+	err = uclass_get_device_by_phandle(UCLASS_WDT, dev,
+					   "wdt", &priv->wdt);
+	if (err) {
+		error("unable to find wdt device\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static const struct udevice_id wdt_reboot_ids[] = {
+	{ .compatible = "wdt-reboot" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(wdt_reboot) = {
+	.name = "wdt_reboot",
+	.id = UCLASS_SYSRESET,
+	.of_match = wdt_reboot_ids,
+	.ops = &wdt_reboot_ops,
+	.priv_auto_alloc_size = sizeof(struct wdt_reboot_priv),
+	.probe = wdt_reboot_probe,
+};
diff --git a/drivers/timer/ae3xx_timer.c b/drivers/timer/ae3xx_timer.c
index 7ccb3eb..bcc07a0 100644
--- a/drivers/timer/ae3xx_timer.c
+++ b/drivers/timer/ae3xx_timer.c
@@ -92,7 +92,7 @@
 static int atctme_timer_ofdata_to_platdata(struct udevice *dev)
 {
 	struct atftmr_timer_platdata *plat = dev_get_platdata(dev);
-	plat->regs = map_physmem(dev_get_addr(dev) , 0x100 , MAP_NOCACHE);
+	plat->regs = map_physmem(devfdt_get_addr(dev) , 0x100 , MAP_NOCACHE);
 	return 0;
 }
 
diff --git a/drivers/timer/ag101p_timer.c b/drivers/timer/ag101p_timer.c
index 163402f..8dc85c4 100644
--- a/drivers/timer/ag101p_timer.c
+++ b/drivers/timer/ag101p_timer.c
@@ -95,7 +95,7 @@
 static int atftme_timer_ofdata_to_platdata(struct udevice *dev)
 {
 	struct atftmr_timer_platdata *plat = dev_get_platdata(dev);
-	plat->regs = map_physmem(dev_get_addr(dev),
+	plat->regs = map_physmem(devfdt_get_addr(dev),
 				 sizeof(struct atftmr_timer_regs),
 				 MAP_NOCACHE);
 	return 0;
diff --git a/drivers/timer/altera_timer.c b/drivers/timer/altera_timer.c
index 89fe05b..1ba85c4 100644
--- a/drivers/timer/altera_timer.c
+++ b/drivers/timer/altera_timer.c
@@ -71,7 +71,7 @@
 {
 	struct altera_timer_platdata *plat = dev_get_platdata(dev);
 
-	plat->regs = map_physmem(dev_get_addr(dev),
+	plat->regs = map_physmem(devfdt_get_addr(dev),
 				 sizeof(struct altera_timer_regs),
 				 MAP_NOCACHE);
 
diff --git a/drivers/timer/arc_timer.c b/drivers/timer/arc_timer.c
index e94e4a4..a5f6b34 100644
--- a/drivers/timer/arc_timer.c
+++ b/drivers/timer/arc_timer.c
@@ -51,7 +51,7 @@
 	struct arc_timer_priv *priv = dev_get_priv(dev);
 
 	/* Get registers offset and size */
-	id = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
+	id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "reg", -1);
 	if (id < 0)
 		return -EINVAL;
 
diff --git a/drivers/timer/ast_timer.c b/drivers/timer/ast_timer.c
index d7c5460..e194c50 100644
--- a/drivers/timer/ast_timer.c
+++ b/drivers/timer/ast_timer.c
@@ -66,7 +66,7 @@
 {
 	struct ast_timer_priv *priv = dev_get_priv(dev);
 
-	priv->regs = dev_get_addr_ptr(dev);
+	priv->regs = devfdt_get_addr_ptr(dev);
 	if (IS_ERR(priv->regs))
 		return PTR_ERR(priv->regs);
 
diff --git a/drivers/timer/omap-timer.c b/drivers/timer/omap-timer.c
index 7422e0a..4cc6105 100644
--- a/drivers/timer/omap-timer.c
+++ b/drivers/timer/omap-timer.c
@@ -79,7 +79,7 @@
 {
 	struct omap_timer_priv *priv = dev_get_priv(dev);
 
-	priv->regs = map_physmem(dev_get_addr(dev),
+	priv->regs = map_physmem(devfdt_get_addr(dev),
 				 sizeof(struct omap_gptimer_regs), MAP_NOCACHE);
 
 	return 0;
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c
index 1caf3cd..ec10b28 100644
--- a/drivers/timer/timer-uclass.c
+++ b/drivers/timer/timer-uclass.c
@@ -103,7 +103,8 @@
 			 * relocation, bind it anyway.
 			 */
 			if (node > 0 &&
-			    !lists_bind_fdt(gd->dm_root, blob, node, &dev)) {
+			    !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node),
+					    &dev)) {
 				ret = device_probe(dev);
 				if (ret)
 					return ret;
diff --git a/drivers/tpm/tpm_tis_lpc.c b/drivers/tpm/tpm_tis_lpc.c
index d2b3783..c00a2d0 100644
--- a/drivers/tpm/tpm_tis_lpc.c
+++ b/drivers/tpm/tpm_tis_lpc.c
@@ -165,7 +165,7 @@
 	u32 didvid;
 	ulong chip_type = dev_get_driver_data(dev);
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 	priv->regs = map_sysmem(addr, 0);
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c
index 9abb323..73fa82b 100644
--- a/drivers/usb/emul/sandbox_flash.c
+++ b/drivers/usb/emul/sandbox_flash.c
@@ -371,10 +371,8 @@
 static int sandbox_flash_ofdata_to_platdata(struct udevice *dev)
 {
 	struct sandbox_flash_plat *plat = dev_get_platdata(dev);
-	const void *blob = gd->fdt_blob;
 
-	plat->pathname = fdt_getprop(blob, dev_of_offset(dev),
-				     "sandbox,filepath", NULL);
+	plat->pathname = dev_read_string(dev, "sandbox,filepath");
 
 	return 0;
 }
diff --git a/drivers/usb/emul/sandbox_hub.c b/drivers/usb/emul/sandbox_hub.c
index f0939b1..9ffda9c 100644
--- a/drivers/usb/emul/sandbox_hub.c
+++ b/drivers/usb/emul/sandbox_hub.c
@@ -277,8 +277,7 @@
 {
 	struct sandbox_hub_platdata *plat = dev_get_parent_platdata(dev);
 
-	plat->port = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "reg",
-				    -1);
+	plat->port = dev_read_u32_default(dev, "reg", -1);
 
 	return 0;
 }
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 0e5df15..bbaefd2 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -1234,7 +1234,7 @@
 	const void *prop;
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 	priv->regs = (struct dwc2_core_regs *)addr;
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index a5c6d34..f6c6b01 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -96,7 +96,7 @@
 	/*
 	 * Get the base address for EHCI controller from the device node
 	 */
-	hcd_base = dev_get_addr(dev);
+	hcd_base = devfdt_get_addr(dev);
 	if (hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the EHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index 981543e..30297b0 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -52,7 +52,7 @@
 	/*
 	 * Get the base address for XHCI controller from the device node
 	 */
-	plat->hcd_base = dev_get_addr(dev);
+	plat->hcd_base = devfdt_get_addr(dev);
 	if (plat->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the XHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 7ad50fc..b57c6cd 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -98,7 +98,7 @@
 	/*
 	 * Get the base address for EHCI controller from the device node
 	 */
-	priv->hcd_base = dev_get_addr(dev);
+	priv->hcd_base = devfdt_get_addr(dev);
 	if (priv->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the EHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
index 2190adb..fb78462 100644
--- a/drivers/usb/host/ehci-generic.c
+++ b/drivers/usb/host/ehci-generic.c
@@ -50,7 +50,7 @@
 		reset_free(&reset);
 	}
 
-	hccr = map_physmem(dev_get_addr(dev), 0x100, MAP_NOCACHE);
+	hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE);
 	hcor = (struct ehci_hcor *)((uintptr_t)hccr +
 				    HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 
diff --git a/drivers/usb/host/ehci-marvell.c b/drivers/usb/host/ehci-marvell.c
index 4642470..7a0f208 100644
--- a/drivers/usb/host/ehci-marvell.c
+++ b/drivers/usb/host/ehci-marvell.c
@@ -108,7 +108,7 @@
 	/*
 	 * Get the base address for EHCI controller from the device node
 	 */
-	priv->hcd_base = dev_get_addr(dev);
+	priv->hcd_base = devfdt_get_addr(dev);
 	if (priv->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the EHCI register base address\n");
 		return -ENXIO;
@@ -121,7 +121,7 @@
 	 * Also, the address decoder doesn't need to get setup with this
 	 * SoC, so don't call usb_brg_adrdec_setup().
 	 */
-	if (of_device_is_compatible(dev, "marvell,armada3700-ehci"))
+	if (device_is_compatible(dev, "marvell,armada3700-ehci"))
 		marvell_ehci_ops.powerup_fixup = marvell_ehci_powerup_fixup;
 	else
 		usb_brg_adrdec_setup((void *)priv->hcd_base);
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 6484c1c..2c0c633 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -147,7 +147,7 @@
 	struct msm_ehci_priv *priv = dev_get_priv(dev);
 
 	priv->ulpi_vp.port_num = 0;
-	priv->ehci = (void *)dev_get_addr(dev);
+	priv->ehci = (void *)devfdt_get_addr(dev);
 
 	if (priv->ehci == (void *)FDT_ADDR_T_NONE)
 		return -EINVAL;
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index 55ac162..2367671 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -434,7 +434,7 @@
 static int ehci_usb_phy_mode(struct udevice *dev)
 {
 	struct usb_platdata *plat = dev_get_platdata(dev);
-	void *__iomem addr = (void *__iomem)dev_get_addr(dev);
+	void *__iomem addr = (void *__iomem)devfdt_get_addr(dev);
 	void *__iomem phy_ctrl, *__iomem phy_status;
 	const void *blob = gd->fdt_blob;
 	int offset = dev_of_offset(dev), phy_off;
@@ -504,7 +504,7 @@
 static int ehci_usb_probe(struct udevice *dev)
 {
 	struct usb_platdata *plat = dev_get_platdata(dev);
-	struct usb_ehci *ehci = (struct usb_ehci *)dev_get_addr(dev);
+	struct usb_ehci *ehci = (struct usb_ehci *)devfdt_get_addr(dev);
 	struct ehci_mx6_priv_data *priv = dev_get_priv(dev);
 	enum usb_init_type type = plat->init_type;
 	struct ehci_hccr *hccr;
diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c
index 068f24f..6ecb7c4 100644
--- a/drivers/usb/host/ehci-sunxi.c
+++ b/drivers/usb/host/ehci-sunxi.c
@@ -36,7 +36,7 @@
 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 	struct usb_platdata *plat = dev_get_platdata(dev);
 	struct ehci_sunxi_priv *priv = dev_get_priv(dev);
-	struct ehci_hccr *hccr = (struct ehci_hccr *)dev_get_addr(dev);
+	struct ehci_hccr *hccr = (struct ehci_hccr *)devfdt_get_addr(dev);
 	struct ehci_hcor *hcor;
 	int extra_ahb_gate_mask = 0;
 
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index beb3b02..7dc37f0 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -699,7 +699,7 @@
 	int node = dev_of_offset(dev);
 	const char *phy, *mode;
 
-	config->reg = (struct usb_ctlr *)dev_get_addr(dev);
+	config->reg = (struct usb_ctlr *)devfdt_get_addr(dev);
 	mode = fdt_getprop(blob, node, "dr_mode", NULL);
 	if (mode) {
 		if (0 == strcmp(mode, "host"))
@@ -728,9 +728,10 @@
 		debug("%s: Missing/invalid peripheral ID\n", __func__);
 		return -EINVAL;
 	}
-	gpio_request_by_name_nodev(blob, node, "nvidia,vbus-gpio", 0,
-				   &config->vbus_gpio, GPIOD_IS_OUT);
-	gpio_request_by_name_nodev(blob, node, "nvidia,phy-reset-gpio", 0,
+	gpio_request_by_name_nodev(offset_to_ofnode(node), "nvidia,vbus-gpio",
+				   0, &config->vbus_gpio, GPIOD_IS_OUT);
+	gpio_request_by_name_nodev(offset_to_ofnode(node),
+				   "nvidia,phy-reset-gpio", 0,
 				   &config->phy_reset_gpio, GPIOD_IS_OUT);
 	debug("enabled=%d, legacy_mode=%d, utmi=%d, ulpi=%d, periph_id=%d, "
 		"vbus=%d, phy_reset=%d, dr_mode=%d\n",
diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c
index 84241cd..a7f6f21 100644
--- a/drivers/usb/host/ehci-vf.c
+++ b/drivers/usb/host/ehci-vf.c
@@ -223,7 +223,7 @@
 
 	priv->portnr = dev->seq;
 
-	priv->ehci = (struct usb_ehci *)dev_get_addr(dev);
+	priv->ehci = (struct usb_ehci *)devfdt_get_addr(dev);
 	mode = fdt_getprop(dt_blob, node, "dr_mode", NULL);
 	if (mode) {
 		if (0 == strcmp(mode, "host")) {
@@ -252,8 +252,9 @@
 	}
 
 	if (priv->dr_mode == DR_MODE_OTG) {
-		gpio_request_by_name_nodev(dt_blob, node, "fsl,cdet-gpio", 0,
-					   &priv->cdet_gpio, GPIOD_IS_IN);
+		gpio_request_by_name_nodev(offset_to_ofnode(node),
+					   "fsl,cdet-gpio", 0, &priv->cdet_gpio,
+					   GPIOD_IS_IN);
 		if (dm_gpio_is_valid(&priv->cdet_gpio)) {
 			if (dm_gpio_get_value(&priv->cdet_gpio))
 				priv->init_type = USB_INIT_DEVICE;
diff --git a/drivers/usb/host/ehci-zynq.c b/drivers/usb/host/ehci-zynq.c
index 1e3b800..4f127d5 100644
--- a/drivers/usb/host/ehci-zynq.c
+++ b/drivers/usb/host/ehci-zynq.c
@@ -26,7 +26,7 @@
 {
 	struct zynq_ehci_priv *priv = dev_get_priv(dev);
 
-	priv->ehci = (struct usb_ehci *)dev_get_addr_ptr(dev);
+	priv->ehci = (struct usb_ehci *)devfdt_get_addr_ptr(dev);
 	if (!priv->ehci)
 		return -EINVAL;
 
diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
index f3307f4..f85738f 100644
--- a/drivers/usb/host/ohci-generic.c
+++ b/drivers/usb/host/ohci-generic.c
@@ -18,7 +18,7 @@
 
 static int ohci_usb_probe(struct udevice *dev)
 {
-	struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev);
+	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
 
 	return ohci_register(dev, regs);
 }
diff --git a/drivers/usb/host/ohci-sunxi.c b/drivers/usb/host/ohci-sunxi.c
index 0c45eec..133774f 100644
--- a/drivers/usb/host/ohci-sunxi.c
+++ b/drivers/usb/host/ohci-sunxi.c
@@ -37,7 +37,7 @@
 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 	struct usb_bus_priv *bus_priv = dev_get_uclass_priv(dev);
 	struct ohci_sunxi_priv *priv = dev_get_priv(dev);
-	struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev);
+	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
 	int extra_ahb_gate_mask = 0;
 
 	bus_priv->companion = true;
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
index 6eded4a..110ddc9 100644
--- a/drivers/usb/host/usb-uclass.c
+++ b/drivers/usb/host/usb-uclass.c
@@ -683,20 +683,18 @@
 int usb_child_post_bind(struct udevice *dev)
 {
 	struct usb_dev_platdata *plat = dev_get_parent_platdata(dev);
-	const void *blob = gd->fdt_blob;
 	int val;
 
-	if (dev_of_offset(dev) == -1)
+	if (!dev_of_valid(dev))
 		return 0;
 
 	/* We only support matching a few things */
-	val = fdtdec_get_int(blob, dev_of_offset(dev), "usb,device-class", -1);
+	val = dev_read_u32_default(dev, "usb,device-class", -1);
 	if (val != -1) {
 		plat->id.match_flags |= USB_DEVICE_ID_MATCH_DEV_CLASS;
 		plat->id.bDeviceClass = val;
 	}
-	val = fdtdec_get_int(blob, dev_of_offset(dev), "usb,interface-class",
-			     -1);
+	val = dev_read_u32_default(dev, "usb,interface-class", -1);
 	if (val != -1) {
 		plat->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;
 		plat->id.bInterfaceClass = val;
diff --git a/drivers/usb/host/xhci-exynos5.c b/drivers/usb/host/xhci-exynos5.c
index b3f48b3..bf72865 100644
--- a/drivers/usb/host/xhci-exynos5.c
+++ b/drivers/usb/host/xhci-exynos5.c
@@ -61,7 +61,7 @@
 	/*
 	 * Get the base address for XHCI controller from the device node
 	 */
-	plat->hcd_base = dev_get_addr(dev);
+	plat->hcd_base = devfdt_get_addr(dev);
 	if (plat->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the XHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/usb/host/xhci-fsl.c b/drivers/usb/host/xhci-fsl.c
index 3a16624..f77c78d 100644
--- a/drivers/usb/host/xhci-fsl.c
+++ b/drivers/usb/host/xhci-fsl.c
@@ -122,7 +122,7 @@
 	/*
 	 * Get the base address for XHCI controller from the device node
 	 */
-	priv->hcd_base = dev_get_addr(dev);
+	priv->hcd_base = devfdt_get_addr(dev);
 	if (priv->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the XHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c
index d880af1..b9201a5 100644
--- a/drivers/usb/host/xhci-mvebu.c
+++ b/drivers/usb/host/xhci-mvebu.c
@@ -74,7 +74,7 @@
 	/*
 	 * Get the base address for XHCI controller from the device node
 	 */
-	plat->hcd_base = dev_get_addr(dev);
+	plat->hcd_base = devfdt_get_addr(dev);
 	if (plat->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the XHCI register base address\n");
 		return -ENXIO;
diff --git a/drivers/usb/host/xhci-rockchip.c b/drivers/usb/host/xhci-rockchip.c
index f559830..38e1c68 100644
--- a/drivers/usb/host/xhci-rockchip.c
+++ b/drivers/usb/host/xhci-rockchip.c
@@ -46,7 +46,7 @@
 	/*
 	 * Get the base address for XHCI controller from the device node
 	 */
-	plat->hcd_base = dev_get_addr(dev);
+	plat->hcd_base = devfdt_get_addr(dev);
 	if (plat->hcd_base == FDT_ADDR_T_NONE) {
 		debug("Can't get the XHCI register base address\n");
 		return -ENXIO;
@@ -55,9 +55,9 @@
 	/* Get the base address for usbphy from the device node */
 	for (device_find_first_child(dev, &child); child;
 	     device_find_next_child(&child)) {
-		if (!of_device_is_compatible(child, "rockchip,rk3399-usb3-phy"))
+		if (!device_is_compatible(child, "rockchip,rk3399-usb3-phy"))
 			continue;
-		plat->phy_base = dev_get_addr(child);
+		plat->phy_base = devfdt_get_addr(child);
 		break;
 	}
 
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index 469377f..5c1a902 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -17,6 +17,7 @@
  * SPDX-License-Identifier:	GPL-2.0
  */
 #include <common.h>
+#include <dm.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/gpio.h>
diff --git a/drivers/usb/musb-new/ti-musb.c b/drivers/usb/musb-new/ti-musb.c
index 852f07f..de10131 100644
--- a/drivers/usb/musb-new/ti-musb.c
+++ b/drivers/usb/musb-new/ti-musb.c
@@ -88,7 +88,7 @@
 	int ctrl_mod;
 	int usb_index;
 
-	platdata->base = (void *)dev_get_addr_index(dev, 1);
+	platdata->base = (void *)devfdt_get_addr_index(dev, 1);
 
 	phys = fdtdec_lookup_phandle(fdt, node, "phys");
 	ctrl_mod = fdtdec_lookup_phandle(fdt, phys, "ti,ctrl_mod");
@@ -227,7 +227,7 @@
 		case USB_DR_MODE_HOST:
 			/* Bind MUSB host */
 			ret = device_bind_driver_to_node(parent, "ti-musb-host",
-							 name, node, &dev);
+					name, offset_to_ofnode(node), &dev);
 			if (ret) {
 				error("musb - not able to bind usb host node\n");
 				return ret;
diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
index 59b9c45..47078fd 100644
--- a/drivers/video/atmel_hlcdfb.c
+++ b/drivers/video/atmel_hlcdfb.c
@@ -497,15 +497,15 @@
 {
 	struct atmel_hlcdc_priv *priv = dev_get_priv(dev);
 	const void *blob = gd->fdt_blob;
-	int node = dev->of_offset;
+	int node = dev_of_offset(dev);
 
-	priv->regs = (struct atmel_hlcd_regs *)dev_get_addr(dev);
+	priv->regs = (struct atmel_hlcd_regs *)devfdt_get_addr(dev);
 	if (!priv->regs) {
 		debug("%s: No display controller address\n", __func__);
 		return -EINVAL;
 	}
 
-	if (fdtdec_decode_display_timing(blob, dev->of_offset,
+	if (fdtdec_decode_display_timing(blob, dev_of_offset(dev),
 					 0, &priv->timing)) {
 		debug("%s: Failed to decode display timing\n", __func__);
 		return -EINVAL;
diff --git a/drivers/video/exynos/exynos_dp.c b/drivers/video/exynos/exynos_dp.c
index c5039e7..092342e 100644
--- a/drivers/video/exynos/exynos_dp.c
+++ b/drivers/video/exynos/exynos_dp.c
@@ -6,7 +6,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <config.h>
+#include <common.h>
 #include <dm.h>
 #include <common.h>
 #include <display.h>
@@ -883,7 +883,7 @@
 	unsigned int node = dev_of_offset(dev);
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE) {
 		debug("Can't get the DP base address\n");
 		return -EINVAL;
diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c
index 46320e7..6ca17f2 100644
--- a/drivers/video/exynos/exynos_fb.c
+++ b/drivers/video/exynos/exynos_fb.c
@@ -486,7 +486,7 @@
 	const void *blob = gd->fdt_blob;
 	fdt_addr_t addr;
 
-	addr = dev_get_addr(dev);
+	addr = devfdt_get_addr(dev);
 	if (addr == FDT_ADDR_T_NONE) {
 		debug("Can't get the FIMD base address\n");
 		return -EINVAL;
diff --git a/drivers/video/rockchip/rk_edp.c b/drivers/video/rockchip/rk_edp.c
index 7ece038..4e2030e 100644
--- a/drivers/video/rockchip/rk_edp.c
+++ b/drivers/video/rockchip/rk_edp.c
@@ -998,7 +998,7 @@
 {
 	struct rk_edp_priv *priv = dev_get_priv(dev);
 
-	priv->regs = (struct rk3288_edp *)dev_get_addr(dev);
+	priv->regs = (struct rk3288_edp *)devfdt_get_addr(dev);
 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
 
 	return 0;
diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
index db07588..cd695ca 100644
--- a/drivers/video/rockchip/rk_hdmi.c
+++ b/drivers/video/rockchip/rk_hdmi.c
@@ -85,7 +85,7 @@
 	struct rk_hdmi_priv *priv = dev_get_priv(dev);
 	struct dw_hdmi *hdmi = &priv->hdmi;
 
-	hdmi->ioaddr = (ulong)dev_get_addr(dev);
+	hdmi->ioaddr = (ulong)devfdt_get_addr(dev);
 	hdmi->mpll_cfg = rockchip_mpll_cfg;
 	hdmi->phy_cfg = rockchip_phy_config;
 	hdmi->i2c_clk_high = 0x7a;
diff --git a/drivers/video/rockchip/rk_lvds.c b/drivers/video/rockchip/rk_lvds.c
index ee43255..66418dd 100644
--- a/drivers/video/rockchip/rk_lvds.c
+++ b/drivers/video/rockchip/rk_lvds.c
@@ -176,7 +176,7 @@
 	const void *blob = gd->fdt_blob;
 	int node = dev_of_offset(dev);
 	int ret;
-	priv->regs = (void *)dev_get_addr(dev);
+	priv->regs = (void *)devfdt_get_addr(dev);
 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
 
 	ret = fdtdec_get_int(blob, node, "rockchip,output", -1);
diff --git a/drivers/video/rockchip/rk_mipi.c b/drivers/video/rockchip/rk_mipi.c
index 4d9d12e..ad00397 100644
--- a/drivers/video/rockchip/rk_mipi.c
+++ b/drivers/video/rockchip/rk_mipi.c
@@ -441,7 +441,7 @@
 		      __func__, (u64)priv->grf);
 		return  -ENXIO;
 	}
-	priv->regs = (void *)dev_get_addr(dev);
+	priv->regs = (void *)devfdt_get_addr(dev);
 	if (priv->regs <= 0) {
 		debug("%s: Get MIPI dsi address failed (ret=%llu)\n", __func__,
 		      (u64)priv->regs);
diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
index aa6ca8c..48bfcd4 100644
--- a/drivers/video/rockchip/rk_vop.c
+++ b/drivers/video/rockchip/rk_vop.c
@@ -294,7 +294,7 @@
 		return 0;
 
 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
-	priv->regs = (struct rk3288_vop *)dev_get_addr(dev);
+	priv->regs = (struct rk3288_vop *)devfdt_get_addr(dev);
 
 	/* lcdc(vop) iodomain select 1.8V */
 	rk_setreg(&priv->grf->io_vsel, 1 << 0);
diff --git a/drivers/video/tegra.c b/drivers/video/tegra.c
index 0ba3f2c..ec62fc9 100644
--- a/drivers/video/tegra.c
+++ b/drivers/video/tegra.c
@@ -343,7 +343,7 @@
 	int rgb;
 	int ret;
 
-	priv->disp = (struct disp_ctlr *)dev_get_addr(dev);
+	priv->disp = (struct disp_ctlr *)devfdt_get_addr(dev);
 	if (!priv->disp) {
 		debug("%s: No display controller address\n", __func__);
 		return -EINVAL;
diff --git a/drivers/video/tegra124/dp.c b/drivers/video/tegra124/dp.c
index 5bf8524..c38b3e5 100644
--- a/drivers/video/tegra124/dp.c
+++ b/drivers/video/tegra124/dp.c
@@ -1572,7 +1572,7 @@
 {
 	struct tegra_dp_plat *plat = dev_get_platdata(dev);
 
-	plat->base = dev_get_addr(dev);
+	plat->base = devfdt_get_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 22a7c4f..b911233 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -54,4 +54,12 @@
 	  It currently does not support Boot Flash Addressing Mode Detection or
 	  Second Boot.
 
+config WDT_BCM6345
+	bool "BCM6345 watchdog timer support"
+	depends on WDT && ARCH_BMIPS
+	help
+	  Select this to enable watchdog timer for BCM6345 SoCs.
+	  The watchdog timer is stopped when initialized.
+	  It performs full SoC reset.
+
 endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 8378601..4b19e4c 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -18,4 +18,5 @@
 obj-$(CONFIG_WDT) += wdt-uclass.o
 obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
 obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
+obj-$(CONFIG_WDT_BCM6345) += bcm6345_wdt.o
 obj-$(CONFIG_BCM2835_WDT)       += bcm2835_wdt.o
diff --git a/drivers/watchdog/ast_wdt.c b/drivers/watchdog/ast_wdt.c
index b2bd912..aab077e 100644
--- a/drivers/watchdog/ast_wdt.c
+++ b/drivers/watchdog/ast_wdt.c
@@ -84,7 +84,7 @@
 {
 	struct ast_wdt_priv *priv = dev_get_priv(dev);
 
-	priv->regs = dev_get_addr_ptr(dev);
+	priv->regs = devfdt_get_addr_ptr(dev);
 	if (IS_ERR(priv->regs))
 		return PTR_ERR(priv->regs);
 
diff --git a/drivers/watchdog/bcm6345_wdt.c b/drivers/watchdog/bcm6345_wdt.c
new file mode 100644
index 0000000..3ef7d43
--- /dev/null
+++ b/drivers/watchdog/bcm6345_wdt.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/watchdog/bcm63xx_wdt.c:
+ *	Copyright (C) 2007 Miguel Gaio <miguel.gaio@efixo.com>
+ *	Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <asm/io.h>
+
+/* WDT Value register */
+#define WDT_VAL_REG		0x0
+#define WDT_VAL_MIN		0x00000002
+#define WDT_VAL_MAX		0xfffffffe
+
+/* WDT Control register */
+#define WDT_CTL_REG		0x4
+#define WDT_CTL_START1_MASK	0x0000ff00
+#define WDT_CTL_START2_MASK	0x000000ff
+#define WDT_CTL_STOP1_MASK	0x0000ee00
+#define WDT_CTL_STOP2_MASK	0x000000ee
+
+struct bcm6345_wdt_priv {
+	void __iomem *regs;
+};
+
+static int bcm6345_wdt_reset(struct udevice *dev)
+{
+	struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
+
+	writel_be(WDT_CTL_START1_MASK, priv->regs + WDT_CTL_REG);
+	writel_be(WDT_CTL_START2_MASK, priv->regs + WDT_CTL_REG);
+
+	return 0;
+}
+
+static int bcm6345_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
+
+	if (timeout < WDT_VAL_MIN) {
+		debug("watchdog won't fire with less than 2 ticks\n");
+		timeout = WDT_VAL_MIN;
+	} else if (timeout > WDT_VAL_MAX) {
+		debug("maximum watchdog timeout exceeded\n");
+		timeout = WDT_VAL_MAX;
+	}
+
+	writel_be(timeout, priv->regs + WDT_VAL_REG);
+
+	return bcm6345_wdt_reset(dev);
+}
+
+static int bcm6345_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+	return bcm6345_wdt_start(dev, WDT_VAL_MIN, flags);
+}
+
+static int bcm6345_wdt_stop(struct udevice *dev)
+{
+	struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
+
+	writel_be(WDT_CTL_STOP1_MASK, priv->regs + WDT_CTL_REG);
+	writel_be(WDT_CTL_STOP2_MASK, priv->regs + WDT_CTL_REG);
+
+	return 0;
+}
+
+static const struct wdt_ops bcm6345_wdt_ops = {
+	.expire_now = bcm6345_wdt_expire_now,
+	.reset = bcm6345_wdt_reset,
+	.start = bcm6345_wdt_start,
+	.stop = bcm6345_wdt_stop,
+};
+
+static const struct udevice_id bcm6345_wdt_ids[] = {
+	{ .compatible = "brcm,bcm6345-wdt" },
+	{ /* sentinel */ }
+};
+
+static int bcm6345_wdt_probe(struct udevice *dev)
+{
+	struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
+	fdt_addr_t addr;
+	fdt_size_t size;
+
+	addr = devfdt_get_addr_size_index(dev, 0, &size);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->regs = ioremap(addr, size);
+
+	bcm6345_wdt_stop(dev);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(wdt_bcm6345) = {
+	.name = "wdt_bcm6345",
+	.id = UCLASS_WDT,
+	.of_match = bcm6345_wdt_ids,
+	.ops = &bcm6345_wdt_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm6345_wdt_priv),
+	.probe = bcm6345_wdt_probe,
+};
diff --git a/dts/Kconfig b/dts/Kconfig
index 9a06221..b3009af 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -32,6 +32,17 @@
 	  which is not enough to support device tree. Enable this option to
 	  allow such boards to be supported by U-Boot SPL.
 
+config OF_LIVE
+	bool "Enable use of a live tree"
+	depends on OF_CONTROL
+	help
+	  Normally U-Boot uses a flat device tree which saves space and
+	  avoids the need to unpack the tree before use. However a flat
+	  tree does not support modifcation from within U-Boot since it
+	  can invalidate driver-model device tree offsets. This option
+	  enables a live tree which is available after relocation,
+	  and can be adjusted as needed.
+
 choice
 	prompt "Provider of DTB for DT control"
 	depends on OF_CONTROL
diff --git a/fs/fat/Kconfig b/fs/fat/Kconfig
index e69de29..e7978aa 100644
--- a/fs/fat/Kconfig
+++ b/fs/fat/Kconfig
@@ -0,0 +1,24 @@
+config FS_FAT
+	bool "Enable FAT filesystem support"
+	help
+	  This provides support for reading images from File Allocation Table
+	  (FAT) filesystem. FAT filesystem is a legacy, lightweight filesystem.
+	  It is useful mainly for its wide compatibility with various operating
+	  systems. You can also enable CMD_FAT to get access to fat commands.
+
+config FAT_WRITE
+	bool "Enable FAT filesystem write support"
+	depends on FS_FAT
+	help
+	  This provides support for creating and writing new files to an
+	  existing FAT filesystem partition.
+
+config FS_FAT_MAX_CLUSTSIZE
+	int "Set maximum possible clusersize"
+	default 65536
+	depends on FS_FAT
+	help
+	  Set the maximum possible clustersize for the FAT filesytem. This
+	  is the smallest amount of disk space that can be used to hold a
+	  file. Unless you have an extremely tight memory memory constraints,
+	  leave the default.
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 51838b5..e6f9051 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -72,6 +72,9 @@
 	const void *fdt_blob;		/* Our device tree, NULL if none */
 	void *new_fdt;			/* Relocated FDT */
 	unsigned long fdt_size;		/* Space reserved for relocated FDT */
+#ifdef CONFIG_OF_LIVE
+	struct device_node *of_root;
+#endif
 	struct jt_funcs *jt;		/* jump table */
 	char env_buf[32];		/* buffer for getenv() before reloc. */
 #ifdef CONFIG_TRACE
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 4aa0004..bf230c1 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -7,6 +7,10 @@
 #ifndef _ASM_GENERIC_GPIO_H_
 #define _ASM_GENERIC_GPIO_H_
 
+#include <dm/ofnode.h>
+
+struct ofnode_phandle_args;
+
 /*
  * Generic GPIO API for U-Boot
  *
@@ -211,10 +215,9 @@
  *
  * This routine sets the offset field to args[0] and the flags field to
  * GPIOD_ACTIVE_LOW if the GPIO_ACTIVE_LOW flag is present in args[1].
- *
  */
 int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc,
-			  struct fdtdec_phandle_args *args);
+			  struct ofnode_phandle_args *args);
 
 /**
  * struct struct dm_gpio_ops - Driver model GPIO operations
@@ -286,7 +289,7 @@
 	 * @return 0 if OK, -ve on error
 	 */
 	int (*xlate)(struct udevice *dev, struct gpio_desc *desc,
-		     struct fdtdec_phandle_args *args);
+		     struct ofnode_phandle_args *args);
 };
 
 /**
@@ -487,9 +490,8 @@
  * This is a version of gpio_request_list_by_name() that does not use a
  * device. Avoid it unless the caller is not yet using driver model
  */
-int gpio_request_by_name_nodev(const void *blob, int node,
-			       const char *list_name,
-			       int index, struct gpio_desc *desc, int flags);
+int gpio_request_by_name_nodev(ofnode node, const char *list_name, int index,
+			       struct gpio_desc *desc, int flags);
 
 /**
  * gpio_request_list_by_name_nodev() - request GPIOs without a device
@@ -497,8 +499,7 @@
  * This is a version of gpio_request_list_by_name() that does not use a
  * device. Avoid it unless the caller is not yet using driver model
  */
-int gpio_request_list_by_name_nodev(const void *blob, int node,
-				    const char *list_name,
+int gpio_request_list_by_name_nodev(ofnode node, const char *list_name,
 				    struct gpio_desc *desc_list, int max_count,
 				    int flags);
 
diff --git a/include/blk.h b/include/blk.h
index 66a1c55..a128ee4 100644
--- a/include/blk.h
+++ b/include/blk.h
@@ -253,12 +253,25 @@
 			 lbaint_t blkcnt);
 
 /**
+ * blk_find_device() - Find a block device
+ *
+ * This function does not activate the device. The device will be returned
+ * whether or not it is activated.
+ *
+ * @if_type:	Interface type (enum if_type_t)
+ * @devnum:	Device number (specific to each interface type)
+ * @devp:	the device, if found
+ * @return 0 if found, -ENODEV if no device found, or other -ve error value
+ */
+int blk_find_device(int if_type, int devnum, struct udevice **devp);
+
+/**
  * blk_get_device() - Find and probe a block device ready for use
  *
  * @if_type:	Interface type (enum if_type_t)
  * @devnum:	Device number (specific to each interface type)
  * @devp:	the device, if found
- * @return - if found, -ENODEV if no device found, or other -ve error value
+ * @return 0 if found, -ENODEV if no device found, or other -ve error value
  */
 int blk_get_device(int if_type, int devnum, struct udevice **devp);
 
diff --git a/include/clk-uclass.h b/include/clk-uclass.h
index 07c1065..e7ea334 100644
--- a/include/clk-uclass.h
+++ b/include/clk-uclass.h
@@ -12,7 +12,8 @@
 /* See clk.h for background documentation. */
 
 #include <clk.h>
-#include <fdtdec.h>
+
+struct ofnode_phandle_args;
 
 /**
  * struct clk_ops - The functions that a clock driver must implement.
@@ -37,7 +38,7 @@
 	 * @return 0 if OK, or a negative error code.
 	 */
 	int (*of_xlate)(struct clk *clock,
-			struct fdtdec_phandle_args *args);
+			struct ofnode_phandle_args *args);
 	/**
 	 * request - Request a translated clock.
 	 *
diff --git a/include/config_fallbacks.h b/include/config_fallbacks.h
index 5a698a8..2656c75 100644
--- a/include/config_fallbacks.h
+++ b/include/config_fallbacks.h
@@ -29,10 +29,14 @@
 #define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
 #endif
 
-#if defined(CONFIG_CMD_FAT) && !defined(CONFIG_FS_FAT)
+#if defined(CONFIG_ENV_IS_IN_FAT) && !defined(CONFIG_FS_FAT)
 #define CONFIG_FS_FAT
 #endif
 
+#if defined(CONFIG_ENV_IS_IN_FAT) && !defined(CONFIG_FAT_WRITE)
+#define CONFIG_FAT_WRITE
+#endif
+
 #if (defined(CONFIG_CMD_EXT4) || defined(CONFIG_CMD_EXT2)) && \
 						!defined(CONFIG_FS_EXT4)
 #define CONFIG_FS_EXT4
diff --git a/include/configs/am43xx_evm.h b/include/configs/am43xx_evm.h
index 25f63e8..1d8e39c 100644
--- a/include/configs/am43xx_evm.h
+++ b/include/configs/am43xx_evm.h
@@ -75,7 +75,6 @@
 #define FAT_ENV_INTERFACE		"mmc"
 #define FAT_ENV_DEVICE_AND_PART		"0:1"
 #define FAT_ENV_FILE			"uboot.env"
-#define CONFIG_FAT_WRITE
 
 #define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-omap2/u-boot-spl.lds"
 
diff --git a/include/configs/apalis-tk1.h b/include/configs/apalis-tk1.h
index 2c49729..c3cade9 100644
--- a/include/configs/apalis-tk1.h
+++ b/include/configs/apalis-tk1.h
@@ -50,9 +50,6 @@
 #define CONFIG_TFTP_BLOCKSIZE		16352
 #define CONFIG_TFTP_TSIZE
 
-/* Miscellaneous commands */
-#define CONFIG_FAT_WRITE
-
 #undef CONFIG_IPADDR
 #define CONFIG_IPADDR		192.168.10.2
 #define CONFIG_NETMASK		255.255.255.0
diff --git a/include/configs/apalis_imx6.h b/include/configs/apalis_imx6.h
index 9220d04..8be586b 100644
--- a/include/configs/apalis_imx6.h
+++ b/include/configs/apalis_imx6.h
@@ -66,7 +66,6 @@
 
 #define CONFIG_SUPPORT_EMMC_BOOT	/* eMMC specific */
 #define CONFIG_BOUNCE_BUFFER
-#define CONFIG_FAT_WRITE
 
 #ifdef CONFIG_MX6Q
 #define CONFIG_CMD_SATA
@@ -321,6 +320,4 @@
 
 #define CONFIG_SUPPORT_RAW_INITRD
 
-#define CONFIG_CRC32_VERIFY
-
 #endif	/* __CONFIG_H */
diff --git a/include/configs/apalis_t30.h b/include/configs/apalis_t30.h
index cdb50cc..9772d8b 100644
--- a/include/configs/apalis_t30.h
+++ b/include/configs/apalis_t30.h
@@ -46,9 +46,6 @@
 #define CONFIG_TFTP_BLOCKSIZE		16352
 #define CONFIG_TFTP_TSIZE
 
-/* Miscellaneous commands */
-#define CONFIG_FAT_WRITE
-
 /* Increase console I/O buffer size */
 #undef CONFIG_SYS_CBSIZE
 #define CONFIG_SYS_CBSIZE		1024
diff --git a/include/configs/at91-sama5_common.h b/include/configs/at91-sama5_common.h
index dbd4d84..dea8130 100644
--- a/include/configs/at91-sama5_common.h
+++ b/include/configs/at91-sama5_common.h
@@ -54,7 +54,6 @@
 #else
 /* u-boot env in sd/mmc card */
 #define CONFIG_ENV_IS_IN_FAT
-#define CONFIG_FAT_WRITE
 #define FAT_ENV_INTERFACE	"mmc"
 #define FAT_ENV_DEVICE_AND_PART	"0"
 #define FAT_ENV_FILE		"uboot.env"
diff --git a/include/configs/at91sam9m10g45ek.h b/include/configs/at91sam9m10g45ek.h
index 010ebdb..a0c5b9a 100644
--- a/include/configs/at91sam9m10g45ek.h
+++ b/include/configs/at91sam9m10g45ek.h
@@ -115,7 +115,6 @@
 #define FAT_ENV_DEVICE_AND_PART	"0"
 #define FAT_ENV_FILE		"uboot.env"
 #define CONFIG_ENV_IS_IN_FAT
-#define CONFIG_FAT_WRITE
 #define CONFIG_ENV_SIZE		0x4000
 
 #define CONFIG_BOOTARGS		"console=ttyS0,115200 " \
diff --git a/include/configs/at91sam9n12ek.h b/include/configs/at91sam9n12ek.h
index 411d741..50ddbd6 100644
--- a/include/configs/at91sam9n12ek.h
+++ b/include/configs/at91sam9n12ek.h
@@ -160,7 +160,6 @@
 #else
 /* Use file in FAT file to save environment */
 #define CONFIG_ENV_IS_IN_FAT
-#define CONFIG_FAT_WRITE
 #define FAT_ENV_INTERFACE		"mmc"
 #define FAT_ENV_FILE			"uboot.env"
 #define FAT_ENV_DEVICE_AND_PART		"0"
diff --git a/include/configs/at91sam9rlek.h b/include/configs/at91sam9rlek.h
index 7dcf791..8a8eb7c 100644
--- a/include/configs/at91sam9rlek.h
+++ b/include/configs/at91sam9rlek.h
@@ -127,7 +127,6 @@
 
 /* bootstrap + u-boot + env + linux in mmc */
 #define CONFIG_ENV_IS_IN_FAT
-#define CONFIG_FAT_WRITE
 #define FAT_ENV_INTERFACE	"mmc"
 #define FAT_ENV_FILE		"uboot.env"
 #define FAT_ENV_DEVICE_AND_PART	"0"
diff --git a/include/configs/at91sam9x5ek.h b/include/configs/at91sam9x5ek.h
index 33cc5fc..fd2dbed 100644
--- a/include/configs/at91sam9x5ek.h
+++ b/include/configs/at91sam9x5ek.h
@@ -147,7 +147,6 @@
 #else /* CONFIG_SYS_USE_MMC */
 /* bootstrap + u-boot + env + linux in mmc */
 #define CONFIG_ENV_IS_IN_FAT
-#define CONFIG_FAT_WRITE
 #define FAT_ENV_INTERFACE	"mmc"
 #define FAT_ENV_FILE		"uboot.env"
 #define FAT_ENV_DEVICE_AND_PART "0"
diff --git a/include/configs/bcm23550_w1d.h b/include/configs/bcm23550_w1d.h
index 77d6e6a..02ae65f 100644
--- a/include/configs/bcm23550_w1d.h
+++ b/include/configs/bcm23550_w1d.h
@@ -104,15 +104,11 @@
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_SYS_LONGHELP
 
-#define CONFIG_CRC32_VERIFY
 #define CONFIG_MX_CYCLIC
 
 /* Initial upstream - boot to cmd prompt only */
 #define CONFIG_BOOTCOMMAND		""
 
-/* Commands */
-#define CONFIG_FAT_WRITE
-
 #undef CONFIG_USB_GADGET_VBUS_DRAW
 #define CONFIG_USB_GADGET_VBUS_DRAW	0
 #define CONFIG_USBID_ADDR		0x34052c46
diff --git a/include/configs/bcm28155_ap.h b/include/configs/bcm28155_ap.h
index 03f4ca0..5a85f7f 100644
--- a/include/configs/bcm28155_ap.h
+++ b/include/configs/bcm28155_ap.h
@@ -103,15 +103,11 @@
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_SYS_LONGHELP
 
-#define CONFIG_CRC32_VERIFY
 #define CONFIG_MX_CYCLIC
 
 /* Initial upstream - boot to cmd prompt only */
 #define CONFIG_BOOTCOMMAND		""
 
-/* Commands */
-#define CONFIG_FAT_WRITE
-
 #define CONFIG_USBID_ADDR		0x34052c46
 
 #endif /* __BCM28155_AP_H */
diff --git a/include/configs/bcm_ep_board.h b/include/configs/bcm_ep_board.h
index 957cd9e..2afbbea 100644
--- a/include/configs/bcm_ep_board.h
+++ b/include/configs/bcm_ep_board.h
@@ -60,19 +60,11 @@
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_SYS_LONGHELP
 
-#define CONFIG_CRC32_VERIFY
 #define CONFIG_MX_CYCLIC
 
-/* Commands */
-#define CONFIG_FAT_WRITE
-
-/* SHA hashing */
-#define CONFIG_HASH_VERIFY
-
 /* Enable Time Command */
 
 /* Misc utility code */
 #define CONFIG_BOUNCE_BUFFER
-#define CONFIG_CRC32_VERIFY
 
 #endif /* __BCM_EP_BOARD_H */
diff --git a/include/configs/bmips_bcm3380.h b/include/configs/bmips_bcm3380.h
new file mode 100644
index 0000000..0c3f7f5
--- /dev/null
+++ b/include/configs/bmips_bcm3380.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_BMIPS_BCM3380_H
+#define __CONFIG_BMIPS_BCM3380_H
+
+/* CPU */
+#define CONFIG_SYS_MIPS_TIMER_FREQ	166500000
+
+/* RAM */
+#define CONFIG_NR_DRAM_BANKS		1
+#define CONFIG_SYS_SDRAM_BASE		0x80000000
+
+/* U-Boot */
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_SYS_SDRAM_BASE + 0x100000
+
+#if defined(CONFIG_BMIPS_BOOT_RAM)
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_SYS_INIT_SP_OFFSET	0x2000
+#endif
+
+#endif /* __CONFIG_BMIPS_BCM3380_H */
diff --git a/include/configs/bmips_bcm6338.h b/include/configs/bmips_bcm6338.h
new file mode 100644
index 0000000..52d72c8
--- /dev/null
+++ b/include/configs/bmips_bcm6338.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_BMIPS_BCM6338_H
+#define __CONFIG_BMIPS_BCM6338_H
+
+/* CPU */
+#define CONFIG_SYS_MIPS_TIMER_FREQ	120000000
+
+/* RAM */
+#define CONFIG_NR_DRAM_BANKS		1
+#define CONFIG_SYS_SDRAM_BASE		0x80000000
+
+/* U-Boot */
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_SYS_SDRAM_BASE + 0x100000
+
+#if defined(CONFIG_BMIPS_BOOT_RAM)
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_SYS_INIT_SP_OFFSET	0x2000
+#endif
+
+#define CONFIG_SYS_FLASH_BASE			0xbfc00000
+#define CONFIG_SYS_FLASH_EMPTY_INFO
+#define CONFIG_SYS_FLASH_PROTECTION
+#define CONFIG_SYS_MAX_FLASH_BANKS_DETECT	1
+
+#endif /* __CONFIG_BMIPS_BCM6338_H */
diff --git a/include/configs/bmips_bcm6348.h b/include/configs/bmips_bcm6348.h
new file mode 100644
index 0000000..e9f53d6
--- /dev/null
+++ b/include/configs/bmips_bcm6348.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_BMIPS_BCM6348_H
+#define __CONFIG_BMIPS_BCM6348_H
+
+/* CPU */
+#define CONFIG_SYS_MIPS_TIMER_FREQ	128000000
+
+/* RAM */
+#define CONFIG_NR_DRAM_BANKS		1
+#define CONFIG_SYS_SDRAM_BASE		0x80000000
+
+/* U-Boot */
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_SYS_SDRAM_BASE + 0x100000
+
+#if defined(CONFIG_BMIPS_BOOT_RAM)
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_SYS_INIT_SP_OFFSET	0x2000
+#endif
+
+#define CONFIG_SYS_FLASH_BASE			0xbfc00000
+#define CONFIG_SYS_FLASH_EMPTY_INFO
+#define CONFIG_SYS_FLASH_PROTECTION
+#define CONFIG_SYS_MAX_FLASH_BANKS_DETECT	1
+
+#endif /* __CONFIG_BMIPS_BCM6348_H */
diff --git a/include/configs/bmips_common.h b/include/configs/bmips_common.h
index d2b05d4..38bf7a2 100644
--- a/include/configs/bmips_common.h
+++ b/include/configs/bmips_common.h
@@ -7,6 +7,10 @@
 #ifndef __CONFIG_BMIPS_COMMON_H
 #define __CONFIG_BMIPS_COMMON_H
 
+/* UART */
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200, \
+					  230400, 500000, 1500000 }
+
 /* RAM */
 #define CONFIG_SYS_MEMTEST_START	0xa0000000
 #define CONFIG_SYS_MEMTEST_END		0xa2000000
diff --git a/include/configs/brppt1.h b/include/configs/brppt1.h
index 521d097..10e8f88 100644
--- a/include/configs/brppt1.h
+++ b/include/configs/brppt1.h
@@ -276,7 +276,6 @@
  * enabled a number of useful commands and support.
  */
 #if defined(CONFIG_MMC) || defined(CONFIG_USB_STORAGE)
-#define CONFIG_FAT_WRITE
 #define CONFIG_FS_EXT4
 #define CONFIG_EXT4_WRITE
 #endif /* CONFIG_MMC, ... */
diff --git a/include/configs/brxre1.h b/include/configs/brxre1.h
index 9984689..5814d74 100644
--- a/include/configs/brxre1.h
+++ b/include/configs/brxre1.h
@@ -118,12 +118,5 @@
 #define CONFIG_ENV_OFFSET		0x40000	/* TODO: Adresse definieren */
 #define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
 #define CONFIG_SYS_REDUNDAND_ENVIRONMENT
-/*
- * Common filesystems support.  When we have removable storage we
- * enabled a number of useful commands and support.
- */
-#if defined(CONFIG_MMC) || defined(CONFIG_USB_STORAGE)
-#define CONFIG_FAT_WRITE
-#endif /* CONFIG_MMC, ... */
 
 #endif	/* __CONFIG_BRXRE1_H__ */
diff --git a/include/configs/calimain.h b/include/configs/calimain.h
index f5d108e..29d3bda 100644
--- a/include/configs/calimain.h
+++ b/include/configs/calimain.h
@@ -196,7 +196,6 @@
 #define CONFIG_AUTO_COMPLETE
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_SYS_LONGHELP
-#define CONFIG_CRC32_VERIFY
 #define CONFIG_MX_CYCLIC
 
 /*
diff --git a/include/configs/clearfog.h b/include/configs/clearfog.h
index 3397aaf..77c2493 100644
--- a/include/configs/clearfog.h
+++ b/include/configs/clearfog.h
@@ -79,7 +79,7 @@
 #define CONFIG_SYS_ALT_MEMTEST
 
 /* Keep device tree and initrd in lower memory so the kernel can access them */
-#define CONFIG_EXTRA_ENV_SETTINGS	\
+#define RELOCATION_LIMITS_ENV_SETTINGS	\
 	"fdt_high=0x10000000\0"		\
 	"initrd_high=0x10000000\0"
 
@@ -133,4 +133,50 @@
  */
 #include "mv-common.h"
 
+/* Include the common distro boot environment */
+#ifndef CONFIG_SPL_BUILD
+#include <config_distro_defaults.h>
+
+#ifdef CONFIG_MMC
+#define BOOT_TARGET_DEVICES_MMC(func) func(MMC, mmc, 0)
+#else
+#define BOOT_TARGET_DEVICES_MMC(func)
+#endif
+
+#ifdef CONFIG_USB_STORAGE
+#define BOOT_TARGET_DEVICES_USB(func) func(USB, usb, 0)
+#else
+#define BOOT_TARGET_DEVICES_USB(func)
+#endif
+
+#define BOOT_TARGET_DEVICES(func) \
+	BOOT_TARGET_DEVICES_MMC(func) \
+	BOOT_TARGET_DEVICES_USB(func) \
+	func(PXE, pxe, na) \
+	func(DHCP, dhcp, na)
+
+#define KERNEL_ADDR_R	__stringify(0x800000)
+#define FDT_ADDR_R	__stringify(0x100000)
+#define RAMDISK_ADDR_R	__stringify(0x1800000)
+#define SCRIPT_ADDR_R	__stringify(0x200000)
+#define PXEFILE_ADDR_R	__stringify(0x300000)
+
+#define LOAD_ADDRESS_ENV_SETTINGS \
+	"kernel_addr_r=" KERNEL_ADDR_R "\0" \
+	"fdt_addr_r=" FDT_ADDR_R "\0" \
+	"ramdisk_addr_r=" RAMDISK_ADDR_R "\0" \
+	"scriptaddr=" SCRIPT_ADDR_R "\0" \
+	"pxefile_addr_r=" PXEFILE_ADDR_R "\0"
+
+#include <config_distro_bootcmd.h>
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	RELOCATION_LIMITS_ENV_SETTINGS \
+	LOAD_ADDRESS_ENV_SETTINGS \
+	"fdtfile=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
+	"console=ttyS0,115200\0" \
+	BOOTENV
+
+#endif /* CONFIG_SPL_BUILD */
+
 #endif /* _CONFIG_CLEARFOG_H */
diff --git a/include/configs/colibri_imx6.h b/include/configs/colibri_imx6.h
index 0882ef8..82812e5 100644
--- a/include/configs/colibri_imx6.h
+++ b/include/configs/colibri_imx6.h
@@ -64,7 +64,6 @@
 
 #define CONFIG_SUPPORT_EMMC_BOOT	/* eMMC specific */
 #define CONFIG_BOUNCE_BUFFER
-#define CONFIG_FAT_WRITE
 
 /* Network */
 #define CONFIG_FEC_MXC
@@ -288,6 +287,4 @@
 
 #define CONFIG_SUPPORT_RAW_INITRD
 
-#define CONFIG_CRC32_VERIFY
-
 #endif	/* __CONFIG_H */
diff --git a/include/configs/colibri_t20.h b/include/configs/colibri_t20.h
index 03f6863..7355f78 100644
--- a/include/configs/colibri_t20.h
+++ b/include/configs/colibri_t20.h
@@ -67,10 +67,6 @@
 #define CONFIG_LZO
 #define CONFIG_RBTREE
 
-/* Debug commands */
-
-/* Miscellaneous commands */
-#define CONFIG_FAT_WRITE
 
 #define BOARD_EXTRA_ENV_SETTINGS \
 	"mtdparts=" MTDPARTS_DEFAULT "\0"
diff --git a/include/configs/colibri_t30.h b/include/configs/colibri_t30.h
index 853cd52..53ff33e 100644
--- a/include/configs/colibri_t30.h
+++ b/include/configs/colibri_t30.h
@@ -44,9 +44,6 @@
 #define CONFIG_TFTP_BLOCKSIZE		16352
 #define CONFIG_TFTP_TSIZE
 
-/* Miscellaneous commands */
-#define CONFIG_FAT_WRITE
-
 /* Increase console I/O buffer size */
 #undef CONFIG_SYS_CBSIZE
 #define CONFIG_SYS_CBSIZE		1024
diff --git a/include/configs/comtrend_ct5361.h b/include/configs/comtrend_ct5361.h
new file mode 100644
index 0000000..099684d
--- /dev/null
+++ b/include/configs/comtrend_ct5361.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <configs/bmips_common.h>
+#include <configs/bmips_bcm6348.h>
+
+#define CONFIG_REMAKE_ELF
+
+#define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_SIZE			(8 * 1024)
+
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_SYS_LONGHELP
+
+#define CONFIG_SYS_FLASH_CFI		1
+#define CONFIG_FLASH_CFI_DRIVER		1
diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h
index e0bbf94..f46f466 100644
--- a/include/configs/da850evm.h
+++ b/include/configs/da850evm.h
@@ -255,7 +255,6 @@
 #define CONFIG_AUTO_COMPLETE
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_SYS_LONGHELP
-#define CONFIG_CRC32_VERIFY
 #define CONFIG_MX_CYCLIC
 
 /*
diff --git a/include/configs/devkit8000.h b/include/configs/devkit8000.h
index c892b5f..92ce127 100644
--- a/include/configs/devkit8000.h
+++ b/include/configs/devkit8000.h
@@ -94,7 +94,6 @@
 #define CONFIG_CMD_NAND_LOCK_UNLOCK	/* nand (un)lock commands	*/
 
 #undef CONFIG_SUPPORT_RAW_INITRD
-#undef CONFIG_FAT_WRITE
 
 /* BOOTP/DHCP options */
 #define CONFIG_BOOTP_SUBNETMASK
diff --git a/include/configs/ds109.h b/include/configs/ds109.h
index 4c87436..133b2b0 100644
--- a/include/configs/ds109.h
+++ b/include/configs/ds109.h
@@ -24,7 +24,6 @@
  * Commands configuration
  */
 #define CONFIG_CMD_EXT2
-#define CONFIG_CMD_FAT
 
 /*
  * mv-plug-common.h should be defined after CMD configs since it used them
diff --git a/include/configs/ea20.h b/include/configs/ea20.h
index 53ee1ad..fc0f5e6 100644
--- a/include/configs/ea20.h
+++ b/include/configs/ea20.h
@@ -115,7 +115,6 @@
 #define CONFIG_AUTO_COMPLETE
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_SYS_LONGHELP
-#define CONFIG_CRC32_VERIFY
 #define CONFIG_MX_CYCLIC
 
 /*
diff --git a/include/configs/etamin.h b/include/configs/etamin.h
index a0152a4..1662dbf 100644
--- a/include/configs/etamin.h
+++ b/include/configs/etamin.h
@@ -87,8 +87,6 @@
 	"led4=60,0,1\0" \
 	"led5=63,0,1\0"
 
-#undef CONFIG_CMD_FAT
-
 /* Physical Memory Map */
 #define CONFIG_MAX_RAM_BANK_SIZE       (1024 << 20)    /* 1GB */
 
diff --git a/include/configs/exynos-common.h b/include/configs/exynos-common.h
index ade66a4..031586b 100644
--- a/include/configs/exynos-common.h
+++ b/include/configs/exynos-common.h
@@ -41,9 +41,6 @@
 /* PWM */
 #define CONFIG_PWM
 
-/* Command definition*/
-#define CONFIG_FAT_WRITE
-
 /* Miscellaneous configurable options */
 #define CONFIG_SYS_CBSIZE		1024	/* Console I/O Buffer Size */
 #define CONFIG_SYS_PBSIZE		1024	/* Print Buffer Size */
diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h
index 6915dc1..378219d 100644
--- a/include/configs/exynos5-common.h
+++ b/include/configs/exynos5-common.h
@@ -131,9 +131,6 @@
 #define CONFIG_ENV_SROM_BANK		1
 #endif /*CONFIG_CMD_NET*/
 
-/* SHA hashing */
-#define CONFIG_HASH_VERIFY
-
 /* Enable Time Command */
 
 /* USB */
diff --git a/include/configs/hikey.h b/include/configs/hikey.h
index 0fb6fb3..2b4fec4 100644
--- a/include/configs/hikey.h
+++ b/include/configs/hikey.h
@@ -111,7 +111,6 @@
 #define FAT_ENV_INTERFACE               "mmc"
 #define FAT_ENV_DEVICE_AND_PART         "1:1"
 #define FAT_ENV_FILE                    "uboot.env"
-#define CONFIG_FAT_WRITE
 #define CONFIG_ENV_VARS_UBOOT_CONFIG
 
 /* Monitor Command Prompt */
diff --git a/include/configs/imx6qdl_icore.h b/include/configs/imx6qdl_icore.h
index 741bdfa..13fc48f 100644
--- a/include/configs/imx6qdl_icore.h
+++ b/include/configs/imx6qdl_icore.h
@@ -125,7 +125,6 @@
 
 /* FIT */
 #ifdef CONFIG_FIT
-# define CONFIG_HASH_VERIFY
 # define CONFIG_IMAGE_FORMAT_LEGACY
 #endif
 
diff --git a/include/configs/imx6qdl_icore_rqs.h b/include/configs/imx6qdl_icore_rqs.h
index f52865b..a588823 100644
--- a/include/configs/imx6qdl_icore_rqs.h
+++ b/include/configs/imx6qdl_icore_rqs.h
@@ -107,7 +107,6 @@
 
 /* FIT */
 #ifdef CONFIG_FIT
-# define CONFIG_HASH_VERIFY
 # define CONFIG_IMAGE_FORMAT_LEGACY
 #endif
 
diff --git a/include/configs/imx6ul_geam.h b/include/configs/imx6ul_geam.h
index 2e12b97..1d48726 100644
--- a/include/configs/imx6ul_geam.h
+++ b/include/configs/imx6ul_geam.h
@@ -124,7 +124,6 @@
 
 /* FIT */
 #ifdef CONFIG_FIT
-# define CONFIG_HASH_VERIFY
 # define CONFIG_IMAGE_FORMAT_LEGACY
 #endif
 
diff --git a/include/configs/imx6ul_isiot.h b/include/configs/imx6ul_isiot.h
index 76ae159..a0eb6e2 100644
--- a/include/configs/imx6ul_isiot.h
+++ b/include/configs/imx6ul_isiot.h
@@ -124,7 +124,6 @@
 
 /* FIT */
 #ifdef CONFIG_FIT
-# define CONFIG_HASH_VERIFY
 # define CONFIG_IMAGE_FORMAT_LEGACY
 #endif
 
diff --git a/include/configs/ipam390.h b/include/configs/ipam390.h
index a3c0cfa..127e7e7 100644
--- a/include/configs/ipam390.h
+++ b/include/configs/ipam390.h
@@ -205,7 +205,6 @@
 #define CONFIG_AUTO_COMPLETE
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_SYS_LONGHELP
-#define CONFIG_CRC32_VERIFY
 #define CONFIG_MX_CYCLIC
 
 /*
diff --git a/include/configs/k2e_evm.h b/include/configs/k2e_evm.h
index 3a7993e..b186bfc 100644
--- a/include/configs/k2e_evm.h
+++ b/include/configs/k2e_evm.h
@@ -27,6 +27,10 @@
 	"name_uboot=u-boot-spi-k2e-evm.gph\0"				\
 	"name_fs=arago-console-image-k2e-evm.cpio.gz\0"
 
+#define CONFIG_ENV_SIZE				(256 << 10)  /* 256 KiB */
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_OFFSET			0x100000
+
 #include <configs/ti_armv7_keystone2.h>
 
 /* SPL SPI Loader Configuration */
diff --git a/include/configs/k2g_evm.h b/include/configs/k2g_evm.h
index bee1be7..1cc3576 100644
--- a/include/configs/k2g_evm.h
+++ b/include/configs/k2g_evm.h
@@ -48,8 +48,6 @@
 	"get_pmmc_${boot} run_pmmc get_mon_${boot} run_mon "		\
 	"get_fdt_${boot} get_kern_${boot} run_kern"
 
-#include <configs/ti_armv7_keystone2.h>
-
 /* SPL SPI Loader Configuration */
 #define CONFIG_SPL_TEXT_BASE		0x0c080000
 
@@ -63,8 +61,8 @@
 #define CONFIG_PHY_MICREL
 #define PHY_ANEG_TIMEOUT	10000 /* PHY needs longer aneg time */
 
-#undef CONFIG_ENV_IS_IN_NAND
 #define CONFIG_ENV_IS_IN_FAT
+#define CONFIG_ENV_SIZE			(256 << 10)  /* 256 KiB */
 #define FAT_ENV_INTERFACE		"mmc"
 #define FAT_ENV_DEVICE_AND_PART		"0:1"
 #define FAT_ENV_FILE			"uboot.env"
@@ -80,4 +78,7 @@
 #endif
 
 #define SPI_MTD_PARTS	KEYSTONE_SPI1_MTD_PARTS
+
+#include <configs/ti_armv7_keystone2.h>
+
 #endif /* __CONFIG_K2G_EVM_H */
diff --git a/include/configs/k2hk_evm.h b/include/configs/k2hk_evm.h
index 202167b..9598bc6 100644
--- a/include/configs/k2hk_evm.h
+++ b/include/configs/k2hk_evm.h
@@ -27,6 +27,10 @@
 	"name_uboot=u-boot-spi-k2hk-evm.gph\0"				\
 	"name_fs=arago-console-image-k2hk-evm.cpio.gz\0"
 
+#define CONFIG_ENV_SIZE				(256 << 10)  /* 256 KiB */
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_OFFSET			0x100000
+
 #include <configs/ti_armv7_keystone2.h>
 
 /* SPL SPI Loader Configuration */
diff --git a/include/configs/k2l_evm.h b/include/configs/k2l_evm.h
index a7ccdd1..d054276 100644
--- a/include/configs/k2l_evm.h
+++ b/include/configs/k2l_evm.h
@@ -27,6 +27,10 @@
 	"name_uboot=u-boot-spi-k2l-evm.gph\0"				\
 	"name_fs=arago-console-image-k2l-evm.cpio.gz\0"
 
+#define CONFIG_ENV_SIZE				(256 << 10)  /* 256 KiB */
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_OFFSET			0x100000
+
 #include <configs/ti_armv7_keystone2.h>
 
 /* SPL SPI Loader Configuration */
diff --git a/include/configs/legoev3.h b/include/configs/legoev3.h
index c5e7d62..f230f40 100644
--- a/include/configs/legoev3.h
+++ b/include/configs/legoev3.h
@@ -150,7 +150,6 @@
 #define CONFIG_AUTO_COMPLETE
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_SYS_LONGHELP
-#define CONFIG_CRC32_VERIFY
 #define CONFIG_MX_CYCLIC
 
 /*
diff --git a/include/configs/ls1021aiot.h b/include/configs/ls1021aiot.h
index d6839c0..c1ec2d4 100644
--- a/include/configs/ls1021aiot.h
+++ b/include/configs/ls1021aiot.h
@@ -158,8 +158,6 @@
 #define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
 		CONFIG_SYS_SCSI_MAX_LUN)
 
-#define CONFIG_CMD_FAT
-
 /* SPI */
 #if defined(CONFIG_QSPI_BOOT) || defined(CONFIG_SD_BOOT_QSPI)
 #define CONFIG_SPI_FLASH_SPANSION
diff --git a/include/configs/ls1043ardb.h b/include/configs/ls1043ardb.h
index aaa6ee0..deae787 100644
--- a/include/configs/ls1043ardb.h
+++ b/include/configs/ls1043ardb.h
@@ -300,9 +300,6 @@
 #define CONFIG_LIBATA
 #define CONFIG_SCSI_AHCI
 #define CONFIG_CMD_SCSI
-#ifndef CONFIG_CMD_FAT
-#define CONFIG_CMD_FAT
-#endif
 #ifndef CONFIG_CMD_EXT2
 #define CONFIG_CMD_EXT2
 #endif
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index c471723..8dea031 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -14,8 +14,6 @@
 #define CONFIG_TIMESTAMP		/* Print image info with timestamp */
 
 /* U-Boot Commands */
-#define CONFIG_FAT_WRITE
-
 #define CONFIG_CMD_NAND
 #define CONFIG_CMD_NAND_TRIMFFS
 
diff --git a/include/configs/m53evk.h b/include/configs/m53evk.h
index b237cea..5181225 100644
--- a/include/configs/m53evk.h
+++ b/include/configs/m53evk.h
@@ -20,8 +20,6 @@
 /*
  * U-Boot Commands
  */
-#define CONFIG_FAT_WRITE
-
 #define CONFIG_CMD_NAND
 #define CONFIG_CMD_NAND_TRIMFFS
 #define CONFIG_CMD_SATA
diff --git a/include/configs/ma5d4evk.h b/include/configs/ma5d4evk.h
index 6dc1fb0..bb66140 100644
--- a/include/configs/ma5d4evk.h
+++ b/include/configs/ma5d4evk.h
@@ -15,11 +15,6 @@
 #define CONFIG_SYS_USE_SERIALFLASH	1
 
 /*
- * U-Boot Commands
- */
-#define CONFIG_FAT_WRITE
-
-/*
  * Memory configurations
  */
 #define CONFIG_NR_DRAM_BANKS		1
diff --git a/include/configs/mx7ulp_evk.h b/include/configs/mx7ulp_evk.h
index 37f365d..288a889 100644
--- a/include/configs/mx7ulp_evk.h
+++ b/include/configs/mx7ulp_evk.h
@@ -45,9 +45,6 @@
 #define CONFIG_ENV_IS_IN_MMC
 #define CONFIG_ENV_SIZE			SZ_8K
 
-#define CONFIG_CMD_FAT
-#define CONFIG_DOS_PARTITION
-
 /* Using ULP WDOG for reset */
 #define WDOG_BASE_ADDR			WDG1_RBASE
 
diff --git a/include/configs/netgear_cg3100d.h b/include/configs/netgear_cg3100d.h
new file mode 100644
index 0000000..c97d4e5
--- /dev/null
+++ b/include/configs/netgear_cg3100d.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <configs/bmips_common.h>
+#include <configs/bmips_bcm3380.h>
+
+#define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_SIZE			(8 * 1024)
+
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_SYS_LONGHELP
diff --git a/include/configs/novena.h b/include/configs/novena.h
index 6cb1807..1f1bf15 100644
--- a/include/configs/novena.h
+++ b/include/configs/novena.h
@@ -17,7 +17,6 @@
 #include "mx6_common.h"
 
 /* U-Boot Commands */
-#define CONFIG_FAT_WRITE
 #define CONFIG_CMD_PCI
 #define CONFIG_CMD_SATA
 
diff --git a/include/configs/omapl138_lcdk.h b/include/configs/omapl138_lcdk.h
index 9db4eeb..8904cd5 100644
--- a/include/configs/omapl138_lcdk.h
+++ b/include/configs/omapl138_lcdk.h
@@ -249,7 +249,6 @@
 #define CONFIG_AUTO_COMPLETE
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_SYS_LONGHELP
-#define CONFIG_CRC32_VERIFY
 #define CONFIG_MX_CYCLIC
 
 /*
diff --git a/include/configs/pic32mzdask.h b/include/configs/pic32mzdask.h
index 2dcc6c4..c5bfdec 100644
--- a/include/configs/pic32mzdask.h
+++ b/include/configs/pic32mzdask.h
@@ -90,8 +90,6 @@
  */
 /* FAT FS */
 #define CONFIG_SUPPORT_VFAT
-#define CONFIG_FS_FAT
-#define CONFIG_FAT_WRITE
 
 /* EXT4 FS */
 #define CONFIG_FS_EXT4
diff --git a/include/configs/picosam9g45.h b/include/configs/picosam9g45.h
index 998a7a3..c83e559 100644
--- a/include/configs/picosam9g45.h
+++ b/include/configs/picosam9g45.h
@@ -116,7 +116,6 @@
 #define FAT_ENV_DEVICE_AND_PART	"0"
 #define FAT_ENV_FILE		"uboot.env"
 #define CONFIG_ENV_IS_IN_FAT
-#define CONFIG_FAT_WRITE
 #define CONFIG_ENV_SIZE		0x4000
 
 #define CONFIG_BOOTARGS		"console=ttyS0,115200 " \
diff --git a/include/configs/rcar-gen2-common.h b/include/configs/rcar-gen2-common.h
index 3a719c0..365950d 100644
--- a/include/configs/rcar-gen2-common.h
+++ b/include/configs/rcar-gen2-common.h
@@ -14,7 +14,6 @@
 #define CONFIG_CMD_SDRAM
 
 /* Support File sytems */
-#define CONFIG_FAT_WRITE
 #define CONFIG_SUPPORT_VFAT
 #define CONFIG_FS_EXT4
 #define CONFIG_EXT4_WRITE
diff --git a/include/configs/rcar-gen3-common.h b/include/configs/rcar-gen3-common.h
index e73bc61..8da3e7a 100644
--- a/include/configs/rcar-gen3-common.h
+++ b/include/configs/rcar-gen3-common.h
@@ -13,7 +13,6 @@
 #include <asm/arch/rmobile.h>
 
 #define CONFIG_CMD_SDRAM
-#define CONFIG_CMD_FAT
 #define CONFIG_CMD_EXT2
 #define CONFIG_CMD_EXT4
 #define CONFIG_CMD_EXT4_WRITE
@@ -24,7 +23,6 @@
 #define CONFIG_SUPPORT_RAW_INITRD
 
 /* Support File sytems */
-#define CONFIG_FAT_WRITE
 #define CONFIG_SUPPORT_VFAT
 #define CONFIG_FS_EXT4
 #define CONFIG_EXT4_WRITE
diff --git a/include/configs/rk3036_common.h b/include/configs/rk3036_common.h
index 2893f80..836c5e3 100644
--- a/include/configs/rk3036_common.h
+++ b/include/configs/rk3036_common.h
@@ -36,8 +36,6 @@
 /* MMC/SD IP block */
 #define CONFIG_BOUNCE_BUFFER
 
-#define CONFIG_FAT_WRITE
-
 #define CONFIG_SYS_SDRAM_BASE		0x60000000
 #define CONFIG_NR_DRAM_BANKS		1
 #define SDRAM_BANK_SIZE			(512UL << 20UL)
diff --git a/include/configs/rk3188_common.h b/include/configs/rk3188_common.h
index 81a1553..a1e0eb7 100644
--- a/include/configs/rk3188_common.h
+++ b/include/configs/rk3188_common.h
@@ -61,8 +61,6 @@
 /* MMC/SD IP block */
 #define CONFIG_BOUNCE_BUFFER
 
-#define CONFIG_FAT_WRITE
-
 #define CONFIG_SYS_SDRAM_BASE		0x60000000
 #define CONFIG_NR_DRAM_BANKS		1
 #define SDRAM_BANK_SIZE			(2UL << 30)
diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
index 4cf71fa..ecf2675 100644
--- a/include/configs/rk3288_common.h
+++ b/include/configs/rk3288_common.h
@@ -38,8 +38,6 @@
 /* MMC/SD IP block */
 #define CONFIG_BOUNCE_BUFFER
 
-#define CONFIG_FAT_WRITE
-
 /* RAW SD card / eMMC locations. */
 #define CONFIG_SYS_SPI_U_BOOT_OFFS	(128 << 10)
 
diff --git a/include/configs/rk3328_common.h b/include/configs/rk3328_common.h
index b0dcd48..7ccbc9b 100644
--- a/include/configs/rk3328_common.h
+++ b/include/configs/rk3328_common.h
@@ -28,8 +28,6 @@
 #define CONFIG_BOUNCE_BUFFER
 
 #define CONFIG_SUPPORT_VFAT
-#define CONFIG_FS_FAT
-#define CONFIG_FAT_WRITE
 #define CONFIG_FS_EXT4
 
 /* RAW SD card / eMMC locations. */
diff --git a/include/configs/rk3399_common.h b/include/configs/rk3399_common.h
index 49f56f2..7a8a442 100644
--- a/include/configs/rk3399_common.h
+++ b/include/configs/rk3399_common.h
@@ -43,8 +43,6 @@
 #define CONFIG_ROCKCHIP_SDHCI_MAX_FREQ	200000000
 
 #define CONFIG_SUPPORT_VFAT
-#define CONFIG_FS_FAT
-#define CONFIG_FAT_WRITE
 #define CONFIG_FS_EXT4
 
 /* RAW SD card / eMMC locations. */
diff --git a/include/configs/rpi.h b/include/configs/rpi.h
index 7b9017f..d715eaa 100644
--- a/include/configs/rpi.h
+++ b/include/configs/rpi.h
@@ -97,7 +97,6 @@
 #define FAT_ENV_INTERFACE		"mmc"
 #define FAT_ENV_DEVICE_AND_PART		"0:1"
 #define FAT_ENV_FILE			"uboot.env"
-#define CONFIG_FAT_WRITE
 #define CONFIG_ENV_VARS_UBOOT_CONFIG
 #define CONFIG_SYS_LOAD_ADDR		0x1000000
 #define CONFIG_PREBOOT			"usb start"
diff --git a/include/configs/s5p_goni.h b/include/configs/s5p_goni.h
index e49b3d9..c328e43 100644
--- a/include/configs/s5p_goni.h
+++ b/include/configs/s5p_goni.h
@@ -210,7 +210,6 @@
 #define CONFIG_SYS_ONENAND_BASE		0xB0000000
 
 /* write support for filesystems */
-#define CONFIG_FAT_WRITE
 #define CONFIG_EXT4_WRITE
 
 /* GPT */
diff --git a/include/configs/s5pc210_universal.h b/include/configs/s5pc210_universal.h
index 6c75626..0265684 100644
--- a/include/configs/s5pc210_universal.h
+++ b/include/configs/s5pc210_universal.h
@@ -176,7 +176,6 @@
 
 /* Download menu - definitions for check keys */
 #ifndef __ASSEMBLY__
-#include <power/max8998_pmic.h>
 
 #define KEY_PWR_PMIC_NAME		"MAX8998_PMIC"
 #define KEY_PWR_STATUS_REG		MAX8998_REG_STATUS1
diff --git a/include/configs/sagem_f@st1704.h b/include/configs/sagem_f@st1704.h
new file mode 100644
index 0000000..dbc7725
--- /dev/null
+++ b/include/configs/sagem_f@st1704.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <configs/bmips_common.h>
+#include <configs/bmips_bcm6338.h>
+
+#define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_SIZE			(8 * 1024)
+
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_SYS_LONGHELP
diff --git a/include/configs/sama5d2_ptc.h b/include/configs/sama5d2_ptc.h
index 57fa67d..7607f94 100644
--- a/include/configs/sama5d2_ptc.h
+++ b/include/configs/sama5d2_ptc.h
@@ -77,10 +77,6 @@
 #define CONFIG_USB_ETH_RNDIS
 #define CONFIG_USBNET_MANUFACTURER      "Atmel SAMA5D2_PTC"
 
-#if defined(CONFIG_CMD_USB)
-#define CONFIG_CMD_FAT
-#endif
-
 /* Ethernet Hardware */
 #define CONFIG_MACB
 #define CONFIG_RMII
diff --git a/include/configs/sama5d3_xplained.h b/include/configs/sama5d3_xplained.h
index 074c756..fbe26ca 100644
--- a/include/configs/sama5d3_xplained.h
+++ b/include/configs/sama5d3_xplained.h
@@ -74,10 +74,6 @@
 #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS	2
 #endif
 
-#if defined(CONFIG_CMD_USB) || defined(CONFIG_CMD_MMC)
-#define CONFIG_FAT_WRITE
-#endif
-
 #define CONFIG_SYS_LOAD_ADDR			0x22000000 /* load address */
 
 #if CONFIG_SYS_USE_NANDFLASH
diff --git a/include/configs/sama5d3xek.h b/include/configs/sama5d3xek.h
index 9540a4a..891d6a0 100644
--- a/include/configs/sama5d3xek.h
+++ b/include/configs/sama5d3xek.h
@@ -101,10 +101,6 @@
 #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS	3
 #endif
 
-#if defined(CONFIG_CMD_USB) || defined(CONFIG_CMD_MMC)
-#define CONFIG_FAT_WRITE
-#endif
-
 #define CONFIG_SYS_LOAD_ADDR			0x22000000 /* load address */
 
 #ifdef CONFIG_SYS_USE_SERIALFLASH
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index c62b45e..31ceb54 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -29,8 +29,6 @@
 
 #define CONFIG_CMD_PCI
 
-#define CONFIG_FS_FAT
-#define CONFIG_FAT_WRITE
 #define CONFIG_FS_EXT4
 #define CONFIG_EXT4_WRITE
 #define CONFIG_HOST_MAX_DEVICES 4
@@ -98,8 +96,6 @@
 #define CONFIG_BOOTP_SERVERIP
 #define CONFIG_IP_DEFRAG
 
-#define CONFIG_HASH_VERIFY
-
 #define CONFIG_CMD_SANDBOX
 
 #define CONFIG_BOOTARGS ""
diff --git a/include/configs/siemens-am33x-common.h b/include/configs/siemens-am33x-common.h
index 9161867..b5705b7 100644
--- a/include/configs/siemens-am33x-common.h
+++ b/include/configs/siemens-am33x-common.h
@@ -120,7 +120,6 @@
 
 #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
 #define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME	"u-boot.img"
-#define CONFIG_FS_FAT
 
 #define CONFIG_SPL_SPI_LOAD
 #define CONFIG_SYS_SPI_U_BOOT_OFFS	0x20000
diff --git a/include/configs/snapper9g45.h b/include/configs/snapper9g45.h
index 99b5b23..4e0b9b1 100644
--- a/include/configs/snapper9g45.h
+++ b/include/configs/snapper9g45.h
@@ -129,7 +129,6 @@
 /* Command line configuration */
 #define CONFIG_CMD_PING
 #define CONFIG_CMD_DHCP
-#define CONFIG_CMD_FAT
 #define CONFIG_CMD_USB
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_MMC
diff --git a/include/configs/socfpga_arria10_socdk.h b/include/configs/socfpga_arria10_socdk.h
index 7ea780b..3b59b6a 100644
--- a/include/configs/socfpga_arria10_socdk.h
+++ b/include/configs/socfpga_arria10_socdk.h
@@ -8,8 +8,7 @@
 #define __CONFIG_SOCFGPA_ARRIA10_H__
 
 #include <asm/arch/base_addr_a10.h>
-/* U-Boot Commands */
-#define CONFIG_FAT_WRITE
+
 #define CONFIG_HW_WATCHDOG
 
 /* Booting Linux */
diff --git a/include/configs/socfpga_arria5_socdk.h b/include/configs/socfpga_arria5_socdk.h
index b60d007..fe40319 100644
--- a/include/configs/socfpga_arria5_socdk.h
+++ b/include/configs/socfpga_arria5_socdk.h
@@ -8,8 +8,6 @@
 
 #include <asm/arch/base_addr_ac5.h>
 
-/* U-Boot Commands */
-#define CONFIG_FAT_WRITE
 #define CONFIG_HW_WATCHDOG
 
 /* Memory configurations */
diff --git a/include/configs/socfpga_common.h b/include/configs/socfpga_common.h
index bdc6512..fd18ae5 100644
--- a/include/configs/socfpga_common.h
+++ b/include/configs/socfpga_common.h
@@ -15,8 +15,6 @@
 #define CONFIG_DISPLAY_BOARDINFO_LATE
 #define CONFIG_CLOCKS
 
-#define CONFIG_CRC32_VERIFY
-
 #define CONFIG_SYS_BOOTMAPSZ		(64 * 1024 * 1024)
 
 #define CONFIG_TIMESTAMP		/* Print image info with timestamp */
diff --git a/include/configs/socfpga_cyclone5_socdk.h b/include/configs/socfpga_cyclone5_socdk.h
index dfe4980..be56521 100644
--- a/include/configs/socfpga_cyclone5_socdk.h
+++ b/include/configs/socfpga_cyclone5_socdk.h
@@ -8,8 +8,6 @@
 
 #include <asm/arch/base_addr_ac5.h>
 
-/* U-Boot Commands */
-#define CONFIG_FAT_WRITE
 #define CONFIG_HW_WATCHDOG
 
 /* Memory configurations */
diff --git a/include/configs/socfpga_de0_nano_soc.h b/include/configs/socfpga_de0_nano_soc.h
index dd5933d..320c585 100644
--- a/include/configs/socfpga_de0_nano_soc.h
+++ b/include/configs/socfpga_de0_nano_soc.h
@@ -8,8 +8,6 @@
 
 #include <asm/arch/base_addr_ac5.h>
 
-/* U-Boot Commands */
-#define CONFIG_FAT_WRITE
 #define CONFIG_HW_WATCHDOG
 
 /* Memory configurations */
diff --git a/include/configs/socfpga_de10_nano.h b/include/configs/socfpga_de10_nano.h
index 302ec20..ef693b0 100644
--- a/include/configs/socfpga_de10_nano.h
+++ b/include/configs/socfpga_de10_nano.h
@@ -8,8 +8,6 @@
 
 #include <asm/arch/base_addr_ac5.h>
 
-/* U-Boot Commands */
-#define CONFIG_FAT_WRITE
 #define CONFIG_HW_WATCHDOG
 
 /* Memory configurations */
diff --git a/include/configs/socfpga_de1_soc.h b/include/configs/socfpga_de1_soc.h
index 014828b..522ac74 100644
--- a/include/configs/socfpga_de1_soc.h
+++ b/include/configs/socfpga_de1_soc.h
@@ -8,8 +8,6 @@
 
 #include <asm/arch/base_addr_ac5.h>
 
-/* U-Boot Commands */
-#define CONFIG_FAT_WRITE
 #define CONFIG_HW_WATCHDOG
 
 /* Memory configurations */
diff --git a/include/configs/socfpga_is1.h b/include/configs/socfpga_is1.h
index 3585eeb..68403aa 100644
--- a/include/configs/socfpga_is1.h
+++ b/include/configs/socfpga_is1.h
@@ -9,8 +9,6 @@
 
 #include <asm/arch/base_addr_ac5.h>
 
-/* U-Boot Commands */
-#define CONFIG_FAT_WRITE
 #define CONFIG_HW_WATCHDOG
 
 /* Memory configurations */
diff --git a/include/configs/socfpga_mcvevk.h b/include/configs/socfpga_mcvevk.h
index 2d36702..ee85708 100644
--- a/include/configs/socfpga_mcvevk.h
+++ b/include/configs/socfpga_mcvevk.h
@@ -8,8 +8,6 @@
 
 #include <asm/arch/base_addr_ac5.h>
 
-/* U-Boot Commands */
-#define CONFIG_FAT_WRITE
 #define CONFIG_HW_WATCHDOG
 
 /* Memory configurations */
diff --git a/include/configs/socfpga_sockit.h b/include/configs/socfpga_sockit.h
index c9fc5c9..c75acc0 100644
--- a/include/configs/socfpga_sockit.h
+++ b/include/configs/socfpga_sockit.h
@@ -8,8 +8,6 @@
 
 #include <asm/arch/base_addr_ac5.h>
 
-/* U-Boot Commands */
-#define CONFIG_FAT_WRITE
 #define CONFIG_HW_WATCHDOG
 
 /* Memory configurations */
diff --git a/include/configs/socfpga_socrates.h b/include/configs/socfpga_socrates.h
index 5dc9298..a08fa9f 100644
--- a/include/configs/socfpga_socrates.h
+++ b/include/configs/socfpga_socrates.h
@@ -8,8 +8,6 @@
 
 #include <asm/arch/base_addr_ac5.h>
 
-/* U-Boot Commands */
-#define CONFIG_FAT_WRITE
 #define CONFIG_HW_WATCHDOG
 
 /* Memory configurations */
diff --git a/include/configs/socfpga_sr1500.h b/include/configs/socfpga_sr1500.h
index 64e1595..4366061 100644
--- a/include/configs/socfpga_sr1500.h
+++ b/include/configs/socfpga_sr1500.h
@@ -8,8 +8,6 @@
 
 #include <asm/arch/base_addr_ac5.h>
 
-#define CONFIG_FAT_WRITE
-
 #define CONFIG_HW_WATCHDOG
 
 /* Memory configurations */
diff --git a/include/configs/socfpga_vining_fpga.h b/include/configs/socfpga_vining_fpga.h
index 251dd0e..e2bdfb1 100644
--- a/include/configs/socfpga_vining_fpga.h
+++ b/include/configs/socfpga_vining_fpga.h
@@ -8,8 +8,6 @@
 
 #include <asm/arch/base_addr_ac5.h>
 
-/* U-Boot Commands */
-#define CONFIG_FAT_WRITE
 #define CONFIG_HW_WATCHDOG
 
 /* Memory configurations */
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index f042f0d..9b514ff 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -180,8 +180,6 @@
 
 #define CONFIG_SYS_MONITOR_LEN		(768 << 10)	/* 768 KiB */
 
-#define CONFIG_FAT_WRITE	/* enable write access */
-
 #define CONFIG_SPL_FRAMEWORK
 
 #ifndef CONFIG_ARM64		/* AArch64 FEL support is not ready yet */
diff --git a/include/configs/tegra-common-post.h b/include/configs/tegra-common-post.h
index 1a4a7e2..c03efd8 100644
--- a/include/configs/tegra-common-post.h
+++ b/include/configs/tegra-common-post.h
@@ -118,9 +118,6 @@
 #ifdef CONFIG_FS_EXT4
 #undef CONFIG_FS_EXT4
 #endif
-#ifdef CONFIG_FS_FAT
-#undef CONFIG_FS_FAT
-#endif
 
 /* remove USB */
 #ifdef CONFIG_USB_EHCI_TEGRA
diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h
index 6982eaa..723435e 100644
--- a/include/configs/tegra-common.h
+++ b/include/configs/tegra-common.h
@@ -96,11 +96,9 @@
 
 /* Misc utility code */
 #define CONFIG_BOUNCE_BUFFER
-#define CONFIG_CRC32_VERIFY
 
 #ifndef CONFIG_SPL_BUILD
 #include <config_distro_defaults.h>
-#define CONFIG_FAT_WRITE
 #endif
 
 #endif /* _TEGRA_COMMON_H_ */
diff --git a/include/configs/ti816x_evm.h b/include/configs/ti816x_evm.h
index 2303970..68eb08f 100644
--- a/include/configs/ti816x_evm.h
+++ b/include/configs/ti816x_evm.h
@@ -50,8 +50,6 @@
 
 #define CONFIG_CMD_ASKENV
 
-#define CONFIG_FS_FAT
-
 /*
  * Only one of the following two options (DDR3/DDR2) should be enabled
  * CONFIG_TI816X_EVM_DDR2
diff --git a/include/configs/ti_armv7_common.h b/include/configs/ti_armv7_common.h
index 0bd3c9f..5321ed6 100644
--- a/include/configs/ti_armv7_common.h
+++ b/include/configs/ti_armv7_common.h
@@ -145,14 +145,6 @@
 #define CONFIG_SUPPORT_RAW_INITRD
 
 /*
- * Common filesystems support.  When we have removable storage we
- * enabled a number of useful commands and support.
- */
-#if defined(CONFIG_MMC) || defined(CONFIG_USB_STORAGE)
-#define CONFIG_FAT_WRITE
-#endif
-
-/*
  * Our platforms make use of SPL to initalize the hardware (primarily
  * memory) enough for full U-Boot to be loaded. We make use of the general
  * SPL framework found under common/spl/.  Given our generally common memory
diff --git a/include/configs/ti_armv7_keystone2.h b/include/configs/ti_armv7_keystone2.h
index 3161c50..ac8dabd 100644
--- a/include/configs/ti_armv7_keystone2.h
+++ b/include/configs/ti_armv7_keystone2.h
@@ -185,9 +185,6 @@
 #define CONFIG_SYS_MAX_NAND_DEVICE		1
 #define CONFIG_SYS_NAND_MAX_CHIPS		1
 #define CONFIG_SYS_NAND_NO_SUBPAGE_WRITE
-#define CONFIG_ENV_SIZE				(256 << 10)  /* 256 KiB */
-#define CONFIG_ENV_IS_IN_NAND
-#define CONFIG_ENV_OFFSET			0x100000
 #define CONFIG_MTD_PARTITIONS
 #define CONFIG_RBTREE
 #define CONFIG_LZO
@@ -199,7 +196,6 @@
 /* USB Configuration */
 #define CONFIG_USB_XHCI_KEYSTONE
 #define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS	2
-#define CONFIG_FS_FAT
 #define CONFIG_USB_SS_BASE			KS2_USB_SS_BASE
 #define CONFIG_USB_HOST_XHCI_BASE		KS2_USB_HOST_XHCI_BASE
 #define CONFIG_DEV_USB_PHY_BASE			KS2_DEV_USB_PHY_BASE
@@ -211,7 +207,6 @@
 
 /* U-Boot general configuration */
 #define CONFIG_MISC_INIT_R
-#define CONFIG_CRC32_VERIFY
 #define CONFIG_MX_CYCLIC
 #define CONFIG_TIMESTAMP
 
diff --git a/include/configs/trats.h b/include/configs/trats.h
index 6806cd9..e08bbc4 100644
--- a/include/configs/trats.h
+++ b/include/configs/trats.h
@@ -188,7 +188,6 @@
 
 /* Download menu - definitions for check keys */
 #ifndef __ASSEMBLY__
-#include <power/max8997_pmic.h>
 
 #define KEY_PWR_PMIC_NAME		"MAX8997_PMIC"
 #define KEY_PWR_STATUS_REG		MAX8997_REG_STATUS1
diff --git a/include/configs/trats2.h b/include/configs/trats2.h
index 6a4604c..927d482 100644
--- a/include/configs/trats2.h
+++ b/include/configs/trats2.h
@@ -169,7 +169,6 @@
 
 /* Download menu - definitions for check keys */
 #ifndef __ASSEMBLY__
-#include <power/max77686_pmic.h>
 
 #define KEY_PWR_PMIC_NAME		"MAX77686_PMIC"
 #define KEY_PWR_STATUS_REG		MAX77686_REG_PMIC_STATUS1
diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h
index bc57e8a..e45b506 100644
--- a/include/configs/uniphier.h
+++ b/include/configs/uniphier.h
@@ -116,7 +116,6 @@
 
 /* USB */
 #define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS	4
-#define CONFIG_FAT_WRITE
 
 /* SD/MMC */
 #define CONFIG_SUPPORT_EMMC_BOOT
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index 1b43620..c56cd8c 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -82,10 +82,6 @@
 # define FAT_ENV_INTERFACE		"mmc"
 #endif
 
-#if defined(CONFIG_MMC_SDHCI_ZYNQ) || defined(CONFIG_ZYNQMP_USB)
-# define CONFIG_FAT_WRITE
-#endif
-
 #ifdef CONFIG_NAND_ARASAN
 # define CONFIG_CMD_NAND_LOCK_UNLOCK
 # define CONFIG_SYS_MAX_NAND_DEVICE	1
diff --git a/include/configs/xtfpga.h b/include/configs/xtfpga.h
index 7b15f31..7d7d9bb 100644
--- a/include/configs/xtfpga.h
+++ b/include/configs/xtfpga.h
@@ -138,7 +138,6 @@
 #define CONFIG_AUTO_COMPLETE			/* Support tab autocompletion */
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_SYS_LONGHELP
-#define CONFIG_CRC32_VERIFY
 #define CONFIG_MX_CYCLIC
 #define CONFIG_SHOW_BOOT_PROGRESS
 
diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h
index df4765c..4b6b088 100644
--- a/include/configs/zynq-common.h
+++ b/include/configs/zynq-common.h
@@ -129,7 +129,6 @@
 
 #if defined(CONFIG_MMC_SDHCI_ZYNQ) || defined(CONFIG_ZYNQ_USB)
 # define CONFIG_SUPPORT_VFAT
-# define CONFIG_FAT_WRITE
 #endif
 
 #if defined(CONFIG_ZYNQ_I2C0) || defined(CONFIG_ZYNQ_I2C1)
diff --git a/include/cros_ec.h b/include/cros_ec.h
index 0271f2b..771a176 100644
--- a/include/cros_ec.h
+++ b/include/cros_ec.h
@@ -11,9 +11,9 @@
 
 #include <linux/compiler.h>
 #include <ec_commands.h>
-#include <fdtdec.h>
 #include <cros_ec_message.h>
 #include <asm/gpio.h>
+#include <dm/of_extra.h>
 
 /* Our configuration information */
 struct cros_ec_dev {
@@ -377,12 +377,10 @@
 /**
  * Returns information from the FDT about the Chrome EC flash
  *
- * @param blob		FDT blob to use
- * @param node		Node offset to read from
+ * @param dev		Device to read from
  * @param config	Structure to use to return information
  */
-int cros_ec_decode_ec_flash(const void *blob, int node,
-			    struct fdt_cros_ec *config);
+int cros_ec_decode_ec_flash(struct udevice *dev, struct fdt_cros_ec *config);
 
 /**
  * Check the current keyboard state, in case recovery mode is requested.
diff --git a/include/dm.h b/include/dm.h
index a179c8a..f752792 100644
--- a/include/dm.h
+++ b/include/dm.h
@@ -7,7 +7,11 @@
 #ifndef _DM_H_
 #define _DM_H_
 
+#include <dm/ofnode.h>
 #include <dm/device.h>
+#include <dm/fdtaddr.h>
+#include <dm/ofnode.h>
+#include <dm/read.h>
 #include <dm/platdata.h>
 #include <dm/uclass.h>
 
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index 2cabc87..81ab893 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -11,6 +11,9 @@
 #ifndef _DM_DEVICE_INTERNAL_H
 #define _DM_DEVICE_INTERNAL_H
 
+#include <dm/ofnode.h>
+
+struct device_node;
 struct udevice;
 
 /**
@@ -52,16 +55,15 @@
  * @drv: Device's driver
  * @name: Name of device (e.g. device tree node name)
  * @driver_data: The driver_data field from the driver's match table.
- * @of_offset: Offset of device tree node for this device. This is -1 for
- * devices which don't use device tree.
+ * @node: Device tree node for this device. This is invalid for devices which
+ * don't use device tree.
  * @devp: if non-NULL, returns a pointer to the bound device
  * @return 0 if OK, -ve on error
  */
 int device_bind_with_driver_data(struct udevice *parent,
 				 const struct driver *drv, const char *name,
-				 ulong driver_data, int of_offset,
+				 ulong driver_data, ofnode node,
 				 struct udevice **devp);
-
 /**
  * device_bind_by_name: Create a device and bind it to a driver
  *
diff --git a/include/dm/device.h b/include/dm/device.h
index df02e41..4866f7c 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -11,6 +11,7 @@
 #ifndef _DM_DEVICE_H
 #define _DM_DEVICE_H
 
+#include <dm/ofnode.h>
 #include <dm/uclass-id.h>
 #include <fdtdec.h>
 #include <linker_lists.h>
@@ -103,7 +104,7 @@
  * @platdata: Configuration data for this device
  * @parent_platdata: The parent bus's configuration data for this device
  * @uclass_platdata: The uclass's configuration data for this device
- * @of_offset: Device tree node offset for this device (- for none)
+ * @node: Reference to device tree node for this device
  * @driver_data: Driver data word for the entry that matched this device with
  *		its driver
  * @parent: Parent of this device, or NULL for the top level device
@@ -129,7 +130,7 @@
 	void *platdata;
 	void *parent_platdata;
 	void *uclass_platdata;
-	int of_offset;
+	ofnode node;
 	ulong driver_data;
 	struct udevice *parent;
 	void *priv;
@@ -158,12 +159,17 @@
 
 static inline int dev_of_offset(const struct udevice *dev)
 {
-	return dev->of_offset;
+	return ofnode_to_offset(dev->node);
 }
 
 static inline void dev_set_of_offset(struct udevice *dev, int of_offset)
 {
-	dev->of_offset = of_offset;
+	dev->node = offset_to_ofnode(of_offset);
+}
+
+static inline bool dev_has_of_node(struct udevice *dev)
+{
+	return ofnode_valid(dev->node);
 }
 
 /**
@@ -499,77 +505,6 @@
 int device_find_next_child(struct udevice **devp);
 
 /**
- * dev_get_addr() - Get the reg property of a device
- *
- * @dev: Pointer to a device
- *
- * @return addr
- */
-fdt_addr_t dev_get_addr(struct udevice *dev);
-
-/**
- * dev_get_addr_ptr() - Return pointer to the address of the reg property
- *                      of a device
- *
- * @dev: Pointer to a device
- *
- * @return Pointer to addr, or NULL if there is no such property
- */
-void *dev_get_addr_ptr(struct udevice *dev);
-
-/**
- * dev_map_physmem() - Read device address from reg property of the
- *                     device node and map the address into CPU address
- *                     space.
- *
- * @dev: Pointer to device
- * @size: size of the memory to map
- *
- * @return  mapped address, or NULL if the device does not have reg
- *          property.
- */
-void *dev_map_physmem(struct udevice *dev, unsigned long size);
-
-/**
- * dev_get_addr_index() - Get the indexed reg property of a device
- *
- * @dev: Pointer to a device
- * @index: the 'reg' property can hold a list of <addr, size> pairs
- *	   and @index is used to select which one is required
- *
- * @return addr
- */
-fdt_addr_t dev_get_addr_index(struct udevice *dev, int index);
-
-/**
- * dev_get_addr_size_index() - Get the indexed reg property of a device
- *
- * Returns the address and size specified in the 'reg' property of a device.
- *
- * @dev: Pointer to a device
- * @index: the 'reg' property can hold a list of <addr, size> pairs
- *	   and @index is used to select which one is required
- * @size: Pointer to size varible - this function returns the size
- *        specified in the 'reg' property here
- *
- * @return addr
- */
-fdt_addr_t dev_get_addr_size_index(struct udevice *dev, int index,
-				   fdt_size_t *size);
-
-/**
- * dev_get_addr_name() - Get the reg property of a device, indexed by name
- *
- * @dev: Pointer to a device
- * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
- *	  'reg-names' property providing named-based identification. @index
- *	  indicates the value to search for in 'reg-names'.
- *
- * @return addr
- */
-fdt_addr_t dev_get_addr_name(struct udevice *dev, const char *name);
-
-/**
  * device_has_children() - check if a device has any children
  *
  * @dev:	Device to check
@@ -628,7 +563,7 @@
 void device_set_name_alloced(struct udevice *dev);
 
 /**
- * of_device_is_compatible() - check if the device is compatible with the compat
+ * device_is_compatible() - check if the device is compatible with the compat
  *
  * This allows to check whether the device is comaptible with the compat.
  *
@@ -637,7 +572,7 @@
  *		device
  * @return true if OK, false if the compatible is not found
  */
-bool of_device_is_compatible(struct udevice *dev, const char *compat);
+bool device_is_compatible(struct udevice *dev, const char *compat);
 
 /**
  * of_machine_is_compatible() - check if the machine is compatible with
@@ -944,25 +879,4 @@
 
 #endif /* ! CONFIG_DEVRES */
 
-/**
- * dm_set_translation_offset() - Set translation offset
- * @offs: Translation offset
- *
- * Some platforms need a special address translation. Those
- * platforms (e.g. mvebu in SPL) can configure a translation
- * offset in the DM by calling this function. It will be
- * added to all addresses returned in dev_get_addr().
- */
-void dm_set_translation_offset(fdt_addr_t offs);
-
-/**
- * dm_get_translation_offset() - Get translation offset
- *
- * This function returns the translation offset that can
- * be configured by calling dm_set_translation_offset().
- *
- * @return translation offset for the device address (0 as default).
- */
-fdt_addr_t dm_get_translation_offset(void);
-
 #endif
diff --git a/include/dm/fdtaddr.h b/include/dm/fdtaddr.h
new file mode 100644
index 0000000..c46f0e9
--- /dev/null
+++ b/include/dm/fdtaddr.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ * Marek Vasut <marex@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_FDTADDR_H
+#define _DM_FDTADDR_H
+
+#include <fdtdec.h>
+
+struct udevice;
+
+/**
+ * devfdt_get_addr() - Get the reg property of a device
+ *
+ * @dev: Pointer to a device
+ *
+ * @return addr
+ */
+fdt_addr_t devfdt_get_addr(struct udevice *dev);
+
+/**
+ * devfdt_get_addr_ptr() - Return pointer to the address of the reg property
+ *                      of a device
+ *
+ * @dev: Pointer to a device
+ *
+ * @return Pointer to addr, or NULL if there is no such property
+ */
+void *devfdt_get_addr_ptr(struct udevice *dev);
+
+/**
+ * devfdt_map_physmem() - Read device address from reg property of the
+ *                     device node and map the address into CPU address
+ *                     space.
+ *
+ * @dev: Pointer to device
+ * @size: size of the memory to map
+ *
+ * @return  mapped address, or NULL if the device does not have reg
+ *          property.
+ */
+void *devfdt_map_physmem(struct udevice *dev, unsigned long size);
+
+/**
+ * devfdt_get_addr_index() - Get the indexed reg property of a device
+ *
+ * @dev: Pointer to a device
+ * @index: the 'reg' property can hold a list of <addr, size> pairs
+ *	   and @index is used to select which one is required
+ *
+ * @return addr
+ */
+fdt_addr_t devfdt_get_addr_index(struct udevice *dev, int index);
+
+/**
+ * devfdt_get_addr_size_index() - Get the indexed reg property of a device
+ *
+ * Returns the address and size specified in the 'reg' property of a device.
+ *
+ * @dev: Pointer to a device
+ * @index: the 'reg' property can hold a list of <addr, size> pairs
+ *	   and @index is used to select which one is required
+ * @size: Pointer to size varible - this function returns the size
+ *        specified in the 'reg' property here
+ *
+ * @return addr
+ */
+fdt_addr_t devfdt_get_addr_size_index(struct udevice *dev, int index,
+				   fdt_size_t *size);
+
+/**
+ * devfdt_get_addr_name() - Get the reg property of a device, indexed by name
+ *
+ * @dev: Pointer to a device
+ * @name: the 'reg' property can hold a list of <addr, size> pairs, with the
+ *	  'reg-names' property providing named-based identification. @index
+ *	  indicates the value to search for in 'reg-names'.
+ *
+ * @return addr
+ */
+fdt_addr_t devfdt_get_addr_name(struct udevice *dev, const char *name);
+
+/**
+ * dm_set_translation_offset() - Set translation offset
+ * @offs: Translation offset
+ *
+ * Some platforms need a special address translation. Those
+ * platforms (e.g. mvebu in SPL) can configure a translation
+ * offset in the DM by calling this function. It will be
+ * added to all addresses returned in devfdt_get_addr().
+ */
+void dm_set_translation_offset(fdt_addr_t offs);
+
+/**
+ * dm_get_translation_offset() - Get translation offset
+ *
+ * This function returns the translation offset that can
+ * be configured by calling dm_set_translation_offset().
+ *
+ * @return translation offset for the device address (0 as default).
+ */
+fdt_addr_t dm_get_translation_offset(void);
+
+#endif
diff --git a/include/dm/lists.h b/include/dm/lists.h
index 4513d6a..d4d82d2 100644
--- a/include/dm/lists.h
+++ b/include/dm/lists.h
@@ -10,6 +10,7 @@
 #ifndef _DM_LISTS_H_
 #define _DM_LISTS_H_
 
+#include <dm/ofnode.h>
 #include <dm/uclass-id.h>
 
 /**
@@ -51,14 +52,12 @@
  * @parent as its parent.
  *
  * @parent: parent device (root)
- * @blob: device tree blob
- * @offset: offset of this device tree node
+ * @node: device tree node to bind
  * @devp: if non-NULL, returns a pointer to the bound device
  * @return 0 if device was bound, -EINVAL if the device tree is invalid,
  * other -ve value on error
  */
-int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
-		   struct udevice **devp);
+int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp);
 
 /**
  * device_bind_driver() - bind a device to a driver
@@ -86,7 +85,7 @@
  * @devp:	If non-NULL, returns the newly bound device
  */
 int device_bind_driver_to_node(struct udevice *parent, const char *drv_name,
-			       const char *dev_name, int node,
+			       const char *dev_name, ofnode node,
 			       struct udevice **devp);
 
 #endif
diff --git a/include/dm/of.h b/include/dm/of.h
new file mode 100644
index 0000000..d4d941e
--- /dev/null
+++ b/include/dm/of.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_OF_H
+#define _DM_OF_H
+
+#include <asm/u-boot.h>
+#include <asm/global_data.h>
+
+/* integer value within a device tree property which references another node */
+typedef u32 phandle;
+
+/**
+ * struct property: Device tree property
+ *
+ * @name: Property name
+ * @length: Length of property in bytes
+ * @value: Pointer to property value
+ * @next: Pointer to next property, or NULL if none
+ */
+struct property {
+	char *name;
+	int length;
+	void *value;
+	struct property *next;
+};
+
+/**
+ * struct device_node: Device tree node
+ *
+ * @name: Node name
+ * @type: Node type (value of device_type property) or "<NULL>" if none
+ * @phandle: Phandle value of this none, or 0 if none
+ * @full_name: Full path to node, e.g. "/bus@1/spi@1100"
+ * @properties: Pointer to head of list of properties, or NULL if none
+ * @parent: Pointer to parent node, or NULL if this is the root node
+ * @child: Pointer to head of child node list, or NULL if no children
+ * @sibling: Pointer to the next sibling node, or NULL if this is the last
+ */
+struct device_node {
+	const char *name;
+	const char *type;
+	phandle phandle;
+	const char *full_name;
+
+	struct property *properties;
+	struct device_node *parent;
+	struct device_node *child;
+	struct device_node *sibling;
+};
+
+#define OF_MAX_PHANDLE_ARGS 16
+
+/**
+ * struct of_phandle_args - structure to hold phandle and arguments
+ *
+ * This is used when decoding a phandle in a device tree property. Typically
+ * these look like this:
+ *
+ * wibble {
+ *    phandle = <5>;
+ * };
+ *
+ * ...
+ * some-prop = <&wibble 1 2 3>
+ *
+ * Here &node is the phandle of the node 'wibble', i.e. 5. There are three
+ * arguments: 1, 2, 3.
+ *
+ * So when decoding the phandle in some-prop, np will point to wibble,
+ * args_count will be 3 and the three arguments will be in args.
+ *
+ * @np: Node that the phandle refers to
+ * @args_count: Number of arguments
+ * @args: Argument values
+ */
+struct of_phandle_args {
+	struct device_node *np;
+	int args_count;
+	uint32_t args[OF_MAX_PHANDLE_ARGS];
+};
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * of_live_active() - check if livetree is active
+ *
+ * @returns true if livetree is active, false it not
+ */
+#ifdef CONFIG_OF_LIVE
+static inline bool of_live_active(void)
+{
+	return gd->of_root != NULL;
+}
+#else
+static inline bool of_live_active(void)
+{
+	return false;
+}
+#endif
+
+#define OF_BAD_ADDR	((u64)-1)
+
+static inline const char *of_node_full_name(const struct device_node *np)
+{
+	return np ? np->full_name : "<no-node>";
+}
+
+/* Default #address and #size cells */
+#if !defined(OF_ROOT_NODE_ADDR_CELLS_DEFAULT)
+#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 1
+#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1
+#endif
+
+/* Default string compare functions */
+#if !defined(of_compat_cmp)
+#define of_compat_cmp(s1, s2, l)	strcasecmp((s1), (s2))
+#define of_prop_cmp(s1, s2)		strcmp((s1), (s2))
+#define of_node_cmp(s1, s2)		strcasecmp((s1), (s2))
+#endif
+
+/* Helper to read a big number; size is in cells (not bytes) */
+static inline u64 of_read_number(const __be32 *cell, int size)
+{
+	u64 r = 0;
+	while (size--)
+		r = (r << 32) | be32_to_cpu(*(cell++));
+	return r;
+}
+
+/* Like of_read_number, but we want an unsigned long result */
+static inline unsigned long of_read_ulong(const __be32 *cell, int size)
+{
+	/* toss away upper bits if unsigned long is smaller than u64 */
+	return of_read_number(cell, size);
+}
+
+#endif
diff --git a/include/dm/of_access.h b/include/dm/of_access.h
new file mode 100644
index 0000000..142f0f4
--- /dev/null
+++ b/include/dm/of_access.h
@@ -0,0 +1,347 @@
+/*
+ * Originally from Linux v4.9
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
+ * Updates for SPARC64 by David S. Miller
+ * Derived from PowerPC and Sparc prom.h files by Stephen Rothwell, IBM Corp.
+ *
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * Modified for U-Boot
+ * Copyright (c) 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_OF_ACCESS_H
+#define _DM_OF_ACCESS_H
+
+#include <dm/of.h>
+
+/**
+ * of_find_all_nodes - Get next node in global list
+ * @prev:	Previous node or NULL to start iteration
+ *		of_node_put() will be called on it
+ *
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_find_all_nodes(struct device_node *prev);
+
+#define for_each_of_allnodes_from(from, dn) \
+	for (dn = of_find_all_nodes(from); dn; dn = of_find_all_nodes(dn))
+#define for_each_of_allnodes(dn) for_each_of_allnodes_from(NULL, dn)
+
+/* Dummy functions to mirror Linux. These are not used in U-Boot */
+#define of_node_get(x) (x)
+static inline void of_node_put(const struct device_node *np) { }
+
+/**
+ * of_n_addr_cells() - Get the number of address cells for a node
+ *
+ * This walks back up the tree to find the closest #address-cells property
+ * which controls the given node.
+ *
+ * @np: Node pointer to check
+ * @return number of address cells this node uses
+ */
+int of_n_addr_cells(const struct device_node *np);
+
+/**
+ * of_n_size_cells() - Get the number of size cells for a node
+ *
+ * This walks back up the tree to find the closest #size-cells property
+ * which controls the given node.
+ *
+ * @np: Node pointer to check
+ * @return number of size cells this node uses
+ */
+int of_n_size_cells(const struct device_node *np);
+
+/**
+ * of_find_property() - find a property in a node
+ *
+ * @np: Pointer to device node holding property
+ * @name: Name of property
+ * @lenp: If non-NULL, returns length of property
+ * @return pointer to property, or NULL if not found
+ */
+struct property *of_find_property(const struct device_node *np,
+				  const char *name, int *lenp);
+
+/**
+ * of_get_property() - get a property value
+ *
+ * Find a property with a given name for a given node and return the value.
+ *
+ * @np: Pointer to device node holding property
+ * @name: Name of property
+ * @lenp: If non-NULL, returns length of property
+ * @return pointer to property value, or NULL if not found
+ */
+const void *of_get_property(const struct device_node *np, const char *name,
+			    int *lenp);
+
+/**
+ * of_device_is_compatible() - Check if the node matches given constraints
+ * @device: pointer to node
+ * @compat: required compatible string, NULL or "" for any match
+ * @type: required device_type value, NULL or "" for any match
+ * @name: required node name, NULL or "" for any match
+ *
+ * Checks if the given @compat, @type and @name strings match the
+ * properties of the given @device. A constraints can be skipped by
+ * passing NULL or an empty string as the constraint.
+ *
+ * @return 0 for no match, and a positive integer on match. The return
+ * value is a relative score with larger values indicating better
+ * matches. The score is weighted for the most specific compatible value
+ * to get the highest score. Matching type is next, followed by matching
+ * name. Practically speaking, this results in the following priority
+ * order for matches:
+ *
+ * 1. specific compatible && type && name
+ * 2. specific compatible && type
+ * 3. specific compatible && name
+ * 4. specific compatible
+ * 5. general compatible && type && name
+ * 6. general compatible && type
+ * 7. general compatible && name
+ * 8. general compatible
+ * 9. type && name
+ * 10. type
+ * 11. name
+ */
+int of_device_is_compatible(const struct device_node *np, const char *compat,
+			    const char *type, const char *name);
+
+/**
+ * of_device_is_available() - check if a device is available for use
+ *
+ * @device: Node to check for availability
+ *
+ * @return true if the status property is absent or set to "okay", false
+ * otherwise
+ */
+bool of_device_is_available(const struct device_node *np);
+
+/**
+ * of_get_parent() - Get a node's parent, if any
+ *
+ * @node: Node to check
+ * @eturns a node pointer, or NULL if none
+ */
+struct device_node *of_get_parent(const struct device_node *np);
+
+/**
+ * of_find_node_opts_by_path() - Find a node matching a full OF path
+ *
+ * @path: Either the full path to match, or if the path does not start with
+ *	'/', the name of a property of the /aliases node (an alias). In the
+ *	case of an alias, the node matching the alias' value will be returned.
+ * @opts: Address of a pointer into which to store the start of an options
+ *	string appended to the end of the path with a ':' separator. Can be NULL
+ *
+ * Valid paths:
+ *	/foo/bar	Full path
+ *	foo		Valid alias
+ *	foo/bar		Valid alias + relative path
+ *
+ * @return a node pointer or NULL if not found
+ */
+struct device_node *of_find_node_opts_by_path(const char *path,
+					      const char **opts);
+
+static inline struct device_node *of_find_node_by_path(const char *path)
+{
+	return of_find_node_opts_by_path(path, NULL);
+}
+
+/**
+ * of_find_compatible_node() - find a node based on its compatible string
+ *
+ * Find a node based on type and one of the tokens in its "compatible" property
+ * @from: Node to start searching from or NULL. the node you pass will not be
+ *	searched, only the next one will; typically, you pass what the previous
+ *	call returned.
+ * @type: The type string to match "device_type" or NULL to ignore
+ * @compatible:	The string to match to one of the tokens in the device
+ *	"compatible" list.
+ * @return node pointer or NULL if not found
+ */
+struct device_node *of_find_compatible_node(struct device_node *from,
+				const char *type, const char *compatible);
+
+/**
+ * of_find_node_by_phandle() - Find a node given a phandle
+ *
+ * @handle:	phandle of the node to find
+ *
+ * @return node pointer, or NULL if not found
+ */
+struct device_node *of_find_node_by_phandle(phandle handle);
+
+/**
+ * of_read_u32() - Find and read a 32-bit integer from a property
+ *
+ * Search for a property in a device node and read a 32-bit value from
+ * it.
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @outp:	pointer to return value, modified only if return value is 0.
+ *
+ * @return 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ */
+int of_read_u32(const struct device_node *np, const char *propname, u32 *outp);
+
+/**
+ * of_read_u32_array() - Find and read an array of 32 bit integers
+ *
+ * Search for a property in a device node and read 32-bit value(s) from
+ * it.
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @out_values:	pointer to return value, modified only if return value is 0.
+ * @sz:		number of array elements to read
+ * @return 0 on success, -EINVAL if the property does not exist, -ENODATA
+ * if property does not have a value, and -EOVERFLOW is longer than sz.
+ */
+int of_read_u32_array(const struct device_node *np, const char *propname,
+		      u32 *out_values, size_t sz);
+
+/**
+ * of_property_match_string() - Find string in a list and return index
+ *
+ * This function searches a string list property and returns the index
+ * of a specific string value.
+ *
+ * @np: pointer to node containing string list property
+ * @propname: string list property name
+ * @string: pointer to string to search for in string list
+ * @return 0 on success, -EINVAL if the property does not exist, -ENODATA
+ * if property does not have a value, and -EOVERFLOW is longer than sz.
+ */
+int of_property_match_string(const struct device_node *np, const char *propname,
+			     const char *string);
+
+int of_property_read_string_helper(const struct device_node *np,
+				   const char *propname, const char **out_strs,
+				   size_t sz, int index);
+
+/**
+ * of_property_read_string_index() - Find and read a string from a multiple
+ * strings property.
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @index:	index of the string in the list of strings
+ * @out_string:	pointer to null terminated return string, modified only if
+ *		return value is 0.
+ *
+ * Search for a property in a device tree node and retrieve a null
+ * terminated string value (pointer to data, not a copy) in the list of strings
+ * contained in that property.
+ * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
+ * property does not have a value, and -EILSEQ if the string is not
+ * null-terminated within the length of the property data.
+ *
+ * The out_string pointer is modified only if a valid string can be decoded.
+ */
+static inline int of_property_read_string_index(const struct device_node *np,
+						const char *propname,
+						int index, const char **output)
+{
+	int rc = of_property_read_string_helper(np, propname, output, 1, index);
+	return rc < 0 ? rc : 0;
+}
+
+/**
+ * of_parse_phandle - Resolve a phandle property to a device_node pointer
+ * @np: Pointer to device node holding phandle property
+ * @phandle_name: Name of property holding a phandle value
+ * @index: For properties holding a table of phandles, this is the index into
+ *         the table
+ *
+ * Returns the device_node pointer with refcount incremented.  Use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_parse_phandle(const struct device_node *np,
+				     const char *phandle_name, int index);
+
+/**
+ * of_parse_phandle_with_args() - Find a node pointed by phandle in a list
+ *
+ * @np:		pointer to a device tree node containing a list
+ * @list_name:	property name that contains a list
+ * @cells_name:	property name that specifies phandles' arguments count
+ * @index:	index of a phandle to parse out
+ * @out_args:	optional pointer to output arguments structure (will be filled)
+ * @return 0 on success (with @out_args filled out if not NULL), -ENOENT if
+ *	@list_name does not exist, -EINVAL if a phandle was not found,
+ *	@cells_name could not be found, the arguments were truncated or there
+ *	were too many arguments.
+ *
+ * This function is useful to parse lists of phandles and their arguments.
+ * Returns 0 on success and fills out_args, on error returns appropriate
+ * errno value.
+ *
+ * Caller is responsible to call of_node_put() on the returned out_args->np
+ * pointer.
+ *
+ * Example:
+ *
+ * phandle1: node1 {
+ *	#list-cells = <2>;
+ * }
+ *
+ * phandle2: node2 {
+ *	#list-cells = <1>;
+ * }
+ *
+ * node3 {
+ *	list = <&phandle1 1 2 &phandle2 3>;
+ * }
+ *
+ * To get a device_node of the `node2' node you may call this:
+ * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
+ */
+int of_parse_phandle_with_args(const struct device_node *np,
+			       const char *list_name, const char *cells_name,
+			       int index, struct of_phandle_args *out_args);
+
+/**
+ * of_alias_scan() - Scan all properties of the 'aliases' node
+ *
+ * The function scans all the properties of the 'aliases' node and populates
+ * the lookup table with the properties.  It returns the number of alias
+ * properties found, or an error code in case of failure.
+ *
+ * @return 9 if OK, -ENOMEM if not enough memory
+ */
+int of_alias_scan(void);
+
+/**
+ * of_alias_get_id - Get alias id for the given device_node
+ *
+ * Travels the lookup table to get the alias id for the given device_node and
+ * alias stem.
+ *
+ * @np:		Pointer to the given device_node
+ * @stem:	Alias stem of the given device_node
+ * @return alias ID, if found, else -ENODEV
+ */
+int of_alias_get_id(const struct device_node *np, const char *stem);
+
+/**
+ * of_get_stdout() - Get node to use for stdout
+ *
+ * @return node referred to by stdout-path alias, or NULL if none
+ */
+struct device_node *of_get_stdout(void);
+
+#endif
diff --git a/include/dm/of_addr.h b/include/dm/of_addr.h
new file mode 100644
index 0000000..25ca05b
--- /dev/null
+++ b/include/dm/of_addr.h
@@ -0,0 +1,64 @@
+/*
+ * Taken from Linux v4.9 drivers/of/address.c
+ *
+ * Modified for U-Boot
+ * Copyright (c) 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_OF_ADDR_H
+#define _DM_OF_ADDR_H
+
+/**
+ * of_translate_address() - translate a device-tree address to a CPU address
+ *
+ * Translate an address from the device-tree into a CPU physical address,
+ * this walks up the tree and applies the various bus mappings on the  way.
+ *
+ * Note: We consider that crossing any level with #size-cells == 0 to mean
+ * that translation is impossible (that is we are not dealing with a value
+ * that can be mapped to a cpu physical address). This is not really specified
+ * that way, but this is traditionally the way IBM at least do things
+ *
+ * @np: node to check
+ * @in_addr: pointer to input address
+ * @return translated address or OF_BAD_ADDR on error
+ */
+u64 of_translate_address(const struct device_node *no, const __be32 *in_addr);
+
+/**
+ * of_get_address() - obtain an address from a node
+ *
+ * Extract an address from a node, returns the region size and the address
+ * space flags too. The PCI version uses a BAR number instead of an absolute
+ * index.
+ *
+ * @np: Node to check
+ * @index: Index of address to read (0 = first)
+ * @size: place to put size on success
+ * @flags: place to put flags on success
+ * @return pointer to address which can be read
+ */
+const __be32 *of_get_address(const struct device_node *no, int index,
+			     u64 *size, unsigned int *flags);
+
+struct resource;
+
+/**
+ * of_address_to_resource() - translate device tree address to resource
+ *
+ * Note that if your address is a PIO address, the conversion will fail if
+ * the physical address can't be internally converted to an IO token with
+ * pci_address_to_pio(), that is because it's either called to early or it
+ * can't be matched to any host bridge IO space
+ *
+ * @np: node to check
+ * @index: index of address to read (0 = first)
+ * @r: place to put resource information
+ * @return 0 if OK, -ve on error
+ */
+int of_address_to_resource(const struct device_node *no, int index,
+			   struct resource *r);
+
+#endif
diff --git a/include/dm/of_extra.h b/include/dm/of_extra.h
new file mode 100644
index 0000000..01b6ebe
--- /dev/null
+++ b/include/dm/of_extra.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_OF_EXTRA_H
+#define _DM_OF_EXTRA_H
+
+#include <dm/ofnode.h>
+
+enum fmap_compress_t {
+	FMAP_COMPRESS_NONE,
+	FMAP_COMPRESS_LZO,
+};
+
+enum fmap_hash_t {
+	FMAP_HASH_NONE,
+	FMAP_HASH_SHA1,
+	FMAP_HASH_SHA256,
+};
+
+/* A flash map entry, containing an offset and length */
+struct fmap_entry {
+	uint32_t offset;
+	uint32_t length;
+	uint32_t used;			/* Number of bytes used in region */
+	enum fmap_compress_t compress_algo;	/* Compression type */
+	enum fmap_hash_t hash_algo;		/* Hash algorithm */
+	const uint8_t *hash;			/* Hash value */
+	int hash_size;				/* Hash size */
+};
+
+/**
+ * Read a flash entry from the fdt
+ *
+ * @param node	Reference to node to read
+ * @param name		Name of node being read
+ * @param entry		Place to put offset and size of this node
+ * @return 0 if ok, -ve on error
+ */
+int of_read_fmap_entry(ofnode node, const char *name,
+		       struct fmap_entry *entry);
+
+#endif
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
new file mode 100644
index 0000000..149622a
--- /dev/null
+++ b/include/dm/ofnode.h
@@ -0,0 +1,578 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_OFNODE_H
+#define _DM_OFNODE_H
+
+/* TODO(sjg@chromium.org): Drop fdtdec.h include */
+#include <fdtdec.h>
+#include <dm/of.h>
+
+/* Enable checks to protect against invalid calls */
+#undef OF_CHECKS
+
+/**
+ * ofnode - reference to a device tree node
+ *
+ * This union can hold either a straightforward pointer to a struct device_node
+ * in the live device tree, or an offset within the flat device tree. In the
+ * latter case, the pointer value is just the integer offset within the flat DT.
+ *
+ * Thus we can reference nodes in both the live tree (once available) and the
+ * flat tree (until then). Functions are available to translate between an
+ * ofnode and either an offset or a struct device_node *.
+ *
+ * The reference can also hold a null offset, in which case the pointer value
+ * here is NULL. This corresponds to a struct device_node * value of
+ * NULL, or an offset of -1.
+ *
+ * There is no ambiguity as to whether ofnode holds an offset or a node
+ * pointer: when the live tree is active it holds a node pointer, otherwise it
+ * holds an offset. The value itself does not need to be unique and in theory
+ * the same value could point to a valid device node or a valid offset. We
+ * could arrange for a unique value to be used (e.g. by making the pointer
+ * point to an offset within the flat device tree in the case of an offset) but
+ * this increases code size slightly due to the subtraction. Since it offers no
+ * real benefit, the approach described here seems best.
+ *
+ * For now these points use constant types, since we don't allow writing
+ * the DT.
+ *
+ * @np: Pointer to device node, used for live tree
+ * @flat_ptr: Pointer into flat device tree, used for flat tree. Note that this
+ *	is not a really a pointer to a node: it is an offset value. See above.
+ */
+typedef union ofnode_union {
+	const struct device_node *np;	/* will be used for future live tree */
+	long of_offset;
+} ofnode;
+
+struct ofnode_phandle_args {
+	ofnode node;
+	int args_count;
+	uint32_t args[OF_MAX_PHANDLE_ARGS];
+};
+
+/**
+ * _ofnode_to_np() - convert an ofnode to a live DT node pointer
+ *
+ * This cannot be called if the reference contains an offset.
+ *
+ * @node: Reference containing struct device_node * (possibly invalid)
+ * @return pointer to device node (can be NULL)
+ */
+static inline const struct device_node *ofnode_to_np(ofnode node)
+{
+#ifdef OF_CHECKS
+	if (!of_live_active())
+		return NULL;
+#endif
+	return node.np;
+}
+
+/**
+ * ofnode_to_offset() - convert an ofnode to a flat DT offset
+ *
+ * This cannot be called if the reference contains a node pointer.
+ *
+ * @node: Reference containing offset (possibly invalid)
+ * @return DT offset (can be -1)
+ */
+static inline int ofnode_to_offset(ofnode node)
+{
+#ifdef OF_CHECKS
+	if (of_live_active())
+		return -1;
+#endif
+	return node.of_offset;
+}
+
+/**
+ * ofnode_valid() - check if an ofnode is valid
+ *
+ * @return true if the reference contains a valid ofnode, false if it is NULL
+ */
+static inline bool ofnode_valid(ofnode node)
+{
+	if (of_live_active())
+		return node.np != NULL;
+	else
+		return node.of_offset != -1;
+}
+
+/**
+ * offset_to_ofnode() - convert a DT offset to an ofnode
+ *
+ * @of_offset: DT offset (either valid, or -1)
+ * @return reference to the associated DT offset
+ */
+static inline ofnode offset_to_ofnode(int of_offset)
+{
+	ofnode node;
+
+	if (of_live_active())
+		node.np = NULL;
+	else
+		node.of_offset = of_offset;
+
+	return node;
+}
+
+/**
+ * np_to_ofnode() - convert a node pointer to an ofnode
+ *
+ * @np: Live node pointer (can be NULL)
+ * @return reference to the associated node pointer
+ */
+static inline ofnode np_to_ofnode(const struct device_node *np)
+{
+	ofnode node;
+
+	node.np = np;
+
+	return node;
+}
+
+/**
+ * ofnode_is_np() - check if a reference is a node pointer
+ *
+ * This function associated that if there is a valid live tree then all
+ * references will use it. This is because using the flat DT when the live tree
+ * is valid is not permitted.
+ *
+ * @node: reference to check (possibly invalid)
+ * @return true if the reference is a live node pointer, false if it is a DT
+ * offset
+ */
+static inline bool ofnode_is_np(ofnode node)
+{
+#ifdef OF_CHECKS
+	/*
+	 * Check our assumption that flat tree offsets are not used when a
+	 * live tree is in use.
+	 */
+	assert(!ofnode_valid(node) ||
+	       (of_live_active() ? _ofnode_to_np(node)
+				  : _ofnode_to_np(node)));
+#endif
+	return of_live_active() && ofnode_valid(node);
+}
+
+/**
+ * ofnode_equal() - check if two references are equal
+ *
+ * @return true if equal, else false
+ */
+static inline bool ofnode_equal(ofnode ref1, ofnode ref2)
+{
+	/* We only need to compare the contents */
+	return ref1.of_offset == ref2.of_offset;
+}
+
+/**
+ * ofnode_null() - Obtain a null ofnode
+ *
+ * This returns an ofnode which points to no node. It works both with the flat
+ * tree and livetree.
+ */
+static inline ofnode ofnode_null(void)
+{
+	ofnode node;
+
+	if (of_live_active())
+		node.np = NULL;
+	else
+		node.of_offset = -1;
+
+	return node;
+}
+
+/**
+ * ofnode_read_u32() - Read a 32-bit integer from a property
+ *
+ * @ref:	valid node reference to read property from
+ * @propname:	name of the property to read from
+ * @outp:	place to put value (if found)
+ * @return 0 if OK, -ve on error
+ */
+int ofnode_read_u32(ofnode node, const char *propname, u32 *outp);
+
+/**
+ * ofnode_read_s32() - Read a 32-bit integer from a property
+ *
+ * @ref:	valid node reference to read property from
+ * @propname:	name of the property to read from
+ * @outp:	place to put value (if found)
+ * @return 0 if OK, -ve on error
+ */
+static inline int ofnode_read_s32(ofnode node, const char *propname,
+				  s32 *out_value)
+{
+	return ofnode_read_u32(node, propname, (u32 *)out_value);
+}
+
+/**
+ * ofnode_read_u32_default() - Read a 32-bit integer from a property
+ *
+ * @ref:	valid node reference to read property from
+ * @propname:	name of the property to read from
+ * @def:	default value to return if the property has no value
+ * @return property value, or @def if not found
+ */
+int ofnode_read_u32_default(ofnode ref, const char *propname, u32 def);
+
+/**
+ * ofnode_read_s32_default() - Read a 32-bit integer from a property
+ *
+ * @ref:	valid node reference to read property from
+ * @propname:	name of the property to read from
+ * @def:	default value to return if the property has no value
+ * @return property value, or @def if not found
+ */
+int ofnode_read_s32_default(ofnode node, const char *propname, s32 def);
+
+/**
+ * ofnode_read_string() - Read a string from a property
+ *
+ * @ref:	valid node reference to read property from
+ * @propname:	name of the property to read
+ * @return string from property value, or NULL if there is no such property
+ */
+const char *ofnode_read_string(ofnode node, const char *propname);
+
+/**
+ * ofnode_read_u32_array() - Find and read an array of 32 bit integers
+ *
+ * @node:	valid node reference to read property from
+ * @propname:	name of the property to read
+ * @out_values:	pointer to return value, modified only if return value is 0
+ * @sz:		number of array elements to read
+ *
+ * Search for a property in a device node and read 32-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * The out_values is modified only if a valid u32 value can be decoded.
+ */
+int ofnode_read_u32_array(ofnode node, const char *propname,
+			  u32 *out_values, size_t sz);
+
+/**
+ * ofnode_read_bool() - read a boolean value from a property
+ *
+ * @node:	valid node reference to read property from
+ * @propname:	name of property to read
+ * @return true if property is present (meaning true), false if not present
+ */
+bool ofnode_read_bool(ofnode node, const char *propname);
+
+/**
+ * ofnode_find_subnode() - find a named subnode of a parent node
+ *
+ * @node:	valid reference to parent node
+ * @subnode_name: name of subnode to find
+ * @return reference to subnode (which can be invalid if there is no such
+ * subnode)
+ */
+ofnode ofnode_find_subnode(ofnode node, const char *subnode_name);
+
+/**
+ * ofnode_first_subnode() - find the first subnode of a parent node
+ *
+ * @node:	valid reference to a valid parent node
+ * @return reference to the first subnode (which can be invalid if the parent
+ * node has no subnodes)
+ */
+ofnode ofnode_first_subnode(ofnode node);
+
+/**
+ * ofnode_next_subnode() - find the next sibling of a subnode
+ *
+ * @node:	valid reference to previous node (sibling)
+ * @return reference to the next subnode (which can be invalid if the node
+ * has no more siblings)
+ */
+ofnode ofnode_next_subnode(ofnode node);
+
+/**
+ * ofnode_get_name() - get the name of a node
+ *
+ * @node: valid node to look up
+ * @return name or node
+ */
+const char *ofnode_get_name(ofnode node);
+
+/**
+ * ofnode_read_size() - read the size of a property
+ *
+ * @node: node to check
+ * @propname: property to check
+ * @return size of property if present, or -EINVAL if not
+ */
+int ofnode_read_size(ofnode node, const char *propname);
+
+/**
+ * ofnode_get_addr_index() - get an address from a node
+ *
+ * This reads the register address from a node
+ *
+ * @node: node to read from
+ * @index: Index of address to read (0 for first)
+ * @return address, or FDT_ADDR_T_NONE if not present or invalid
+ */
+phys_addr_t ofnode_get_addr_index(ofnode node, int index);
+
+/**
+ * ofnode_get_addr() - get an address from a node
+ *
+ * This reads the register address from a node
+ *
+ * @node: node to read from
+ * @return address, or FDT_ADDR_T_NONE if not present or invalid
+ */
+phys_addr_t ofnode_get_addr(ofnode node);
+
+/**
+ * ofnode_stringlist_search() - find a string in a string list and return index
+ *
+ * Note that it is possible for this function to succeed on property values
+ * that are not NUL-terminated. That's because the function will stop after
+ * finding the first occurrence of @string. This can for example happen with
+ * small-valued cell properties, such as #address-cells, when searching for
+ * the empty string.
+ *
+ * @node: node to check
+ * @propname: name of the property containing the string list
+ * @string: string to look up in the string list
+ *
+ * @return:
+ *   the index of the string in the list of strings
+ *   -ENODATA if the property is not found
+ *   -EINVAL on some other error
+ */
+int ofnode_stringlist_search(ofnode node, const char *propname,
+			     const char *string);
+
+/**
+ * fdt_stringlist_get() - obtain the string at a given index in a string list
+ *
+ * Note that this will successfully extract strings from properties with
+ * non-NUL-terminated values. For example on small-valued cell properties
+ * this function will return the empty string.
+ *
+ * If non-NULL, the length of the string (on success) or a negative error-code
+ * (on failure) will be stored in the integer pointer to by lenp.
+ *
+ * @node: node to check
+ * @propname: name of the property containing the string list
+ * @index: index of the string to return
+ * @lenp: return location for the string length or an error code on failure
+ *
+ * @return:
+ *   length of string, if found or -ve error value if not found
+ */
+int ofnode_read_string_index(ofnode node, const char *propname, int index,
+			     const char **outp);
+
+/**
+ * ofnode_parse_phandle_with_args() - Find a node pointed by phandle in a list
+ *
+ * This function is useful to parse lists of phandles and their arguments.
+ * Returns 0 on success and fills out_args, on error returns appropriate
+ * errno value.
+ *
+ * Caller is responsible to call of_node_put() on the returned out_args->np
+ * pointer.
+ *
+ * Example:
+ *
+ * phandle1: node1 {
+ *	#list-cells = <2>;
+ * }
+ *
+ * phandle2: node2 {
+ *	#list-cells = <1>;
+ * }
+ *
+ * node3 {
+ *	list = <&phandle1 1 2 &phandle2 3>;
+ * }
+ *
+ * To get a device_node of the `node2' node you may call this:
+ * ofnode_parse_phandle_with_args(node3, "list", "#list-cells", 0, 1, &args);
+ *
+ * @node:	device tree node containing a list
+ * @list_name:	property name that contains a list
+ * @cells_name:	property name that specifies phandles' arguments count
+ * @cells_count: Cell count to use if @cells_name is NULL
+ * @index:	index of a phandle to parse out
+ * @out_args:	optional pointer to output arguments structure (will be filled)
+ * @return 0 on success (with @out_args filled out if not NULL), -ENOENT if
+ *	@list_name does not exist, -EINVAL if a phandle was not found,
+ *	@cells_name could not be found, the arguments were truncated or there
+ *	were too many arguments.
+ */
+int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
+				   const char *cells_name, int cell_count,
+				   int index,
+				   struct ofnode_phandle_args *out_args);
+
+/**
+ * ofnode_path() - find a node by full path
+ *
+ * @path: Full path to node, e.g. "/bus/spi@1"
+ * @return reference to the node found. Use ofnode_valid() to check if it exists
+ */
+ofnode ofnode_path(const char *path);
+
+/**
+ * ofnode_get_chosen_prop() - get the value of a chosen property
+ *
+ * This looks for a property within the /chosen node and returns its value
+ *
+ * @propname: Property name to look for
+ */
+const char *ofnode_get_chosen_prop(const char *propname);
+
+/**
+ * ofnode_get_chosen_node() - get the chosen node
+ *
+ * @return the chosen node if present, else ofnode_null()
+ */
+ofnode ofnode_get_chosen_node(const char *name);
+
+struct display_timing;
+/**
+ * ofnode_decode_display_timing() - decode display timings
+ *
+ * Decode display timings from the supplied 'display-timings' node.
+ * See doc/device-tree-bindings/video/display-timing.txt for binding
+ * information.
+ *
+ * @node	'display-timing' node containing the timing subnodes
+ * @index	Index number to read (0=first timing subnode)
+ * @config	Place to put timings
+ * @return 0 if OK, -FDT_ERR_NOTFOUND if not found
+ */
+int ofnode_decode_display_timing(ofnode node, int index,
+				 struct display_timing *config);
+
+/**
+ * ofnode_read_prop()- - read a node property
+ *
+ * @node: node to read
+ * @propname: property to read
+ * @lenp: place to put length on success
+ * @return pointer to property, or NULL if not found
+ */
+const u32 *ofnode_read_prop(ofnode node, const char *propname, int *lenp);
+
+/**
+ * ofnode_is_available() - check if a node is marked available
+ *
+ * @node: node to check
+ * @return true if node's 'status' property is "okay" (or is missing)
+ */
+bool ofnode_is_available(ofnode node);
+
+/**
+ * ofnode_get_addr_size() - get address and size from a property
+ *
+ * This does no address translation. It simply reads an property that contains
+ * an address and a size value, one after the other.
+ *
+ * @node: node to read from
+ * @propname: property to read
+ * @sizep: place to put size value (on success)
+ * @return address value, or FDT_ADDR_T_NONE on error
+ */
+phys_addr_t ofnode_get_addr_size(ofnode node, const char *propname,
+				 phys_size_t *sizep);
+
+/**
+ * ofnode_read_u8_array_ptr() - find an 8-bit array
+ *
+ * Look up a property in a node and return a pointer to its contents as a
+ * byte array of given length. The property must have at least enough data
+ * for the array (count bytes). It may have more, but this will be ignored.
+ * The data is not copied.
+ *
+ * @node	node to examine
+ * @propname	name of property to find
+ * @sz		number of array elements
+ * @return pointer to byte array if found, or NULL if the property is not
+ *		found or there is not enough data
+ */
+const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
+					size_t sz);
+
+/**
+ * ofnode_read_pci_addr() - look up a PCI address
+ *
+ * Look at an address property in a node and return the PCI address which
+ * corresponds to the given type in the form of fdt_pci_addr.
+ * The property must hold one fdt_pci_addr with a lengh.
+ *
+ * @node	node to examine
+ * @type	pci address type (FDT_PCI_SPACE_xxx)
+ * @propname	name of property to find
+ * @addr	returns pci address in the form of fdt_pci_addr
+ * @return 0 if ok, -ENOENT if the property did not exist, -EINVAL if the
+ *		format of the property was invalid, -ENXIO if the requested
+ *		address type was not found
+ */
+int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
+			 const char *propname, struct fdt_pci_addr *addr);
+
+/**
+ * ofnode_read_addr_cells() - Get the number of address cells for a node
+ *
+ * This walks back up the tree to find the closest #address-cells property
+ * which controls the given node.
+ *
+ * @node: Node to check
+ * @return number of address cells this node uses
+ */
+int ofnode_read_addr_cells(ofnode node);
+
+/**
+ * ofnode_read_size_cells() - Get the number of size cells for a node
+ *
+ * This walks back up the tree to find the closest #size-cells property
+ * which controls the given node.
+ *
+ * @node: Node to check
+ * @return number of size cells this node uses
+ */
+int ofnode_read_size_cells(ofnode node);
+
+/**
+ * ofnode_pre_reloc() - check if a node should be bound before relocation
+ *
+ * Device tree nodes can be marked as needing-to-be-bound in the loader stages
+ * via special device tree properties.
+ *
+ * Before relocation this function can be used to check if nodes are required
+ * in either SPL or TPL stages.
+ *
+ * After relocation and jumping into the real U-Boot binary it is possible to
+ * determine if a node was bound in one of SPL/TPL stages.
+ *
+ * There are 3 settings currently in use
+ * -
+ * - u-boot,dm-pre-reloc: legacy and indicates any of TPL or SPL
+ *   Existing platforms only use it to indicate nodes needed in
+ *   SPL. Should probably be replaced by u-boot,dm-spl for
+ *   new platforms.
+ *
+ * @node: node to check
+ * @eturns true if node is needed in SPL/TL, false otherwise
+ */
+bool ofnode_pre_reloc(ofnode node);
+
+#endif
diff --git a/include/dm/read.h b/include/dm/read.h
new file mode 100644
index 0000000..8c9846e
--- /dev/null
+++ b/include/dm/read.h
@@ -0,0 +1,439 @@
+/*
+ * Function to read values from the device tree node attached to a udevice.
+ *
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DM_READ_H
+#define _DM_READ_H
+
+#include <dm/fdtaddr.h>
+#include <dm/ofnode.h>
+#include <dm/uclass.h>
+
+#if CONFIG_IS_ENABLED(OF_LIVE)
+static inline const struct device_node *dev_np(struct udevice *dev)
+{
+	return ofnode_to_np(dev->node);
+}
+#else
+static inline const struct device_node *dev_np(struct udevice *dev)
+{
+	return NULL;
+}
+#endif
+
+/**
+ * dev_ofnode() - get the DT node reference associated with a udevice
+ *
+ * @dev:	device to check
+ * @return reference of the the device's DT node
+ */
+static inline ofnode dev_ofnode(struct udevice *dev)
+{
+	return dev->node;
+}
+
+static inline bool dev_of_valid(struct udevice *dev)
+{
+	return ofnode_valid(dev_ofnode(dev));
+}
+
+#ifndef CONFIG_DM_DEV_READ_INLINE
+/**
+ * dev_read_u32_default() - read a 32-bit integer from a device's DT property
+ *
+ * @dev:	device to read DT property from
+ * @propname:	name of the property to read from
+ * @def:	default value to return if the property has no value
+ * @return property value, or @def if not found
+ */
+int dev_read_u32_default(struct udevice *dev, const char *propname, int def);
+
+/**
+ * dev_read_string() - Read a string from a device's DT property
+ *
+ * @dev:	device to read DT property from
+ * @propname:	name of the property to read
+ * @return string from property value, or NULL if there is no such property
+ */
+const char *dev_read_string(struct udevice *dev, const char *propname);
+
+/**
+ * dev_read_bool() - read a boolean value from a device's DT property
+ *
+ * @dev:	device to read DT property from
+ * @propname:	name of property to read
+ * @return true if property is present (meaning true), false if not present
+ */
+bool dev_read_bool(struct udevice *dev, const char *propname);
+
+/**
+ * dev_read_subnode() - find a named subnode of a device
+ *
+ * @dev:	device whose DT node contains the subnode
+ * @subnode_name: name of subnode to find
+ * @return reference to subnode (which can be invalid if there is no such
+ * subnode)
+ */
+ofnode dev_read_subnode(struct udevice *dev, const char *subbnode_name);
+
+/**
+ * dev_read_size() - read the size of a property
+ *
+ * @dev: device to check
+ * @propname: property to check
+ * @return size of property if present, or -EINVAL if not
+ */
+int dev_read_size(struct udevice *dev, const char *propname);
+
+/**
+ * dev_read_addr_index() - Get the indexed reg property of a device
+ *
+ * @dev: Device to read from
+ * @index: the 'reg' property can hold a list of <addr, size> pairs
+ *	   and @index is used to select which one is required
+ *
+ * @return address or FDT_ADDR_T_NONE if not found
+ */
+fdt_addr_t dev_read_addr_index(struct udevice *dev, int index);
+
+/**
+ * dev_read_addr() - Get the reg property of a device
+ *
+ * @dev: Device to read from
+ *
+ * @return address or FDT_ADDR_T_NONE if not found
+ */
+fdt_addr_t dev_read_addr(struct udevice *dev);
+
+/**
+ * dev_read_addr_size() - get address and size from a device property
+ *
+ * This does no address translation. It simply reads an property that contains
+ * an address and a size value, one after the other.
+ *
+ * @dev: Device to read from
+ * @propname: property to read
+ * @sizep: place to put size value (on success)
+ * @return address value, or FDT_ADDR_T_NONE on error
+ */
+fdt_addr_t dev_read_addr_size(struct udevice *dev, const char *propname,
+				fdt_size_t *sizep);
+
+/**
+ * dev_read_name() - get the name of a device's node
+ *
+ * @node: valid node to look up
+ * @return name of node
+ */
+const char *dev_read_name(struct udevice *dev);
+
+/**
+ * dev_read_stringlist_search() - find string in a string list and return index
+ *
+ * Note that it is possible for this function to succeed on property values
+ * that are not NUL-terminated. That's because the function will stop after
+ * finding the first occurrence of @string. This can for example happen with
+ * small-valued cell properties, such as #address-cells, when searching for
+ * the empty string.
+ *
+ * @dev: device to check
+ * @propname: name of the property containing the string list
+ * @string: string to look up in the string list
+ *
+ * @return:
+ *   the index of the string in the list of strings
+ *   -ENODATA if the property is not found
+ *   -EINVAL on some other error
+ */
+int dev_read_stringlist_search(struct udevice *dev, const char *property,
+			  const char *string);
+
+/**
+ * dev_read_phandle_with_args() - Find a node pointed by phandle in a list
+ *
+ * This function is useful to parse lists of phandles and their arguments.
+ * Returns 0 on success and fills out_args, on error returns appropriate
+ * errno value.
+ *
+ * Caller is responsible to call of_node_put() on the returned out_args->np
+ * pointer.
+ *
+ * Example:
+ *
+ * phandle1: node1 {
+ *	#list-cells = <2>;
+ * }
+ *
+ * phandle2: node2 {
+ *	#list-cells = <1>;
+ * }
+ *
+ * node3 {
+ *	list = <&phandle1 1 2 &phandle2 3>;
+ * }
+ *
+ * To get a device_node of the `node2' node you may call this:
+ * dev_read_phandle_with_args(dev, "list", "#list-cells", 0, 1, &args);
+ *
+ * @dev:	device whose node containing a list
+ * @list_name:	property name that contains a list
+ * @cells_name:	property name that specifies phandles' arguments count
+ * @cells_count: Cell count to use if @cells_name is NULL
+ * @index:	index of a phandle to parse out
+ * @out_args:	optional pointer to output arguments structure (will be filled)
+ * @return 0 on success (with @out_args filled out if not NULL), -ENOENT if
+ *	@list_name does not exist, -EINVAL if a phandle was not found,
+ *	@cells_name could not be found, the arguments were truncated or there
+ *	were too many arguments.
+ */
+int dev_read_phandle_with_args(struct udevice *dev, const char *list_name,
+				const char *cells_name, int cell_count,
+				int index,
+				struct ofnode_phandle_args *out_args);
+
+/**
+ * dev_read_addr_cells() - Get the number of address cells for a device's node
+ *
+ * This walks back up the tree to find the closest #address-cells property
+ * which controls the given node.
+ *
+ * @dev: devioe to check
+ * @return number of address cells this node uses
+ */
+int dev_read_addr_cells(struct udevice *dev);
+
+/**
+ * dev_read_size_cells() - Get the number of size cells for a device's node
+ *
+ * This walks back up the tree to find the closest #size-cells property
+ * which controls the given node.
+ *
+ * @dev: devioe to check
+ * @return number of size cells this node uses
+ */
+int dev_read_size_cells(struct udevice *dev);
+
+/**
+ * dev_read_phandle() - Get the phandle from a device
+ *
+ * @dev: device to check
+ * @return phandle (1 or greater), or 0 if no phandle or other error
+ */
+int dev_read_phandle(struct udevice *dev);
+
+/**
+ * dev_read_prop()- - read a property from a device's node
+ *
+ * @dev: device to check
+ * @propname: property to read
+ * @lenp: place to put length on success
+ * @return pointer to property, or NULL if not found
+ */
+const u32 *dev_read_prop(struct udevice *dev, const char *propname, int *lenp);
+
+/**
+ * dev_read_alias_seq() - Get the alias sequence number of a node
+ *
+ * This works out whether a node is pointed to by an alias, and if so, the
+ * sequence number of that alias. Aliases are of the form <base><num> where
+ * <num> is the sequence number. For example spi2 would be sequence number 2.
+ *
+ * @dev: device to look up
+ * @devnump: set to the sequence number if one is found
+ * @return 0 if a sequence was found, -ve if not
+ */
+int dev_read_alias_seq(struct udevice *dev, int *devnump);
+
+/**
+ * dev_read_u32_array() - Find and read an array of 32 bit integers
+ *
+ * Search for a property in a device node and read 32-bit value(s) from
+ * it.
+ *
+ * The out_values is modified only if a valid u32 value can be decoded.
+ *
+ * @dev: device to look up
+ * @propname:	name of the property to read
+ * @out_values:	pointer to return value, modified only if return value is 0
+ * @sz:		number of array elements to read
+ * @return 0 on success, -EINVAL if the property does not exist, -ENODATA if
+ * property does not have a value, and -EOVERFLOW if the property data isn't
+ * large enough.
+ */
+int dev_read_u32_array(struct udevice *dev, const char *propname,
+		       u32 *out_values, size_t sz);
+
+/**
+ * dev_read_first_subnode() - find the first subnode of a device's node
+ *
+ * @dev: device to look up
+ * @return reference to the first subnode (which can be invalid if the device's
+ * node has no subnodes)
+ */
+ofnode dev_read_first_subnode(struct udevice *dev);
+
+/**
+ * ofnode_next_subnode() - find the next sibling of a subnode
+ *
+ * @node:	valid reference to previous node (sibling)
+ * @return reference to the next subnode (which can be invalid if the node
+ * has no more siblings)
+ */
+ofnode dev_read_next_subnode(ofnode node);
+
+/**
+ * dev_read_u8_array_ptr() - find an 8-bit array
+ *
+ * Look up a device's node property and return a pointer to its contents as a
+ * byte array of given length. The property must have at least enough data
+ * for the array (count bytes). It may have more, but this will be ignored.
+ * The data is not copied.
+ *
+ * @dev: device to look up
+ * @propname: name of property to find
+ * @sz: number of array elements
+ * @return pointer to byte array if found, or NULL if the property is not
+ *		found or there is not enough data
+ */
+const uint8_t *dev_read_u8_array_ptr(struct udevice *dev, const char *propname,
+				     size_t sz);
+
+#else /* CONFIG_DM_DEV_READ_INLINE is enabled */
+
+static inline int dev_read_u32_default(struct udevice *dev,
+				       const char *propname, int def)
+{
+	return ofnode_read_u32_default(dev_ofnode(dev), propname, def);
+}
+
+static inline const char *dev_read_string(struct udevice *dev,
+					  const char *propname)
+{
+	return ofnode_read_string(dev_ofnode(dev), propname);
+}
+
+static inline bool dev_read_bool(struct udevice *dev, const char *propname)
+{
+	return ofnode_read_bool(dev_ofnode(dev), propname);
+}
+
+static inline ofnode dev_read_subnode(struct udevice *dev,
+				      const char *subbnode_name)
+{
+	return ofnode_find_subnode(dev_ofnode(dev), subbnode_name);
+}
+
+static inline int dev_read_size(struct udevice *dev, const char *propname)
+{
+	return ofnode_read_size(dev_ofnode(dev), propname);
+}
+
+static inline fdt_addr_t dev_read_addr_index(struct udevice *dev, int index)
+{
+	return devfdt_get_addr_index(dev, index);
+}
+
+static inline fdt_addr_t dev_read_addr(struct udevice *dev)
+{
+	return devfdt_get_addr(dev);
+}
+
+static inline fdt_addr_t dev_read_addr_size(struct udevice *dev,
+					    const char *propname,
+					    fdt_size_t *sizep)
+{
+	return ofnode_get_addr_size(dev_ofnode(dev), propname, sizep);
+}
+
+static inline const char *dev_read_name(struct udevice *dev)
+{
+	return ofnode_get_name(dev_ofnode(dev));
+}
+
+static inline int dev_read_stringlist_search(struct udevice *dev,
+					     const char *propname,
+					     const char *string)
+{
+	return ofnode_stringlist_search(dev_ofnode(dev), propname, string);
+}
+
+static inline int dev_read_phandle_with_args(struct udevice *dev,
+		const char *list_name, const char *cells_name, int cell_count,
+		int index, struct ofnode_phandle_args *out_args)
+{
+	return ofnode_parse_phandle_with_args(dev_ofnode(dev), list_name,
+					      cells_name, cell_count, index,
+					      out_args);
+}
+
+static inline int dev_read_addr_cells(struct udevice *dev)
+{
+	return fdt_address_cells(gd->fdt_blob, dev_of_offset(dev));
+}
+
+static inline int dev_read_size_cells(struct udevice *dev)
+{
+	return fdt_size_cells(gd->fdt_blob, dev_of_offset(dev));
+}
+
+static inline int dev_read_phandle(struct udevice *dev)
+{
+	return fdt_get_phandle(gd->fdt_blob, dev_of_offset(dev));
+}
+
+static inline const u32 *dev_read_prop(struct udevice *dev,
+				       const char *propname, int *lenp)
+{
+	return ofnode_read_prop(dev_ofnode(dev), propname, lenp);
+}
+
+static inline int dev_read_alias_seq(struct udevice *dev, int *devnump)
+{
+	return fdtdec_get_alias_seq(gd->fdt_blob, dev->uclass->uc_drv->name,
+				    dev_of_offset(dev), devnump);
+}
+
+static inline int dev_read_u32_array(struct udevice *dev, const char *propname,
+				     u32 *out_values, size_t sz)
+{
+	return ofnode_read_u32_array(dev_ofnode(dev), propname, out_values, sz);
+}
+
+static inline ofnode dev_read_first_subnode(struct udevice *dev)
+{
+	return ofnode_first_subnode(dev_ofnode(dev));
+}
+
+static inline ofnode dev_read_next_subnode(ofnode node)
+{
+	return ofnode_next_subnode(node);
+}
+
+static inline const uint8_t *dev_read_u8_array_ptr(struct udevice *dev,
+					const char *propname, size_t sz)
+{
+	return ofnode_read_u8_array_ptr(dev_ofnode(dev), propname, sz);
+}
+
+#endif /* CONFIG_DM_DEV_READ_INLINE */
+
+/**
+ * dev_for_each_subnode() - Helper function to iterate through subnodes
+ *
+ * This creates a for() loop which works through the subnodes in a device's
+ * device-tree node.
+ *
+ * @subnode: ofnode holding the current subnode
+ * @dev: device to use for interation (struct udevice *)
+ */
+#define dev_for_each_subnode(subnode, dev) \
+	for (subnode = dev_read_first_subnode(dev); \
+	     ofnode_valid(subnode); \
+	     subnode = ofnode_next_subnode(subnode))
+
+#endif
diff --git a/include/dm/root.h b/include/dm/root.h
index 058eb98..50a6011 100644
--- a/include/dm/root.h
+++ b/include/dm/root.h
@@ -56,22 +56,6 @@
 int dm_scan_fdt(const void *blob, bool pre_reloc_only);
 
 /**
- * dm_scan_fdt_node() - Scan the device tree and bind drivers for a node
- *
- * This scans the subnodes of a device tree node and and creates a driver
- * for each one.
- *
- * @parent: Parent device for the devices that will be created
- * @blob: Pointer to device tree blob
- * @offset: Offset of node to scan
- * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC
- * flag. If false bind all drivers.
- * @return 0 if OK, -ve on error
- */
-int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
-		     bool pre_reloc_only);
-
-/**
  * dm_scan_other() - Scan for other devices
  *
  * Some devices may not be visible to Driver Model. This weak function can
@@ -103,9 +87,10 @@
  * This function will initialize roots of driver tree and class tree.
  * This needs to be called before anything uses the DM
  *
+ * @of_live:	Enable live device tree
  * @return 0 if OK, -ve on error
  */
-int dm_init(void);
+int dm_init(bool of_live);
 
 /**
  * dm_uninit - Uninitialise Driver Model structures
diff --git a/include/dm/test.h b/include/dm/test.h
index cba5049..cecee26 100644
--- a/include/dm/test.h
+++ b/include/dm/test.h
@@ -150,6 +150,8 @@
 	DM_TESTF_SCAN_PDATA	= 1 << 0,	/* test needs platform data */
 	DM_TESTF_PROBE_TEST	= 1 << 1,	/* probe test uclass */
 	DM_TESTF_SCAN_FDT	= 1 << 2,	/* scan device tree */
+	DM_TESTF_FLAT_TREE	= 1 << 3,	/* test needs flat DT */
+	DM_TESTF_LIVE_TREE	= 1 << 4,	/* needs live device tree */
 };
 
 /* Declare a new driver model test */
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index ad284b8..c086004 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -10,6 +10,8 @@
 #ifndef _DM_UCLASS_INTERNAL_H
 #define _DM_UCLASS_INTERNAL_H
 
+#include <dm/ofnode.h>
+
 /**
  * uclass_get_device_tail() - handle the end of a get_device call
  *
@@ -115,6 +117,22 @@
 				    struct udevice **devp);
 
 /**
+ * uclass_find_device_by_of_node() - Find a uclass device by device tree node
+ *
+ * This searches the devices in the uclass for one attached to the given
+ * device tree node.
+ *
+ * The device is NOT probed, it is merely returned.
+ *
+ * @id: ID to look up
+ * @node: Device tree offset to search for (if NULL then -ENODEV is returned)
+ * @devp: Returns pointer to device (there is only one for each node)
+ * @return 0 if OK, -ve on error
+ */
+int uclass_find_device_by_ofnode(enum uclass_id id, ofnode node,
+				 struct udevice **devp);
+
+/**
  * uclass_bind_device() - Associate device with a uclass
  *
  * Connect the device into uclass's list of devices.
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index b583aa8..7f5a130 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -10,6 +10,7 @@
 #ifndef _DM_UCLASS_H
 #define _DM_UCLASS_H
 
+#include <dm/ofnode.h>
 #include <dm/uclass-id.h>
 #include <linker_lists.h>
 #include <linux/list.h>
@@ -186,6 +187,22 @@
 				   struct udevice **devp);
 
 /**
+ * uclass_get_device_by_ofnode() - Get a uclass device by device tree node
+ *
+ * This searches the devices in the uclass for one attached to the given
+ * device tree node.
+ *
+ * The device is probed to activate it ready for use.
+ *
+ * @id: ID to look up
+ * @np: Device tree node to search for (if NULL then -ENODEV is returned)
+ * @devp: Returns pointer to device (there is only one for each node)
+ * @return 0 if OK, -ve on error
+ */
+int uclass_get_device_by_ofnode(enum uclass_id id, ofnode node,
+				struct udevice **devp);
+
+/**
  * uclass_get_device_by_phandle() - Get a uclass device by phandle
  *
  * This searches the devices in the uclass for one with the given phandle.
diff --git a/include/dt-bindings/clock/bcm3380-clock.h b/include/dt-bindings/clock/bcm3380-clock.h
new file mode 100644
index 0000000..00add2f
--- /dev/null
+++ b/include/dt-bindings/clock/bcm3380-clock.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from Broadcom GPL Source Code:
+ *	Copyright (C) Broadcom Corporation
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_BCM3380_H
+#define __DT_BINDINGS_CLOCK_BCM3380_H
+
+#define BCM3380_CLK0_DDR	0
+#define BCM3380_CLK0_FPM	1
+#define BCM3380_CLK0_CRYPTO	2
+#define BCM3380_CLK0_EPHY	3
+#define BCM3380_CLK0_PCIE	16
+#define BCM3380_CLK0_SPI	17
+#define BCM3380_CLK0_ENET0	18
+#define BCM3380_CLK0_ENET1	19
+#define BCM3380_CLK0_PCM	27
+
+#endif /* __DT_BINDINGS_CLOCK_BCM3380_H */
diff --git a/include/dt-bindings/clock/bcm6338-clock.h b/include/dt-bindings/clock/bcm6338-clock.h
new file mode 100644
index 0000000..3439c10
--- /dev/null
+++ b/include/dt-bindings/clock/bcm6338-clock.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_BCM6338_H
+#define __DT_BINDINGS_CLOCK_BCM6338_H
+
+#define BCM6338_CLK_ADSL	0
+#define BCM6338_CLK_MPI		1
+#define BCM6338_CLK_SDRAM	2
+#define BCM6338_CLK_ENET	4
+#define BCM6338_CLK_SAR		5
+#define BCM6338_CLK_SPI		9
+
+#endif /* __DT_BINDINGS_CLOCK_BCM6338_H */
diff --git a/include/dt-bindings/clock/bcm6348-clock.h b/include/dt-bindings/clock/bcm6348-clock.h
new file mode 100644
index 0000000..5af066b
--- /dev/null
+++ b/include/dt-bindings/clock/bcm6348-clock.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_BCM6348_H
+#define __DT_BINDINGS_CLOCK_BCM6348_H
+
+#define BCM6348_CLK_ADSL	0
+#define BCM6348_CLK_MPI		1
+#define BCM6348_CLK_SDRAM	2
+#define BCM6348_CLK_M2M		3
+#define BCM6348_CLK_ENET	4
+#define BCM6348_CLK_SAR		5
+#define BCM6348_CLK_USBS	6
+#define BCM6348_CLK_USBH	8
+#define BCM6348_CLK_SPI		9
+
+#endif /* __DT_BINDINGS_CLOCK_BCM6348_H */
diff --git a/include/dt-bindings/clock/sun50i-a64-ccu.h b/include/dt-bindings/clock/sun50i-a64-ccu.h
new file mode 100644
index 0000000..370c0a0
--- /dev/null
+++ b/include/dt-bindings/clock/sun50i-a64-ccu.h
@@ -0,0 +1,134 @@
+/*
+ * 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_SUN50I_A64_H_
+#define _DT_BINDINGS_CLK_SUN50I_A64_H_
+
+#define CLK_BUS_MIPI_DSI	28
+#define CLK_BUS_CE		29
+#define CLK_BUS_DMA		30
+#define CLK_BUS_MMC0		31
+#define CLK_BUS_MMC1		32
+#define CLK_BUS_MMC2		33
+#define CLK_BUS_NAND		34
+#define CLK_BUS_DRAM		35
+#define CLK_BUS_EMAC		36
+#define CLK_BUS_TS		37
+#define CLK_BUS_HSTIMER		38
+#define CLK_BUS_SPI0		39
+#define CLK_BUS_SPI1		40
+#define CLK_BUS_OTG		41
+#define CLK_BUS_EHCI0		42
+#define CLK_BUS_EHCI1		43
+#define CLK_BUS_OHCI0		44
+#define CLK_BUS_OHCI1		45
+#define CLK_BUS_VE		46
+#define CLK_BUS_TCON0		47
+#define CLK_BUS_TCON1		48
+#define CLK_BUS_DEINTERLACE	49
+#define CLK_BUS_CSI		50
+#define CLK_BUS_HDMI		51
+#define CLK_BUS_DE		52
+#define CLK_BUS_GPU		53
+#define CLK_BUS_MSGBOX		54
+#define CLK_BUS_SPINLOCK	55
+#define CLK_BUS_CODEC		56
+#define CLK_BUS_SPDIF		57
+#define CLK_BUS_PIO		58
+#define CLK_BUS_THS		59
+#define CLK_BUS_I2S0		60
+#define CLK_BUS_I2S1		61
+#define CLK_BUS_I2S2		62
+#define CLK_BUS_I2C0		63
+#define CLK_BUS_I2C1		64
+#define CLK_BUS_I2C2		65
+#define CLK_BUS_SCR		66
+#define CLK_BUS_UART0		67
+#define CLK_BUS_UART1		68
+#define CLK_BUS_UART2		69
+#define CLK_BUS_UART3		70
+#define CLK_BUS_UART4		71
+#define CLK_BUS_DBG		72
+#define CLK_THS			73
+#define CLK_NAND		74
+#define CLK_MMC0		75
+#define CLK_MMC1		76
+#define CLK_MMC2		77
+#define CLK_TS			78
+#define CLK_CE			79
+#define CLK_SPI0		80
+#define CLK_SPI1		81
+#define CLK_I2S0		82
+#define CLK_I2S1		83
+#define CLK_I2S2		84
+#define CLK_SPDIF		85
+#define CLK_USB_PHY0		86
+#define CLK_USB_PHY1		87
+#define CLK_USB_HSIC		88
+#define CLK_USB_HSIC_12M	89
+
+#define CLK_USB_OHCI0		91
+
+#define CLK_USB_OHCI1		93
+
+#define CLK_DRAM_VE		95
+#define CLK_DRAM_CSI		96
+#define CLK_DRAM_DEINTERLACE	97
+#define CLK_DRAM_TS		98
+#define CLK_DE			99
+#define CLK_TCON0		100
+#define CLK_TCON1		101
+#define CLK_DEINTERLACE		102
+#define CLK_CSI_MISC		103
+#define CLK_CSI_SCLK		104
+#define CLK_CSI_MCLK		105
+#define CLK_VE			106
+#define CLK_AC_DIG		107
+#define CLK_AC_DIG_4X		108
+#define CLK_AVS			109
+#define CLK_HDMI		110
+#define CLK_HDMI_DDC		111
+
+#define CLK_DSI_DPHY		113
+#define CLK_GPU			114
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_H_ */
diff --git a/include/dt-bindings/reset/bcm3380-reset.h b/include/dt-bindings/reset/bcm3380-reset.h
new file mode 100644
index 0000000..ddc575d
--- /dev/null
+++ b/include/dt-bindings/reset/bcm3380-reset.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from Broadcom GPL Source Code:
+ *	Copyright (C) Broadcom Corporation
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_RESET_BCM3380_H
+#define __DT_BINDINGS_RESET_BCM3380_H
+
+#define BCM3380_RST0_SPI	0
+#define BCM3380_RST0_PCM	13
+
+#endif /* __DT_BINDINGS_RESET_BCM3380_H */
diff --git a/include/dt-bindings/reset/bcm6338-reset.h b/include/dt-bindings/reset/bcm6338-reset.h
new file mode 100644
index 0000000..17a5e12
--- /dev/null
+++ b/include/dt-bindings/reset/bcm6338-reset.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_RESET_BCM6338_H
+#define __DT_BINDINGS_RESET_BCM6338_H
+
+#define BCM6338_RST_SPI		0
+#define BCM6338_RST_ENET	2
+#define BCM6338_RST_USBH	3
+#define BCM6338_RST_USBS	4
+#define BCM6338_RST_ADSL	5
+#define BCM6338_RST_DMAMEM	6
+#define BCM6338_RST_SAR		7
+#define BCM6338_RST_ACLC	8
+#define BCM6338_RST_ADSL_MIPS	10
+
+#endif /* __DT_BINDINGS_RESET_BCM6338_H */
diff --git a/include/dt-bindings/reset/bcm6348-reset.h b/include/dt-bindings/reset/bcm6348-reset.h
new file mode 100644
index 0000000..173937b
--- /dev/null
+++ b/include/dt-bindings/reset/bcm6348-reset.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_RESET_BCM6348_H
+#define __DT_BINDINGS_RESET_BCM6348_H
+
+#define BCM6348_RST_SPI		0
+#define BCM6348_RST_ENET	2
+#define BCM6348_RST_USBH	3
+#define BCM6348_RST_USBS	4
+#define BCM6348_RST_ADSL	5
+#define BCM6348_RST_DMAMEM	6
+#define BCM6348_RST_SAR		7
+#define BCM6348_RST_ACLC	8
+#define BCM6348_RST_ADSL_MIPS	10
+
+#endif /* __DT_BINDINGS_RESET_BCM6348_H */
diff --git a/include/dt-bindings/reset/sun50i-a64-ccu.h b/include/dt-bindings/reset/sun50i-a64-ccu.h
new file mode 100644
index 0000000..db60b29
--- /dev/null
+++ b/include/dt-bindings/reset/sun50i-a64-ccu.h
@@ -0,0 +1,98 @@
+/*
+ * 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_SUN50I_A64_H_
+#define _DT_BINDINGS_RST_SUN50I_A64_H_
+
+#define RST_USB_PHY0		0
+#define RST_USB_PHY1		1
+#define RST_USB_HSIC		2
+#define RST_DRAM		3
+#define RST_MBUS		4
+#define RST_BUS_MIPI_DSI	5
+#define RST_BUS_CE		6
+#define RST_BUS_DMA		7
+#define RST_BUS_MMC0		8
+#define RST_BUS_MMC1		9
+#define RST_BUS_MMC2		10
+#define RST_BUS_NAND		11
+#define RST_BUS_DRAM		12
+#define RST_BUS_EMAC		13
+#define RST_BUS_TS		14
+#define RST_BUS_HSTIMER		15
+#define RST_BUS_SPI0		16
+#define RST_BUS_SPI1		17
+#define RST_BUS_OTG		18
+#define RST_BUS_EHCI0		19
+#define RST_BUS_EHCI1		20
+#define RST_BUS_OHCI0		21
+#define RST_BUS_OHCI1		22
+#define RST_BUS_VE		23
+#define RST_BUS_TCON0		24
+#define RST_BUS_TCON1		25
+#define RST_BUS_DEINTERLACE	26
+#define RST_BUS_CSI		27
+#define RST_BUS_HDMI0		28
+#define RST_BUS_HDMI1		29
+#define RST_BUS_DE		30
+#define RST_BUS_GPU		31
+#define RST_BUS_MSGBOX		32
+#define RST_BUS_SPINLOCK	33
+#define RST_BUS_DBG		34
+#define RST_BUS_LVDS		35
+#define RST_BUS_CODEC		36
+#define RST_BUS_SPDIF		37
+#define RST_BUS_THS		38
+#define RST_BUS_I2S0		39
+#define RST_BUS_I2S1		40
+#define RST_BUS_I2S2		41
+#define RST_BUS_I2C0		42
+#define RST_BUS_I2C1		43
+#define RST_BUS_I2C2		44
+#define RST_BUS_SCR		45
+#define RST_BUS_UART0		46
+#define RST_BUS_UART1		47
+#define RST_BUS_UART2		48
+#define RST_BUS_UART3		49
+#define RST_BUS_UART4		50
+
+#endif /* _DT_BINDINGS_RST_SUN50I_A64_H_ */
diff --git a/include/fat.h b/include/fat.h
index e38f380..71879f0 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -18,9 +18,6 @@
 #define VFAT_MAXSEQ		9   /* Up to 9 of 13 2-byte UTF-16 entries */
 #define PREFETCH_BLOCKS		2
 
-#ifndef CONFIG_FS_FAT_MAX_CLUSTSIZE
-#define CONFIG_FS_FAT_MAX_CLUSTSIZE 65536
-#endif
 #define MAX_CLUSTSIZE	CONFIG_FS_FAT_MAX_CLUSTSIZE
 
 #define DIRENTSPERBLOCK	(mydata->sect_size / sizeof(dir_entry))
diff --git a/include/fdt_support.h b/include/fdt_support.h
index 955c121..5ef78cc 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -207,7 +207,7 @@
 
 int fdt_verify_alias_address(void *fdt, int anode, const char *alias,
 			      u64 addr);
-u64 fdt_get_base_address(void *fdt, int node);
+u64 fdt_get_base_address(const void *fdt, int node);
 int fdt_read_range(void *fdt, int node, int n, uint64_t *child_addr,
 		   uint64_t *addr, uint64_t *len);
 
@@ -248,7 +248,7 @@
 }
 
 /* Helper to read a big number; size is in cells (not bytes) */
-static inline u64 of_read_number(const fdt32_t *cell, int size)
+static inline u64 fdt_read_number(const fdt32_t *cell, int size)
 {
 	u64 r = 0;
 	while (size--)
@@ -256,7 +256,7 @@
 	return r;
 }
 
-void of_bus_default_count_cells(const void *blob, int parentoffset,
+void fdt_support_default_count_cells(const void *blob, int parentoffset,
 					int *addrc, int *sizec);
 int ft_verify_fdt(void *fdt);
 int arch_fixup_memory_node(void *blob);
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 3000ecb..eda2ffa 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -815,40 +815,6 @@
 int fdtdec_decode_region(const void *blob, int node, const char *prop_name,
 			 fdt_addr_t *basep, fdt_size_t *sizep);
 
-enum fmap_compress_t {
-	FMAP_COMPRESS_NONE,
-	FMAP_COMPRESS_LZO,
-};
-
-enum fmap_hash_t {
-	FMAP_HASH_NONE,
-	FMAP_HASH_SHA1,
-	FMAP_HASH_SHA256,
-};
-
-/* A flash map entry, containing an offset and length */
-struct fmap_entry {
-	uint32_t offset;
-	uint32_t length;
-	uint32_t used;			/* Number of bytes used in region */
-	enum fmap_compress_t compress_algo;	/* Compression type */
-	enum fmap_hash_t hash_algo;		/* Hash algorithm */
-	const uint8_t *hash;			/* Hash value */
-	int hash_size;				/* Hash size */
-};
-
-/**
- * Read a flash entry from the fdt
- *
- * @param blob		FDT blob
- * @param node		Offset of node to read
- * @param name		Name of node being read
- * @param entry		Place to put offset and size of this node
- * @return 0 if ok, -ve on error
- */
-int fdtdec_read_fmap_entry(const void *blob, int node, const char *name,
-			   struct fmap_entry *entry);
-
 /**
  * Obtain an indexed resource from a device property.
  *
diff --git a/include/generic-phy.h b/include/generic-phy.h
index d8cf0c9..762704c 100644
--- a/include/generic-phy.h
+++ b/include/generic-phy.h
@@ -50,8 +50,7 @@
 	 * @args:	The phy specifier values from device tree.
 	 * @return 0 if OK, or a negative error code.
 	 */
-	int	(*of_xlate)(struct phy *phy,
-			struct fdtdec_phandle_args *args);
+	int	(*of_xlate)(struct phy *phy, struct ofnode_phandle_args *args);
 
 	/**
 	 * init - initialize the hardware.
diff --git a/include/hash.h b/include/hash.h
index d814337..4f9a8cf 100644
--- a/include/hash.h
+++ b/include/hash.h
@@ -17,10 +17,6 @@
 	HASH_FLAG_ENV		= 1 << 1,	/* Allow env vars */
 };
 
-#if defined(CONFIG_SHA1SUM_VERIFY) || defined(CONFIG_CRC32_VERIFY)
-#define CONFIG_HASH_VERIFY
-#endif
-
 struct hash_algo {
 	const char *name;			/* Name of algorithm */
 	int digest_size;			/* Length of digest */
diff --git a/include/i2c.h b/include/i2c.h
index 2c1643d..7726028 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -525,8 +525,7 @@
  * @node:	Node offset to read from
  * @spi:	Place to put the decoded information
  */
-int i2c_chip_ofdata_to_platdata(const void *blob, int node,
-				struct dm_i2c_chip *chip);
+int i2c_chip_ofdata_to_platdata(struct udevice *dev, struct dm_i2c_chip *chip);
 
 /**
  * i2c_dump_msgs() - Dump a list of I2C messages
diff --git a/include/key_matrix.h b/include/key_matrix.h
index 8db6860..8dfa44d 100644
--- a/include/key_matrix.h
+++ b/include/key_matrix.h
@@ -69,8 +69,7 @@
  * @param node          Node containing compatible data
  * @return 0 if ok, -1 on error
  */
-int key_matrix_decode_fdt(struct key_matrix *config, const void *blob,
-			  int node);
+int key_matrix_decode_fdt(struct udevice *dev, struct key_matrix *config);
 
 /**
  * Set up a new key matrix.
diff --git a/include/linux/compat.h b/include/linux/compat.h
index a43e4d6..03f9bef 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -106,8 +106,12 @@
 #define BUG_ON(condition) do { if (condition) BUG(); } while(0)
 #endif /* BUG */
 
-#define WARN_ON(x) if (x) {printf("WARNING in %s line %d\n" \
-				  , __FILE__, __LINE__); }
+#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
 
diff --git a/include/linux/string.h b/include/linux/string.h
index 091ccab..3606620 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -50,6 +50,19 @@
 #ifndef __HAVE_ARCH_STRCHR
 extern char * strchr(const char *,int);
 #endif
+
+/**
+ * strchrnul() - return position of a character in the string, or end of string
+ *
+ * The strchrnul() function is like strchr() except that if c is not found
+ * in s, then it returns a pointer to the nul byte at the end of s, rather than
+ * NULL
+ * @s: string to search
+ * @c: character to search for
+ * @return position of @c in @s, or end of @s if not found
+ */
+const char *strchrnul(const char *s, int c);
+
 #ifndef __HAVE_ARCH_STRRCHR
 extern char * strrchr(const char *,int);
 #endif
@@ -63,6 +76,21 @@
 #ifndef __HAVE_ARCH_STRNLEN
 extern __kernel_size_t strnlen(const char *,__kernel_size_t);
 #endif
+
+#ifndef __HAVE_ARCH_STRCSPN
+/**
+ * strcspn() - find span of string without given characters
+ *
+ * Calculates the length of the initial segment of @s which consists entirely
+ * of bsytes not in reject.
+ *
+ * @s: string to search
+ * @reject: strings which cause the search to halt
+ * @return number of characters at the start of @s which are not in @reject
+ */
+size_t strcspn(const char *s, const char *reject);
+#endif
+
 #ifndef __HAVE_ARCH_STRDUP
 extern char * strdup(const char *);
 #endif
diff --git a/include/mailbox-uclass.h b/include/mailbox-uclass.h
index 6ec62e5..8a638b0 100644
--- a/include/mailbox-uclass.h
+++ b/include/mailbox-uclass.h
@@ -36,7 +36,7 @@
 	 * @return 0 if OK, or a negative error code.
 	 */
 	int (*of_xlate)(struct mbox_chan *chan,
-			struct fdtdec_phandle_args *args);
+			struct ofnode_phandle_args *args);
 	/**
 	 * request - Request a translated channel.
 	 *
diff --git a/include/mmc.h b/include/mmc.h
index 8346b0e..6a0ea0a 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -430,7 +430,7 @@
 	u8 part_support;
 	u8 part_attr;
 	u8 wr_rel_set;
-	char part_config;
+	u8 part_config;
 	uint tran_speed;
 	uint read_bl_len;
 	uint write_bl_len;
diff --git a/include/of_live.h b/include/of_live.h
new file mode 100644
index 0000000..f5303bb
--- /dev/null
+++ b/include/of_live.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Support for a 'live' (as opposed to flat) device tree
+ */
+
+#ifndef _OF_LIVE_H
+#define _OF_LIVE_H
+
+struct device_node;
+
+/**
+ * of_live_build() - build a live (hierarchical) tree from a flat DT
+ *
+ * @fdt_blob: Input tree to convert
+ * @rootp: Returns live tree that was created
+ * @return 0 if OK, -ve on error
+ */
+int of_live_build(const void *fdt_blob, struct device_node **rootp);
+
+#endif
diff --git a/include/power-domain-uclass.h b/include/power-domain-uclass.h
index 5878021..802233d 100644
--- a/include/power-domain-uclass.h
+++ b/include/power-domain-uclass.h
@@ -40,7 +40,7 @@
 	 * @return 0 if OK, or a negative error code.
 	 */
 	int (*of_xlate)(struct power_domain *power_domain,
-			struct fdtdec_phandle_args *args);
+			struct ofnode_phandle_args *args);
 	/**
 	 * request - Request a translated power domain.
 	 *
diff --git a/include/power/pmic.h b/include/power/pmic.h
index e0b2e12..4b34316 100644
--- a/include/power/pmic.h
+++ b/include/power/pmic.h
@@ -226,7 +226,7 @@
  *     buck2 { ... };
  * };
  */
-int pmic_bind_children(struct udevice *pmic, int offset,
+int pmic_bind_children(struct udevice *pmic, ofnode parent,
 		       const struct pmic_child_info *child_info);
 
 /**
diff --git a/include/power/tps65218.h b/include/power/tps65218.h
index 4d68faa..e3538e2 100644
--- a/include/power/tps65218.h
+++ b/include/power/tps65218.h
@@ -56,6 +56,8 @@
 
 #define TPS65218_MASK_ALL_BITS			0xFF
 
+#define TPS65218_DCDC_VSEL_MASK			0x3F
+
 #define TPS65218_DCDC_VOLT_SEL_0950MV		0x0a
 #define TPS65218_DCDC_VOLT_SEL_1100MV		0x19
 #define TPS65218_DCDC_VOLT_SEL_1200MV		0x23
diff --git a/include/reset-uclass.h b/include/reset-uclass.h
index 38c716ff..50fbeb1 100644
--- a/include/reset-uclass.h
+++ b/include/reset-uclass.h
@@ -11,7 +11,7 @@
 
 #include <reset.h>
 
-struct fdtdec_phandle_args;
+struct ofnode_phandle_args;
 struct udevice;
 
 /**
@@ -38,7 +38,7 @@
 	 * @return 0 if OK, or a negative error code.
 	 */
 	int (*of_xlate)(struct reset_ctl *reset_ctl,
-			struct fdtdec_phandle_args *args);
+			struct ofnode_phandle_args *args);
 	/**
 	 * request - Request a translated reset control.
 	 *
diff --git a/include/spi.h b/include/spi.h
index deb65ef..8c4b882 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -562,7 +562,7 @@
  * @node:	Node offset to read from
  * @plat:	Place to put the decoded information
  */
-int spi_slave_ofdata_to_platdata(const void *blob, int node,
+int spi_slave_ofdata_to_platdata(struct udevice *dev,
 				 struct dm_spi_slave_platdata *plat);
 
 /**
diff --git a/include/test/test.h b/include/test/test.h
index b7e1ae2..646dbfd 100644
--- a/include/test/test.h
+++ b/include/test/test.h
@@ -15,11 +15,13 @@
  * @fail_count: Number of tests that failed
  * @start: Store the starting mallinfo when doing leak test
  * @priv: A pointer to some other info some suites want to track
+ * @of_root: Record of the livetree root node (used for setting up tests)
  */
 struct unit_test_state {
 	int fail_count;
 	struct mallinfo start;
 	void *priv;
+	struct device_node *of_root;
 };
 
 /**
@@ -30,6 +32,7 @@
  * @flags: Flags indicated pre-conditions for test
  */
 struct unit_test {
+	const char *file;
 	const char *name;
 	int (*func)(struct unit_test_state *state);
 	int flags;
@@ -38,6 +41,7 @@
 /* Declare a new unit test */
 #define UNIT_TEST(_name, _flags, _suite)				\
 	ll_entry_declare(struct unit_test, _name, _suite) = {		\
+		.file = __FILE__,					\
 		.name = #_name,						\
 		.flags = _flags,					\
 		.func = _name,						\
diff --git a/include/test/ut.h b/include/test/ut.h
index 85434d7..d176df5 100644
--- a/include/test/ut.h
+++ b/include/test/ut.h
@@ -104,7 +104,7 @@
 }
 
 /* Assert that a pointer is not an error pointer */
-#define ut_assertok_ptr(expr) {					\
+#define ut_assertok_ptr(expr) {						\
 	const void *val = (expr);					\
 									\
 	if (IS_ERR(val)) {						\
diff --git a/lib/Makefile b/lib/Makefile
index 328b4a2..eacc7d6 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -15,6 +15,7 @@
 obj-$(CONFIG_BZIP2) += bzip2/
 obj-$(CONFIG_TIZEN) += tizen/
 obj-$(CONFIG_FIT) += libfdt/
+obj-$(CONFIG_OF_LIVE) += of_live.o
 obj-$(CONFIG_CMD_DHRYSTONE) += dhry/
 
 obj-$(CONFIG_AES) += aes.o
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index c072e54..5a5645a 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -12,6 +12,7 @@
 #include <fdt_support.h>
 #include <fdtdec.h>
 #include <asm/sections.h>
+#include <dm/of_extra.h>
 #include <linux/ctype.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -940,38 +941,6 @@
 	return 0;
 }
 
-/**
- * Read a flash entry from the fdt
- *
- * @param blob		FDT blob
- * @param node		Offset of node to read
- * @param name		Name of node being read
- * @param entry		Place to put offset and size of this node
- * @return 0 if ok, -ve on error
- */
-int fdtdec_read_fmap_entry(const void *blob, int node, const char *name,
-			   struct fmap_entry *entry)
-{
-	const char *prop;
-	u32 reg[2];
-
-	if (fdtdec_get_int_array(blob, node, "reg", reg, 2)) {
-		debug("Node '%s' has bad/missing 'reg' property\n", name);
-		return -FDT_ERR_NOTFOUND;
-	}
-	entry->offset = reg[0];
-	entry->length = reg[1];
-	entry->used = fdtdec_get_int(blob, node, "used", entry->length);
-	prop = fdt_getprop(blob, node, "compress", NULL);
-	entry->compress_algo = prop && !strcmp(prop, "lzo") ?
-		FMAP_COMPRESS_LZO : FMAP_COMPRESS_NONE;
-	prop = fdt_getprop(blob, node, "hash", &entry->hash_size);
-	entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE;
-	entry->hash = (uint8_t *)prop;
-
-	return 0;
-}
-
 u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells)
 {
 	u64 number = 0;
diff --git a/lib/of_live.c b/lib/of_live.c
new file mode 100644
index 0000000..51927f9
--- /dev/null
+++ b/lib/of_live.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
+ * benh@kernel.crashing.org
+ *
+ * Based on parts of drivers/of/fdt.c from Linux v4.9
+ * Modifications for U-Boot
+ * Copyright (c) 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <of_live.h>
+#include <malloc.h>
+#include <dm/of_access.h>
+#include <linux/err.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void *unflatten_dt_alloc(void **mem, unsigned long size,
+				unsigned long align)
+{
+	void *res;
+
+	*mem = PTR_ALIGN(*mem, align);
+	res = *mem;
+	*mem += size;
+
+	return res;
+}
+
+/**
+ * unflatten_dt_node() - Alloc and populate a device_node from the flat tree
+ * @blob: The parent device tree blob
+ * @mem: Memory chunk to use for allocating device nodes and properties
+ * @poffset: pointer to node in flat tree
+ * @dad: Parent struct device_node
+ * @nodepp: The device_node tree created by the call
+ * @fpsize: Size of the node path up at t05he current depth.
+ * @dryrun: If true, do not allocate device nodes but still calculate needed
+ * memory size
+ */
+static void *unflatten_dt_node(const void *blob, void *mem, int *poffset,
+			       struct device_node *dad,
+			       struct device_node **nodepp,
+			       unsigned long fpsize, bool dryrun)
+{
+	const __be32 *p;
+	struct device_node *np;
+	struct property *pp, **prev_pp = NULL;
+	const char *pathp;
+	int l;
+	unsigned int allocl;
+	static int depth;
+	int old_depth;
+	int offset;
+	int has_name = 0;
+	int new_format = 0;
+
+	pathp = fdt_get_name(blob, *poffset, &l);
+	if (!pathp)
+		return mem;
+
+	allocl = ++l;
+
+	/*
+	 * version 0x10 has a more compact unit name here instead of the full
+	 * path. we accumulate the full path size using "fpsize", we'll rebuild
+	 * it later. We detect this because the first character of the name is
+	 * not '/'.
+	 */
+	if ((*pathp) != '/') {
+		new_format = 1;
+		if (fpsize == 0) {
+			/*
+			 * root node: special case. fpsize accounts for path
+			 * plus terminating zero. root node only has '/', so
+			 * fpsize should be 2, but we want to avoid the first
+			 * level nodes to have two '/' so we use fpsize 1 here
+			 */
+			fpsize = 1;
+			allocl = 2;
+			l = 1;
+			pathp = "";
+		} else {
+			/*
+			 * account for '/' and path size minus terminal 0
+			 * already in 'l'
+			 */
+			fpsize += l;
+			allocl = fpsize;
+		}
+	}
+
+	np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
+				__alignof__(struct device_node));
+	if (!dryrun) {
+		char *fn;
+
+		fn = (char *)np + sizeof(*np);
+		np->full_name = fn;
+		if (new_format) {
+			/* rebuild full path for new format */
+			if (dad && dad->parent) {
+				strcpy(fn, dad->full_name);
+#ifdef DEBUG
+				if ((strlen(fn) + l + 1) != allocl) {
+					debug("%s: p: %d, l: %d, a: %d\n",
+					      pathp, (int)strlen(fn), l,
+					      allocl);
+				}
+#endif
+				fn += strlen(fn);
+			}
+			*(fn++) = '/';
+		}
+		memcpy(fn, pathp, l);
+
+		prev_pp = &np->properties;
+		if (dad != NULL) {
+			np->parent = dad;
+			np->sibling = dad->child;
+			dad->child = np;
+		}
+	}
+	/* process properties */
+	for (offset = fdt_first_property_offset(blob, *poffset);
+	     (offset >= 0);
+	     (offset = fdt_next_property_offset(blob, offset))) {
+		const char *pname;
+		int sz;
+
+		p = fdt_getprop_by_offset(blob, offset, &pname, &sz);
+		if (!p) {
+			offset = -FDT_ERR_INTERNAL;
+			break;
+		}
+
+		if (pname == NULL) {
+			debug("Can't find property name in list !\n");
+			break;
+		}
+		if (strcmp(pname, "name") == 0)
+			has_name = 1;
+		pp = unflatten_dt_alloc(&mem, sizeof(struct property),
+					__alignof__(struct property));
+		if (!dryrun) {
+			/*
+			 * We accept flattened tree phandles either in
+			 * ePAPR-style "phandle" properties, or the
+			 * legacy "linux,phandle" properties.  If both
+			 * appear and have different values, things
+			 * will get weird.  Don't do that. */
+			if ((strcmp(pname, "phandle") == 0) ||
+			    (strcmp(pname, "linux,phandle") == 0)) {
+				if (np->phandle == 0)
+					np->phandle = be32_to_cpup(p);
+			}
+			/*
+			 * And we process the "ibm,phandle" property
+			 * used in pSeries dynamic device tree
+			 * stuff */
+			if (strcmp(pname, "ibm,phandle") == 0)
+				np->phandle = be32_to_cpup(p);
+			pp->name = (char *)pname;
+			pp->length = sz;
+			pp->value = (__be32 *)p;
+			*prev_pp = pp;
+			prev_pp = &pp->next;
+		}
+	}
+	/*
+	 * with version 0x10 we may not have the name property, recreate
+	 * it here from the unit name if absent
+	 */
+	if (!has_name) {
+		const char *p1 = pathp, *ps = pathp, *pa = NULL;
+		int sz;
+
+		while (*p1) {
+			if ((*p1) == '@')
+				pa = p1;
+			if ((*p1) == '/')
+				ps = p1 + 1;
+			p1++;
+		}
+		if (pa < ps)
+			pa = p1;
+		sz = (pa - ps) + 1;
+		pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
+					__alignof__(struct property));
+		if (!dryrun) {
+			pp->name = "name";
+			pp->length = sz;
+			pp->value = pp + 1;
+			*prev_pp = pp;
+			prev_pp = &pp->next;
+			memcpy(pp->value, ps, sz - 1);
+			((char *)pp->value)[sz - 1] = 0;
+			debug("fixed up name for %s -> %s\n", pathp,
+			      (char *)pp->value);
+		}
+	}
+	if (!dryrun) {
+		*prev_pp = NULL;
+		np->name = of_get_property(np, "name", NULL);
+		np->type = of_get_property(np, "device_type", NULL);
+
+		if (!np->name)
+			np->name = "<NULL>";
+		if (!np->type)
+			np->type = "<NULL>";	}
+
+	old_depth = depth;
+	*poffset = fdt_next_node(blob, *poffset, &depth);
+	if (depth < 0)
+		depth = 0;
+	while (*poffset > 0 && depth > old_depth)
+		mem = unflatten_dt_node(blob, mem, poffset, np, NULL,
+					fpsize, dryrun);
+
+	if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND) {
+		debug("unflatten: error %d processing FDT\n", *poffset);
+		return NULL;
+	}
+
+	/*
+	 * Reverse the child list. Some drivers assumes node order matches .dts
+	 * node order
+	 */
+	if (!dryrun && np->child) {
+		struct device_node *child = np->child;
+		np->child = NULL;
+		while (child) {
+			struct device_node *next = child->sibling;
+
+			child->sibling = np->child;
+			np->child = child;
+			child = next;
+		}
+	}
+
+	if (nodepp)
+		*nodepp = np;
+
+	return mem;
+}
+
+/**
+ * unflatten_device_tree() - create tree of device_nodes from flat blob
+ *
+ * unflattens a device-tree, creating the
+ * tree of struct device_node. It also fills the "name" and "type"
+ * pointers of the nodes so the normal device-tree walking functions
+ * can be used.
+ * @blob: The blob to expand
+ * @mynodes: The device_node tree created by the call
+ * @return 0 if OK, -ve on error
+ */
+static int unflatten_device_tree(const void *blob,
+				 struct device_node **mynodes)
+{
+	unsigned long size;
+	int start;
+	void *mem;
+
+	debug(" -> unflatten_device_tree()\n");
+
+	if (!blob) {
+		debug("No device tree pointer\n");
+		return -EINVAL;
+	}
+
+	debug("Unflattening device tree:\n");
+	debug("magic: %08x\n", fdt_magic(blob));
+	debug("size: %08x\n", fdt_totalsize(blob));
+	debug("version: %08x\n", fdt_version(blob));
+
+	if (fdt_check_header(blob)) {
+		debug("Invalid device tree blob header\n");
+		return -EINVAL;
+	}
+
+	/* First pass, scan for size */
+	start = 0;
+	size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL,
+						0, true);
+	size = ALIGN(size, 4);
+
+	debug("  size is %lx, allocating...\n", size);
+
+	/* Allocate memory for the expanded device tree */
+	mem = malloc(size + 4);
+	memset(mem, '\0', size);
+
+	*(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef);
+
+	debug("  unflattening %p...\n", mem);
+
+	/* Second pass, do actual unflattening */
+	start = 0;
+	unflatten_dt_node(blob, mem, &start, NULL, mynodes, 0, false);
+	if (be32_to_cpup(mem + size) != 0xdeadbeef) {
+		debug("End of tree marker overwritten: %08x\n",
+		      be32_to_cpup(mem + size));
+		return -ENOSPC;
+	}
+
+	debug(" <- unflatten_device_tree()\n");
+
+	return 0;
+}
+
+int of_live_build(const void *fdt_blob, struct device_node **rootp)
+{
+	int ret;
+
+	debug("%s: start\n", __func__);
+	ret = unflatten_device_tree(fdt_blob, rootp);
+	if (ret) {
+		debug("Failed to create live tree: err=%d\n", ret);
+		return ret;
+	}
+	ret = of_alias_scan();
+	if (ret) {
+		debug("Failed to scan live tree aliases: err=%d\n", ret);
+		return ret;
+	}
+	debug("%s: stop\n", __func__);
+
+	return ret;
+}
diff --git a/lib/string.c b/lib/string.c
index e94021c..c4ca944 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -230,6 +230,14 @@
 }
 #endif
 
+const char *strchrnul(const char *s, int c)
+{
+	for (; *s != (char)c; ++s)
+		if (*s == '\0')
+			break;
+	return s;
+}
+
 #ifndef __HAVE_ARCH_STRRCHR
 /**
  * strrchr - Find the last occurrence of a character in a string
@@ -278,6 +286,30 @@
 }
 #endif
 
+#ifndef __HAVE_ARCH_STRCSPN
+/**
+ * strcspn - Calculate the length of the initial substring of @s which does
+ * not contain letters in @reject
+ * @s: The string to be searched
+ * @reject: The string to avoid
+ */
+size_t strcspn(const char *s, const char *reject)
+{
+	const char *p;
+	const char *r;
+	size_t count = 0;
+
+	for (p = s; *p != '\0'; ++p) {
+		for (r = reject; *r != '\0'; ++r) {
+			if (*p == *r)
+				return count;
+		}
+		++count;
+	}
+	return count;
+}
+#endif
+
 #ifndef __HAVE_ARCH_STRDUP
 char * strdup(const char *s)
 {
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index e8f49eb..e953168 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -507,7 +507,6 @@
 CONFIG_CQSPI_DECODER
 CONFIG_CQSPI_REF_CLK
 CONFIG_CRC32
-CONFIG_CRC32_VERIFY
 CONFIG_CS8900
 CONFIG_CS8900_BASE
 CONFIG_CS8900_BUS16
@@ -855,7 +854,6 @@
 CONFIG_FASTBOOT_FLASH_NAND_DEV
 CONFIG_FASTBOOT_FLASH_NAND_TRIMFFS
 CONFIG_FAST_FLASH_BIT
-CONFIG_FAT_WRITE
 CONFIG_FB_ADDR
 CONFIG_FB_BACKLIGHT
 CONFIG_FB_DEFERRED_IO
@@ -986,8 +984,6 @@
 CONFIG_FSMTDBLK
 CONFIG_FSNOTIFY
 CONFIG_FS_EXT4
-CONFIG_FS_FAT
-CONFIG_FS_FAT_MAX_CLUSTSIZE
 CONFIG_FS_POSIX_ACL
 CONFIG_FTAHBC020S
 CONFIG_FTAHBC020S_BASE
@@ -1074,7 +1070,6 @@
 CONFIG_H8300
 CONFIG_HALEAKALA
 CONFIG_HARD_SPI
-CONFIG_HASH_VERIFY
 CONFIG_HAS_DATAFLASH
 CONFIG_HAS_ETH0
 CONFIG_HAS_ETH1
@@ -2416,7 +2411,6 @@
 CONFIG_SH7780_PCI_LAR
 CONFIG_SH7780_PCI_LSR
 CONFIG_SH7785LCR
-CONFIG_SHA1SUM_VERIFY
 CONFIG_SHARP_16x9
 CONFIG_SHARP_LM8V31
 CONFIG_SHARP_LQ035Q7DH06
diff --git a/test/dm/blk.c b/test/dm/blk.c
index 012bf4c..5c5eb82 100644
--- a/test/dm/blk.c
+++ b/test/dm/blk.c
@@ -83,14 +83,70 @@
 	ut_asserteq_ptr(usb_dev, dev_get_parent(dev));
 
 	/* Check we have one block device for each mass storage device */
-	ut_asserteq(4, count_blk_devices());
+	ut_asserteq(6, count_blk_devices());
 
 	/* Now go around again, making sure the old devices were unbound */
 	ut_assertok(usb_stop());
 	ut_assertok(usb_init());
-	ut_asserteq(4, count_blk_devices());
+	ut_asserteq(6, count_blk_devices());
 	ut_assertok(usb_stop());
 
 	return 0;
 }
 DM_TEST(dm_test_blk_usb, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that we can find block devices without probing them */
+static int dm_test_blk_find(struct unit_test_state *uts)
+{
+	struct udevice *blk, *dev;
+
+	ut_assertok(blk_create_device(gd->dm_root, "sandbox_host_blk", "test",
+				      IF_TYPE_HOST, 1, 512, 1024, &blk));
+	ut_asserteq(-ENODEV, blk_find_device(IF_TYPE_HOST, 0, &dev));
+	ut_assertok(blk_find_device(IF_TYPE_HOST, 1, &dev));
+	ut_asserteq_ptr(blk, dev);
+	ut_asserteq(false, device_active(dev));
+
+	/* Now activate it */
+	ut_assertok(blk_get_device(IF_TYPE_HOST, 1, &dev));
+	ut_asserteq_ptr(blk, dev);
+	ut_asserteq(true, device_active(dev));
+
+	return 0;
+}
+DM_TEST(dm_test_blk_find, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that block device numbering works as expected */
+static int dm_test_blk_devnum(struct unit_test_state *uts)
+{
+	struct udevice *dev, *mmc_dev, *parent;
+	int i;
+
+	/*
+	 * Probe the devices, with the first one being probed last. This is the
+	 * one with no alias / sequence numnber.
+	 */
+	ut_assertok(uclass_get_device(UCLASS_MMC, 1, &dev));
+	ut_assertok(uclass_get_device(UCLASS_MMC, 2, &dev));
+	ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev));
+	for (i = 0; i < 3; i++) {
+		struct blk_desc *desc;
+
+		/* Check that the bblock device is attached */
+		ut_assertok(uclass_get_device_by_seq(UCLASS_MMC, i, &mmc_dev));
+		ut_assertok(blk_find_device(IF_TYPE_MMC, i, &dev));
+		parent = dev_get_parent(dev);
+		ut_asserteq_ptr(parent, mmc_dev);
+		ut_asserteq(trailing_strtol(mmc_dev->name), i);
+
+		/*
+		 * Check that the block device devnum matches its parent's
+		 * sequence number
+		 */
+		desc = dev_get_uclass_platdata(dev);
+		ut_asserteq(desc->devnum, i);
+	}
+
+	return 0;
+}
+DM_TEST(dm_test_blk_devnum, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
diff --git a/test/dm/bus.c b/test/dm/bus.c
index 6a27735..8ba75d4 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -160,8 +160,21 @@
 	node = fdt_path_offset(blob, "/d-test");
 	ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
 
+	return 0;
+}
+DM_TEST(dm_test_bus_children_funcs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_bus_children_of_offset(struct unit_test_state *uts)
+{
+	const void *blob = gd->fdt_blob;
+	struct udevice *bus, *dev;
+	int node;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
+
 	/* Find a valid child */
 	node = fdt_path_offset(blob, "/some-bus/c-test@1");
+	ut_assert(node > 0);
 	ut_assertok(device_find_child_by_of_offset(bus, node, &dev));
 	ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
 	ut_assertok(device_get_child_by_of_offset(bus, node, &dev));
@@ -169,7 +182,8 @@
 
 	return 0;
 }
-DM_TEST(dm_test_bus_children_funcs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+DM_TEST(dm_test_bus_children_of_offset,
+	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE);
 
 /* Test that we can iterate through children */
 static int dm_test_bus_children_iterators(struct unit_test_state *uts)
diff --git a/test/dm/phy.c b/test/dm/phy.c
index 811045f..65b33fe 100644
--- a/test/dm/phy.c
+++ b/test/dm/phy.c
@@ -49,8 +49,8 @@
 
 	/* Try to get a non-existing phy */
 	ut_asserteq(-ENODEV, uclass_get_device(UCLASS_PHY, 3, &dev));
-	ut_assert(generic_phy_get_by_name(parent, "phy_not_existing",
-					  &phy1_method1) < 0)
+	ut_asserteq(-ENODATA, generic_phy_get_by_name(parent,
+					"phy_not_existing", &phy1_method1));
 
 	return 0;
 }
@@ -68,8 +68,11 @@
 					      "gen_phy_user", &parent));
 
 	ut_assertok(generic_phy_get_by_name(parent, "phy1", &phy1));
+	ut_asserteq(0, phy1.id);
 	ut_assertok(generic_phy_get_by_name(parent, "phy2", &phy2));
+	ut_asserteq(1, phy2.id);
 	ut_assertok(generic_phy_get_by_name(parent, "phy3", &phy3));
+	ut_asserteq(0, phy3.id);
 
 	/* test normal operations */
 	ut_assertok(generic_phy_init(&phy1));
@@ -100,12 +103,12 @@
 	/* PHY2 has a known problem with power off */
 	ut_assertok(generic_phy_init(&phy2));
 	ut_assertok(generic_phy_power_on(&phy2));
-	ut_assert(generic_phy_power_off(&phy2) == -EIO);
+	ut_asserteq(-EIO, generic_phy_power_off(&phy2));
 
-	/* PHY3 has a known problem with power off and power on*/
+	/* PHY3 has a known problem with power off and power on */
 	ut_assertok(generic_phy_init(&phy3));
-	ut_assert(generic_phy_power_off(&phy3) == -EIO);
-	ut_assert(generic_phy_power_off(&phy3) == -EIO);
+	ut_asserteq(-EIO, generic_phy_power_off(&phy3));
+	ut_asserteq(-EIO, generic_phy_power_off(&phy3));
 
 	return 0;
 }
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index 3048a7b..987a265 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -265,4 +265,5 @@
 
 	return 0;
 }
-DM_TEST(dm_test_fdt_offset, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+DM_TEST(dm_test_fdt_offset,
+	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE);
diff --git a/test/dm/test-main.c b/test/dm/test-main.c
index f2e0048..9d88d31 100644
--- a/test/dm/test-main.c
+++ b/test/dm/test-main.c
@@ -22,15 +22,20 @@
 static struct dm_test_state _global_priv_dm_test_state;
 
 /* Get ready for testing */
-static int dm_test_init(struct unit_test_state *uts)
+static int dm_test_init(struct unit_test_state *uts, bool of_live)
 {
 	struct dm_test_state *dms = uts->priv;
 
 	memset(dms, '\0', sizeof(*dms));
 	gd->dm_root = NULL;
 	memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count));
+	state_reset_for_test(state_get_current());
 
-	ut_assertok(dm_init());
+#ifdef CONFIG_OF_LIVE
+	/* Determine whether to make the live tree available */
+	gd->of_root = of_live ? uts->of_root : NULL;
+#endif
+	ut_assertok(dm_init(of_live));
 	dms->root = dm_root();
 
 	return 0;
@@ -71,16 +76,64 @@
 	return 0;
 }
 
+static int dm_do_test(struct unit_test_state *uts, struct unit_test *test,
+		      bool of_live)
+{
+	struct sandbox_state *state = state_get_current();
+	const char *fname = strrchr(test->file, '/') + 1;
+
+	printf("Test: %s: %s%s\n", test->name, fname,
+	       !of_live ? " (flat tree)" : "");
+	ut_assertok(dm_test_init(uts, of_live));
+
+	uts->start = mallinfo();
+	if (test->flags & DM_TESTF_SCAN_PDATA)
+		ut_assertok(dm_scan_platdata(false));
+	if (test->flags & DM_TESTF_PROBE_TEST)
+		ut_assertok(do_autoprobe(uts));
+	if (test->flags & DM_TESTF_SCAN_FDT)
+		ut_assertok(dm_scan_fdt(gd->fdt_blob, false));
+
+	/*
+	 * Silence the console and rely on console reocrding to get
+	 * our output.
+	 */
+	console_record_reset();
+	if (!state->show_test_output)
+		gd->flags |= GD_FLG_SILENT;
+	test->func(uts);
+	gd->flags &= ~GD_FLG_SILENT;
+	state_set_skip_delays(false);
+
+	ut_assertok(dm_test_destroy(uts));
+
+	return 0;
+}
+
+/**
+ * dm_test_run_on_flattree() - Check if we should run a test with flat DT
+ *
+ * This skips long/slow tests where there is not much value in running a flat
+ * DT test in addition to a live DT test.
+ *
+ * @return true to run the given test on the flat device tree
+ */
+static bool dm_test_run_on_flattree(struct unit_test *test)
+{
+	const char *fname = strrchr(test->file, '/') + 1;
+
+	return !strstr(fname, "video") || strstr(test->name, "video_base");
+}
+
 static int dm_test_main(const char *test_name)
 {
 	struct unit_test *tests = ll_entry_start(struct unit_test, dm_test);
 	const int n_ents = ll_entry_count(struct unit_test, dm_test);
 	struct unit_test_state *uts = &global_dm_test_state;
-	struct sandbox_state *state = state_get_current();
-	uts->priv = &_global_priv_dm_test_state;
 	struct unit_test *test;
 	int run_count;
 
+	uts->priv = &_global_priv_dm_test_state;
 	uts->fail_count = 0;
 
 	/*
@@ -97,38 +150,38 @@
 		printf("Running %d driver model tests\n", n_ents);
 
 	run_count = 0;
+#ifdef CONFIG_OF_LIVE
+	uts->of_root = gd->of_root;
+#endif
 	for (test = tests; test < tests + n_ents; test++) {
 		const char *name = test->name;
+		int runs;
 
 		/* All tests have this prefix */
 		if (!strncmp(name, "dm_test_", 8))
 			name += 8;
 		if (test_name && strcmp(test_name, name))
 			continue;
-		printf("Test: %s\n", test->name);
-		run_count++;
-		ut_assertok(dm_test_init(uts));
 
-		uts->start = mallinfo();
-		if (test->flags & DM_TESTF_SCAN_PDATA)
-			ut_assertok(dm_scan_platdata(false));
-		if (test->flags & DM_TESTF_PROBE_TEST)
-			ut_assertok(do_autoprobe(uts));
-		if (test->flags & DM_TESTF_SCAN_FDT)
-			ut_assertok(dm_scan_fdt(gd->fdt_blob, false));
+		/* Run with the live tree if possible */
+		runs = 0;
+		if (IS_ENABLED(CONFIG_OF_LIVE)) {
+			if (!(test->flags & DM_TESTF_FLAT_TREE)) {
+				ut_assertok(dm_do_test(uts, test, true));
+				runs++;
+			}
+		}
 
 		/*
-		 * Silence the console and rely on console reocrding to get
-		 * our output.
+		 * Run with the flat tree if we couldn't run it with live tree,
+		 * or it is a core test.
 		 */
-		console_record_reset();
-		if (!state->show_test_output)
-			gd->flags |= GD_FLG_SILENT;
-		test->func(uts);
-		gd->flags &= ~GD_FLG_SILENT;
-		state_set_skip_delays(false);
-
-		ut_assertok(dm_test_destroy(uts));
+		if (!(test->flags & DM_TESTF_LIVE_TREE) &&
+		    (!runs || dm_test_run_on_flattree(test))) {
+			ut_assertok(dm_do_test(uts, test, false));
+			runs++;
+		}
+		run_count += runs;
 	}
 
 	if (test_name && !run_count)
@@ -137,7 +190,7 @@
 		printf("Failures: %d\n", uts->fail_count);
 
 	gd->dm_root = NULL;
-	ut_assertok(dm_init());
+	ut_assertok(dm_init(false));
 	dm_scan_platdata(false);
 	dm_scan_fdt(gd->fdt_blob, false);
 
diff --git a/test/run b/test/run
index a6dcf8f..b1649ee 100755
--- a/test/run
+++ b/test/run
@@ -1,4 +1,10 @@
 #!/bin/sh
 
-# Run all tests
+# Run all tests that the standard sandbox build can support
 ./test/py/test.py --bd sandbox --build
+
+# Run tests which require sandbox_spl
+./test/py/test.py --bd sandbox_spl --build -k test/py/tests/test_ofplatdata.py
+
+# Run tests for the flat DT version of sandbox
+./test/py/test.py --bd sandbox_flattree --build
diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index 8c0e730..edef560 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -1476,47 +1476,6 @@
 	return e->version;
 }
 
-static int image_version_file(const char *input)
-{
-	FILE *fcfg;
-	int version;
-	int ret;
-
-	fcfg = fopen(input, "r");
-	if (!fcfg) {
-		fprintf(stderr, "Could not open input file %s\n", input);
-		return -1;
-	}
-
-	image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
-			   sizeof(struct image_cfg_element));
-	if (!image_cfg) {
-		fprintf(stderr, "Cannot allocate memory\n");
-		fclose(fcfg);
-		return -1;
-	}
-
-	memset(image_cfg, 0,
-	       IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
-	rewind(fcfg);
-
-	ret = image_create_config_parse(fcfg);
-	fclose(fcfg);
-	if (ret) {
-		free(image_cfg);
-		return -1;
-	}
-
-	version = image_get_version();
-	/* Fallback to version 0 is no version is provided in the cfg file */
-	if (version == -1)
-		version = 0;
-
-	free(image_cfg);
-
-	return version;
-}
-
 static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
 				struct image_tool_params *params)
 {
@@ -1657,18 +1616,62 @@
 static int kwbimage_generate(struct image_tool_params *params,
 			     struct image_type_params *tparams)
 {
+	FILE *fcfg;
 	int alloc_len;
+	int version;
 	void *hdr;
-	int version = 0;
+	int ret;
 
-	version = image_version_file(params->imagename);
-	if (version == 0) {
+	fcfg = fopen(params->imagename, "r");
+	if (!fcfg) {
+		fprintf(stderr, "Could not open input file %s\n",
+			params->imagename);
+		exit(EXIT_FAILURE);
+	}
+
+	image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
+			   sizeof(struct image_cfg_element));
+	if (!image_cfg) {
+		fprintf(stderr, "Cannot allocate memory\n");
+		fclose(fcfg);
+		exit(EXIT_FAILURE);
+	}
+
+	memset(image_cfg, 0,
+	       IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
+	rewind(fcfg);
+
+	ret = image_create_config_parse(fcfg);
+	fclose(fcfg);
+	if (ret) {
+		free(image_cfg);
+		exit(EXIT_FAILURE);
+	}
+
+	version = image_get_version();
+	switch (version) {
+		/*
+		 * Fallback to version 0 if no version is provided in the
+		 * cfg file
+		 */
+	case -1:
+	case 0:
 		alloc_len = sizeof(struct main_hdr_v0) +
 			sizeof(struct ext_hdr_v0);
-	} else {
+		break;
+
+	case 1:
 		alloc_len = image_headersz_v1(NULL);
+		break;
+
+	default:
+		fprintf(stderr, "Unsupported version %d\n", version);
+		free(image_cfg);
+		exit(EXIT_FAILURE);
 	}
 
+	free(image_cfg);
+
 	hdr = malloc(alloc_len);
 	if (!hdr) {
 		fprintf(stderr, "%s: malloc return failure: %s\n",