Merge git://git.denx.de/u-boot-usb
diff --git a/arch/arm/dts/tegra124-nyan-big.dts b/arch/arm/dts/tegra124-nyan-big.dts
index 62f89d0..f1c9705 100644
--- a/arch/arm/dts/tegra124-nyan-big.dts
+++ b/arch/arm/dts/tegra124-nyan-big.dts
@@ -8,7 +8,6 @@
 
 	aliases {
 		console = &uarta;
-		stdout-path = &uarta;
 		i2c0 = "/i2c@7000d000";
 		i2c1 = "/i2c@7000c000";
 		i2c2 = "/i2c@7000c400";
@@ -26,6 +25,10 @@
 		usb2 = "/usb@7d004000";
 	};
 
+	chosen {
+		stdout-path = &uarta;
+	};
+
 	host1x@50000000 {
 		dc@54200000 {
 			display-timings {
diff --git a/arch/arm/include/asm/arch-tegra/clock.h b/arch/arm/include/asm/arch-tegra/clock.h
index f62b2a4..92180db 100644
--- a/arch/arm/include/asm/arch-tegra/clock.h
+++ b/arch/arm/include/asm/arch-tegra/clock.h
@@ -266,7 +266,7 @@
  * @param node		Node to look at
  * @return peripheral ID, or PERIPH_ID_NONE if none
  */
-enum periph_id clock_decode_periph_id(const void *blob, int node);
+int clock_decode_periph_id(struct udevice *dev);
 
 /**
  * Checks if the oscillator bypass is enabled (XOBP bit)
diff --git a/arch/arm/include/asm/arch-tegra/tegra.h b/arch/arm/include/asm/arch-tegra/tegra.h
index 3add1b3..3b9711d 100644
--- a/arch/arm/include/asm/arch-tegra/tegra.h
+++ b/arch/arm/include/asm/arch-tegra/tegra.h
@@ -97,6 +97,11 @@
 	TEGRA_SOC_UNKNOWN	= -1,
 };
 
+/* Tegra system controller (SYSCON) devices */
+enum {
+	TEGRA_SYSCON_PMC,
+};
+
 #else  /* __ASSEMBLY__ */
 #define PRM_RSTCTRL		NV_PA_PMC_BASE
 #endif
diff --git a/arch/arm/include/asm/arch-tegra/xusb-padctl.h b/arch/arm/include/asm/arch-tegra/xusb-padctl.h
index b4b4c8b..deccdf4 100644
--- a/arch/arm/include/asm/arch-tegra/xusb-padctl.h
+++ b/arch/arm/include/asm/arch-tegra/xusb-padctl.h
@@ -15,7 +15,7 @@
  */
 struct tegra_xusb_phy *tegra_xusb_phy_get(unsigned int type);
 
-void tegra_xusb_padctl_init(const void *fdt);
+void tegra_xusb_padctl_init(void);
 int tegra_xusb_phy_prepare(struct tegra_xusb_phy *phy);
 int tegra_xusb_phy_enable(struct tegra_xusb_phy *phy);
 int tegra_xusb_phy_disable(struct tegra_xusb_phy *phy);
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 4838758..58085dc 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -88,6 +88,8 @@
 	bool "Tegra124 family"
 	select TEGRA_ARMV7_COMMON
 	imply ENV_IS_IN_MMC
+	imply REGMAP
+	imply SYSCON
 
 config TEGRA210
 	bool "Tegra210 family"
diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c
index 6b5fa7d..bd13796 100644
--- a/arch/arm/mach-tegra/board2.c
+++ b/arch/arm/mach-tegra/board2.c
@@ -29,7 +29,6 @@
 #ifdef CONFIG_TEGRA_CLOCK_SCALING
 #include <asm/arch/emc.h>
 #endif
-#include <power/as3722.h>
 #include "emc.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -142,11 +141,6 @@
 		debug("Memory controller init failed: %d\n", err);
 #  endif
 # endif /* CONFIG_TEGRA_PMU */
-#ifdef CONFIG_PMIC_AS3722
-	err = as3722_init(NULL);
-	if (err && err != -ENODEV)
-		return err;
-#endif
 #endif /* CONFIG_SYS_I2C_TEGRA */
 
 #ifdef CONFIG_USB_EHCI_TEGRA
@@ -166,7 +160,7 @@
 	pin_mux_nand();
 #endif
 
-	tegra_xusb_padctl_init(gd->fdt_blob);
+	tegra_xusb_padctl_init();
 
 #ifdef CONFIG_TEGRA_LP0
 	/* save Sdram params to PMC 2, 4, and 24 for WB0 */
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index 668bbd2..dc58b30 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -655,14 +655,13 @@
 }
 
 #if CONFIG_IS_ENABLED(OF_CONTROL)
-int clock_decode_periph_id(const void *blob, int node)
+int clock_decode_periph_id(struct udevice *dev)
 {
 	enum periph_id id;
 	u32 cell[2];
 	int err;
 
-	err = fdtdec_get_int_array(blob, node, "clocks", cell,
-				   ARRAY_SIZE(cell));
+	err = dev_read_u32_array(dev, "clocks", cell, ARRAY_SIZE(cell));
 	if (err)
 		return -1;
 	id = clk_id_to_periph_id(cell[1]);
diff --git a/arch/arm/mach-tegra/spl.c b/arch/arm/mach-tegra/spl.c
index 41c88cb..189b3da 100644
--- a/arch/arm/mach-tegra/spl.c
+++ b/arch/arm/mach-tegra/spl.c
@@ -7,6 +7,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 #include <common.h>
+#include <debug_uart.h>
 #include <spl.h>
 
 #include <asm/io.h>
@@ -32,6 +33,9 @@
 	gpio_early_init_uart();
 
 	clock_early_init();
+#ifdef CONFIG_DEBUG_UART
+	debug_uart_init();
+#endif
 	preloader_console_init();
 }
 
diff --git a/arch/arm/mach-tegra/tegra124/Makefile b/arch/arm/mach-tegra/tegra124/Makefile
index c00de61..d275daf 100644
--- a/arch/arm/mach-tegra/tegra124/Makefile
+++ b/arch/arm/mach-tegra/tegra124/Makefile
@@ -10,6 +10,7 @@
 obj-y	+= clock.o
 obj-y	+= funcmux.o
 obj-y	+= pinmux.o
+obj-y	+= pmc.o
 obj-y	+= xusb-padctl.o
 obj-y	+= ../xusb-padctl-common.o
 
diff --git a/arch/arm/mach-tegra/tegra124/pmc.c b/arch/arm/mach-tegra/tegra124/pmc.c
new file mode 100644
index 0000000..be82acf
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra124/pmc.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+
+static const struct udevice_id tegra124_syscon_ids[] = {
+	{ .compatible = "nvidia,tegra124-pmc", .data = TEGRA_SYSCON_PMC },
+};
+
+U_BOOT_DRIVER(syscon_tegra124) = {
+	.name = "tegra124_syscon",
+	.id = UCLASS_SYSCON,
+	.of_match = tegra124_syscon_ids,
+};
diff --git a/arch/arm/mach-tegra/tegra124/xusb-padctl.c b/arch/arm/mach-tegra/tegra124/xusb-padctl.c
index 76af924..d326a6a 100644
--- a/arch/arm/mach-tegra/tegra124/xusb-padctl.c
+++ b/arch/arm/mach-tegra/tegra124/xusb-padctl.c
@@ -8,6 +8,8 @@
 
 #include <common.h>
 #include <errno.h>
+#include <dm/of_access.h>
+#include <dm/ofnode.h>
 
 #include "../xusb-padctl-common.h"
 
@@ -317,13 +319,33 @@
 	.num_phys = ARRAY_SIZE(tegra124_phys),
 };
 
-void tegra_xusb_padctl_init(const void *fdt)
+void tegra_xusb_padctl_init(void)
 {
-	int count, nodes[1];
+	ofnode nodes[1];
+	int count = 0;
+	int ret;
 
-	count = fdtdec_find_aliases_for_id(fdt, "padctl",
-					   COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
-					   nodes, ARRAY_SIZE(nodes));
-	if (tegra_xusb_process_nodes(fdt, nodes, count, &tegra124_socdata))
-		return;
+	debug("%s: start\n", __func__);
+	if (of_live_active()) {
+		struct device_node *np = of_find_compatible_node(NULL, NULL,
+						"nvidia,tegra124-xusb-padctl");
+
+		debug("np=%p\n", np);
+		if (np) {
+			nodes[0] = np_to_ofnode(np);
+			count = 1;
+		}
+	} else {
+		int node_offsets[1];
+		int i;
+
+		count = fdtdec_find_aliases_for_id(gd->fdt_blob, "padctl",
+				COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
+				node_offsets, ARRAY_SIZE(node_offsets));
+		for (i = 0; i < count; i++)
+			nodes[i] = offset_to_ofnode(node_offsets[i]);
+	}
+
+	ret = tegra_xusb_process_nodes(nodes, count, &tegra124_socdata);
+	debug("%s: done, ret=%d\n", __func__, ret);
 }
diff --git a/arch/arm/mach-tegra/tegra210/xusb-padctl.c b/arch/arm/mach-tegra/tegra210/xusb-padctl.c
index 9ec93e7..bf85e07 100644
--- a/arch/arm/mach-tegra/tegra210/xusb-padctl.c
+++ b/arch/arm/mach-tegra/tegra210/xusb-padctl.c
@@ -8,6 +8,8 @@
 
 #include <common.h>
 #include <errno.h>
+#include <dm/of_access.h>
+#include <dm/ofnode.h>
 
 #include "../xusb-padctl-common.h"
 
@@ -15,6 +17,8 @@
 
 #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 enum tegra210_function {
 	TEGRA210_FUNC_SNPS,
 	TEGRA210_FUNC_XUSB,
@@ -421,17 +425,33 @@
 	.num_phys = ARRAY_SIZE(tegra210_phys),
 };
 
-void tegra_xusb_padctl_init(const void *fdt)
+void tegra_xusb_padctl_init(void)
 {
-	int count, nodes[1];
+	ofnode nodes[1];
+	int count = 0;
+	int ret;
 
-	debug("> %s(fdt=%p)\n", __func__, fdt);
+	debug("%s: start\n", __func__);
+	if (of_live_active()) {
+		struct device_node *np = of_find_compatible_node(NULL, NULL,
+						"nvidia,tegra210-xusb-padctl");
 
-	count = fdtdec_find_aliases_for_id(fdt, "padctl",
-					   COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL,
-					   nodes, ARRAY_SIZE(nodes));
-	if (tegra_xusb_process_nodes(fdt, nodes, count, &tegra210_socdata))
-		return;
+		debug("np=%p\n", np);
+		if (np) {
+			nodes[0] = np_to_ofnode(np);
+			count = 1;
+		}
+	} else {
+		int node_offsets[1];
+		int i;
 
-	debug("< %s()\n", __func__);
+		count = fdtdec_find_aliases_for_id(gd->fdt_blob, "padctl",
+				COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL,
+				node_offsets, ARRAY_SIZE(node_offsets));
+		for (i = 0; i < count; i++)
+			nodes[i] = offset_to_ofnode(node_offsets[i]);
+	}
+
+	ret = tegra_xusb_process_nodes(nodes, count, &tegra210_socdata);
+	debug("%s: done, ret=%d\n", __func__, ret);
 }
diff --git a/arch/arm/mach-tegra/xusb-padctl-common.c b/arch/arm/mach-tegra/xusb-padctl-common.c
index 43f5bb7..37b5b8f 100644
--- a/arch/arm/mach-tegra/xusb-padctl-common.c
+++ b/arch/arm/mach-tegra/xusb-padctl-common.c
@@ -75,14 +75,14 @@
 static int
 tegra_xusb_padctl_group_parse_dt(struct tegra_xusb_padctl *padctl,
 				 struct tegra_xusb_padctl_group *group,
-				 const void *fdt, int node)
+				 ofnode node)
 {
 	unsigned int i;
-	int len;
+	int len, ret;
 
-	group->name = fdt_get_name(fdt, node, &len);
+	group->name = ofnode_get_name(node);
 
-	len = fdt_stringlist_count(fdt, node, "nvidia,lanes");
+	len = ofnode_read_string_count(node, "nvidia,lanes");
 	if (len < 0) {
 		error("failed to parse \"nvidia,lanes\" property");
 		return -EINVAL;
@@ -91,9 +91,9 @@
 	group->num_pins = len;
 
 	for (i = 0; i < group->num_pins; i++) {
-		group->pins[i] = fdt_stringlist_get(fdt, node, "nvidia,lanes",
-						    i, NULL);
-		if (!group->pins[i]) {
+		ret = ofnode_read_string_index(node, "nvidia,lanes", i,
+					       &group->pins[i]);
+		if (ret) {
 			error("failed to read string from \"nvidia,lanes\" property");
 			return -EINVAL;
 		}
@@ -101,13 +101,14 @@
 
 	group->num_pins = len;
 
-	group->func = fdt_stringlist_get(fdt, node, "nvidia,function", 0, NULL);
-	if (!group->func) {
+	ret = ofnode_read_string_index(node, "nvidia,function", 0,
+				       &group->func);
+	if (ret) {
 		error("failed to parse \"nvidia,func\" property");
 		return -EINVAL;
 	}
 
-	group->iddq = fdtdec_get_int(fdt, node, "nvidia,iddq", -1);
+	group->iddq = ofnode_read_u32_default(node, "nvidia,iddq", -1);
 
 	return 0;
 }
@@ -217,20 +218,21 @@
 static int
 tegra_xusb_padctl_config_parse_dt(struct tegra_xusb_padctl *padctl,
 				  struct tegra_xusb_padctl_config *config,
-				  const void *fdt, int node)
+				  ofnode node)
 {
-	int subnode;
+	ofnode subnode;
 
-	config->name = fdt_get_name(fdt, node, NULL);
+	config->name = ofnode_get_name(node);
 
-	fdt_for_each_subnode(subnode, fdt, node) {
+	for (subnode = ofnode_first_subnode(node);
+	     ofnode_valid(subnode);
+	     subnode = ofnode_next_subnode(subnode)) {
 		struct tegra_xusb_padctl_group *group;
 		int err;
 
 		group = &config->groups[config->num_groups];
 
-		err = tegra_xusb_padctl_group_parse_dt(padctl, group, fdt,
-						       subnode);
+		err = tegra_xusb_padctl_group_parse_dt(padctl, group, subnode);
 		if (err < 0) {
 			error("failed to parse group %s", group->name);
 			return err;
@@ -243,20 +245,24 @@
 }
 
 static int tegra_xusb_padctl_parse_dt(struct tegra_xusb_padctl *padctl,
-				      const void *fdt, int node)
+				      ofnode node)
 {
-	int subnode, err;
+	ofnode subnode;
+	int err;
 
-	err = fdt_get_resource(fdt, node, "reg", 0, &padctl->regs);
+	err = ofnode_read_resource(node, 0, &padctl->regs);
 	if (err < 0) {
 		error("registers not found");
 		return err;
 	}
 
-	fdt_for_each_subnode(subnode, fdt, node) {
+	for (subnode = ofnode_first_subnode(node);
+	     ofnode_valid(subnode);
+	     subnode = ofnode_next_subnode(subnode)) {
 		struct tegra_xusb_padctl_config *config = &padctl->config;
 
-		err = tegra_xusb_padctl_config_parse_dt(padctl, config, fdt,
+		debug("%s: subnode=%s\n", __func__, ofnode_get_name(subnode));
+		err = tegra_xusb_padctl_config_parse_dt(padctl, config,
 							subnode);
 		if (err < 0) {
 			error("failed to parse entry %s: %d",
@@ -264,25 +270,28 @@
 			continue;
 		}
 	}
+	debug("%s: done\n", __func__);
 
 	return 0;
 }
 
 struct tegra_xusb_padctl padctl;
 
-int tegra_xusb_process_nodes(const void *fdt, int nodes[], unsigned int count,
-	const struct tegra_xusb_padctl_soc *socdata)
+int tegra_xusb_process_nodes(ofnode nodes[], unsigned int count,
+			     const struct tegra_xusb_padctl_soc *socdata)
 {
 	unsigned int i;
 	int err;
 
+	debug("%s: count=%d\n", __func__, count);
 	for (i = 0; i < count; i++) {
-		if (!fdtdec_get_is_enabled(fdt, nodes[i]))
+		debug("%s: i=%d, node=%p\n", __func__, i, nodes[i].np);
+		if (!ofnode_is_available(nodes[i]))
 			continue;
 
 		padctl.socdata = socdata;
 
-		err = tegra_xusb_padctl_parse_dt(&padctl, fdt, nodes[i]);
+		err = tegra_xusb_padctl_parse_dt(&padctl, nodes[i]);
 		if (err < 0) {
 			error("failed to parse DT: %d", err);
 			continue;
@@ -300,6 +309,7 @@
 		/* only a single instance is supported */
 		break;
 	}
+	debug("%s: done\n", __func__);
 
 	return 0;
 }
diff --git a/arch/arm/mach-tegra/xusb-padctl-common.h b/arch/arm/mach-tegra/xusb-padctl-common.h
index f44790a..6836588 100644
--- a/arch/arm/mach-tegra/xusb-padctl-common.h
+++ b/arch/arm/mach-tegra/xusb-padctl-common.h
@@ -9,9 +9,11 @@
 
 #include <common.h>
 #include <fdtdec.h>
+#include <dm/ofnode.h>
 
 #include <asm/io.h>
 #include <asm/arch-tegra/xusb-padctl.h>
+#include <linux/ioport.h>
 
 struct tegra_xusb_padctl_lane {
 	const char *name;
@@ -77,7 +79,7 @@
 struct tegra_xusb_padctl {
 	const struct tegra_xusb_padctl_soc *socdata;
 	struct tegra_xusb_padctl_config config;
-	struct fdt_resource regs;
+	struct resource regs;
 	unsigned int enable;
 
 };
@@ -95,7 +97,7 @@
 	writel(value, padctl->regs.start + offset);
 }
 
-int tegra_xusb_process_nodes(const void *fdt, int nodes[], unsigned int count,
-	const struct tegra_xusb_padctl_soc *socdata);
+int tegra_xusb_process_nodes(ofnode nodes[], unsigned int count,
+			     const struct tegra_xusb_padctl_soc *socdata);
 
 #endif
diff --git a/arch/arm/mach-tegra/xusb-padctl-dummy.c b/arch/arm/mach-tegra/xusb-padctl-dummy.c
index 65f8d2e..856d712 100644
--- a/arch/arm/mach-tegra/xusb-padctl-dummy.c
+++ b/arch/arm/mach-tegra/xusb-padctl-dummy.c
@@ -34,6 +34,6 @@
 	return -ENOSYS;
 }
 
-void __weak tegra_xusb_padctl_init(const void *fdt)
+void __weak tegra_xusb_padctl_init(void)
 {
 }
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 7243bfc..22d6aab 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -413,17 +413,6 @@
 	return 0;
 }
 
-void os_putc(int ch)
-{
-	putchar(ch);
-}
-
-void os_puts(const char *str)
-{
-	while (*str)
-		os_putc(*str++);
-}
-
 int os_write_ram_buf(const char *fname)
 {
 	struct sandbox_state *state = state_get_current();
diff --git a/board/cei/cei-tk1-som/cei-tk1-som.c b/board/cei/cei-tk1-som/cei-tk1-som.c
index 9ba7490..7c87bd1 100644
--- a/board/cei/cei-tk1-som/cei-tk1-som.c
+++ b/board/cei/cei-tk1-som/cei-tk1-som.c
@@ -39,6 +39,7 @@
 #ifdef CONFIG_PCI_TEGRA
 int tegra_pcie_board_init(void)
 {
+/* TODO: Convert to driver model
 	struct udevice *pmic;
 	int err;
 
@@ -59,6 +60,7 @@
 		error("failed to set SD4 voltage: %d\n", err);
 		return err;
 	}
+*/
 
 	return 0;
 }
diff --git a/board/nvidia/jetson-tk1/jetson-tk1.c b/board/nvidia/jetson-tk1/jetson-tk1.c
index a66b710..bd08a2e 100644
--- a/board/nvidia/jetson-tk1/jetson-tk1.c
+++ b/board/nvidia/jetson-tk1/jetson-tk1.c
@@ -6,7 +6,9 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <power/as3722.h>
+#include <power/pmic.h>
 
 #include <asm/arch/gpio.h>
 #include <asm/arch/pinmux.h>
@@ -37,27 +39,45 @@
 }
 
 #ifdef CONFIG_PCI_TEGRA
-int tegra_pcie_board_init(void)
+/* TODO: Convert to driver model */
+static int as3722_sd_enable(struct udevice *pmic, unsigned int sd)
 {
-	struct udevice *pmic;
 	int err;
 
-	err = as3722_init(&pmic);
+	if (sd > 6)
+		return -EINVAL;
+
+	err = pmic_clrsetbits(pmic, AS3722_SD_CONTROL, 0, 1 << sd);
 	if (err) {
-		error("failed to initialize AS3722 PMIC: %d\n", err);
+		error("failed to update SD control register: %d", err);
 		return err;
 	}
 
-	err = as3722_sd_enable(pmic, 4);
-	if (err < 0) {
-		error("failed to enable SD4: %d\n", err);
-		return err;
+	return 0;
+}
+
+int tegra_pcie_board_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_get_device_by_driver(UCLASS_PMIC,
+					  DM_GET_DRIVER(pmic_as3722), &dev);
+	if (ret) {
+		debug("%s: Failed to find PMIC\n", __func__);
+		return ret;
 	}
 
-	err = as3722_sd_set_voltage(pmic, 4, 0x24);
-	if (err < 0) {
-		error("failed to set SD4 voltage: %d\n", err);
-		return err;
+	ret = as3722_sd_enable(dev, 4);
+	if (ret < 0) {
+		error("failed to enable SD4: %d\n", ret);
+		return ret;
+	}
+
+	ret = as3722_sd_set_voltage(dev, 4, 0x24);
+	if (ret < 0) {
+		error("failed to set SD4 voltage: %d\n", ret);
+		return ret;
 	}
 
 	return 0;
diff --git a/board/nvidia/nyan-big/nyan-big.c b/board/nvidia/nyan-big/nyan-big.c
index 8f68ae9..54acf54 100644
--- a/board/nvidia/nyan-big/nyan-big.c
+++ b/board/nvidia/nyan-big/nyan-big.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
@@ -46,20 +47,23 @@
 
 int tegra_lcd_pmic_init(int board_id)
 {
-	struct udevice *pmic;
+	struct udevice *dev;
 	int ret;
 
-	ret = as3722_get(&pmic);
-	if (ret)
-		return -ENOENT;
+	ret = uclass_get_device_by_driver(UCLASS_PMIC,
+					  DM_GET_DRIVER(pmic_as3722), &dev);
+	if (ret) {
+		debug("%s: Failed to find PMIC\n", __func__);
+		return ret;
+	}
 
 	if (board_id == 0)
-		as3722_write(pmic, 0x00, 0x3c);
+		pmic_reg_write(dev, 0x00, 0x3c);
 	else
-		as3722_write(pmic, 0x00, 0x50);
-	as3722_write(pmic, 0x12, 0x10);
-	as3722_write(pmic, 0x0c, 0x07);
-	as3722_write(pmic, 0x20, 0x10);
+		pmic_reg_write(dev, 0x00, 0x50);
+	pmic_reg_write(dev, 0x12, 0x10);
+	pmic_reg_write(dev, 0x0c, 0x07);
+	pmic_reg_write(dev, 0x20, 0x10);
 
 	return 0;
 }
diff --git a/board/toradex/apalis-tk1/apalis-tk1.c b/board/toradex/apalis-tk1/apalis-tk1.c
index c7e519c..5de61e7 100644
--- a/board/toradex/apalis-tk1/apalis-tk1.c
+++ b/board/toradex/apalis-tk1/apalis-tk1.c
@@ -61,6 +61,7 @@
 #ifdef CONFIG_PCI_TEGRA
 int tegra_pcie_board_init(void)
 {
+	/* TODO: Convert to driver model
 	struct udevice *pmic;
 	int err;
 
@@ -94,6 +95,7 @@
 		error("failed to set GPIO#2 high: %d\n", err);
 		return err;
 	}
+	*/
 
 	/* Reset I210 Gigabit Ethernet Controller */
 	gpio_request(LAN_RESET_N, "LAN_RESET_N");
@@ -110,6 +112,7 @@
 	gpio_direction_output(TEGRA_GPIO(O, 6), 0);
 
 	/* Make sure LDO9 and LDO10 are initially enabled @ 0V */
+	/* TODO: Convert to driver model
 	err = as3722_ldo_enable(pmic, 9);
 	if (err < 0) {
 		error("failed to enable LDO9: %d\n", err);
@@ -130,6 +133,7 @@
 		error("failed to set LDO10 voltage: %d\n", err);
 		return err;
 	}
+	*/
 
 	mdelay(100);
 
@@ -137,6 +141,7 @@
 	gpio_set_value(TEGRA_GPIO(O, 6), 1);
 
 	/* Enable LDO9 and LDO10 for +V3.3_ETH on patched prototypes */
+	/* TODO: Convert to driver model
 	err = as3722_ldo_set_voltage(pmic, 9, 0xff);
 	if (err < 0) {
 		error("failed to set LDO9 voltage: %d\n", err);
@@ -147,6 +152,7 @@
 		error("failed to set LDO10 voltage: %d\n", err);
 		return err;
 	}
+	*/
 
 	mdelay(100);
 	gpio_set_value(LAN_RESET_N, 1);
diff --git a/cmd/scsi.c b/cmd/scsi.c
index 5709718..8e36de1 100644
--- a/cmd/scsi.c
+++ b/cmd/scsi.c
@@ -36,7 +36,9 @@
 	case 2:
 		if (strncmp(argv[1], "res", 3) == 0) {
 			printf("\nReset SCSI\n");
+#ifndef CONFIG_DM_SCSI
 			scsi_bus_reset(NULL);
+#endif
 			ret = scsi_scan(true);
 			if (ret)
 				return CMD_RET_FAILURE;
diff --git a/common/console.c b/common/console.c
index c6156f3..01eef55 100644
--- a/common/console.c
+++ b/common/console.c
@@ -426,12 +426,6 @@
 	unmap_sysmem(buffer);
 }
 
-static void pre_console_puts(const char *s)
-{
-	while (*s)
-		pre_console_putc(*s++);
-}
-
 static void print_pre_console_buffer(int flushpoint)
 {
 	unsigned long in = 0, out = 0;
@@ -459,7 +453,6 @@
 }
 #else
 static inline void pre_console_putc(const char c) {}
-static inline void pre_console_puts(const char *s) {}
 static inline void print_pre_console_buffer(int flushpoint) {}
 #endif
 
@@ -501,41 +494,8 @@
 
 void puts(const char *s)
 {
-#ifdef CONFIG_DEBUG_UART
-	if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
-		while (*s) {
-			int ch = *s++;
-
-			printch(ch);
-		}
-		return;
-	}
-#endif
-#ifdef CONFIG_CONSOLE_RECORD
-	if (gd && (gd->flags & GD_FLG_RECORD) && gd->console_out.start)
-		membuff_put(&gd->console_out, s, strlen(s));
-#endif
-#ifdef CONFIG_SILENT_CONSOLE
-	if (gd->flags & GD_FLG_SILENT)
-		return;
-#endif
-
-#ifdef CONFIG_DISABLE_CONSOLE
-	if (gd->flags & GD_FLG_DISABLE_CONSOLE)
-		return;
-#endif
-
-	if (!gd->have_console)
-		return pre_console_puts(s);
-
-	if (gd->flags & GD_FLG_DEVINIT) {
-		/* Send to the standard output */
-		fputs(stdout, s);
-	} else {
-		/* Send directly to the handler */
-		pre_console_puts(s);
-		serial_puts(s);
-	}
+	while (*s)
+		putc(*s++);
 }
 
 #ifdef CONFIG_CONSOLE_RECORD
diff --git a/configs/apalis-tk1_defconfig b/configs/apalis-tk1_defconfig
index 9179aaf..ccff112 100644
--- a/configs/apalis-tk1_defconfig
+++ b/configs/apalis-tk1_defconfig
@@ -32,7 +32,10 @@
 CONFIG_DM_PCI=y
 CONFIG_DM_PCI_COMPAT=y
 CONFIG_PCI_TEGRA=y
+CONFIG_DM_PMIC=y
 CONFIG_PMIC_AS3722=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_AS3722=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
diff --git a/configs/beaver_defconfig b/configs/beaver_defconfig
index 71d6cd5..10fd50d 100644
--- a/configs/beaver_defconfig
+++ b/configs/beaver_defconfig
@@ -25,6 +25,7 @@
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_OF_LIVE=y
 CONFIG_SPL_DM=y
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
diff --git a/configs/cei-tk1-som_defconfig b/configs/cei-tk1-som_defconfig
index 1a5e47d..5623bbf 100644
--- a/configs/cei-tk1-som_defconfig
+++ b/configs/cei-tk1-som_defconfig
@@ -36,7 +36,10 @@
 CONFIG_DM_PCI=y
 CONFIG_DM_PCI_COMPAT=y
 CONFIG_PCI_TEGRA=y
+CONFIG_DM_PMIC=y
 CONFIG_PMIC_AS3722=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_AS3722=y
 CONFIG_SYS_NS16550=y
 CONFIG_TEGRA114_SPI=y
 CONFIG_USB=y
diff --git a/configs/jetson-tk1_defconfig b/configs/jetson-tk1_defconfig
index 65a5832..a533c64 100644
--- a/configs/jetson-tk1_defconfig
+++ b/configs/jetson-tk1_defconfig
@@ -25,6 +25,7 @@
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_OF_LIVE=y
 CONFIG_SPL_DM=y
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
@@ -36,7 +37,10 @@
 CONFIG_DM_PCI=y
 CONFIG_DM_PCI_COMPAT=y
 CONFIG_PCI_TEGRA=y
+CONFIG_DM_PMIC=y
 CONFIG_PMIC_AS3722=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_AS3722=y
 CONFIG_SYS_NS16550=y
 CONFIG_TEGRA114_SPI=y
 CONFIG_USB=y
diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig
index 8183856..03d83c1 100644
--- a/configs/nyan-big_defconfig
+++ b/configs/nyan-big_defconfig
@@ -38,6 +38,7 @@
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_ISO_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_OF_LIVE=y
 CONFIG_SPL_DM=y
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
@@ -50,6 +51,7 @@
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_AS3722=y
 CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_AS3722=y
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_PWM_TEGRA=y
 CONFIG_DEBUG_UART_BASE=0x70006000
diff --git a/configs/p2371-2180_defconfig b/configs/p2371-2180_defconfig
index d04f052..4345fb0 100644
--- a/configs/p2371-2180_defconfig
+++ b/configs/p2371-2180_defconfig
@@ -22,6 +22,7 @@
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NFS is not set
 CONFIG_CMD_EXT4_WRITE=y
+CONFIG_OF_LIVE=y
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 6da412d..606347f 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1183,11 +1183,6 @@
 	ret = ahci_start_ports(uc_priv);
 	if (ret)
 		return ret;
-
-	debug("Scanning %s\n", dev->name);
-	ret = scsi_scan_dev(dev, true);
-	if (ret)
-		return ret;
 #endif
 
 	return 0;
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 5fc77c5..c1a2e9f 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -14,6 +14,7 @@
 #include <dm/of_addr.h>
 #include <dm/ofnode.h>
 #include <linux/err.h>
+#include <linux/ioport.h>
 
 int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
 {
@@ -198,13 +199,14 @@
 		const __be32 *prop_val;
 		uint flags;
 		u64 size;
+		int na;
 
-		prop_val = of_get_address(
-			(struct device_node *)ofnode_to_np(node), index,
-			&size, &flags);
+		prop_val = of_get_address(ofnode_to_np(node), index, &size,
+					  &flags);
 		if (!prop_val)
 			return FDT_ADDR_T_NONE;
-		return  be32_to_cpup(prop_val);
+		na = of_n_addr_cells(ofnode_to_np(node));
+		return of_read_number(prop_val, na);
 	} else {
 		return fdt_get_base_address(gd->fdt_blob,
 					    ofnode_to_offset(node));
@@ -605,3 +607,23 @@
 
 	return false;
 }
+
+int ofnode_read_resource(ofnode node, uint index, struct resource *res)
+{
+	if (ofnode_is_np(node)) {
+		return of_address_to_resource(ofnode_to_np(node), index, res);
+	} else {
+		struct fdt_resource fres;
+		int ret;
+
+		ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node),
+				       "reg", index, &fres);
+		if (ret < 0)
+			return -EINVAL;
+		memset(res, '\0', sizeof(*res));
+		res->start = fres.start;
+		res->end = fres.end;
+
+		return 0;
+	}
+}
diff --git a/drivers/core/read.c b/drivers/core/read.c
index eafe727..fe40bed 100644
--- a/drivers/core/read.c
+++ b/drivers/core/read.c
@@ -114,7 +114,7 @@
 		return fdt_get_phandle(gd->fdt_blob, ofnode_to_offset(node));
 }
 
-const u32 *dev_read_prop(struct udevice *dev, const char *propname, int *lenp)
+const void *dev_read_prop(struct udevice *dev, const char *propname, int *lenp)
 {
 	return ofnode_get_property(dev_ofnode(dev), propname, lenp);
 }
@@ -159,3 +159,8 @@
 		return fdtdec_get_is_enabled(gd->fdt_blob,
 					     ofnode_to_offset(node));
 }
+
+int dev_read_resource(struct udevice *dev, uint index, struct resource *res)
+{
+	return ofnode_read_resource(dev_ofnode(dev), index, res);
+}
diff --git a/drivers/core/read_extra.c b/drivers/core/read_extra.c
index a6d2f34..e94648f 100644
--- a/drivers/core/read_extra.c
+++ b/drivers/core/read_extra.c
@@ -11,27 +11,4 @@
 #include <dm/read.h>
 #include <linux/ioport.h>
 
-int dev_read_resource(struct udevice *dev, uint index, struct resource *res)
-{
-	ofnode node = dev_ofnode(dev);
-
-#ifdef CONFIG_OF_LIVE
-	if (ofnode_is_np(node)) {
-		return of_address_to_resource(ofnode_to_np(node), index, res);
-	} else
-#endif
-		{
-		struct fdt_resource fres;
-		int ret;
-
-		ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node),
-				       "reg", index, &fres);
-		if (ret < 0)
-			return -EINVAL;
-		memset(res, '\0', sizeof(*res));
-		res->start = fres.start;
-		res->end = fres.end;
-
-		return 0;
-	}
-}
+/* This file can hold non-inlined dev_read_...() functions */
diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c
index 687cd74..4965583 100644
--- a/drivers/gpio/tegra_gpio.c
+++ b/drivers/gpio/tegra_gpio.c
@@ -337,11 +337,13 @@
 	 * This driver does not make use of interrupts, other than to figure
 	 * out the number of GPIO banks
 	 */
-	if (!fdt_getprop(gd->fdt_blob, dev_of_offset(parent), "interrupts",
-			 &len))
-		return -EINVAL;
+	len = dev_read_size(parent, "interrupts");
+	if (len < 0)
+		return len;
 	bank_count = len / 3 / sizeof(u32);
-	ctlr = (struct gpio_ctlr *)devfdt_get_addr(parent);
+	ctlr = (struct gpio_ctlr *)dev_read_addr(parent);
+	if ((ulong)ctlr == FDT_ADDR_T_NONE)
+		return -EINVAL;
 	}
 #endif
 	for (bank = 0; bank < bank_count; bank++) {
diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c
index 055f481..3255e8e 100644
--- a/drivers/i2c/tegra_i2c.c
+++ b/drivers/i2c/tegra_i2c.c
@@ -9,7 +9,6 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
-#include <fdtdec.h>
 #include <i2c.h>
 #include <asm/io.h>
 #include <clk.h>
@@ -365,7 +364,11 @@
 
 	i2c_bus->id = dev->seq;
 	i2c_bus->type = dev_get_driver_data(dev);
-	i2c_bus->regs = (struct i2c_ctlr *)devfdt_get_addr(dev);
+	i2c_bus->regs = (struct i2c_ctlr *)dev_read_addr(dev);
+	if ((ulong)i2c_bus->regs == FDT_ADDR_T_NONE) {
+		debug("%s: Cannot get regs address\n", __func__);
+		return -EINVAL;
+	}
 
 	ret = reset_get_by_name(dev, "i2c", &i2c_bus->reset_ctl);
 	if (ret) {
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 7d945a1..7474529 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -11,10 +11,10 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
+#include <mmc.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch-tegra/tegra_mmc.h>
-#include <mmc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -599,8 +599,7 @@
 
 	cfg->name = dev->name;
 
-	bus_width = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-				   "bus-width", 1);
+	bus_width = dev_read_u32_default(dev, "bus-width", 1);
 
 	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 	cfg->host_caps = 0;
@@ -621,7 +620,7 @@
 
 	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
-	priv->reg = (void *)devfdt_get_addr(dev);
+	priv->reg = (void *)dev_read_addr(dev);
 
 	ret = reset_get_by_name(dev, "sdhci", &priv->reset_ctl);
 	if (ret) {
@@ -648,12 +647,10 @@
 		return ret;
 
 	/* These GPIOs are optional */
-	gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio,
-			     GPIOD_IS_IN);
-	gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio,
-			     GPIOD_IS_IN);
-	gpio_request_by_name(dev, "power-gpios", 0,
-			     &priv->pwr_gpio, GPIOD_IS_OUT);
+	gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN);
+	gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, GPIOD_IS_IN);
+	gpio_request_by_name(dev, "power-gpios", 0, &priv->pwr_gpio,
+			     GPIOD_IS_OUT);
 	if (dm_gpio_is_valid(&priv->pwr_gpio))
 		dm_gpio_set_value(&priv->pwr_gpio, 1);
 
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c
index 7d9c63b..cb5cf8b 100644
--- a/drivers/pci/pci_tegra.c
+++ b/drivers/pci/pci_tegra.c
@@ -16,7 +16,6 @@
 #include <clk.h>
 #include <dm.h>
 #include <errno.h>
-#include <fdtdec.h>
 #include <malloc.h>
 #include <pci.h>
 #include <power-domain.h>
@@ -25,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/gpio.h>
 
+#include <linux/ioport.h>
 #include <linux/list.h>
 
 #ifndef CONFIG_TEGRA186
@@ -220,9 +220,9 @@
 struct tegra_pcie {
 	struct pci_controller hose;
 
-	struct fdt_resource pads;
-	struct fdt_resource afi;
-	struct fdt_resource cs;
+	struct resource pads;
+	struct resource afi;
+	struct resource cs;
 
 	struct list_head ports;
 	unsigned long xbar;
@@ -364,13 +364,12 @@
 	return 0;
 }
 
-static int tegra_pcie_port_parse_dt(const void *fdt, int node,
-				    struct tegra_pcie_port *port)
+static int tegra_pcie_port_parse_dt(ofnode node, struct tegra_pcie_port *port)
 {
 	const u32 *addr;
 	int len;
 
-	addr = fdt_getprop(fdt, node, "assigned-addresses", &len);
+	addr = ofnode_get_property(node, "assigned-addresses", &len);
 	if (!addr) {
 		error("property \"assigned-addresses\" not found");
 		return -FDT_ERR_NOTFOUND;
@@ -382,7 +381,7 @@
 	return 0;
 }
 
-static int tegra_pcie_get_xbar_config(const void *fdt, int node, u32 lanes,
+static int tegra_pcie_get_xbar_config(ofnode node, u32 lanes,
 				      enum tegra_pci_id id, unsigned long *xbar)
 {
 	switch (id) {
@@ -456,14 +455,12 @@
 	return -FDT_ERR_NOTFOUND;
 }
 
-static int tegra_pcie_parse_port_info(const void *fdt, int node,
-				      unsigned int *index,
-				      unsigned int *lanes)
+static int tegra_pcie_parse_port_info(ofnode node, uint *index, uint *lanes)
 {
 	struct fdt_pci_addr addr;
 	int err;
 
-	err = fdtdec_get_int(fdt, node, "nvidia,num-lanes", 0);
+	err = ofnode_read_u32_default(node, "nvidia,num-lanes", -1);
 	if (err < 0) {
 		error("failed to parse \"nvidia,num-lanes\" property");
 		return err;
@@ -471,7 +468,7 @@
 
 	*lanes = err;
 
-	err = fdtdec_get_pci_addr(fdt, node, 0, "reg", &addr);
+	err = ofnode_read_pci_addr(node, 0, "reg", &addr);
 	if (err < 0) {
 		error("failed to parse \"reg\" property");
 		return err;
@@ -487,28 +484,26 @@
 	return 0;
 }
 
-static int tegra_pcie_parse_dt(const void *fdt, int node, enum tegra_pci_id id,
+static int tegra_pcie_parse_dt(struct udevice *dev, enum tegra_pci_id id,
 			       struct tegra_pcie *pcie)
 {
-	int err, subnode;
+	ofnode subnode;
 	u32 lanes = 0;
+	int err;
 
-	err = fdt_get_named_resource(fdt, node, "reg", "reg-names", "pads",
-				     &pcie->pads);
+	err = dev_read_resource(dev, 0, &pcie->pads);
 	if (err < 0) {
 		error("resource \"pads\" not found");
 		return err;
 	}
 
-	err = fdt_get_named_resource(fdt, node, "reg", "reg-names", "afi",
-				     &pcie->afi);
+	err = dev_read_resource(dev, 1, &pcie->afi);
 	if (err < 0) {
 		error("resource \"afi\" not found");
 		return err;
 	}
 
-	err = fdt_get_named_resource(fdt, node, "reg", "reg-names", "cs",
-				     &pcie->cs);
+	err = dev_read_resource(dev, 2, &pcie->cs);
 	if (err < 0) {
 		error("resource \"cs\" not found");
 		return err;
@@ -531,12 +526,11 @@
 	}
 #endif
 
-	fdt_for_each_subnode(subnode, fdt, node) {
+	dev_for_each_subnode(subnode, dev) {
 		unsigned int index = 0, num_lanes = 0;
 		struct tegra_pcie_port *port;
 
-		err = tegra_pcie_parse_port_info(fdt, subnode, &index,
-						 &num_lanes);
+		err = tegra_pcie_parse_port_info(subnode, &index, &num_lanes);
 		if (err < 0) {
 			error("failed to obtain root port info");
 			continue;
@@ -544,7 +538,7 @@
 
 		lanes |= num_lanes << (index << 3);
 
-		if (!fdtdec_get_is_enabled(fdt, subnode))
+		if (!ofnode_is_available(subnode))
 			continue;
 
 		port = malloc(sizeof(*port));
@@ -555,7 +549,7 @@
 		port->num_lanes = num_lanes;
 		port->index = index;
 
-		err = tegra_pcie_port_parse_dt(fdt, subnode, port);
+		err = tegra_pcie_port_parse_dt(subnode, port);
 		if (err < 0) {
 			free(port);
 			continue;
@@ -565,7 +559,8 @@
 		port->pcie = pcie;
 	}
 
-	err = tegra_pcie_get_xbar_config(fdt, node, lanes, id, &pcie->xbar);
+	err = tegra_pcie_get_xbar_config(dev_ofnode(dev), lanes, id,
+					 &pcie->xbar);
 	if (err < 0) {
 		error("invalid lane configuration");
 		return err;
@@ -815,7 +810,7 @@
 
 	/* BAR 0: type 1 extended configuration space */
 	fpci = 0xfe100000;
-	size = fdt_resource_size(&pcie->cs);
+	size = resource_size(&pcie->cs);
 	axi = pcie->cs.start;
 
 	afi_writel(pcie, axi, AFI_AXI_BAR0_START);
@@ -1099,7 +1094,7 @@
 
 	INIT_LIST_HEAD(&pcie->ports);
 
-	if (tegra_pcie_parse_dt(gd->fdt_blob, dev_of_offset(dev), id, pcie))
+	if (tegra_pcie_parse_dt(dev, id, pcie))
 		return -EINVAL;
 
 	return 0;
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index f488799..f7bdfa5 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -12,7 +12,7 @@
 obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
 obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
 obj-$(CONFIG_PMIC_ACT8846) += act8846.o
-obj-$(CONFIG_PMIC_AS3722) += as3722.o
+obj-$(CONFIG_PMIC_AS3722) += as3722.o as3722_gpio.o
 obj-$(CONFIG_PMIC_MAX8997) += max8997.o
 obj-$(CONFIG_PMIC_PM8916) += pm8916.o
 obj-$(CONFIG_PMIC_RK8XX) += rk8xx.o
diff --git a/drivers/power/pmic/as3722.c b/drivers/power/pmic/as3722.c
index c09e1de..4efe8ee 100644
--- a/drivers/power/pmic/as3722.c
+++ b/drivers/power/pmic/as3722.c
@@ -11,253 +11,99 @@
 #include <errno.h>
 #include <fdtdec.h>
 #include <i2c.h>
-
+#include <dm/lists.h>
 #include <power/as3722.h>
+#include <power/pmic.h>
 
-#define AS3722_SD_VOLTAGE(n) (0x00 + (n))
-#define AS3722_GPIO_CONTROL(n) (0x08 + (n))
-#define  AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH (1 << 0)
-#define  AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL (7 << 0)
-#define  AS3722_GPIO_CONTROL_INVERT (1 << 7)
-#define AS3722_LDO_VOLTAGE(n) (0x10 + (n))
-#define AS3722_GPIO_SIGNAL_OUT 0x20
-#define AS3722_SD_CONTROL 0x4d
-#define AS3722_LDO_CONTROL 0x4e
-#define AS3722_ASIC_ID1 0x90
-#define  AS3722_DEVICE_ID 0x0c
-#define AS3722_ASIC_ID2 0x91
+#define AS3722_NUM_OF_REGS	0x92
 
-int as3722_read(struct udevice *pmic, u8 reg, u8 *value)
+static int as3722_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
 {
-	int err;
+	int ret;
 
-	err = dm_i2c_read(pmic, reg, value, 1);
-	if (err < 0)
-		return err;
+	ret = dm_i2c_read(dev, reg, buff, len);
+	if (ret < 0)
+		return ret;
 
 	return 0;
 }
 
-int as3722_write(struct udevice *pmic, u8 reg, u8 value)
+static int as3722_write(struct udevice *dev, uint reg, const uint8_t *buff,
+			int len)
 {
-	int err;
+	int ret;
 
-	err = dm_i2c_write(pmic, reg, &value, 1);
-	if (err < 0)
-		return err;
+	ret = dm_i2c_write(dev, reg, buff, len);
+	if (ret < 0)
+		return ret;
 
 	return 0;
 }
 
-static int as3722_read_id(struct udevice *pmic, u8 *id, u8 *revision)
+static int as3722_read_id(struct udevice *dev, uint *idp, uint *revisionp)
 {
-	int err;
+	int ret;
 
-	err = as3722_read(pmic, AS3722_ASIC_ID1, id);
-	if (err) {
-		error("failed to read ID1 register: %d", err);
-		return err;
+	ret = pmic_reg_read(dev, AS3722_ASIC_ID1);
+	if (ret < 0) {
+		error("failed to read ID1 register: %d", ret);
+		return ret;
 	}
+	*idp = ret;
 
-	err = as3722_read(pmic, AS3722_ASIC_ID2, revision);
-	if (err) {
-		error("failed to read ID2 register: %d", err);
-		return err;
+	ret = pmic_reg_read(dev, AS3722_ASIC_ID2);
+	if (ret < 0) {
+		error("failed to read ID2 register: %d", ret);
+		return ret;
 	}
+	*revisionp = ret;
 
 	return 0;
 }
 
-int as3722_sd_enable(struct udevice *pmic, unsigned int sd)
+/* TODO(treding@nvidia.com): Add proper regulator support to avoid this */
+int as3722_sd_set_voltage(struct udevice *dev, unsigned int sd, u8 value)
 {
-	u8 value;
-	int err;
+	int ret;
 
 	if (sd > 6)
 		return -EINVAL;
 
-	err = as3722_read(pmic, AS3722_SD_CONTROL, &value);
-	if (err) {
-		error("failed to read SD control register: %d", err);
-		return err;
-	}
-
-	value |= 1 << sd;
-
-	err = as3722_write(pmic, AS3722_SD_CONTROL, value);
-	if (err < 0) {
-		error("failed to write SD control register: %d", err);
-		return err;
+	ret = pmic_reg_write(dev, AS3722_SD_VOLTAGE(sd), value);
+	if (ret < 0) {
+		error("failed to write SD%u voltage register: %d", sd, ret);
+		return ret;
 	}
 
 	return 0;
 }
 
-int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 value)
+int as3722_ldo_set_voltage(struct udevice *dev, unsigned int ldo, u8 value)
 {
-	int err;
-
-	if (sd > 6)
-		return -EINVAL;
-
-	err = as3722_write(pmic, AS3722_SD_VOLTAGE(sd), value);
-	if (err < 0) {
-		error("failed to write SD%u voltage register: %d", sd, err);
-		return err;
-	}
-
-	return 0;
-}
-
-int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo)
-{
-	u8 value;
-	int err;
+	int ret;
 
 	if (ldo > 11)
 		return -EINVAL;
 
-	err = as3722_read(pmic, AS3722_LDO_CONTROL, &value);
-	if (err) {
-		error("failed to read LDO control register: %d", err);
-		return err;
-	}
-
-	value |= 1 << ldo;
-
-	err = as3722_write(pmic, AS3722_LDO_CONTROL, value);
-	if (err < 0) {
-		error("failed to write LDO control register: %d", err);
-		return err;
-	}
-
-	return 0;
-}
-
-int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, u8 value)
-{
-	int err;
-
-	if (ldo > 11)
-		return -EINVAL;
-
-	err = as3722_write(pmic, AS3722_LDO_VOLTAGE(ldo), value);
-	if (err < 0) {
+	ret = pmic_reg_write(dev, AS3722_LDO_VOLTAGE(ldo), value);
+	if (ret < 0) {
 		error("failed to write LDO%u voltage register: %d", ldo,
-		      err);
-		return err;
+		      ret);
+		return ret;
 	}
 
 	return 0;
 }
 
-int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio,
-			  unsigned long flags)
+static int as3722_probe(struct udevice *dev)
 {
-	u8 value = 0;
-	int err;
+	uint id, revision;
+	int ret;
 
-	if (flags & AS3722_GPIO_OUTPUT_VDDH)
-		value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
-
-	if (flags & AS3722_GPIO_INVERT)
-		value |= AS3722_GPIO_CONTROL_INVERT;
-
-	err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
-	if (err) {
-		error("failed to configure GPIO#%u: %d", gpio, err);
-		return err;
-	}
-
-	return 0;
-}
-
-static int as3722_gpio_set(struct udevice *pmic, unsigned int gpio,
-			   unsigned int level)
-{
-	const char *l;
-	u8 value;
-	int err;
-
-	if (gpio > 7)
-		return -EINVAL;
-
-	err = as3722_read(pmic, AS3722_GPIO_SIGNAL_OUT, &value);
-	if (err < 0) {
-		error("failed to read GPIO signal out register: %d", err);
-		return err;
-	}
-
-	if (level == 0) {
-		value &= ~(1 << gpio);
-		l = "low";
-	} else {
-		value |= 1 << gpio;
-		l = "high";
-	}
-
-	err = as3722_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
-	if (err) {
-		error("failed to set GPIO#%u %s: %d", gpio, l, err);
-		return err;
-	}
-
-	return 0;
-}
-
-int as3722_gpio_direction_output(struct udevice *pmic, unsigned int gpio,
-				 unsigned int level)
-{
-	u8 value;
-	int err;
-
-	if (gpio > 7)
-		return -EINVAL;
-
-	if (level == 0)
-		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
-	else
-		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
-
-	err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
-	if (err) {
-		error("failed to configure GPIO#%u as output: %d", gpio, err);
-		return err;
-	}
-
-	err = as3722_gpio_set(pmic, gpio, level);
-	if (err < 0) {
-		error("failed to set GPIO#%u high: %d", gpio, err);
-		return err;
-	}
-
-	return 0;
-}
-
-/* Temporary function until we get the pmic framework */
-int as3722_get(struct udevice **devp)
-{
-	int bus = 0;
-	int address = 0x40;
-
-	return i2c_get_chip_for_busnum(bus, address, 1, devp);
-}
-
-int as3722_init(struct udevice **devp)
-{
-	struct udevice *pmic;
-	u8 id, revision;
-	const unsigned int bus = 0;
-	const unsigned int address = 0x40;
-	int err;
-
-	err = i2c_get_chip_for_busnum(bus, address, 1, &pmic);
-	if (err)
-		return err;
-	err = as3722_read_id(pmic, &id, &revision);
-	if (err < 0) {
-		error("failed to read ID: %d", err);
-		return err;
+	ret = as3722_read_id(dev, &id, &revision);
+	if (ret < 0) {
+		error("failed to read ID: %d", ret);
+		return ret;
 	}
 
 	if (id != AS3722_DEVICE_ID) {
@@ -265,10 +111,68 @@
 		return -ENOENT;
 	}
 
-	debug("AS3722 revision %#x found on I2C bus %u, address %#x\n",
-	      revision, bus, address);
-	if (devp)
-		*devp = pmic;
+	debug("AS3722 revision %#x found on I2C bus %s\n", revision, dev->name);
 
 	return 0;
 }
+
+#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
+static const struct pmic_child_info pmic_children_info[] = {
+	{ .prefix = "sd", .driver = "as3722_stepdown"},
+	{ .prefix = "ldo", .driver = "as3722_ldo"},
+	{ },
+};
+
+static int as3722_bind(struct udevice *dev)
+{
+	struct udevice *gpio_dev;
+	ofnode regulators_node;
+	int children;
+	int ret;
+
+	regulators_node = dev_read_subnode(dev, "regulators");
+	if (!ofnode_valid(regulators_node)) {
+		debug("%s: %s regulators subnode not found\n", __func__,
+		      dev->name);
+		return -ENXIO;
+	}
+
+	children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+	if (!children)
+		debug("%s: %s - no child found\n", __func__, dev->name);
+	ret = device_bind_driver(dev, "gpio_as3722", "gpio_as3722", &gpio_dev);
+	if (ret) {
+		debug("%s: Cannot bind GPIOs (ret=%d)\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+#endif
+
+static int as3722_reg_count(struct udevice *dev)
+{
+	return AS3722_NUM_OF_REGS;
+}
+
+static struct dm_pmic_ops as3722_ops = {
+	.reg_count = as3722_reg_count,
+	.read = as3722_read,
+	.write = as3722_write,
+};
+
+static const struct udevice_id as3722_ids[] = {
+	{ .compatible = "ams,as3722" },
+	{ }
+};
+
+U_BOOT_DRIVER(pmic_as3722) = {
+	.name = "as3722_pmic",
+	.id = UCLASS_PMIC,
+	.of_match = as3722_ids,
+#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
+	.bind = as3722_bind,
+#endif
+	.probe = as3722_probe,
+	.ops = &as3722_ops,
+};
diff --git a/drivers/power/pmic/as3722_gpio.c b/drivers/power/pmic/as3722_gpio.c
new file mode 100644
index 0000000..d0b681c
--- /dev/null
+++ b/drivers/power/pmic/as3722_gpio.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <power/as3722.h>
+#include <power/pmic.h>
+
+#define NUM_GPIOS	8
+
+int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio,
+			  unsigned long flags)
+{
+	u8 value = 0;
+	int err;
+
+	if (flags & AS3722_GPIO_OUTPUT_VDDH)
+		value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+
+	if (flags & AS3722_GPIO_INVERT)
+		value |= AS3722_GPIO_CONTROL_INVERT;
+
+	err = pmic_reg_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
+	if (err) {
+		error("failed to configure GPIO#%u: %d", gpio, err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int as3722_gpio_set_value(struct udevice *dev, unsigned int gpio,
+				 int level)
+{
+	struct udevice *pmic = dev_get_parent(dev);
+	const char *l;
+	u8 value;
+	int err;
+
+	if (gpio >= NUM_GPIOS)
+		return -EINVAL;
+
+	err = pmic_reg_read(pmic, AS3722_GPIO_SIGNAL_OUT);
+	if (err < 0) {
+		error("failed to read GPIO signal out register: %d", err);
+		return err;
+	}
+	value = err;
+
+	if (level == 0) {
+		value &= ~(1 << gpio);
+		l = "low";
+	} else {
+		value |= 1 << gpio;
+		l = "high";
+	}
+
+	err = pmic_reg_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
+	if (err) {
+		error("failed to set GPIO#%u %s: %d", gpio, l, err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_gpio_direction_output(struct udevice *dev, unsigned int gpio,
+				 int value)
+{
+	struct udevice *pmic = dev_get_parent(dev);
+	int err;
+
+	if (gpio > 7)
+		return -EINVAL;
+
+	if (value == 0)
+		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
+	else
+		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+
+	err = pmic_reg_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
+	if (err) {
+		error("failed to configure GPIO#%u as output: %d", gpio, err);
+		return err;
+	}
+
+	err = as3722_gpio_set_value(pmic, gpio, value);
+	if (err < 0) {
+		error("failed to set GPIO#%u high: %d", gpio, err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int as3722_gpio_probe(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	uc_priv->gpio_count = NUM_GPIOS;
+	uc_priv->bank_name = "as3722_";
+
+	return 0;
+}
+
+static const struct dm_gpio_ops gpio_as3722_ops = {
+	.direction_output	= as3722_gpio_direction_output,
+	.set_value		= as3722_gpio_set_value,
+};
+
+U_BOOT_DRIVER(gpio_as3722) = {
+	.name	= "gpio_as3722",
+	.id	= UCLASS_GPIO,
+	.ops	= &gpio_as3722_ops,
+	.probe	= as3722_gpio_probe,
+};
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index f213487..c82a936 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -34,6 +34,15 @@
 	by the PMIC device. This driver is controlled by a device tree node
 	which includes voltage limits.
 
+config REGULATOR_AS3722
+	bool "Enable driver for AS7322 regulator"
+	depends on DM_REGULATOR && PMIC_AS3722
+	help
+	  Enable support for the regulator functions of the AS3722. The
+	  driver implements enable/disable for step-down bucks and LDOs,
+	  but does not yet support change voltages. Currently this must be
+	  done using direct register writes to the PMIC.
+
 config DM_REGULATOR_PFUZE100
 	bool "Enable Driver Model for REGULATOR PFUZE100"
 	depends on DM_REGULATOR && DM_PMIC_PFUZE100
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index ce14d08..18fb870 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -7,6 +7,7 @@
 
 obj-$(CONFIG_$(SPL_)DM_REGULATOR) += regulator-uclass.o
 obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o
+obj-$(CONFIG_REGULATOR_AS3722)	+= as3722_regulator.o
 obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
 obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o
 obj-$(CONFIG_REGULATOR_PWM) += pwm_regulator.o
diff --git a/drivers/power/regulator/as3722_regulator.c b/drivers/power/regulator/as3722_regulator.c
new file mode 100644
index 0000000..3e1e6f1
--- /dev/null
+++ b/drivers/power/regulator/as3722_regulator.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * Placeholder regulator driver for as3722.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <power/as3722.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+
+static int stepdown_get_value(struct udevice *dev)
+{
+	return -ENOSYS;
+}
+
+static int stepdown_set_value(struct udevice *dev, int uvolt)
+{
+	return -ENOSYS;
+}
+
+static int stepdown_set_enable(struct udevice *dev, bool enable)
+{
+	struct udevice *pmic = dev_get_parent(dev);
+	int sd = dev->driver_data;
+	int ret;
+
+	ret = pmic_clrsetbits(pmic, AS3722_SD_CONTROL, 0, 1 << sd);
+	if (ret < 0) {
+		debug("%s: failed to write SD control register: %d", __func__,
+		      ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int stepdown_get_enable(struct udevice *dev)
+{
+	struct udevice *pmic = dev_get_parent(dev);
+	int sd = dev->driver_data;
+	int ret;
+
+	ret = pmic_reg_read(pmic, AS3722_SD_CONTROL);
+	if (ret < 0) {
+		debug("%s: failed to read SD control register: %d", __func__,
+		      ret);
+		return ret;
+	}
+
+	return ret & (1 << sd) ? true : false;
+}
+
+static int ldo_get_value(struct udevice *dev)
+{
+	return -ENOSYS;
+}
+
+static int ldo_set_value(struct udevice *dev, int uvolt)
+{
+	return -ENOSYS;
+}
+
+static int ldo_set_enable(struct udevice *dev, bool enable)
+{
+	struct udevice *pmic = dev_get_parent(dev);
+	int ldo = dev->driver_data;
+	int ret;
+
+	ret = pmic_clrsetbits(pmic, AS3722_LDO_CONTROL, 0, 1 << ldo);
+	if (ret < 0) {
+		debug("%s: failed to write LDO control register: %d", __func__,
+		      ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ldo_get_enable(struct udevice *dev)
+{
+	struct udevice *pmic = dev_get_parent(dev);
+	int ldo = dev->driver_data;
+	int ret;
+
+	ret = pmic_reg_read(pmic, AS3722_LDO_CONTROL);
+	if (ret < 0) {
+		debug("%s: failed to read SD control register: %d", __func__,
+		      ret);
+		return ret;
+	}
+
+	return ret & (1 << ldo) ? true : false;
+}
+
+static int as3722_stepdown_probe(struct udevice *dev)
+{
+	struct dm_regulator_uclass_platdata *uc_pdata;
+
+	uc_pdata = dev_get_uclass_platdata(dev);
+
+	uc_pdata->type = REGULATOR_TYPE_BUCK;
+
+	return 0;
+}
+
+static int as3722_ldo_probe(struct udevice *dev)
+{
+	struct dm_regulator_uclass_platdata *uc_pdata;
+
+	uc_pdata = dev_get_uclass_platdata(dev);
+
+	uc_pdata->type = REGULATOR_TYPE_LDO;
+
+	return 0;
+}
+
+static const struct dm_regulator_ops as3722_stepdown_ops = {
+	.get_value  = stepdown_get_value,
+	.set_value  = stepdown_set_value,
+	.get_enable = stepdown_get_enable,
+	.set_enable = stepdown_set_enable,
+};
+
+static const struct dm_regulator_ops as3722_ldo_ops = {
+	.get_value  = ldo_get_value,
+	.set_value  = ldo_set_value,
+	.get_enable = ldo_get_enable,
+	.set_enable = ldo_set_enable,
+};
+
+U_BOOT_DRIVER(as3722_stepdown) = {
+	.name = "as3722_stepdown",
+	.id = UCLASS_REGULATOR,
+	.ops = &as3722_stepdown_ops,
+	.probe = as3722_stepdown_probe,
+};
+
+U_BOOT_DRIVER(as3722_ldo) = {
+	.name = "as3722_ldo",
+	.id = UCLASS_REGULATOR,
+	.ops = &as3722_ldo_ops,
+	.probe = as3722_ldo_probe,
+};
diff --git a/drivers/pwm/tegra_pwm.c b/drivers/pwm/tegra_pwm.c
index d93ac28..b8acc15 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 *)devfdt_get_addr(dev);
+	priv->regs = (struct pwm_ctlr *)dev_read_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/spi/tegra114_spi.c b/drivers/spi/tegra114_spi.c
index 9165934..04b4fce 100644
--- a/drivers/spi/tegra114_spi.c
+++ b/drivers/spi/tegra114_spi.c
@@ -12,7 +12,6 @@
 #include <asm/arch/clock.h>
 #include <asm/arch-tegra/clk_rst.h>
 #include <spi.h>
-#include <fdtdec.h>
 #include "tegra_spi.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -100,11 +99,9 @@
 static int tegra114_spi_ofdata_to_platdata(struct udevice *bus)
 {
 	struct tegra_spi_platdata *plat = bus->platdata;
-	const void *blob = gd->fdt_blob;
-	int node = dev_of_offset(bus);
 
-	plat->base = devfdt_get_addr(bus);
-	plat->periph_id = clock_decode_periph_id(blob, node);
+	plat->base = dev_read_addr(bus);
+	plat->periph_id = clock_decode_periph_id(bus);
 
 	if (plat->periph_id == PERIPH_ID_NONE) {
 		debug("%s: could not decode periph id %d\n", __func__,
@@ -113,10 +110,10 @@
 	}
 
 	/* Use 500KHz as a suitable default */
-	plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
-					500000);
-	plat->deactivate_delay_us = fdtdec_get_int(blob, node,
-					"spi-deactivate-delay", 0);
+	plat->frequency = dev_read_u32_default(bus, "spi-max-frequency",
+					       500000);
+	plat->deactivate_delay_us = dev_read_u32_default(bus,
+						"spi-deactivate-delay", 0);
 	debug("%s: base=%#08lx, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n",
 	      __func__, plat->base, plat->periph_id, plat->frequency,
 	      plat->deactivate_delay_us);
diff --git a/drivers/spi/tegra20_sflash.c b/drivers/spi/tegra20_sflash.c
index 299e1b4..e70210d 100644
--- a/drivers/spi/tegra20_sflash.c
+++ b/drivers/spi/tegra20_sflash.c
@@ -91,7 +91,7 @@
 	int node = dev_of_offset(bus);
 
 	plat->base = devfdt_get_addr(bus);
-	plat->periph_id = clock_decode_periph_id(blob, node);
+	plat->periph_id = clock_decode_periph_id(bus);
 
 	if (plat->periph_id == PERIPH_ID_NONE) {
 		debug("%s: could not decode periph id %d\n", __func__,
diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c
index 4cbde7b..f242574 100644
--- a/drivers/spi/tegra20_slink.c
+++ b/drivers/spi/tegra20_slink.c
@@ -97,7 +97,7 @@
 	int node = dev_of_offset(bus);
 
 	plat->base = devfdt_get_addr(bus);
-	plat->periph_id = clock_decode_periph_id(blob, node);
+	plat->periph_id = clock_decode_periph_id(bus);
 
 	if (plat->periph_id == PERIPH_ID_NONE) {
 		debug("%s: could not decode periph id %d\n", __func__,
diff --git a/drivers/spi/tegra210_qspi.c b/drivers/spi/tegra210_qspi.c
index 6d0b5da..2a35a58 100644
--- a/drivers/spi/tegra210_qspi.c
+++ b/drivers/spi/tegra210_qspi.c
@@ -100,7 +100,7 @@
 	int node = dev_of_offset(bus);
 
 	plat->base = devfdt_get_addr(bus);
-	plat->periph_id = clock_decode_periph_id(blob, node);
+	plat->periph_id = clock_decode_periph_id(bus);
 
 	if (plat->periph_id == PERIPH_ID_NONE) {
 		debug("%s: could not decode periph id %d\n", __func__,
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 7dc37f0..1c72330 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -17,7 +17,6 @@
 #include <usb.h>
 #include <usb/ulpi.h>
 #include <libfdt.h>
-#include <fdtdec.h>
 
 #include "ehci.h"
 
@@ -695,12 +694,11 @@
 
 static int fdt_decode_usb(struct udevice *dev, struct fdt_usb *config)
 {
-	const void *blob = gd->fdt_blob;
-	int node = dev_of_offset(dev);
 	const char *phy, *mode;
 
-	config->reg = (struct usb_ctlr *)devfdt_get_addr(dev);
-	mode = fdt_getprop(blob, node, "dr_mode", NULL);
+	config->reg = (struct usb_ctlr *)dev_read_addr(dev);
+	debug("reg=%p\n", config->reg);
+	mode = dev_read_string(dev, "dr_mode");
 	if (mode) {
 		if (0 == strcmp(mode, "host"))
 			config->dr_mode = DR_MODE_HOST;
@@ -717,28 +715,24 @@
 		config->dr_mode = DR_MODE_HOST;
 	}
 
-	phy = fdt_getprop(blob, node, "phy_type", NULL);
+	phy = dev_read_string(dev, "phy_type");
 	config->utmi = phy && 0 == strcmp("utmi", phy);
 	config->ulpi = phy && 0 == strcmp("ulpi", phy);
-	config->enabled = fdtdec_get_is_enabled(blob, node);
-	config->has_legacy_mode = fdtdec_get_bool(blob, node,
-						  "nvidia,has-legacy-mode");
-	config->periph_id = clock_decode_periph_id(blob, node);
+	config->has_legacy_mode = dev_read_bool(dev, "nvidia,has-legacy-mode");
+	config->periph_id = clock_decode_periph_id(dev);
 	if (config->periph_id == PERIPH_ID_NONE) {
 		debug("%s: Missing/invalid peripheral ID\n", __func__);
 		return -EINVAL;
 	}
-	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",
-		config->enabled, config->has_legacy_mode, config->utmi,
-		config->ulpi, config->periph_id,
-		gpio_get_number(&config->vbus_gpio),
-		gpio_get_number(&config->phy_reset_gpio), config->dr_mode);
+	gpio_request_by_name(dev, "nvidia,vbus-gpio", 0, &config->vbus_gpio,
+			     GPIOD_IS_OUT);
+	gpio_request_by_name(dev, "nvidia,phy-reset-gpio", 0,
+			     &config->phy_reset_gpio, GPIOD_IS_OUT);
+	debug("legacy_mode=%d, utmi=%d, ulpi=%d, periph_id=%d, vbus=%d, phy_reset=%d, dr_mode=%d, reg=%p\n",
+	      config->has_legacy_mode, config->utmi, config->ulpi,
+	      config->periph_id, gpio_get_number(&config->vbus_gpio),
+	      gpio_get_number(&config->phy_reset_gpio), config->dr_mode,
+	      config->reg);
 
 	return 0;
 }
diff --git a/drivers/video/tegra124/display.c b/drivers/video/tegra124/display.c
index 47752b2..4164fa1 100644
--- a/drivers/video/tegra124/display.c
+++ b/drivers/video/tegra124/display.c
@@ -12,7 +12,6 @@
 #include <errno.h>
 #include <display.h>
 #include <edid.h>
-#include <fdtdec.h>
 #include <lcd.h>
 #include <video.h>
 #include <asm/gpio.h>
@@ -334,7 +333,6 @@
 {
 	struct display_plat *disp_uc_plat;
 	struct dc_ctlr *dc_ctlr;
-	const void *blob = gd->fdt_blob;
 	struct udevice *dp_dev;
 	const int href_to_sync = 1, vref_to_sync = 1;
 	int panel_bpp = 18;	/* default 18 bits per pixel */
@@ -363,9 +361,8 @@
 		return ret;
 	}
 
-	dc_ctlr = (struct dc_ctlr *)fdtdec_get_addr(blob, dev_of_offset(dev),
-						    "reg");
-	if (fdtdec_decode_display_timing(blob, dev_of_offset(dev), 0, timing)) {
+	dc_ctlr = (struct dc_ctlr *)dev_read_addr(dev);
+	if (ofnode_decode_display_timing(dev_ofnode(dev), 0, timing)) {
 		debug("%s: Failed to decode display timing\n", __func__);
 		return -EINVAL;
 	}
@@ -416,6 +413,7 @@
 		debug("dc: failed to update window\n");
 		return ret;
 	}
+	debug("%s: ready\n", __func__);
 
 	return 0;
 }
diff --git a/drivers/video/tegra124/dp.c b/drivers/video/tegra124/dp.c
index c38b3e5..95d743d 100644
--- a/drivers/video/tegra124/dp.c
+++ b/drivers/video/tegra124/dp.c
@@ -10,7 +10,6 @@
 #include <dm.h>
 #include <div64.h>
 #include <errno.h>
-#include <fdtdec.h>
 #include <video_bridge.h>
 #include <asm/io.h>
 #include <asm/arch-tegra/dc.h>
@@ -1572,7 +1571,7 @@
 {
 	struct tegra_dp_plat *plat = dev_get_platdata(dev);
 
-	plat->base = devfdt_get_addr(dev);
+	plat->base = dev_read_addr(dev);
 
 	return 0;
 }
diff --git a/drivers/video/tegra124/sor.c b/drivers/video/tegra124/sor.c
index 4324071..700ab25 100644
--- a/drivers/video/tegra124/sor.c
+++ b/drivers/video/tegra124/sor.c
@@ -7,9 +7,9 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
-#include <fdtdec.h>
 #include <malloc.h>
 #include <panel.h>
+#include <syscon.h>
 #include <video_bridge.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
@@ -759,15 +759,12 @@
 			const struct display_timing *timing)
 {
 	struct tegra_dc_sor_data *sor = dev_get_priv(dev);
-	const void *blob = gd->fdt_blob;
 	struct dc_ctlr *disp_ctrl;
 	u32 reg_val;
-	int node;
 
 	/* Use the first display controller */
 	debug("%s\n", __func__);
-	node = dev_of_offset(dc_dev);
-	disp_ctrl = (struct dc_ctlr *)fdtdec_get_addr(blob, node, "reg");
+	disp_ctrl = (struct dc_ctlr *)dev_read_addr(dc_dev);
 
 	tegra_dc_sor_enable_dc(disp_ctrl);
 	tegra_dc_sor_config_panel(sor, 0, link_cfg, timing);
@@ -974,16 +971,13 @@
 {
 	struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 	int dc_reg_ctx[DC_REG_SAVE_SPACE];
-	const void *blob = gd->fdt_blob;
 	struct dc_ctlr *disp_ctrl;
 	unsigned long dc_int_mask;
-	int node;
 	int ret;
 
 	debug("%s\n", __func__);
 	/* Use the first display controller */
-	node = dev_of_offset(dc_dev);
-	disp_ctrl = (struct dc_ctlr *)fdtdec_get_addr(blob, node, "reg");
+	disp_ctrl = (struct dc_ctlr *)dev_read_addr(dev);
 
 	/* Sleep mode */
 	tegra_sor_writel(sor, SUPER_STATE1, SUPER_STATE1_ASY_HEAD_OP_SLEEP |
@@ -1050,18 +1044,13 @@
 static int tegra_sor_ofdata_to_platdata(struct udevice *dev)
 {
 	struct tegra_dc_sor_data *priv = dev_get_priv(dev);
-	const void *blob = gd->fdt_blob;
-	int node;
 	int ret;
 
-	priv->base = (void *)fdtdec_get_addr(blob, dev_of_offset(dev), "reg");
+	priv->base = (void *)dev_read_addr(dev);
 
-	node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_PMC);
-	if (node < 0) {
-		debug("%s: Cannot find PMC\n", __func__);
-		return -ENOENT;
-	}
-	priv->pmc_base = (void *)fdtdec_get_addr(blob, node, "reg");
+	priv->pmc_base = (void *)syscon_get_first_range(TEGRA_SYSCON_PMC);
+	if (IS_ERR(priv->pmc_base))
+		return PTR_ERR(priv->pmc_base);
 
 	ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, "nvidia,panel",
 					   &priv->panel);
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 8eecce5..210ddb2 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -15,6 +15,8 @@
 /* Enable checks to protect against invalid calls */
 #undef OF_CHECKS
 
+struct resource;
+
 /**
  * ofnode - reference to a device tree node
  *
@@ -622,4 +624,6 @@
  */
 bool ofnode_pre_reloc(ofnode node);
 
+int ofnode_read_resource(ofnode node, uint index, struct resource *res);
+
 #endif
diff --git a/include/dm/read.h b/include/dm/read.h
index d09b04d..c3a4a56 100644
--- a/include/dm/read.h
+++ b/include/dm/read.h
@@ -44,16 +44,6 @@
 	return ofnode_valid(dev_ofnode(dev));
 }
 
-/**
- * dev_read_resource() - obtain an indexed resource from a device.
- *
- * @dev: devuce to examine
- * @index index of the resource to retrieve (0 = first)
- * @res returns the resource
- * @return 0 if ok, negative on error
- */
-int dev_read_resource(struct udevice *dev, uint index, struct resource *res);
-
 #ifndef CONFIG_DM_DEV_READ_INLINE
 /**
  * dev_read_u32_default() - read a 32-bit integer from a device's DT property
@@ -284,7 +274,7 @@
  * @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);
+const void *dev_read_prop(struct udevice *dev, const char *propname, int *lenp);
 
 /**
  * dev_read_alias_seq() - Get the alias sequence number of a node
@@ -366,6 +356,16 @@
  */
 int dev_read_enabled(struct udevice *dev);
 
+/**
+ * dev_read_resource() - obtain an indexed resource from a device.
+ *
+ * @dev: devuce to examine
+ * @index index of the resource to retrieve (0 = first)
+ * @res returns the resource
+ * @return 0 if ok, negative on error
+ */
+int dev_read_resource(struct udevice *dev, uint index, struct resource *res);
+
 #else /* CONFIG_DM_DEV_READ_INLINE is enabled */
 
 static inline int dev_read_u32_default(struct udevice *dev,
@@ -468,8 +468,8 @@
 	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)
+static inline const void *dev_read_prop(struct udevice *dev,
+					const char *propname, int *lenp)
 {
 	return ofnode_get_property(dev_ofnode(dev), propname, lenp);
 }
@@ -507,6 +507,12 @@
 	return fdtdec_get_is_enabled(gd->fdt_blob, dev_of_offset(dev));
 }
 
+static inline int dev_read_resource(struct udevice *dev, uint index,
+				    struct resource *res)
+{
+	return ofnode_read_resource(dev_ofnode(dev), index, res);
+}
+
 #endif /* CONFIG_DM_DEV_READ_INLINE */
 
 /**
diff --git a/include/dt-structs.h b/include/dt-structs.h
index e13afa6..0732c44 100644
--- a/include/dt-structs.h
+++ b/include/dt-structs.h
@@ -4,8 +4,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#ifndef __DT_STTUCTS
-#define __DT_STTUCTS
+#ifndef __DT_STRUCTS
+#define __DT_STRUCTS
 
 /* These structures may only be used in SPL */
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
diff --git a/include/fdtdec.h b/include/fdtdec.h
index eda2ffa..4a0947c 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -119,12 +119,6 @@
 	COMPAT_NVIDIA_TEGRA20_EMC,	/* Tegra20 memory controller */
 	COMPAT_NVIDIA_TEGRA20_EMC_TABLE, /* Tegra20 memory timing table */
 	COMPAT_NVIDIA_TEGRA20_NAND,	/* Tegra2 NAND controller */
-	COMPAT_NVIDIA_TEGRA124_PMC,	/* Tegra 124 power mgmt controller */
-	COMPAT_NVIDIA_TEGRA186_SDMMC,	/* Tegra186 SDMMC controller */
-	COMPAT_NVIDIA_TEGRA210_SDMMC,	/* Tegra210 SDMMC controller */
-	COMPAT_NVIDIA_TEGRA124_SDMMC,	/* Tegra124 SDMMC controller */
-	COMPAT_NVIDIA_TEGRA30_SDMMC,	/* Tegra30 SDMMC controller */
-	COMPAT_NVIDIA_TEGRA20_SDMMC,	/* Tegra20 SDMMC controller */
 	COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
 					/* Tegra124 XUSB pad controller */
 	COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL,
diff --git a/include/os.h b/include/os.h
index 049b248..2bf4bdb 100644
--- a/include/os.h
+++ b/include/os.h
@@ -241,26 +241,6 @@
 int os_get_filesize(const char *fname, loff_t *size);
 
 /**
- * Write a character to the controlling OS terminal
- *
- * This bypasses the U-Boot console support and writes directly to the OS
- * stdout file descriptor.
- *
- * @param ch	Character to write
- */
-void os_putc(int ch);
-
-/**
- * Write a string to the controlling OS terminal
- *
- * This bypasses the U-Boot console support and writes directly to the OS
- * stdout file descriptor.
- *
- * @param str	String to write (note that \n is not appended)
- */
-void os_puts(const char *str);
-
-/**
  * Write the sandbox RAM buffer to a existing file
  *
  * @param fname		Filename to write memory to (simple binary format)
diff --git a/include/power/as3722.h b/include/power/as3722.h
index 0f22482..cb4b188 100644
--- a/include/power/as3722.h
+++ b/include/power/as3722.h
@@ -7,24 +7,23 @@
 #ifndef __POWER_AS3722_H__
 #define __POWER_AS3722_H__
 
-#include <asm/types.h>
-
 #define AS3722_GPIO_OUTPUT_VDDH (1 << 0)
 #define AS3722_GPIO_INVERT (1 << 1)
 
-struct udevice;
+#define AS3722_DEVICE_ID 0x0c
+#define AS3722_SD_VOLTAGE(n) (0x00 + (n))
+#define AS3722_LDO_VOLTAGE(n) (0x10 + (n))
+#define AS3722_SD_CONTROL 0x4d
+#define AS3722_LDO_CONTROL 0x4e
+#define AS3722_ASIC_ID1 0x90
+#define AS3722_ASIC_ID2 0x91
 
-int as3722_init(struct udevice **devp);
-int as3722_sd_enable(struct udevice *pmic, unsigned int sd);
-int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 value);
-int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo);
-int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, u8 value);
-int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio,
-			  unsigned long flags);
-int as3722_gpio_direction_output(struct udevice *pmic, unsigned int gpio,
-				 unsigned int level);
-int as3722_read(struct udevice *pmic, u8 reg, u8 *value);
-int as3722_write(struct udevice *pmic, u8 reg, u8 value);
-int as3722_get(struct udevice **devp);
+#define AS3722_GPIO_CONTROL(n) (0x08 + (n))
+#define AS3722_GPIO_SIGNAL_OUT 0x20
+#define AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH (1 << 0)
+#define AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL (7 << 0)
+#define AS3722_GPIO_CONTROL_INVERT (1 << 7)
+
+int as3722_sd_set_voltage(struct udevice *dev, unsigned int sd, u8 value);
 
 #endif /* __POWER_AS3722_H__ */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index fbb48bf..d2dbd0f 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -34,12 +34,6 @@
 	COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"),
 	COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"),
 	COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),
-	COMPAT(NVIDIA_TEGRA124_PMC, "nvidia,tegra124-pmc"),
-	COMPAT(NVIDIA_TEGRA186_SDMMC, "nvidia,tegra186-sdhci"),
-	COMPAT(NVIDIA_TEGRA210_SDMMC, "nvidia,tegra210-sdhci"),
-	COMPAT(NVIDIA_TEGRA124_SDMMC, "nvidia,tegra124-sdhci"),
-	COMPAT(NVIDIA_TEGRA30_SDMMC, "nvidia,tegra30-sdhci"),
-	COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"),
 	COMPAT(NVIDIA_TEGRA124_XUSB_PADCTL, "nvidia,tegra124-xusb-padctl"),
 	COMPAT(NVIDIA_TEGRA210_XUSB_PADCTL, "nvidia,tegra210-xusb-padctl"),
 	COMPAT(SMSC_LAN9215, "smsc,lan9215"),