Merge tag 'for-master-20181210' of git://git.denx.de/u-boot-rockchip

Improvements:
- init DRAM for RK322x in SPL
- add FAN53555 PMIC/regulator driver
- update MicroCrystal RV3029 driver to Kconfig and sync from Linux
- add bootcount uclass and first DM-driver for bootcount
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 13ba774..cb7ec58 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -817,15 +817,11 @@
 	select SPL_DM_RESET if DM_RESET
 	select SPL_DM_SERIAL
 	select SPL_LIBCOMMON_SUPPORT
-	select SPL_LIBDISK_SUPPORT
 	select SPL_LIBGENERIC_SUPPORT
-	select SPL_MMC_SUPPORT if DM_MMC
 	select SPL_NAND_SUPPORT if SPL_NAND_DENALI
 	select SPL_OF_CONTROL
 	select SPL_SEPARATE_BSS if TARGET_SOCFPGA_STRATIX10
 	select SPL_SERIAL_SUPPORT
-	select SPL_SPI_FLASH_SUPPORT if SPL_SPI_SUPPORT
-	select SPL_SPI_SUPPORT if DM_SPI
 	select SPL_WATCHDOG_SUPPORT
 	select SUPPORT_SPL
 	select SYS_NS16550
@@ -836,8 +832,12 @@
 	imply DM_SPI
 	imply DM_SPI_FLASH
 	imply FAT_WRITE
+	imply SPL_LIBDISK_SUPPORT
+	imply SPL_MMC_SUPPORT
 	imply SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
 	imply SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE
+	imply SPL_SPI_FLASH_SUPPORT
+	imply SPL_SPI_SUPPORT
 
 config ARCH_SUNXI
 	bool "Support sunxi (Allwinner) SoCs"
@@ -932,6 +932,7 @@
 	select DM_SERIAL
 	select OF_CONTROL
 	imply CMD_DM
+	imply DM_USB_GADGET
 
 config ARCH_ZYNQMP
 	bool "Xilinx ZynqMP based platform"
@@ -949,6 +950,7 @@
 	imply CMD_DM
 	imply FAT_WRITE
 	imply MP
+	imply DM_USB_GADGET
 
 config TEGRA
 	bool "NVIDIA Tegra"
diff --git a/arch/arm/dts/am437x-gp-evm-u-boot.dtsi b/arch/arm/dts/am437x-gp-evm-u-boot.dtsi
index 530f549..03a1c1d 100644
--- a/arch/arm/dts/am437x-gp-evm-u-boot.dtsi
+++ b/arch/arm/dts/am437x-gp-evm-u-boot.dtsi
@@ -36,3 +36,7 @@
 &phy_sel {
 	u-boot,dm-spl;
 };
+
+&i2c0 {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/omap5-u-boot.dtsi b/arch/arm/dts/omap5-u-boot.dtsi
index bf2684c..1eb50cd 100644
--- a/arch/arm/dts/omap5-u-boot.dtsi
+++ b/arch/arm/dts/omap5-u-boot.dtsi
@@ -15,6 +15,10 @@
 	ocp {
 		u-boot,dm-spl;
 
+		ocp2scp@4a080000 {
+			compatible = "ti,omap-ocp2scp", "simple-bus";
+		};
+
 		ocp2scp@4a090000 {
 			compatible = "ti,omap-ocp2scp", "simple-bus";
 		};
@@ -91,3 +95,7 @@
 &gpio7 {
 	u-boot,dm-spl;
 };
+
+&i2c1 {
+	u-boot,dm-spl;
+};
diff --git a/arch/arm/include/asm/arch-am33xx/i2c.h b/arch/arm/include/asm/arch-am33xx/i2c.h
index 491fca9..c2a9850 100644
--- a/arch/arm/include/asm/arch-am33xx/i2c.h
+++ b/arch/arm/include/asm/arch-am33xx/i2c.h
@@ -6,57 +6,14 @@
 #ifndef _I2C_AM33XX_H_
 #define _I2C_AM33XX_H_
 
+#include <asm/omap_i2c.h>
+
 #define  I2C_BASE1		0x44E0B000
 #define  I2C_BASE2		0x4802A000
 #define  I2C_BASE3		0x4819C000
 
 #define I2C_DEFAULT_BASE		I2C_BASE1
 
-struct i2c {
-	unsigned short revnb_lo;        /* 0x00 */
-	unsigned short res1;
-	unsigned short revnb_hi;        /* 0x04 */
-	unsigned short res2[5];
-	unsigned short sysc;		/* 0x10 */
-	unsigned short res3[9];
-	unsigned short irqstatus_raw;   /* 0x24 */
-	unsigned short res4;
-	unsigned short stat;            /* 0x28 */
-	unsigned short res5;
-	unsigned short ie;              /* 0x2C */
-	unsigned short res6;
-	unsigned short irqenable_clr;   /* 0x30 */
-	unsigned short res7;
-	unsigned short iv;              /* 0x34 */
-	unsigned short res8[45];
-	unsigned short syss;            /* 0x90 */
-	unsigned short res9;
-	unsigned short buf;             /* 0x94 */
-	unsigned short res10;
-	unsigned short cnt;             /* 0x98 */
-	unsigned short res11;
-	unsigned short data;            /* 0x9C */
-	unsigned short res13;
-	unsigned short res14;           /* 0xA0 */
-	unsigned short res15;
-	unsigned short con;             /* 0xA4 */
-	unsigned short res16;
-	unsigned short oa;              /* 0xA8 */
-	unsigned short res17;
-	unsigned short sa;              /* 0xAC */
-	unsigned short res18;
-	unsigned short psc;             /* 0xB0 */
-	unsigned short res19;
-	unsigned short scll;            /* 0xB4 */
-	unsigned short res20;
-	unsigned short sclh;            /* 0xB8 */
-	unsigned short res21;
-	unsigned short systest;         /* 0xBC */
-	unsigned short res22;
-	unsigned short bufstat;         /* 0xC0 */
-	unsigned short res23;
-};
-
 #define I2C_IP_CLK			48000000
 #define I2C_INTERNAL_SAMPLING_CLK	12000000
 
diff --git a/arch/arm/include/asm/arch-omap3/i2c.h b/arch/arm/include/asm/arch-omap3/i2c.h
index 5ddaa0d..b04c012 100644
--- a/arch/arm/include/asm/arch-omap3/i2c.h
+++ b/arch/arm/include/asm/arch-omap3/i2c.h
@@ -8,51 +8,4 @@
 
 #define I2C_DEFAULT_BASE	I2C_BASE1
 
-struct i2c {
-	unsigned short rev;	/* 0x00 */
-	unsigned short res1;
-	unsigned short ie;	/* 0x04 */
-	unsigned short res2;
-	unsigned short stat;	/* 0x08 */
-	unsigned short res3;
-	unsigned short we;	/* 0x0C */
-	unsigned short res4;
-	unsigned short syss;	/* 0x10 */
-	unsigned short res4a;
-	unsigned short buf;	/* 0x14 */
-	unsigned short res5;
-	unsigned short cnt;	/* 0x18 */
-	unsigned short res6;
-	unsigned short data;	/* 0x1C */
-	unsigned short res7;
-	unsigned short sysc;	/* 0x20 */
-	unsigned short res8;
-	unsigned short con;	/* 0x24 */
-	unsigned short res9;
-	unsigned short oa;	/* 0x28 */
-	unsigned short res10;
-	unsigned short sa;	/* 0x2C */
-	unsigned short res11;
-	unsigned short psc;	/* 0x30 */
-	unsigned short res12;
-	unsigned short scll;	/* 0x34 */
-	unsigned short res13;
-	unsigned short sclh;	/* 0x38 */
-	unsigned short res14;
-	unsigned short systest;	/* 0x3c */
-	unsigned short res15;
-	unsigned short bufstat;	/* 0x40 */
-	unsigned short res16;
-	unsigned short oa1;	/* 0x44 */
-	unsigned short res17;
-	unsigned short oa2;	/* 0x48 */
-	unsigned short res18;
-	unsigned short oa3;	/* 0x4c */
-	unsigned short res19;
-	unsigned short actoa;	/* 0x50 */
-	unsigned short res20;
-	unsigned short sblock;	/* 0x54 */
-	unsigned short res21;
-};
-
 #endif /* _OMAP3_I2C_H_ */
diff --git a/arch/arm/include/asm/arch-omap4/i2c.h b/arch/arm/include/asm/arch-omap4/i2c.h
index c60aac7..c8f2f97 100644
--- a/arch/arm/include/asm/arch-omap4/i2c.h
+++ b/arch/arm/include/asm/arch-omap4/i2c.h
@@ -8,49 +8,4 @@
 
 #define I2C_DEFAULT_BASE	I2C_BASE1
 
-struct i2c {
-	unsigned short revnb_lo;	/* 0x00 */
-	unsigned short res1;
-	unsigned short revnb_hi;	/* 0x04 */
-	unsigned short res2[5];
-	unsigned short sysc;		/* 0x10 */
-	unsigned short res3[9];
-	unsigned short irqstatus_raw;	/* 0x24 */
-	unsigned short res4;
-	unsigned short stat;		/* 0x28 */
-	unsigned short res5;
-	unsigned short ie;		/* 0x2C */
-	unsigned short res6;
-	unsigned short irqenable_clr;	/* 0x30 */
-	unsigned short res7;
-	unsigned short iv;		/* 0x34 */
-	unsigned short res8[45];
-	unsigned short syss;		/* 0x90 */
-	unsigned short res9;
-	unsigned short buf;		/* 0x94 */
-	unsigned short res10;
-	unsigned short cnt;		/* 0x98 */
-	unsigned short res11;
-	unsigned short data;		/* 0x9C */
-	unsigned short res13;
-	unsigned short res14;		/* 0xA0 */
-	unsigned short res15;
-	unsigned short con;		/* 0xA4 */
-	unsigned short res16;
-	unsigned short oa;		/* 0xA8 */
-	unsigned short res17;
-	unsigned short sa;		/* 0xAC */
-	unsigned short res18;
-	unsigned short psc;		/* 0xB0 */
-	unsigned short res19;
-	unsigned short scll;		/* 0xB4 */
-	unsigned short res20;
-	unsigned short sclh;		/* 0xB8 */
-	unsigned short res21;
-	unsigned short systest;		/* 0xBC */
-	unsigned short res22;
-	unsigned short bufstat;		/* 0xC0 */
-	unsigned short res23;
-};
-
 #endif /* _OMAP4_I2C_H_ */
diff --git a/arch/arm/include/asm/arch-omap5/i2c.h b/arch/arm/include/asm/arch-omap5/i2c.h
index 60e2b4b..9e1edcf 100644
--- a/arch/arm/include/asm/arch-omap5/i2c.h
+++ b/arch/arm/include/asm/arch-omap5/i2c.h
@@ -8,49 +8,4 @@
 
 #define I2C_DEFAULT_BASE	I2C_BASE1
 
-struct i2c {
-	unsigned short revnb_lo;	/* 0x00 */
-	unsigned short res1;
-	unsigned short revnb_hi;	/* 0x04 */
-	unsigned short res2[5];
-	unsigned short sysc;		/* 0x10 */
-	unsigned short res3[9];
-	unsigned short irqstatus_raw;	/* 0x24 */
-	unsigned short res4;
-	unsigned short stat;		/* 0x28 */
-	unsigned short res5;
-	unsigned short ie;		/* 0x2C */
-	unsigned short res6;
-	unsigned short irqenable_clr;	/* 0x30 */
-	unsigned short res7;
-	unsigned short iv;		/* 0x34 */
-	unsigned short res8[45];
-	unsigned short syss;		/* 0x90 */
-	unsigned short res9;
-	unsigned short buf;		/* 0x94 */
-	unsigned short res10;
-	unsigned short cnt;		/* 0x98 */
-	unsigned short res11;
-	unsigned short data;		/* 0x9C */
-	unsigned short res13;
-	unsigned short res14;		/* 0xA0 */
-	unsigned short res15;
-	unsigned short con;		/* 0xA4 */
-	unsigned short res16;
-	unsigned short oa;		/* 0xA8 */
-	unsigned short res17;
-	unsigned short sa;		/* 0xAC */
-	unsigned short res18;
-	unsigned short psc;		/* 0xB0 */
-	unsigned short res19;
-	unsigned short scll;		/* 0xB4 */
-	unsigned short res20;
-	unsigned short sclh;		/* 0xB8 */
-	unsigned short res21;
-	unsigned short systest;		/* 0xBC */
-	unsigned short res22;
-	unsigned short bufstat;		/* 0xC0 */
-	unsigned short res23;
-};
-
 #endif /* _OMAP5_I2C_H_ */
diff --git a/arch/arm/include/asm/omap_i2c.h b/arch/arm/include/asm/omap_i2c.h
new file mode 100644
index 0000000..c1695cb
--- /dev/null
+++ b/arch/arm/include/asm/omap_i2c.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _OMAP_I2C_H
+#define _OMAP_I2C_H
+
+#include <asm/arch/cpu.h>
+
+#ifdef CONFIG_DM_I2C
+
+/* Information about a GPIO bank */
+struct omap_i2c_platdata {
+	ulong base;	/* address of registers in physical memory */
+	int speed;
+	int ip_rev;
+};
+
+#endif
+
+enum {
+	OMAP_I2C_REV_V1 = 0,
+	OMAP_I2C_REV_V2 = 1,
+};
+
+#endif /* _OMAP_I2C_H */
diff --git a/arch/arm/mach-keystone/ddr3_spd.c b/arch/arm/mach-keystone/ddr3_spd.c
index 2613092..6eee9ad 100644
--- a/arch/arm/mach-keystone/ddr3_spd.c
+++ b/arch/arm/mach-keystone/ddr3_spd.c
@@ -403,6 +403,7 @@
 static int ddr3_read_spd(ddr3_spd_eeprom_t *spd_params)
 {
 	int ret;
+#ifndef CONFIG_DM_I2C
 	int old_bus;
 
 	i2c_init(CONFIG_SYS_DAVINCI_I2C_SPEED, CONFIG_SYS_DAVINCI_I2C_SLAVE);
@@ -413,7 +414,13 @@
 	ret = i2c_read(0x53, 0, 1, (unsigned char *)spd_params, 256);
 
 	i2c_set_bus_num(old_bus);
+#else
+	struct udevice *dev;
 
+	ret = i2c_get_chip_for_busnum(1, 0x53, 1, &dev);
+	if (!ret)
+		ret = dm_i2c_read(dev, 0, (unsigned char *)spd_params, 256);
+#endif
 	if (ret) {
 		printf("Cannot read DIMM params\n");
 		return 1;
diff --git a/arch/arm/mach-omap2/am33xx/board.c b/arch/arm/mach-omap2/am33xx/board.c
index f5f2bd5..2fc364d 100644
--- a/arch/arm/mach-omap2/am33xx/board.c
+++ b/arch/arm/mach-omap2/am33xx/board.c
@@ -19,6 +19,7 @@
 #include <asm/arch/ddr_defs.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/gpio.h>
+#include <asm/arch/i2c.h>
 #include <asm/arch/mem.h>
 #include <asm/arch/mmc_host_def.h>
 #include <asm/arch/sys_proto.h>
@@ -93,6 +94,20 @@
 #  endif
 };
 
+#ifdef CONFIG_DM_I2C
+static const struct omap_i2c_platdata am33xx_i2c[] = {
+	{ I2C_BASE1, 100000, OMAP_I2C_REV_V2},
+	{ I2C_BASE2, 100000, OMAP_I2C_REV_V2},
+	{ I2C_BASE3, 100000, OMAP_I2C_REV_V2},
+};
+
+U_BOOT_DEVICES(am33xx_i2c) = {
+	{ "i2c_omap", &am33xx_i2c[0] },
+	{ "i2c_omap", &am33xx_i2c[1] },
+	{ "i2c_omap", &am33xx_i2c[2] },
+};
+#endif
+
 #ifdef CONFIG_DM_GPIO
 static const struct omap_gpio_platdata am33xx_gpio[] = {
 	{ 0, AM33XX_GPIO0_BASE },
@@ -457,12 +472,15 @@
 #ifdef CONFIG_DEBUG_UART_OMAP
 	debug_uart_init();
 #endif
-#ifdef CONFIG_TI_I2C_BOARD_DETECT
-	do_board_detect();
-#endif
+
 #ifdef CONFIG_SPL_BUILD
 	spl_early_init();
 #endif
+
+#ifdef CONFIG_TI_I2C_BOARD_DETECT
+	do_board_detect();
+#endif
+
 #if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC)
 	/* Enable RTC32K clock */
 	rtc32k_enable();
diff --git a/arch/arm/mach-omap2/am33xx/clk_synthesizer.c b/arch/arm/mach-omap2/am33xx/clk_synthesizer.c
index 0e7ad1d..ff1bfaf 100644
--- a/arch/arm/mach-omap2/am33xx/clk_synthesizer.c
+++ b/arch/arm/mach-omap2/am33xx/clk_synthesizer.c
@@ -14,6 +14,7 @@
 
 /**
  * clk_synthesizer_reg_read - Read register from synthesizer.
+ * dev:		i2c bus device (not used if CONFIG_DM_I2C is not set)
  * @addr:	addr within the i2c device
  * buf:		Buffer to which value is to be read.
  *
@@ -21,13 +22,14 @@
  * be send along with enabling byte read more, and then read can happen.
  * Returns 0 on success
  */
-static int clk_synthesizer_reg_read(int addr, uint8_t *buf)
+static int clk_synthesizer_reg_read(struct udevice *dev, int addr, u8 *buf)
 {
 	int rc;
 
 	/* Enable Bye read */
 	addr = addr | CLK_SYNTHESIZER_BYTE_MODE;
 
+#ifndef CONFIG_DM_I2C
 	/* Send the command byte */
 	rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
 	if (rc)
@@ -35,26 +37,46 @@
 
 	/* Read the Data */
 	return i2c_read(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1);
+#else
+	/* Send the command byte */
+	rc = dm_i2c_reg_write(dev, addr, *buf);
+	if (rc)
+		printf("Failed to send command to clock synthesizer\n");
+
+	/* Read the Data */
+	rc = dm_i2c_reg_read(dev, addr);
+	if (rc < 0)
+		return rc;
+
+	*buf = (u8)rc;
+	return 0;
+#endif
+
 }
 
 /**
  * clk_synthesizer_reg_write - Write a value to register in synthesizer.
+ * dev:		i2c bus device (not used if CONFIG_DM_I2C is not set)
  * @addr:	addr within the i2c device
  * val:		Value to be written in the addr.
  *
  * Enable the byte read mode in the address and start the i2c transfer.
  * Returns 0 on success
  */
-static int clk_synthesizer_reg_write(int addr, uint8_t val)
+static int clk_synthesizer_reg_write(struct udevice *dev, int addr, u8 val)
 {
-	uint8_t cmd[2];
+	u8 cmd[2];
 	int rc = 0;
 
 	/* Enable byte write */
 	cmd[0] = addr | CLK_SYNTHESIZER_BYTE_MODE;
 	cmd[1] = val;
 
+#ifndef CONFIG_DM_I2C
 	rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, cmd, 2);
+#else
+	rc = dm_i2c_write(dev, addr, cmd, 2);
+#endif
 	if (rc)
 		printf("Clock synthesizer reg write failed at addr = 0x%x\n",
 		       addr);
@@ -72,30 +94,42 @@
 int setup_clock_synthesizer(struct clk_synth *data)
 {
 	int rc;
-	uint8_t val;
-
+	u8 val = 0;
+	struct udevice *dev = NULL;
+#ifndef CONFIG_DM_I2C
 	rc =  i2c_probe(CLK_SYNTHESIZER_I2C_ADDR);
 	if (rc) {
 		printf("i2c probe failed at address 0x%x\n",
 		       CLK_SYNTHESIZER_I2C_ADDR);
 		return rc;
 	}
-
-	rc = clk_synthesizer_reg_read(CLK_SYNTHESIZER_ID_REG, &val);
+#else
+	rc = i2c_get_chip_for_busnum(0, CLK_SYNTHESIZER_I2C_ADDR, 1, &dev);
+	if (rc) {
+		printf("failed to get device for synthesizer at address 0x%x\n",
+		       CLK_SYNTHESIZER_I2C_ADDR);
+		return rc;
+	}
+#endif
+	rc = clk_synthesizer_reg_read(dev, CLK_SYNTHESIZER_ID_REG, &val);
 	if (val != data->id)
 		return rc;
 
 	/* Crystal Load capacitor selection */
-	rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_XCSEL, data->capacitor);
+	rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_XCSEL,
+				       data->capacitor);
 	if (rc)
 		return rc;
-	rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_MUX_REG, data->mux);
+	rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_MUX_REG,
+				       data->mux);
 	if (rc)
 		return rc;
-	rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_PDIV2_REG, data->pdiv2);
+	rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV2_REG,
+				       data->pdiv2);
 	if (rc)
 		return rc;
-	rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_PDIV3_REG, data->pdiv3);
+	rc = clk_synthesizer_reg_write(dev, CLK_SYNTHESIZER_PDIV3_REG,
+				       data->pdiv3);
 	if (rc)
 		return rc;
 
diff --git a/arch/arm/mach-omap2/clocks-common.c b/arch/arm/mach-omap2/clocks-common.c
index 790548e..5932d69 100644
--- a/arch/arm/mach-omap2/clocks-common.c
+++ b/arch/arm/mach-omap2/clocks-common.c
@@ -909,6 +909,7 @@
 		enable_basic_uboot_clocks();
 }
 
+#if !defined(CONFIG_DM_I2C)
 void gpi2c_init(void)
 {
 	static int gpi2c = 1;
@@ -919,3 +920,4 @@
 		gpi2c = 0;
 	}
 }
+#endif
diff --git a/arch/arm/mach-omap2/hwinit-common.c b/arch/arm/mach-omap2/hwinit-common.c
index 1a24acb..772b4c4 100644
--- a/arch/arm/mach-omap2/hwinit-common.c
+++ b/arch/arm/mach-omap2/hwinit-common.c
@@ -12,6 +12,7 @@
  */
 #include <common.h>
 #include <debug_uart.h>
+#include <fdtdec.h>
 #include <spl.h>
 #include <asm/arch/sys_proto.h>
 #include <linux/sizes.h>
@@ -19,6 +20,7 @@
 #include <asm/omap_common.h>
 #include <linux/compiler.h>
 #include <asm/system.h>
+#include <dm/root.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -171,6 +173,10 @@
  */
 void early_system_init(void)
 {
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_MULTI_DTB_FIT)
+	int ret;
+	int rescan;
+#endif
 	init_omap_revision();
 	hw_data_init();
 	init_package_revision();
@@ -186,6 +192,7 @@
 	do_io_settings();
 #endif
 	setup_early_clocks();
+
 #ifdef CONFIG_SPL_BUILD
 	/*
 	 * Save the boot parameters passed from romcode.
@@ -193,11 +200,23 @@
 	 * to prevent overwrites.
 	 */
 	save_omap_boot_params();
-#endif
-	do_board_detect();
-#ifdef CONFIG_SPL_BUILD
 	spl_early_init();
 #endif
+	do_board_detect();
+
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_MULTI_DTB_FIT)
+	/*
+	 * Board detection has been done.
+	 * Let us see if another dtb wouldn't be a better match
+	 * for our board
+	 */
+	ret = fdtdec_resetup(&rescan);
+	if (!ret && rescan) {
+		dm_uninit();
+		dm_init_and_scan(true);
+	}
+#endif
+
 	vcores_init();
 #ifdef CONFIG_DEBUG_UART_OMAP
 	debug_uart_init();
diff --git a/arch/arm/mach-rmobile/cpu_info.c b/arch/arm/mach-rmobile/cpu_info.c
index 65a9ca8..aa5be52 100644
--- a/arch/arm/mach-rmobile/cpu_info.c
+++ b/arch/arm/mach-rmobile/cpu_info.c
@@ -7,8 +7,6 @@
 #include <asm/io.h>
 #include <linux/ctype.h>
 
-/* R-Car Gen3 caches are enabled in memmap-gen3.c */
-#ifndef CONFIG_RCAR_GEN3
 #ifdef CONFIG_ARCH_CPU_INIT
 int arch_cpu_init(void)
 {
@@ -17,6 +15,8 @@
 }
 #endif
 
+/* R-Car Gen3 D-cache is enabled in memmap-gen3.c */
+#ifndef CONFIG_RCAR_GEN3
 #ifndef CONFIG_SYS_DCACHE_OFF
 void enable_caches(void)
 {
diff --git a/arch/arm/mach-rmobile/memmap-gen3.c b/arch/arm/mach-rmobile/memmap-gen3.c
index 7e29ccc..1a9eb72 100644
--- a/arch/arm/mach-rmobile/memmap-gen3.c
+++ b/arch/arm/mach-rmobile/memmap-gen3.c
@@ -21,7 +21,13 @@
 	}, {
 		.virt = 0x40000000UL,
 		.phys = 0x40000000UL,
-		.size = 0x80000000UL,
+		.size = 0x03F00000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		.virt = 0x47E00000UL,
+		.phys = 0x47E00000UL,
+		.size = 0x78200000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
 	}, {
@@ -76,8 +82,16 @@
 
 		/* Mark memory reserved by ATF as cacheable too. */
 		if (start == 0x48000000) {
-			start = 0x40000000ULL;
-			size += 0x08000000ULL;
+			/* Unmark protection area (0x43F00000 to 0x47DFFFFF) */
+			gen3_mem_map[i].virt = 0x40000000ULL;
+			gen3_mem_map[i].phys = 0x40000000ULL;
+			gen3_mem_map[i].size = 0x03F00000ULL;
+			gen3_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+						PTE_BLOCK_INNER_SHARE;
+			i++;
+
+			start = 0x47E00000ULL;
+			size += 0x00200000ULL;
 		}
 
 		gen3_mem_map[i].virt = start;
@@ -126,6 +140,8 @@
 		gen3_mem_map[i].attrs = 0;
 	}
 
-	icache_enable();
+	if (!icache_status())
+		icache_enable();
+
 	dcache_enable();
 }
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 082fcec..6b1c269 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -460,6 +460,8 @@
 
 		test4 {
 			compatible = "denx,u-boot-probe-test";
+			first-syscon = <&syscon0>;
+			second-sys-ctrl = <&another_system_controller>;
 		};
 	};
 
@@ -540,12 +542,12 @@
 		};
 	};
 
-	syscon@0 {
+	syscon0: syscon@0 {
 		compatible = "sandbox,syscon0";
 		reg = <0x10 16>;
 	};
 
-	syscon@1 {
+	another_system_controller: syscon@1 {
 		compatible = "sandbox,syscon1";
 		reg = <0x20 5
 			0x28 6
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index a1c18d2..e052093 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -729,13 +729,22 @@
 	  maximum number of PCI buses as defined by the PCI specification.
 
 config I8259_PIC
-	bool
+	bool "Enable Intel 8259 compatible interrupt controller"
 	default y
 	help
 	  Intel 8259 ISA compatible chipset incorporates two 8259 (master and
 	  slave) interrupt controllers. Include this to have U-Boot set up
 	  the interrupt correctly.
 
+config APIC
+	bool "Enable Intel Advanced Programmable Interrupt Controller"
+	default y
+	help
+	  The (A)dvanced (P)rogrammable (I)nterrupt (C)ontroller is responsible
+	  for catching interrupts and distributing them to one or more CPU
+	  cores. In most cases there are some LAPICs (local) for each core and
+	  one I/O APIC. This conjunction is found on most modern x86 systems.
+
 config PINCTRL_ICH6
 	bool
 	help
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index f862d8c..54668aa 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -35,7 +35,7 @@
 obj-$(CONFIG_INTEL_QUARK) += quark/
 obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
 obj-$(CONFIG_INTEL_TANGIER) += tangier/
-obj-y += lapic.o ioapic.o
+obj-$(CONFIG_APIC) += lapic.o ioapic.o
 obj-y += irq.o
 ifndef CONFIG_$(SPL_)X86_64
 obj-$(CONFIG_SMP) += mp_init.o
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c
index aaf0d07..4c6ed0b 100644
--- a/arch/x86/cpu/coreboot/coreboot.c
+++ b/arch/x86/cpu/coreboot/coreboot.c
@@ -77,7 +77,8 @@
 		timestamp_add_to_bootstage();
 
 	/* start usb so that usb keyboard can be used as input device */
-	usb_init();
+	if (CONFIG_IS_ENABLED(USB_KEYBOARD))
+		usb_init();
 
 	board_final_cleanup();
 
diff --git a/arch/x86/cpu/efi/payload.c b/arch/x86/cpu/efi/payload.c
index c323c7b..225aef7 100644
--- a/arch/x86/cpu/efi/payload.c
+++ b/arch/x86/cpu/efi/payload.c
@@ -166,7 +166,8 @@
 int last_stage_init(void)
 {
 	/* start usb so that usb keyboard can be used as input device */
-	usb_init();
+	if (CONFIG_IS_ENABLED(USB_KEYBOARD))
+		usb_init();
 
 	return 0;
 }
diff --git a/arch/x86/cpu/i386/interrupt.c b/arch/x86/cpu/i386/interrupt.c
index ed8423e..1ea415b 100644
--- a/arch/x86/cpu/i386/interrupt.c
+++ b/arch/x86/cpu/i386/interrupt.c
@@ -264,7 +264,9 @@
 	i8259_init();
 #endif
 
+#ifdef CONFIG_APIC
 	lapic_setup();
+#endif
 
 	/* Initialize core interrupt and exception functionality of CPU */
 	cpu_init_interrupts();
diff --git a/arch/x86/include/asm/arch-tangier/acpi/platform.asl b/arch/x86/include/asm/arch-tangier/acpi/platform.asl
index 7abea4b..353b879 100644
--- a/arch/x86/include/asm/arch-tangier/acpi/platform.asl
+++ b/arch/x86/include/asm/arch-tangier/acpi/platform.asl
@@ -21,6 +21,19 @@
     Return (Package() {0, 0})
 }
 
+Scope (_SB)
+{
+    /* Real Time Clock */
+    Device (RTC0)
+    {
+        Name (_HID, EisaId ("PNP0B00"))
+        Name (_CRS, ResourceTemplate()
+        {
+            IO(Decode16, 0x70, 0x70, 0x01, 0x08)
+        })
+    }
+}
+
 /* ACPI global NVS */
 #include "global_nvs.asl"
 
diff --git a/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl b/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl
index 48193ba..e166e51 100644
--- a/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl
+++ b/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl
@@ -295,16 +295,16 @@
 
             Method (_CRS, 0, Serialized)
             {
-                Name (RBUF, ResourceTemplate ()
+                Name (RBUF, ResourceTemplate()
                 {
-                    UartSerialBus (0x0001C200, DataBitsEight, StopBitsOne,
+                    UartSerialBus(0x0001C200, DataBitsEight, StopBitsOne,
                         0xFC, LittleEndian, ParityTypeNone, FlowControlHardware,
                         0x20, 0x20, "\\_SB.PCI0.HSU0", 0, ResourceConsumer, , )
-                    GpioInt (Level, ActiveHigh, Exclusive, PullNone, 0,
+                    GpioInt(Level, ActiveHigh, Exclusive, PullNone, 0,
                         "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 185 }
-                    GpioIo (Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly,
+                    GpioIo(Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly,
                         "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 184 }
-                    GpioIo (Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly,
+                    GpioIo(Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly,
                         "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 71 }
                 })
                 Return (RBUF)
@@ -328,7 +328,7 @@
     Name (_DDN, "Intel Merrifield Family-Level Interface Shim")
     Name (RBUF, ResourceTemplate()
     {
-        Memory32Fixed(ReadWrite, 0xFF0C0000, 0x00008000, )
+        Memory32Fixed(ReadWrite, 0xFF0C0000, 0x00008000)
         PinGroup("spi5", ResourceProducer, ) { 90, 91, 92, 93, 94, 95, 96 }
         PinGroup("uart0", ResourceProducer, ) { 115, 116, 117, 118 }
         PinGroup("uart1", ResourceProducer, ) { 119, 120, 121, 122 }
diff --git a/arch/x86/lib/interrupts.c b/arch/x86/lib/interrupts.c
index 297067d..39f8dea 100644
--- a/arch/x86/lib/interrupts.c
+++ b/arch/x86/lib/interrupts.c
@@ -64,7 +64,8 @@
 	irq_handlers[irq].arg = arg;
 	irq_handlers[irq].count = 0;
 
-	unmask_irq(irq);
+	if (CONFIG_IS_ENABLED(I8259_PIC))
+		unmask_irq(irq);
 
 	if (status)
 		enable_interrupts();
@@ -83,7 +84,8 @@
 
 	status = disable_interrupts();
 
-	mask_irq(irq);
+	if (CONFIG_IS_ENABLED(I8259_PIC))
+		mask_irq(irq);
 
 	irq_handlers[irq].handler = NULL;
 	irq_handlers[irq].arg = NULL;
@@ -104,14 +106,16 @@
 	}
 
 	if (irq_handlers[irq].handler) {
-		mask_irq(irq);
+		if (CONFIG_IS_ENABLED(I8259_PIC))
+			mask_irq(irq);
 
 		irq_handlers[irq].handler(irq_handlers[irq].arg);
 		irq_handlers[irq].count++;
 
-		unmask_irq(irq);
-		specific_eoi(irq);
-
+		if (CONFIG_IS_ENABLED(I8259_PIC)) {
+			unmask_irq(irq);
+			specific_eoi(irq);
+		}
 	} else {
 		if ((irq & 7) != 7) {
 			spurious_irq_cnt++;
diff --git a/board/eets/pdu001/board.c b/board/eets/pdu001/board.c
index b4b8081..b857a5a 100644
--- a/board/eets/pdu001/board.c
+++ b/board/eets/pdu001/board.c
@@ -209,7 +209,6 @@
 const struct dpll_params *get_dpll_ddr_params(void)
 {
 	enable_i2c0_pin_mux();
-	i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE);
 
 	return &dpll_ddr;
 }
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 8e20dc7..917f5b1 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -665,7 +665,7 @@
 	struct phy phy;
 	int ret;
 
-	ret = uclass_get_device(UCLASS_USB_DEV_GENERIC, 0, &dev);
+	ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, 0, &dev);
 	if (ret) {
 		pr_err("%s: Cannot find USB device\n", __func__);
 		return ret;
diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c
index 1384525..d67f94a 100644
--- a/board/ti/am335x/board.c
+++ b/board/ti/am335x/board.c
@@ -70,8 +70,9 @@
 void do_board_detect(void)
 {
 	enable_i2c0_pin_mux();
+#ifndef CONFIG_DM_I2C
 	i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE);
-
+#endif
 	if (ti_i2c_eeprom_am_get(CONFIG_EEPROM_BUS_ADDRESS,
 				 CONFIG_EEPROM_CHIP_ADDRESS))
 		printf("ti_i2c_eeprom_init failed\n");
@@ -328,8 +329,14 @@
 	if (board_is_bone() && !strncmp(board_ti_get_rev(), "00A1", 4))
 		return;
 
+#ifndef CONFIG_DM_I2C
 	if (i2c_probe(TPS65217_CHIP_PM))
 		return;
+#else
+	if (power_tps65217_init(0))
+		return;
+#endif
+
 
 	/*
 	 * On Beaglebone White we need to ensure we have AC power
@@ -421,9 +428,13 @@
 	 * 1.10V.  For MPU voltage we need to switch based on
 	 * the frequency we are running at.
 	 */
+#ifndef CONFIG_DM_I2C
 	if (i2c_probe(TPS65910_CTRL_I2C_ADDR))
 		return;
-
+#else
+	if (power_tps65910_init(0))
+		return;
+#endif
 	/*
 	 * Depending on MPU clock and PG we will need a different
 	 * VDD to drive at that speed.
@@ -451,8 +462,10 @@
 
 	if (first_time) {
 		enable_i2c0_pin_mux();
+#ifndef CONFIG_DM_I2C
 		i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED,
 			 CONFIG_SYS_OMAP24_I2C_SLAVE);
+#endif
 		first_time = false;
 	}
 }
diff --git a/board/ti/am335x/mux.c b/board/ti/am335x/mux.c
index 41333f9..04f4b8e 100644
--- a/board/ti/am335x/mux.c
+++ b/board/ti/am335x/mux.c
@@ -329,12 +329,23 @@
 {
 	unsigned short val;
 
+#ifndef CONFIG_DM_I2C
 	if (i2c_probe(I2C_CPLD_ADDR))
 		return PROFILE_NONE;
 
 	if (i2c_read(I2C_CPLD_ADDR, CFG_REG, 1, (unsigned char *)(&val), 2))
 		return PROFILE_NONE;
+#else
+	struct udevice *dev = NULL;
+	int rc;
 
+	rc = i2c_get_chip_for_busnum(0, I2C_CPLD_ADDR, 1, &dev);
+	if (rc)
+		return PROFILE_NONE;
+	rc = dm_i2c_read(dev, CFG_REG, (unsigned char *)(&val), 2);
+	if (rc)
+		return PROFILE_NONE;
+#endif
 	return (1 << (val & PROFILE_MASK));
 }
 
diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c
index 2a59b06..31bc0f4 100644
--- a/board/ti/am43xx/board.c
+++ b/board/ti/am43xx/board.c
@@ -43,6 +43,8 @@
 #ifdef CONFIG_TI_I2C_BOARD_DETECT
 void do_board_detect(void)
 {
+	/* Ensure I2C is initialized for EEPROM access*/
+	gpi2c_init();
 	if (ti_i2c_eeprom_am_get(CONFIG_EEPROM_BUS_ADDRESS,
 				 CONFIG_EEPROM_CHIP_ADDRESS))
 		printf("ti_i2c_eeprom_init failed\n");
@@ -386,8 +388,13 @@
 {
 	int mpu_vdd, ddr_volt;
 
+#ifndef CONFIG_DM_I2C
 	if (i2c_probe(TPS65218_CHIP_PM))
 		return;
+#else
+	if (power_tps65218_init(0))
+		return;
+#endif
 
 	switch (m) {
 	case 1000:
@@ -439,8 +446,13 @@
 {
 	int mpu_vdd;
 
+#ifndef CONFIG_DM_I2C
 	if (i2c_probe(TPS62362_I2C_ADDR))
 		return;
+#else
+	if (power_tps62362_init(0))
+		return;
+#endif
 
 	switch (m) {
 	case 1000:
@@ -462,14 +474,12 @@
 		puts("Unknown MPU clock, not scaling\n");
 		return;
 	}
-
 	/* Set VDD_MPU voltage */
 	if (tps62362_voltage_update(TPS62362_SET3, mpu_vdd)) {
 		printf("%s failure\n", __func__);
 		return;
 	}
 }
-
 void gpi2c_init(void)
 {
 	/* When needed to be invoked prior to BSS initialization */
@@ -477,8 +487,10 @@
 
 	if (first_time) {
 		enable_i2c0_pin_mux();
+#ifndef CONFIG_DM_I2C
 		i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED,
 			 CONFIG_SYS_OMAP24_I2C_SLAVE);
+#endif
 		first_time = false;
 	}
 }
@@ -614,20 +626,32 @@
 /* setup board specific PMIC */
 int power_init_board(void)
 {
-	struct pmic *p;
-
+	int rc;
+#ifndef CONFIG_DM_I2C
+	struct pmic *p = NULL;
+#endif
 	if (board_is_idk()) {
-		power_tps62362_init(I2C_PMIC);
+		rc = power_tps62362_init(0);
+		if (rc)
+			goto done;
+#ifndef CONFIG_DM_I2C
 		p = pmic_get("TPS62362");
-		if (p && !pmic_probe(p))
-			puts("PMIC:  TPS62362\n");
+		if (!p || pmic_probe(p))
+			goto done;
+#endif
+		puts("PMIC:  TPS62362\n");
 	} else {
-		power_tps65218_init(I2C_PMIC);
+		rc = power_tps65218_init(0);
+		if (rc)
+			goto done;
+#ifndef CONFIG_DM_I2C
 		p = pmic_get("TPS65218_PMIC");
-		if (p && !pmic_probe(p))
-			puts("PMIC:  TPS65218\n");
+		if (!p || pmic_probe(p))
+			goto done;
+#endif
+		puts("PMIC:  TPS65218\n");
 	}
-
+done:
 	return 0;
 }
 
diff --git a/board/ti/am57xx/board.c b/board/ti/am57xx/board.c
index 177a324..7063345 100644
--- a/board/ti/am57xx/board.c
+++ b/board/ti/am57xx/board.c
@@ -623,7 +623,7 @@
 {
 	int r = -ENODEV;
 	char *idk_lcd = "no";
-	uint8_t buf = 0;
+	struct udevice *dev;
 
 	/* Only valid for IDKs */
 	if (board_is_x15() || board_is_am572x_evm())
@@ -633,32 +633,29 @@
 	if (board_is_am571x_idk() && !am571x_idk_needs_lcd())
 		goto out;
 
-	r = i2c_set_bus_num(OSD_TS_FT_BUS_ADDRESS);
+	r = i2c_get_chip_for_busnum(OSD_TS_FT_BUS_ADDRESS,
+				    OSD_TS_FT_CHIP_ADDRESS, 1, &dev);
 	if (r) {
-		printf("%s: Failed to set bus address to %d: %d\n",
-		       __func__, OSD_TS_FT_BUS_ADDRESS, r);
-		goto out;
-	}
-	r = i2c_probe(OSD_TS_FT_CHIP_ADDRESS);
-	if (r) {
+		printf("%s: Failed to get I2C device %d/%d (ret %d)\n",
+		       __func__, OSD_TS_FT_BUS_ADDRESS, OSD_TS_FT_CHIP_ADDRESS,
+		       r);
 		/* AM572x IDK has no explicit settings for optional LCD kit */
-		if (board_is_am571x_idk()) {
+		if (board_is_am571x_idk())
 			printf("%s: Touch screen detect failed: %d!\n",
 			       __func__, r);
-		}
 		goto out;
 	}
 
 	/* Read FT ID */
-	r = i2c_read(OSD_TS_FT_CHIP_ADDRESS, OSD_TS_FT_REG_ID, 1, &buf, 1);
-	if (r) {
+	r = dm_i2c_reg_read(dev, OSD_TS_FT_REG_ID);
+	if (r < 0) {
 		printf("%s: Touch screen ID read %d:0x%02x[0x%02x] failed:%d\n",
 		       __func__, OSD_TS_FT_BUS_ADDRESS, OSD_TS_FT_CHIP_ADDRESS,
 		       OSD_TS_FT_REG_ID, r);
 		goto out;
 	}
 
-	switch (buf) {
+	switch (r) {
 	case OSD_TS_FT_ID_5606:
 		idk_lcd = "osd101t2045";
 		break;
@@ -667,7 +664,7 @@
 		break;
 	default:
 		printf("%s: Unidentifed Touch screen ID 0x%02x\n",
-		       __func__, buf);
+		       __func__, r);
 		/* we will let default be "no lcd" */
 	}
 out:
@@ -675,6 +672,19 @@
 	return;
 }
 
+#if CONFIG_IS_ENABLED(DM_USB) && CONFIG_IS_ENABLED(OF_CONTROL)
+static int device_okay(const char *path)
+{
+	int node;
+
+	node = fdt_path_offset(gd->fdt_blob, path);
+	if (node < 0)
+		return 0;
+
+	return fdtdec_get_is_enabled(gd->fdt_blob, node);
+}
+#endif
+
 int board_late_init(void)
 {
 	setup_board_eeprom_env();
@@ -714,6 +724,12 @@
 	board_ti_set_ethaddr(2);
 #endif
 
+#if CONFIG_IS_ENABLED(DM_USB) && CONFIG_IS_ENABLED(OF_CONTROL)
+	if (device_okay("/ocp/omap_dwc3_1@48880000"))
+		enable_usb_clocks(0);
+	if (device_okay("/ocp/omap_dwc3_2@488c0000"))
+		enable_usb_clocks(1);
+#endif
 	return 0;
 }
 
@@ -864,93 +880,6 @@
 }
 #endif
 
-#ifdef CONFIG_USB_DWC3
-static struct dwc3_device usb_otg_ss2 = {
-	.maximum_speed = USB_SPEED_HIGH,
-	.base = DRA7_USB_OTG_SS2_BASE,
-	.tx_fifo_resize = false,
-	.index = 1,
-};
-
-static struct dwc3_omap_device usb_otg_ss2_glue = {
-	.base = (void *)DRA7_USB_OTG_SS2_GLUE_BASE,
-	.utmi_mode = DWC3_OMAP_UTMI_MODE_SW,
-	.index = 1,
-};
-
-static struct ti_usb_phy_device usb_phy2_device = {
-	.usb2_phy_power = (void *)DRA7_USB2_PHY2_POWER,
-	.index = 1,
-};
-
-int usb_gadget_handle_interrupts(int index)
-{
-	u32 status;
-
-	status = dwc3_omap_uboot_interrupt_status(index);
-	if (status)
-		dwc3_uboot_handle_interrupt(index);
-
-	return 0;
-}
-#endif /* CONFIG_USB_DWC3 */
-
-#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP)
-int board_usb_init(int index, enum usb_init_type init)
-{
-	enable_usb_clocks(index);
-	switch (index) {
-	case 0:
-		if (init == USB_INIT_DEVICE) {
-			printf("port %d can't be used as device\n", index);
-			disable_usb_clocks(index);
-			return -EINVAL;
-		}
-		break;
-	case 1:
-		if (init == USB_INIT_DEVICE) {
-#ifdef CONFIG_USB_DWC3
-			usb_otg_ss2.dr_mode = USB_DR_MODE_PERIPHERAL;
-			usb_otg_ss2_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID;
-			ti_usb_phy_uboot_init(&usb_phy2_device);
-			dwc3_omap_uboot_init(&usb_otg_ss2_glue);
-			dwc3_uboot_init(&usb_otg_ss2);
-#endif
-		} else {
-			printf("port %d can't be used as host\n", index);
-			disable_usb_clocks(index);
-			return -EINVAL;
-		}
-
-		break;
-	default:
-		printf("Invalid Controller Index\n");
-	}
-
-	return 0;
-}
-
-int board_usb_cleanup(int index, enum usb_init_type init)
-{
-#ifdef CONFIG_USB_DWC3
-	switch (index) {
-	case 0:
-	case 1:
-		if (init == USB_INIT_DEVICE) {
-			ti_usb_phy_uboot_exit(index);
-			dwc3_uboot_exit(index);
-			dwc3_omap_uboot_exit(index);
-		}
-		break;
-	default:
-		printf("Invalid Controller Index\n");
-	}
-#endif
-	disable_usb_clocks(index);
-	return 0;
-}
-#endif /* defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP) */
-
 #ifdef CONFIG_DRIVER_TI_CPSW
 
 /* Delay value to add to calibrated value */
diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c
index c475f10..e258e22 100644
--- a/board/ti/common/board_detect.c
+++ b/board/ti/common/board_detect.c
@@ -14,42 +14,7 @@
 
 #include "board_detect.h"
 
-#if defined(CONFIG_DM_I2C_COMPAT)
-/**
- * ti_i2c_set_alen - Set chip's i2c address length
- * @bus_addr - I2C bus number
- * @dev_addr - I2C eeprom id
- * @alen     - I2C address length in bytes
- *
- * DM_I2C by default sets the address length to be used to 1. This
- * function allows this address length to be changed to match the
- * eeprom used for board detection.
- */
-int __maybe_unused ti_i2c_set_alen(int bus_addr, int dev_addr, int alen)
-{
-	struct udevice *dev;
-	struct udevice *bus;
-	int rc;
-
-	rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus);
-	if (rc)
-		return rc;
-	rc = i2c_get_chip(bus, dev_addr, 1, &dev);
-	if (rc)
-		return rc;
-	rc = i2c_set_chip_offset_len(dev, alen);
-	if (rc)
-		return rc;
-
-	return 0;
-}
-#else
-int __maybe_unused ti_i2c_set_alen(int bus_addr, int dev_addr, int alen)
-{
-	return 0;
-}
-#endif
-
+#if !defined(CONFIG_DM_I2C)
 /**
  * ti_i2c_eeprom_init - Initialize an i2c bus and probe for a device
  * @i2c_bus: i2c bus number to initialize
@@ -82,18 +47,9 @@
 static int __maybe_unused ti_i2c_eeprom_read(int dev_addr, int offset,
 					     uchar *ep, int epsize)
 {
-	int bus_num, rc, alen;
-
-	bus_num = i2c_get_bus_num();
-
-	alen = 2;
-
-	rc = ti_i2c_set_alen(bus_num, dev_addr, alen);
-	if (rc)
-		return rc;
-
-	return i2c_read(dev_addr, offset, alen, ep, epsize);
+	return i2c_read(dev_addr, offset, 2, ep, epsize);
 }
+#endif
 
 /**
  * ti_eeprom_string_cleanup() - Handle eeprom programming errors
@@ -122,9 +78,57 @@
 static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr,
 					    u32 header, u32 size, uint8_t *ep)
 {
-	u32 byte, hdr_read;
+	u32 hdr_read;
 	int rc;
 
+#if defined(CONFIG_DM_I2C)
+	struct udevice *dev;
+	struct udevice *bus;
+
+	rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus);
+	if (rc)
+		return rc;
+	rc = i2c_get_chip(bus, dev_addr, 1, &dev);
+	if (rc)
+		return rc;
+
+	/*
+	 * Read the header first then only read the other contents.
+	 */
+	rc = i2c_set_chip_offset_len(dev, 2);
+	if (rc)
+		return rc;
+
+	rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
+	if (rc)
+		return rc;
+
+	/* Corrupted data??? */
+	if (hdr_read != header) {
+		rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
+		/*
+		 * read the eeprom header using i2c again, but use only a
+		 * 1 byte address (some legacy boards need this..)
+		 */
+		if (rc) {
+			rc =  i2c_set_chip_offset_len(dev, 1);
+			if (rc)
+				return rc;
+
+			rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
+		}
+		if (rc)
+			return rc;
+	}
+	if (hdr_read != header)
+		return -1;
+
+	rc = dm_i2c_read(dev, 0, ep, size);
+	if (rc)
+		return rc;
+#else
+	u32 byte;
+
 	gpi2c_init();
 	rc = ti_i2c_eeprom_init(bus_addr, dev_addr);
 	if (rc)
@@ -135,10 +139,6 @@
 	 */
 	byte = 2;
 
-	rc = ti_i2c_set_alen(bus_addr, dev_addr, byte);
-	if (rc)
-		return rc;
-
 	rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read, 4);
 	if (rc)
 		return rc;
@@ -152,10 +152,6 @@
 		 */
 		byte = 1;
 		if (rc) {
-			rc = ti_i2c_set_alen(bus_addr, dev_addr, byte);
-			if (rc)
-				return rc;
-
 			rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read,
 				      4);
 		}
@@ -168,7 +164,7 @@
 	rc = i2c_read(dev_addr, 0x0, byte, ep, size);
 	if (rc)
 		return rc;
-
+#endif
 	return 0;
 }
 
diff --git a/board/ti/dra7xx/evm.c b/board/ti/dra7xx/evm.c
index bbe5445..d69641e 100644
--- a/board/ti/dra7xx/evm.c
+++ b/board/ti/dra7xx/evm.c
@@ -646,6 +646,19 @@
 	return 0;
 }
 
+#if CONFIG_IS_ENABLED(DM_USB) && CONFIG_IS_ENABLED(OF_CONTROL)
+static int device_okay(const char *path)
+{
+	int node;
+
+	node = fdt_path_offset(gd->fdt_blob, path);
+	if (node < 0)
+		return 0;
+
+	return fdtdec_get_is_enabled(gd->fdt_blob, node);
+}
+#endif
+
 int board_late_init(void)
 {
 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
@@ -685,6 +698,12 @@
 	if (board_is_dra71x_evm())
 		palmas_i2c_write_u8(LP873X_I2C_SLAVE_ADDR, 0x9, 0x7);
 #endif
+#if CONFIG_IS_ENABLED(DM_USB) && CONFIG_IS_ENABLED(OF_CONTROL)
+	if (device_okay("/ocp/omap_dwc3_1@48880000"))
+		enable_usb_clocks(0);
+	if (device_okay("/ocp/omap_dwc3_2@488c0000"))
+		enable_usb_clocks(1);
+#endif
 	return 0;
 }
 
@@ -896,110 +915,6 @@
 }
 #endif
 
-#ifdef CONFIG_USB_DWC3
-static struct dwc3_device usb_otg_ss1 = {
-	.maximum_speed = USB_SPEED_SUPER,
-	.base = DRA7_USB_OTG_SS1_BASE,
-	.tx_fifo_resize = false,
-	.index = 0,
-};
-
-static struct dwc3_omap_device usb_otg_ss1_glue = {
-	.base = (void *)DRA7_USB_OTG_SS1_GLUE_BASE,
-	.utmi_mode = DWC3_OMAP_UTMI_MODE_SW,
-	.index = 0,
-};
-
-static struct ti_usb_phy_device usb_phy1_device = {
-	.pll_ctrl_base = (void *)DRA7_USB3_PHY1_PLL_CTRL,
-	.usb2_phy_power = (void *)DRA7_USB2_PHY1_POWER,
-	.usb3_phy_power = (void *)DRA7_USB3_PHY1_POWER,
-	.index = 0,
-};
-
-static struct dwc3_device usb_otg_ss2 = {
-	.maximum_speed = USB_SPEED_SUPER,
-	.base = DRA7_USB_OTG_SS2_BASE,
-	.tx_fifo_resize = false,
-	.index = 1,
-};
-
-static struct dwc3_omap_device usb_otg_ss2_glue = {
-	.base = (void *)DRA7_USB_OTG_SS2_GLUE_BASE,
-	.utmi_mode = DWC3_OMAP_UTMI_MODE_SW,
-	.index = 1,
-};
-
-static struct ti_usb_phy_device usb_phy2_device = {
-	.usb2_phy_power = (void *)DRA7_USB2_PHY2_POWER,
-	.index = 1,
-};
-
-int board_usb_init(int index, enum usb_init_type init)
-{
-	enable_usb_clocks(index);
-	switch (index) {
-	case 0:
-		if (init == USB_INIT_DEVICE) {
-			usb_otg_ss1.dr_mode = USB_DR_MODE_PERIPHERAL;
-			usb_otg_ss1_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID;
-		} else {
-			usb_otg_ss1.dr_mode = USB_DR_MODE_HOST;
-			usb_otg_ss1_glue.vbus_id_status = OMAP_DWC3_ID_GROUND;
-		}
-
-		ti_usb_phy_uboot_init(&usb_phy1_device);
-		dwc3_omap_uboot_init(&usb_otg_ss1_glue);
-		dwc3_uboot_init(&usb_otg_ss1);
-		break;
-	case 1:
-		if (init == USB_INIT_DEVICE) {
-			usb_otg_ss2.dr_mode = USB_DR_MODE_PERIPHERAL;
-			usb_otg_ss2_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID;
-		} else {
-			usb_otg_ss2.dr_mode = USB_DR_MODE_HOST;
-			usb_otg_ss2_glue.vbus_id_status = OMAP_DWC3_ID_GROUND;
-		}
-
-		ti_usb_phy_uboot_init(&usb_phy2_device);
-		dwc3_omap_uboot_init(&usb_otg_ss2_glue);
-		dwc3_uboot_init(&usb_otg_ss2);
-		break;
-	default:
-		printf("Invalid Controller Index\n");
-	}
-
-	return 0;
-}
-
-int board_usb_cleanup(int index, enum usb_init_type init)
-{
-	switch (index) {
-	case 0:
-	case 1:
-		ti_usb_phy_uboot_exit(index);
-		dwc3_uboot_exit(index);
-		dwc3_omap_uboot_exit(index);
-		break;
-	default:
-		printf("Invalid Controller Index\n");
-	}
-	disable_usb_clocks(index);
-	return 0;
-}
-
-int usb_gadget_handle_interrupts(int index)
-{
-	u32 status;
-
-	status = dwc3_omap_uboot_interrupt_status(index);
-	if (status)
-		dwc3_uboot_handle_interrupt(index);
-
-	return 0;
-}
-#endif
-
 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_OS_BOOT)
 int spl_start_uboot(void)
 {
diff --git a/board/ti/ks2_evm/board_k2g.c b/board/ti/ks2_evm/board_k2g.c
index 87dc4d0..39a782e 100644
--- a/board/ti/ks2_evm/board_k2g.c
+++ b/board/ti/ks2_evm/board_k2g.c
@@ -251,6 +251,7 @@
 #if defined(CONFIG_DTB_RESELECT)
 static int k2g_alt_board_detect(void)
 {
+#ifndef CONFIG_DM_I2C
 	int rc;
 
 	rc = i2c_set_bus_num(1);
@@ -260,7 +261,17 @@
 	rc = i2c_probe(K2G_GP_AUDIO_CODEC_ADDRESS);
 	if (rc)
 		return rc;
+#else
+	struct udevice *bus, *dev;
+	int rc;
 
+	rc = uclass_get_device_by_seq(UCLASS_I2C, 1, &bus);
+	if (rc)
+		return rc;
+	rc = dm_i2c_probe(bus, K2G_GP_AUDIO_CODEC_ADDRESS, 0, &dev);
+	if (rc)
+		return rc;
+#endif
 	ti_i2c_eeprom_am_set("66AK2GGP", "1.0X");
 
 	return 0;
diff --git a/cmd/Kconfig b/cmd/Kconfig
index b1cd1c9..ea1a325 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -445,6 +445,7 @@
 
 config CMD_EEPROM
 	bool "eeprom - EEPROM subsystem"
+	depends on !DM_I2C || DM_I2C_COMPAT
 	help
 	  (deprecated, needs conversion to driver model)
 	  Provides commands to read and write EEPROM (Electrically Erasable
diff --git a/cmd/fastboot.c b/cmd/fastboot.c
index ae3a5f6..0be83b7 100644
--- a/cmd/fastboot.c
+++ b/cmd/fastboot.c
@@ -51,7 +51,7 @@
 		return CMD_RET_FAILURE;
 	}
 
-	ret = board_usb_init(controller_index, USB_INIT_DEVICE);
+	ret = usb_gadget_initialize(controller_index);
 	if (ret) {
 		pr_err("USB init failed: %d\n", ret);
 		return CMD_RET_FAILURE;
@@ -82,7 +82,7 @@
 exit:
 	g_dnl_unregister();
 	g_dnl_clear_detach();
-	board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+	usb_gadget_release(controller_index);
 
 	return ret;
 #else
diff --git a/cmd/i2c.c b/cmd/i2c.c
index 56df8eb..09c4ba9 100644
--- a/cmd/i2c.c
+++ b/cmd/i2c.c
@@ -2023,6 +2023,7 @@
 static char i2c_help_text[] =
 #if defined(CONFIG_SYS_I2C) || defined(CONFIG_DM_I2C)
 	"bus [muxtype:muxaddr:muxchannel] - show I2C bus info\n"
+	"i2c " /* That's the prefix for the crc32 command below. */
 #endif
 	"crc32 chip address[.0, .1, .2] count - compute CRC32 checksum\n"
 #if defined(CONFIG_SYS_I2C) || \
diff --git a/cmd/rockusb.c b/cmd/rockusb.c
index 8206643..e0c1480 100644
--- a/cmd/rockusb.c
+++ b/cmd/rockusb.c
@@ -33,7 +33,7 @@
 	dev_index = simple_strtoul(devnum, NULL, 0);
 	rockusb_dev_init(devtype, dev_index);
 
-	ret = board_usb_init(controller_index, USB_INIT_DEVICE);
+	ret = usb_gadget_initialize(controller_index);
 	if (ret) {
 		printf("USB init failed: %d\n", ret);
 		return CMD_RET_FAILURE;
@@ -62,7 +62,7 @@
 exit:
 	g_dnl_unregister();
 	g_dnl_clear_detach();
-	board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+	usb_gadget_release(controller_index);
 
 	return ret;
 }
diff --git a/cmd/thordown.c b/cmd/thordown.c
index 2615ada..ce3660d 100644
--- a/cmd/thordown.c
+++ b/cmd/thordown.c
@@ -30,7 +30,7 @@
 		goto done;
 
 	int controller_index = simple_strtoul(usb_controller, NULL, 0);
-	ret = board_usb_init(controller_index, USB_INIT_DEVICE);
+	ret = usb_gadget_initialize(controller_index);
 	if (ret) {
 		pr_err("USB init failed: %d\n", ret);
 		ret = CMD_RET_FAILURE;
@@ -55,7 +55,7 @@
 
 exit:
 	g_dnl_unregister();
-	board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+	usb_gadget_release(controller_index);
 done:
 	dfu_free_entities();
 
diff --git a/cmd/usb_gadget_sdp.c b/cmd/usb_gadget_sdp.c
index ba1f66a..808ed97 100644
--- a/cmd/usb_gadget_sdp.c
+++ b/cmd/usb_gadget_sdp.c
@@ -20,7 +20,7 @@
 
 	char *usb_controller = argv[1];
 	int controller_index = simple_strtoul(usb_controller, NULL, 0);
-	board_usb_init(controller_index, USB_INIT_DEVICE);
+	usb_gadget_initialize(controller_index);
 
 	g_dnl_clear_detach();
 	g_dnl_register("usb_dnl_sdp");
@@ -37,7 +37,7 @@
 
 exit:
 	g_dnl_unregister();
-	board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+	usb_gadget_release(controller_index);
 
 	return ret;
 }
diff --git a/cmd/usb_mass_storage.c b/cmd/usb_mass_storage.c
index 0d55114..753ae4f 100644
--- a/cmd/usb_mass_storage.c
+++ b/cmd/usb_mass_storage.c
@@ -160,7 +160,7 @@
 
 	controller_index = (unsigned int)(simple_strtoul(
 				usb_controller,	NULL, 0));
-	if (board_usb_init(controller_index, USB_INIT_DEVICE)) {
+	if (usb_gadget_initialize(controller_index)) {
 		pr_err("Couldn't init USB controller.\n");
 		rc = CMD_RET_FAILURE;
 		goto cleanup_ums_init;
@@ -231,7 +231,7 @@
 cleanup_register:
 	g_dnl_unregister();
 cleanup_board:
-	board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+	usb_gadget_release(controller_index);
 cleanup_ums_init:
 	ums_fini();
 
diff --git a/common/dfu.c b/common/dfu.c
index 2620d32..44d1484 100644
--- a/common/dfu.c
+++ b/common/dfu.c
@@ -23,9 +23,9 @@
 	bool dfu_reset = false;
 	int ret, i = 0;
 
-	ret = board_usb_init(usbctrl_index, USB_INIT_DEVICE);
+	ret = usb_gadget_initialize(usbctrl_index);
 	if (ret) {
-		pr_err("board usb init failed\n");
+		pr_err("usb_gadget_initialize failed\n");
 		return CMD_RET_FAILURE;
 	}
 	g_dnl_clear_detach();
@@ -84,7 +84,7 @@
 	}
 exit:
 	g_dnl_unregister();
-	board_usb_cleanup(usbctrl_index, USB_INIT_DEVICE);
+	usb_gadget_release(usbctrl_index);
 
 	if (dfu_reset)
 		do_reset(NULL, 0, 0, NULL);
diff --git a/configs/am335x_pdu001_defconfig b/configs/am335x_pdu001_defconfig
index 3cb38af..dc8094e 100644
--- a/configs/am335x_pdu001_defconfig
+++ b/configs/am335x_pdu001_defconfig
@@ -36,6 +36,7 @@
 CONFIG_DEFAULT_DEVICE_TREE="am335x-pdu001"
 # CONFIG_NET is not set
 CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_BLK=y
diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig
index 5242ab6..aa82830 100644
--- a/configs/am57xx_evm_defconfig
+++ b/configs/am57xx_evm_defconfig
@@ -37,6 +37,7 @@
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
 CONFIG_DM=y
 CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_SCSI_AHCI=y
 # CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
@@ -50,6 +51,7 @@
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
+CONFIG_MISC=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_DM_SPI_FLASH=y
@@ -61,6 +63,9 @@
 CONFIG_DM_ETH=y
 CONFIG_DRIVER_TI_CPSW=y
 CONFIG_MII=y
+CONFIG_PHY=y
+CONFIG_PIPE3_PHY=y
+CONFIG_OMAP_USB2_PHY=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_PALMAS=y
 CONFIG_DM_REGULATOR=y
@@ -70,13 +75,15 @@
 CONFIG_DM_SPI=y
 CONFIG_TI_QSPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_SPL_DM_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_SPL_DM_USB_GADGET=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
-CONFIG_USB_DWC3_OMAP=y
-CONFIG_USB_DWC3_PHY_OMAP=y
-CONFIG_OMAP_USB_PHY=y
+CONFIG_USB_DWC3_GENERIC=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am57xx_hs_evm_defconfig b/configs/am57xx_hs_evm_defconfig
index be4aa0f..09f3774 100644
--- a/configs/am57xx_hs_evm_defconfig
+++ b/configs/am57xx_hs_evm_defconfig
@@ -40,6 +40,7 @@
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
 CONFIG_DM=y
 CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_SCSI_AHCI=y
 # CONFIG_BLK is not set
 CONFIG_DFU_MMC=y
@@ -53,6 +54,7 @@
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
+CONFIG_MISC=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_DM_SPI_FLASH=y
@@ -64,6 +66,9 @@
 CONFIG_DM_ETH=y
 CONFIG_DRIVER_TI_CPSW=y
 CONFIG_MII=y
+CONFIG_PHY=y
+CONFIG_PIPE3_PHY=y
+CONFIG_OMAP_USB2_PHY=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_PALMAS=y
 CONFIG_DM_REGULATOR=y
@@ -73,13 +78,15 @@
 CONFIG_DM_SPI=y
 CONFIG_TI_QSPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_SPL_DM_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_SPL_DM_USB_GADGET=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
-CONFIG_USB_DWC3_OMAP=y
-CONFIG_USB_DWC3_PHY_OMAP=y
-CONFIG_OMAP_USB_PHY=y
+CONFIG_USB_DWC3_GENERIC=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig
index 27f6b5d..2b6606f 100644
--- a/configs/dra7xx_evm_defconfig
+++ b/configs/dra7xx_evm_defconfig
@@ -1,7 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_TI_COMMON_CMD_OPTIONS=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SYS_MALLOC_F_LEN=0x18000
 CONFIG_OMAP54XX=y
 CONFIG_TARGET_DRA7XX_EVM=y
 CONFIG_SPL=y
@@ -34,11 +34,13 @@
 CONFIG_DEFAULT_DEVICE_TREE="dra7-evm"
 CONFIG_OF_LIST="dra7-evm dra72-evm dra72-evm-revc dra71-evm dra76-evm"
 CONFIG_SPL_MULTI_DTB_FIT=y
+CONFIG_SPL_MULTI_DTB_FIT_UNCOMPRESS_SZ=0x9000
 CONFIG_OF_SPL_REMOVE_PROPS="clocks clock-names interrupt-parent"
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
 CONFIG_DM=y
 CONFIG_SPL_DM=y
+CONFIG_SPL_DM_DEVICE_REMOVE=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_SPL_REGMAP=y
 CONFIG_SPL_SYSCON=y
@@ -56,6 +58,7 @@
 CONFIG_DM_GPIO=y
 CONFIG_PCF8575_GPIO=y
 CONFIG_DM_I2C=y
+CONFIG_MISC=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_IO_VOLTAGE=y
 CONFIG_MMC_UHS_SUPPORT=y
@@ -72,6 +75,7 @@
 CONFIG_MII=y
 CONFIG_SPL_PHY=y
 CONFIG_PIPE3_PHY=y
+CONFIG_OMAP_USB2_PHY=y
 CONFIG_PMIC_PALMAS=y
 CONFIG_PMIC_LP873X=y
 CONFIG_DM_REGULATOR_FIXED=y
@@ -87,14 +91,14 @@
 CONFIG_OMAP_TIMER=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_SPL_DM_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_SPL_DM_USB_GADGET=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
-CONFIG_USB_XHCI_DRA7XX_INDEX=1
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
-CONFIG_USB_DWC3_OMAP=y
-CONFIG_USB_DWC3_PHY_OMAP=y
-CONFIG_OMAP_USB_PHY=y
+CONFIG_USB_DWC3_GENERIC=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig
index 651fc4f..725acb5 100644
--- a/configs/dra7xx_hs_evm_defconfig
+++ b/configs/dra7xx_hs_evm_defconfig
@@ -41,6 +41,7 @@
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
 CONFIG_DM=y
 CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_SPL_REGMAP=y
 CONFIG_SPL_SYSCON=y
 CONFIG_DWC_AHCI=y
@@ -56,6 +57,7 @@
 CONFIG_DM_GPIO=y
 CONFIG_PCF8575_GPIO=y
 CONFIG_DM_I2C=y
+CONFIG_MISC=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_IO_VOLTAGE=y
 CONFIG_MMC_UHS_SUPPORT=y
@@ -71,6 +73,7 @@
 CONFIG_MII=y
 CONFIG_SPL_PHY=y
 CONFIG_PIPE3_PHY=y
+CONFIG_OMAP_USB2_PHY=y
 CONFIG_PMIC_PALMAS=y
 CONFIG_PMIC_LP873X=y
 CONFIG_DM_REGULATOR_FIXED=y
@@ -86,14 +89,14 @@
 CONFIG_OMAP_TIMER=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_SPL_DM_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_SPL_DM_USB_GADGET=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
-CONFIG_USB_XHCI_DRA7XX_INDEX=1
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
-CONFIG_USB_DWC3_OMAP=y
-CONFIG_USB_DWC3_PHY_OMAP=y
-CONFIG_OMAP_USB_PHY=y
+CONFIG_USB_DWC3_GENERIC=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig
index 5b3bb8e..f022163 100644
--- a/configs/evb-rk3328_defconfig
+++ b/configs/evb-rk3328_defconfig
@@ -49,6 +49,7 @@
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYSRESET=y
 CONFIG_USB=y
+CONFIG_USB_DWC3=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/configs/omap3_logic_defconfig b/configs/omap3_logic_defconfig
index 969387a..3197259 100644
--- a/configs/omap3_logic_defconfig
+++ b/configs/omap3_logic_defconfig
@@ -34,6 +34,7 @@
 # CONFIG_ENV_IS_IN_FAT is not set
 CONFIG_ENV_IS_IN_NAND=y
 CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x82000000
 CONFIG_DM_I2C=y
diff --git a/doc/README.fdt-control b/doc/README.fdt-control
index d6ab7bf..446401c 100644
--- a/doc/README.fdt-control
+++ b/doc/README.fdt-control
@@ -184,6 +184,24 @@
 'SPL Support' in doc/driver-model/README.txt for more details.
 
 
+Using several DTBs in the SPL (CONFIG_SPL_MULTI_DTB)
+----------------------------------------------------
+In some rare cases it is desirable to let SPL be able to select one DTB among
+many. This usually not very useful as the DTB for the SPL is small and usually
+fits several platforms. However the DTB sometimes include information that do
+work on several platforms (like IO tuning parameters).
+In this case it is possible to use CONFIG_SPL_MULTI_DTB. This option appends to
+the SPL a FIT image containing several DTBs listed in SPL_OF_LIST.
+board_fit_config_name_match() is called to select the right DTB.
+
+If board_fit_config_name_match() relies on DM (DM driver to access an EEPROM
+containing the board ID for example), it possible to start with a generic DTB
+and then switch over to the right DTB after the detection. For this purpose,
+the platform code must call fdtdec_resetup(). Based on the returned flag, the
+platform may have to re-initiliaze the DM subusystem using dm_uninit() and
+dm_init_and_scan().
+
+
 Limitations
 -----------
 
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index e8ba20c..046b87a 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -57,13 +57,21 @@
 	default y
 	help
 	  We can save some code space by dropping support for removing a
-	  device. This is not normally required in SPL, so by default this
-	  option is disabled for SPL.
+	  device.
 
 	  Note that this may have undesirable results in the USB subsystem as
 	  it causes unplugged devices to linger around in the dm-tree, and it
 	  causes USB host controllers to not be stopped when booting the OS.
 
+config SPL_DM_DEVICE_REMOVE
+	bool "Support device removal in SPL"
+	depends on SPL_DM
+	default n
+	help
+	  We can save some code space by dropping support for removing a
+	  device. This is not normally required in SPL, so by default this
+	  option is disabled for SPL.
+
 config DM_STDIO
 	bool "Support stdio registration"
 	depends on DM
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 836bcad..0d15e50 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -70,7 +70,8 @@
 
 	dev->seq = -1;
 	dev->req_seq = -1;
-	if (CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_SEQ_ALIAS)) {
+	if (CONFIG_IS_ENABLED(DM_SEQ_ALIAS) &&
+	    (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS)) {
 		/*
 		 * Some devices, such as a SPI bus, I2C bus and serial ports
 		 * are numbered using aliases.
@@ -78,10 +79,11 @@
 		 * This is just a 'requested' sequence, and will be
 		 * resolved (and ->seq updated) when the device is probed.
 		 */
-		if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {
-			if (uc->uc_drv->name && ofnode_valid(node)) {
+		if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
+			if (uc->uc_drv->name && ofnode_valid(node))
 				dev_read_alias_seq(dev, &dev->req_seq);
-			}
+		} else {
+			dev->req_seq = uclass_find_next_free_req_seq(drv->id);
 		}
 	}
 
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 4ce55f9..e6ec7fa 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -187,6 +187,7 @@
 {
 	device_remove(dm_root(), DM_REMOVE_NORMAL);
 	device_unbind(dm_root());
+	gd->dm_root = NULL;
 
 	return 0;
 }
diff --git a/drivers/core/syscon-uclass.c b/drivers/core/syscon-uclass.c
index 303e166..661cf61 100644
--- a/drivers/core/syscon-uclass.c
+++ b/drivers/core/syscon-uclass.c
@@ -53,6 +53,29 @@
 #endif
 }
 
+struct regmap *syscon_regmap_lookup_by_phandle(struct udevice *dev,
+					       const char *name)
+{
+	struct udevice *syscon;
+	struct regmap *r;
+	int err;
+
+	err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
+					   name, &syscon);
+	if (err) {
+		dev_dbg(dev, "unable to find syscon device\n");
+		return ERR_PTR(err);
+	}
+
+	r = syscon_get_regmap(syscon);
+	if (!r) {
+		dev_dbg(dev, "unable to find regmap\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	return r;
+}
+
 int syscon_get_by_driver_data(ulong driver_data, struct udevice **devp)
 {
 	struct udevice *dev;
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 9766aea..a622f07 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -269,6 +269,30 @@
 	return -ENODEV;
 }
 
+#if !CONFIG_IS_ENABLED(OF_CONTROL) || CONFIG_IS_ENABLED(OF_PLATDATA)
+int uclass_find_next_free_req_seq(enum uclass_id id)
+{
+	struct uclass *uc;
+	struct udevice *dev;
+	int ret;
+	int max = -1;
+
+	ret = uclass_get(id, &uc);
+	if (ret)
+		return ret;
+
+	list_for_each_entry(dev, &uc->dev_head, uclass_node) {
+		if ((dev->req_seq != -1) && (dev->req_seq > max))
+			max = dev->req_seq;
+	}
+
+	if (max == -1)
+		return 0;
+
+	return max + 1;
+}
+#endif
+
 int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq,
 			      bool find_req_seq, struct udevice **devp)
 {
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c
index c5a3c4e..975318e 100644
--- a/drivers/i2c/i2c-uclass.c
+++ b/drivers/i2c/i2c-uclass.c
@@ -347,6 +347,17 @@
 		debug("Cannot find I2C bus %d\n", busnum);
 		return ret;
 	}
+
+	/* detect the presence of the chip on the bus */
+	ret = i2c_probe_chip(bus, chip_addr, 0);
+	debug("%s: bus='%s', address %02x, ret=%d\n", __func__, bus->name,
+	      chip_addr, ret);
+	if (ret) {
+		debug("Cannot detect I2C chip %02x on bus %d\n", chip_addr,
+		      busnum);
+		return ret;
+	}
+
 	ret = i2c_get_chip(bus, chip_addr, offset_len, devp);
 	if (ret) {
 		debug("Cannot find I2C chip %02x on bus %d\n", chip_addr,
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 51f9237..4b93e02 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -42,8 +42,18 @@
 #include <dm.h>
 #include <i2c.h>
 
-#include <asm/arch/i2c.h>
 #include <asm/io.h>
+#include <asm/omap_i2c.h>
+
+/*
+ * Provide access to architecture-specific I2C header files for platforms
+ * that are NOT yet solely relying on CONFIG_DM_I2C, CONFIG_OF_CONTROL, and
+ * the defaults provided in 'omap24xx_i2c.h' for all U-Boot stages where I2C
+ * access is desired.
+ */
+#ifndef CONFIG_ARCH_K3
+#include <asm/arch/i2c.h>
+#endif
 
 #include "omap24xx_i2c.h"
 
@@ -52,14 +62,107 @@
 /* Absolutely safe for status update at 100 kHz I2C: */
 #define I2C_WAIT	200
 
+enum {
+	OMAP_I2C_REV_REG = 0,		/* Only on IP V1 (OMAP34XX) */
+	OMAP_I2C_IE_REG,		/* Only on IP V1 (OMAP34XX) */
+	OMAP_I2C_STAT_REG,
+	OMAP_I2C_WE_REG,
+	OMAP_I2C_SYSS_REG,
+	OMAP_I2C_BUF_REG,
+	OMAP_I2C_CNT_REG,
+	OMAP_I2C_DATA_REG,
+	OMAP_I2C_SYSC_REG,
+	OMAP_I2C_CON_REG,
+	OMAP_I2C_OA_REG,
+	OMAP_I2C_SA_REG,
+	OMAP_I2C_PSC_REG,
+	OMAP_I2C_SCLL_REG,
+	OMAP_I2C_SCLH_REG,
+	OMAP_I2C_SYSTEST_REG,
+	OMAP_I2C_BUFSTAT_REG,
+	/* Only on IP V2 (OMAP4430, etc.) */
+	OMAP_I2C_IP_V2_REVNB_LO,
+	OMAP_I2C_IP_V2_REVNB_HI,
+	OMAP_I2C_IP_V2_IRQSTATUS_RAW,
+	OMAP_I2C_IP_V2_IRQENABLE_SET,
+	OMAP_I2C_IP_V2_IRQENABLE_CLR,
+};
+
+static const u8 __maybe_unused reg_map_ip_v1[] = {
+	[OMAP_I2C_REV_REG] = 0x00,
+	[OMAP_I2C_IE_REG] = 0x04,
+	[OMAP_I2C_STAT_REG] = 0x08,
+	[OMAP_I2C_WE_REG] = 0x0c,
+	[OMAP_I2C_SYSS_REG] = 0x10,
+	[OMAP_I2C_BUF_REG] = 0x14,
+	[OMAP_I2C_CNT_REG] = 0x18,
+	[OMAP_I2C_DATA_REG] = 0x1c,
+	[OMAP_I2C_SYSC_REG] = 0x20,
+	[OMAP_I2C_CON_REG] = 0x24,
+	[OMAP_I2C_OA_REG] = 0x28,
+	[OMAP_I2C_SA_REG] = 0x2c,
+	[OMAP_I2C_PSC_REG] = 0x30,
+	[OMAP_I2C_SCLL_REG] = 0x34,
+	[OMAP_I2C_SCLH_REG] = 0x38,
+	[OMAP_I2C_SYSTEST_REG] = 0x3c,
+	[OMAP_I2C_BUFSTAT_REG] = 0x40,
+};
+
+static const u8 __maybe_unused reg_map_ip_v2[] = {
+	[OMAP_I2C_STAT_REG] = 0x28,
+	[OMAP_I2C_WE_REG] = 0x34,
+	[OMAP_I2C_SYSS_REG] = 0x90,
+	[OMAP_I2C_BUF_REG] = 0x94,
+	[OMAP_I2C_CNT_REG] = 0x98,
+	[OMAP_I2C_DATA_REG] = 0x9c,
+	[OMAP_I2C_SYSC_REG] = 0x10,
+	[OMAP_I2C_CON_REG] = 0xa4,
+	[OMAP_I2C_OA_REG] = 0xa8,
+	[OMAP_I2C_SA_REG] = 0xac,
+	[OMAP_I2C_PSC_REG] = 0xb0,
+	[OMAP_I2C_SCLL_REG] = 0xb4,
+	[OMAP_I2C_SCLH_REG] = 0xb8,
+	[OMAP_I2C_SYSTEST_REG] = 0xbc,
+	[OMAP_I2C_BUFSTAT_REG] = 0xc0,
+	[OMAP_I2C_IP_V2_REVNB_LO] = 0x00,
+	[OMAP_I2C_IP_V2_REVNB_HI] = 0x04,
+	[OMAP_I2C_IP_V2_IRQSTATUS_RAW] = 0x24,
+	[OMAP_I2C_IP_V2_IRQENABLE_SET] = 0x2c,
+	[OMAP_I2C_IP_V2_IRQENABLE_CLR] = 0x30,
+};
+
 struct omap_i2c {
 	struct udevice *clk;
+	int ip_rev;
 	struct i2c *regs;
 	unsigned int speed;
 	int waitdelay;
 	int clk_id;
 };
 
+static inline const u8 *omap_i2c_get_ip_reg_map(int ip_rev)
+{
+	switch (ip_rev) {
+	case OMAP_I2C_REV_V1:
+		return reg_map_ip_v1;
+	case OMAP_I2C_REV_V2:
+		/* Fall through... */
+	default:
+		return reg_map_ip_v2;
+	}
+}
+
+static inline void omap_i2c_write_reg(void __iomem *base, int ip_rev,
+				      u16 val, int reg)
+{
+	writew(val, base + omap_i2c_get_ip_reg_map(ip_rev)[reg]);
+}
+
+static inline u16 omap_i2c_read_reg(void __iomem *base, int ip_rev, int reg)
+{
+	return readw(base + omap_i2c_get_ip_reg_map(ip_rev)[reg]);
+}
+
 static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed)
 {
 	unsigned long internal_clk = 0, fclk;
@@ -114,29 +217,31 @@
  * Wait for the bus to be free by checking the Bus Busy (BB)
  * bit to become clear
  */
-static int wait_for_bb(struct i2c *i2c_base, int waitdelay)
+static int wait_for_bb(void __iomem *i2c_base, int ip_rev, int waitdelay)
 {
 	int timeout = I2C_TIMEOUT;
+	int irq_stat_reg;
 	u16 stat;
 
-	writew(0xFFFF, &i2c_base->stat);	/* clear current interrupts...*/
-#if defined(CONFIG_OMAP34XX)
-	while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) {
-#else
-	/* Read RAW status */
-	while ((stat = readw(&i2c_base->irqstatus_raw) &
+	irq_stat_reg = (ip_rev == OMAP_I2C_REV_V1) ?
+		       OMAP_I2C_STAT_REG : OMAP_I2C_IP_V2_IRQSTATUS_RAW;
+
+	/* clear current interrupts */
+	omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG);
+
+	while ((stat = omap_i2c_read_reg(i2c_base, ip_rev, irq_stat_reg) &
 		I2C_STAT_BB) && timeout--) {
-#endif
-		writew(stat, &i2c_base->stat);
+		omap_i2c_write_reg(i2c_base, ip_rev, stat, OMAP_I2C_STAT_REG);
 		udelay(waitdelay);
 	}
 
 	if (timeout <= 0) {
-		printf("Timed out in wait_for_bb: status=%04x\n",
-		       stat);
+		printf("Timed out in %s: status=%04x\n", __func__, stat);
 		return 1;
 	}
-	writew(0xFFFF, &i2c_base->stat);	 /* clear delayed stuff*/
+
+	/* clear delayed stuff */
+	omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG);
 	return 0;
 }
 
@@ -144,40 +249,37 @@
  * Wait for the I2C controller to complete current action
  * and update status
  */
-static u16 wait_for_event(struct i2c *i2c_base, int waitdelay)
+static u16 wait_for_event(void __iomem *i2c_base, int ip_rev, int waitdelay)
 {
 	u16 status;
 	int timeout = I2C_TIMEOUT;
+	int irq_stat_reg;
 
+	irq_stat_reg = (ip_rev == OMAP_I2C_REV_V1) ?
+		       OMAP_I2C_STAT_REG : OMAP_I2C_IP_V2_IRQSTATUS_RAW;
 	do {
 		udelay(waitdelay);
-#if defined(CONFIG_OMAP34XX)
-		status = readw(&i2c_base->stat);
-#else
-		/* Read RAW status */
-		status = readw(&i2c_base->irqstatus_raw);
-#endif
+		status = omap_i2c_read_reg(i2c_base, ip_rev, irq_stat_reg);
 	} while (!(status &
 		   (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
 		    I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
 		    I2C_STAT_AL)) && timeout--);
 
 	if (timeout <= 0) {
-		printf("Timed out in wait_for_event: status=%04x\n",
-		       status);
+		printf("Timed out in %s: status=%04x\n", __func__, status);
 		/*
 		 * If status is still 0 here, probably the bus pads have
 		 * not been configured for I2C, and/or pull-ups are missing.
 		 */
 		printf("Check if pads/pull-ups of bus are properly configured\n");
-		writew(0xFFFF, &i2c_base->stat);
+		omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG);
 		status = 0;
 	}
 
 	return status;
 }
 
-static void flush_fifo(struct i2c *i2c_base)
+static void flush_fifo(void __iomem *i2c_base, int ip_rev)
 {
 	u16 stat;
 
@@ -186,17 +288,18 @@
 	 * you get a bus error
 	 */
 	while (1) {
-		stat = readw(&i2c_base->stat);
+		stat = omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_STAT_REG);
 		if (stat == I2C_STAT_RRDY) {
-			readb(&i2c_base->data);
-			writew(I2C_STAT_RRDY, &i2c_base->stat);
+			omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_DATA_REG);
+			omap_i2c_write_reg(i2c_base, ip_rev,
+					   I2C_STAT_RRDY, OMAP_I2C_STAT_REG);
 			udelay(1000);
 		} else
 			break;
 	}
 }
 
-static int __omap24_i2c_setspeed(struct i2c *i2c_base, uint speed,
+static int __omap24_i2c_setspeed(void __iomem *i2c_base, int ip_rev, uint speed,
 				 int *waitdelay)
 {
 	int psc, fsscll = 0, fssclh = 0;
@@ -248,79 +351,89 @@
 		}
 	}
 
-	*waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods */
-	writew(0, &i2c_base->con);
-	writew(psc, &i2c_base->psc);
-	writew(scll, &i2c_base->scll);
-	writew(sclh, &i2c_base->sclh);
-	writew(I2C_CON_EN, &i2c_base->con);
-	writew(0xFFFF, &i2c_base->stat);	/* clear all pending status */
+	/* wait for 20 clkperiods */
+	*waitdelay = (10000000 / speed) * 2;
+
+	omap_i2c_write_reg(i2c_base, ip_rev, 0,  OMAP_I2C_CON_REG);
+	omap_i2c_write_reg(i2c_base, ip_rev, psc, OMAP_I2C_PSC_REG);
+	omap_i2c_write_reg(i2c_base, ip_rev, scll, OMAP_I2C_SCLL_REG);
+	omap_i2c_write_reg(i2c_base, ip_rev, sclh, OMAP_I2C_SCLH_REG);
+	omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN, OMAP_I2C_CON_REG);
+
+	/* clear all pending status */
+	omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG);
 
 	return 0;
 }
 
-static void omap24_i2c_deblock(struct i2c *i2c_base)
+static void omap24_i2c_deblock(void __iomem *i2c_base, int ip_rev)
 {
 	int i;
 	u16 systest;
 	u16 orgsystest;
 
 	/* set test mode ST_EN = 1 */
-	orgsystest = readw(&i2c_base->systest);
+	orgsystest = omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_SYSTEST_REG);
 	systest = orgsystest;
+
 	/* enable testmode */
 	systest |= I2C_SYSTEST_ST_EN;
-	writew(systest, &i2c_base->systest);
+	omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG);
 	systest &= ~I2C_SYSTEST_TMODE_MASK;
 	systest |= 3 << I2C_SYSTEST_TMODE_SHIFT;
-	writew(systest, &i2c_base->systest);
+	omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG);
 
 	/* set SCL, SDA  = 1 */
 	systest |= I2C_SYSTEST_SCL_O | I2C_SYSTEST_SDA_O;
-	writew(systest, &i2c_base->systest);
+	omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG);
 	udelay(10);
 
 	/* toggle scl 9 clocks */
 	for (i = 0; i < 9; i++) {
 		/* SCL = 0 */
 		systest &= ~I2C_SYSTEST_SCL_O;
-		writew(systest, &i2c_base->systest);
+		omap_i2c_write_reg(i2c_base, ip_rev,
+				   systest, OMAP_I2C_SYSTEST_REG);
 		udelay(10);
 		/* SCL = 1 */
 		systest |= I2C_SYSTEST_SCL_O;
-		writew(systest, &i2c_base->systest);
+		omap_i2c_write_reg(i2c_base, ip_rev,
+				   systest, OMAP_I2C_SYSTEST_REG);
 		udelay(10);
 	}
 
 	/* send stop */
 	systest &= ~I2C_SYSTEST_SDA_O;
-	writew(systest, &i2c_base->systest);
+	omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG);
 	udelay(10);
 	systest |= I2C_SYSTEST_SCL_O | I2C_SYSTEST_SDA_O;
-	writew(systest, &i2c_base->systest);
+	omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG);
 	udelay(10);
 
 	/* restore original mode */
-	writew(orgsystest, &i2c_base->systest);
+	omap_i2c_write_reg(i2c_base, ip_rev, orgsystest, OMAP_I2C_SYSTEST_REG);
 }
 
-static void __omap24_i2c_init(struct i2c *i2c_base, int speed, int slaveadd,
-			      int *waitdelay)
+static void __omap24_i2c_init(void __iomem *i2c_base, int ip_rev, int speed,
+			      int slaveadd, int *waitdelay)
 {
 	int timeout = I2C_TIMEOUT;
 	int deblock = 1;
 
 retry:
-	if (readw(&i2c_base->con) & I2C_CON_EN) {
-		writew(0, &i2c_base->con);
+	if (omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_CON_REG) &
+	    I2C_CON_EN) {
+		omap_i2c_write_reg(i2c_base, ip_rev, 0, OMAP_I2C_CON_REG);
 		udelay(50000);
 	}
 
-	writew(0x2, &i2c_base->sysc); /* for ES2 after soft reset */
+	/* for ES2 after soft reset */
+	omap_i2c_write_reg(i2c_base, ip_rev, 0x2, OMAP_I2C_SYSC_REG);
 	udelay(1000);
 
-	writew(I2C_CON_EN, &i2c_base->con);
-	while (!(readw(&i2c_base->syss) & I2C_SYSS_RDONE) && timeout--) {
+	omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN, OMAP_I2C_CON_REG);
+	while (!(omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_SYSS_REG) &
+		 I2C_SYSS_RDONE) && timeout--) {
 		if (timeout <= 0) {
 			puts("ERROR: Timeout in soft-reset\n");
 			return;
@@ -328,30 +441,33 @@
 		udelay(1000);
 	}
 
-	if (0 != __omap24_i2c_setspeed(i2c_base, speed, waitdelay)) {
+	if (__omap24_i2c_setspeed(i2c_base, ip_rev, speed, waitdelay)) {
 		printf("ERROR: failed to setup I2C bus-speed!\n");
 		return;
 	}
 
 	/* own address */
-	writew(slaveadd, &i2c_base->oa);
+	omap_i2c_write_reg(i2c_base, ip_rev, slaveadd, OMAP_I2C_OA_REG);
 
-#if defined(CONFIG_OMAP34XX)
-	/*
-	 * Have to enable interrupts for OMAP2/3, these IPs don't have
-	 * an 'irqstatus_raw' register and we shall have to poll 'stat'
-	 */
-	writew(I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
-	       I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie);
-#endif
+	if (ip_rev == OMAP_I2C_REV_V1) {
+		/*
+		 * Have to enable interrupts for OMAP2/3, these IPs don't have
+		 * an 'irqstatus_raw' register and we shall have to poll 'stat'
+		 */
+		omap_i2c_write_reg(i2c_base, ip_rev, I2C_IE_XRDY_IE |
+				   I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
+				   I2C_IE_NACK_IE | I2C_IE_AL_IE,
+				   OMAP_I2C_IE_REG);
+	}
+
 	udelay(1000);
-	flush_fifo(i2c_base);
-	writew(0xFFFF, &i2c_base->stat);
+	flush_fifo(i2c_base, ip_rev);
+	omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG);
 
 	/* Handle possible failed I2C state */
-	if (wait_for_bb(i2c_base, *waitdelay))
+	if (wait_for_bb(i2c_base, ip_rev, *waitdelay))
 		if (deblock == 1) {
-			omap24_i2c_deblock(i2c_base);
+			omap24_i2c_deblock(i2c_base, ip_rev);
 			deblock = 0;
 			goto retry;
 		}
@@ -361,25 +477,28 @@
  * i2c_probe: Use write access. Allows to identify addresses that are
  *            write-only (like the config register of dual-port EEPROMs)
  */
-static int __omap24_i2c_probe(struct i2c *i2c_base, int waitdelay, uchar chip)
+static int __omap24_i2c_probe(void __iomem *i2c_base, int ip_rev, int waitdelay,
+			      uchar chip)
 {
 	u16 status;
 	int res = 1; /* default = fail */
 
-	if (chip == readw(&i2c_base->oa))
+	if (chip == omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_OA_REG))
 		return res;
 
 	/* Wait until bus is free */
-	if (wait_for_bb(i2c_base, waitdelay))
+	if (wait_for_bb(i2c_base, ip_rev, waitdelay))
 		return res;
 
 	/* No data transfer, slave addr only */
-	writew(chip, &i2c_base->sa);
-	/* Stop bit needed here */
-	writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
-	       I2C_CON_STP, &i2c_base->con);
+	omap_i2c_write_reg(i2c_base, ip_rev, chip, OMAP_I2C_SA_REG);
 
-	status = wait_for_event(i2c_base, waitdelay);
+	/* Stop bit needed here */
+	omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST |
+			   I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP,
+			   OMAP_I2C_CON_REG);
+
+	status = wait_for_event(i2c_base, ip_rev, waitdelay);
 
 	if ((status & ~I2C_STAT_XRDY) == 0 || (status & I2C_STAT_AL)) {
 		/*
@@ -400,14 +519,17 @@
 		res = 0;				/* Device found */
 		udelay(waitdelay);/* Required by AM335X in SPL */
 		/* Abort transfer (force idle state) */
-		writew(I2C_CON_MST | I2C_CON_TRX, &i2c_base->con); /* Reset */
+		omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_MST | I2C_CON_TRX,
+				   OMAP_I2C_CON_REG);	/* Reset */
 		udelay(1000);
-		writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_TRX |
-		       I2C_CON_STP, &i2c_base->con);		/* STP */
+		omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST |
+				   I2C_CON_TRX | I2C_CON_STP,
+				   OMAP_I2C_CON_REG);	/* STP */
 	}
+
 pr_exit:
-	flush_fifo(i2c_base);
-	writew(0xFFFF, &i2c_base->stat);
+	flush_fifo(i2c_base, ip_rev);
+	omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG);
 	return res;
 }
 
@@ -424,8 +546,9 @@
  *           or that do not need a register address at all (such as some clock
  *           distributors).
  */
-static int __omap24_i2c_read(struct i2c *i2c_base, int waitdelay, uchar chip,
-			     uint addr, int alen, uchar *buffer, int len)
+static int __omap24_i2c_read(void __iomem *i2c_base, int ip_rev, int waitdelay,
+			     uchar chip, uint addr, int alen, uchar *buffer,
+			     int len)
 {
 	int i2c_error = 0;
 	u16 status;
@@ -434,10 +557,12 @@
 		puts("I2C read: addr len < 0\n");
 		return 1;
 	}
+
 	if (len < 0) {
 		puts("I2C read: data len < 0\n");
 		return 1;
 	}
+
 	if (buffer == NULL) {
 		puts("I2C read: NULL pointer passed\n");
 		return 1;
@@ -471,28 +596,29 @@
 #endif
 
 	/* Wait until bus not busy */
-	if (wait_for_bb(i2c_base, waitdelay))
+	if (wait_for_bb(i2c_base, ip_rev, waitdelay))
 		return 1;
 
 	/* Zero, one or two bytes reg address (offset) */
-	writew(alen, &i2c_base->cnt);
+	omap_i2c_write_reg(i2c_base, ip_rev, alen, OMAP_I2C_CNT_REG);
 	/* Set slave address */
-	writew(chip, &i2c_base->sa);
+	omap_i2c_write_reg(i2c_base, ip_rev, chip, OMAP_I2C_SA_REG);
 
 	if (alen) {
 		/* Must write reg offset first */
 #ifdef CONFIG_I2C_REPEATED_START
 		/* No stop bit, use Repeated Start (Sr) */
-		writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT |
-		       I2C_CON_TRX, &i2c_base->con);
+		omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST |
+				   I2C_CON_STT | I2C_CON_TRX, OMAP_I2C_CON_REG);
 #else
 		/* Stop - Start (P-S) */
-		writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP |
-		       I2C_CON_TRX, &i2c_base->con);
+		omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST |
+				   I2C_CON_STT | I2C_CON_STP | I2C_CON_TRX,
+				   OMAP_I2C_CON_REG);
 #endif
 		/* Send register offset */
 		while (1) {
-			status = wait_for_event(i2c_base, waitdelay);
+			status = wait_for_event(i2c_base, ip_rev, waitdelay);
 			/* Try to identify bus that is not padconf'd for I2C */
 			if (status == I2C_STAT_XRDY) {
 				i2c_error = 2;
@@ -508,31 +634,37 @@
 			}
 			if (alen) {
 				if (status & I2C_STAT_XRDY) {
+					u8 addr_byte;
 					alen--;
-					/* Do we have to use byte access? */
-					writeb((addr >> (8 * alen)) & 0xff,
-					       &i2c_base->data);
-					writew(I2C_STAT_XRDY, &i2c_base->stat);
+					addr_byte = (addr >> (8 * alen)) & 0xff;
+					omap_i2c_write_reg(i2c_base, ip_rev,
+							   addr_byte,
+							   OMAP_I2C_DATA_REG);
+					omap_i2c_write_reg(i2c_base, ip_rev,
+							   I2C_STAT_XRDY,
+							   OMAP_I2C_STAT_REG);
 				}
 			}
 			if (status & I2C_STAT_ARDY) {
-				writew(I2C_STAT_ARDY, &i2c_base->stat);
+				omap_i2c_write_reg(i2c_base, ip_rev,
+						   I2C_STAT_ARDY,
+						   OMAP_I2C_STAT_REG);
 				break;
 			}
 		}
 	}
+
 	/* Set slave address */
-	writew(chip, &i2c_base->sa);
+	omap_i2c_write_reg(i2c_base, ip_rev, chip, OMAP_I2C_SA_REG);
 	/* Read len bytes from slave */
-	writew(len, &i2c_base->cnt);
+	omap_i2c_write_reg(i2c_base, ip_rev, len, OMAP_I2C_CNT_REG);
 	/* Need stop bit here */
-	writew(I2C_CON_EN | I2C_CON_MST |
-	       I2C_CON_STT | I2C_CON_STP,
-	       &i2c_base->con);
+	omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST |
+			   I2C_CON_STT | I2C_CON_STP, OMAP_I2C_CON_REG);
 
 	/* Receive data */
 	while (1) {
-		status = wait_for_event(i2c_base, waitdelay);
+		status = wait_for_event(i2c_base, ip_rev, waitdelay);
 		/*
 		 * Try to identify bus that is not padconf'd for I2C. This
 		 * state could be left over from previous transactions if
@@ -549,24 +681,28 @@
 			goto rd_exit;
 		}
 		if (status & I2C_STAT_RRDY) {
-			*buffer++ = readb(&i2c_base->data);
-			writew(I2C_STAT_RRDY, &i2c_base->stat);
+			*buffer++ = omap_i2c_read_reg(i2c_base, ip_rev,
+						      OMAP_I2C_DATA_REG);
+			omap_i2c_write_reg(i2c_base, ip_rev,
+					   I2C_STAT_RRDY, OMAP_I2C_STAT_REG);
 		}
 		if (status & I2C_STAT_ARDY) {
-			writew(I2C_STAT_ARDY, &i2c_base->stat);
+			omap_i2c_write_reg(i2c_base, ip_rev,
+					   I2C_STAT_ARDY, OMAP_I2C_STAT_REG);
 			break;
 		}
 	}
 
 rd_exit:
-	flush_fifo(i2c_base);
-	writew(0xFFFF, &i2c_base->stat);
+	flush_fifo(i2c_base, ip_rev);
+	omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG);
 	return i2c_error;
 }
 
 /* i2c_write: Address (reg offset) may be 0, 1 or 2 bytes long. */
-static int __omap24_i2c_write(struct i2c *i2c_base, int waitdelay, uchar chip,
-			      uint addr, int alen, uchar *buffer, int len)
+static int __omap24_i2c_write(void __iomem *i2c_base, int ip_rev, int waitdelay,
+			      uchar chip, uint addr, int alen, uchar *buffer,
+			      int len)
 {
 	int i;
 	u16 status;
@@ -617,20 +753,21 @@
 #endif
 
 	/* Wait until bus not busy */
-	if (wait_for_bb(i2c_base, waitdelay))
+	if (wait_for_bb(i2c_base, ip_rev, waitdelay))
 		return 1;
 
 	/* Start address phase - will write regoffset + len bytes data */
-	writew(alen + len, &i2c_base->cnt);
+	omap_i2c_write_reg(i2c_base, ip_rev, alen + len, OMAP_I2C_CNT_REG);
 	/* Set slave address */
-	writew(chip, &i2c_base->sa);
+	omap_i2c_write_reg(i2c_base, ip_rev, chip, OMAP_I2C_SA_REG);
 	/* Stop bit needed here */
-	writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
-	       I2C_CON_STP, &i2c_base->con);
+	omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST |
+			   I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP,
+			   OMAP_I2C_CON_REG);
 
 	while (alen) {
 		/* Must write reg offset (one or two bytes) */
-		status = wait_for_event(i2c_base, waitdelay);
+		status = wait_for_event(i2c_base, ip_rev, waitdelay);
 		/* Try to identify bus that is not padconf'd for I2C */
 		if (status == I2C_STAT_XRDY) {
 			i2c_error = 2;
@@ -646,8 +783,11 @@
 		}
 		if (status & I2C_STAT_XRDY) {
 			alen--;
-			writeb((addr >> (8 * alen)) & 0xff, &i2c_base->data);
-			writew(I2C_STAT_XRDY, &i2c_base->stat);
+			omap_i2c_write_reg(i2c_base, ip_rev,
+					   (addr >> (8 * alen)) & 0xff,
+					   OMAP_I2C_DATA_REG);
+			omap_i2c_write_reg(i2c_base, ip_rev,
+					   I2C_STAT_XRDY, OMAP_I2C_STAT_REG);
 		} else {
 			i2c_error = 1;
 			printf("i2c_write: bus not ready for addr Tx (status=0x%x)\n",
@@ -655,9 +795,10 @@
 			goto wr_exit;
 		}
 	}
+
 	/* Address phase is over, now write data */
 	for (i = 0; i < len; i++) {
-		status = wait_for_event(i2c_base, waitdelay);
+		status = wait_for_event(i2c_base, ip_rev, waitdelay);
 		if (status == 0 || (status & I2C_STAT_NACK)) {
 			i2c_error = 1;
 			printf("i2c_write: error waiting for data ACK (status=0x%x)\n",
@@ -665,8 +806,10 @@
 			goto wr_exit;
 		}
 		if (status & I2C_STAT_XRDY) {
-			writeb(buffer[i], &i2c_base->data);
-			writew(I2C_STAT_XRDY, &i2c_base->stat);
+			omap_i2c_write_reg(i2c_base, ip_rev,
+					   buffer[i], OMAP_I2C_DATA_REG);
+			omap_i2c_write_reg(i2c_base, ip_rev,
+					   I2C_STAT_XRDY, OMAP_I2C_STAT_REG);
 		} else {
 			i2c_error = 1;
 			printf("i2c_write: bus not ready for data Tx (i=%d)\n",
@@ -674,19 +817,20 @@
 			goto wr_exit;
 		}
 	}
+
 	/*
 	 * poll ARDY bit for making sure that last byte really has been
 	 * transferred on the bus.
 	 */
 	do {
-		status = wait_for_event(i2c_base, waitdelay);
+		status = wait_for_event(i2c_base, ip_rev, waitdelay);
 	} while (!(status & I2C_STAT_ARDY) && timeout--);
 	if (timeout <= 0)
 		printf("i2c_write: timed out writig last byte!\n");
 
 wr_exit:
-	flush_fifo(i2c_base);
-	writew(0xFFFF, &i2c_base->stat);
+	flush_fifo(i2c_base, ip_rev);
+	omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG);
 	return i2c_error;
 }
 
@@ -695,26 +839,26 @@
  * The legacy I2C functions. These need to get removed once
  * all users of this driver are converted to DM.
  */
-static struct i2c *omap24_get_base(struct i2c_adapter *adap)
+static void __iomem *omap24_get_base(struct i2c_adapter *adap)
 {
 	switch (adap->hwadapnr) {
 	case 0:
-		return (struct i2c *)I2C_BASE1;
+		return (void __iomem *)I2C_BASE1;
 		break;
 	case 1:
-		return (struct i2c *)I2C_BASE2;
+		return (void __iomem *)I2C_BASE2;
 		break;
 #if (CONFIG_SYS_I2C_BUS_MAX > 2)
 	case 2:
-		return (struct i2c *)I2C_BASE3;
+		return (void __iomem *)I2C_BASE3;
 		break;
 #if (CONFIG_SYS_I2C_BUS_MAX > 3)
 	case 3:
-		return (struct i2c *)I2C_BASE4;
+		return (void __iomem *)I2C_BASE4;
 		break;
 #if (CONFIG_SYS_I2C_BUS_MAX > 4)
 	case 4:
-		return (struct i2c *)I2C_BASE5;
+		return (void __iomem *)I2C_BASE5;
 		break;
 #endif
 #endif
@@ -723,35 +867,46 @@
 		printf("wrong hwadapnr: %d\n", adap->hwadapnr);
 		break;
 	}
+
 	return NULL;
 }
 
+static int omap24_get_ip_rev(void)
+{
+#ifdef CONFIG_OMAP34XX
+	return OMAP_I2C_REV_V1;
+#else
+	return OMAP_I2C_REV_V2;
+#endif
+}
 
 static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
 			   int alen, uchar *buffer, int len)
 {
-	struct i2c *i2c_base = omap24_get_base(adap);
+	void __iomem *i2c_base = omap24_get_base(adap);
+	int ip_rev = omap24_get_ip_rev();
 
-	return __omap24_i2c_read(i2c_base, adap->waitdelay, chip, addr,
+	return __omap24_i2c_read(i2c_base, ip_rev, adap->waitdelay, chip, addr,
 				 alen, buffer, len);
 }
 
-
 static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
 			    int alen, uchar *buffer, int len)
 {
-	struct i2c *i2c_base = omap24_get_base(adap);
+	void __iomem *i2c_base = omap24_get_base(adap);
+	int ip_rev = omap24_get_ip_rev();
 
-	return __omap24_i2c_write(i2c_base, adap->waitdelay, chip, addr,
+	return __omap24_i2c_write(i2c_base, ip_rev, adap->waitdelay, chip, addr,
 				  alen, buffer, len);
 }
 
 static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed)
 {
-	struct i2c *i2c_base = omap24_get_base(adap);
+	void __iomem *i2c_base = omap24_get_base(adap);
+	int ip_rev = omap24_get_ip_rev();
 	int ret;
 
-	ret = __omap24_i2c_setspeed(i2c_base, speed, &adap->waitdelay);
+	ret = __omap24_i2c_setspeed(i2c_base, ip_rev, speed, &adap->waitdelay);
 	if (ret) {
 		pr_err("%s: set i2c speed failed\n", __func__);
 		return ret;
@@ -764,16 +919,19 @@
 
 static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
 {
-	struct i2c *i2c_base = omap24_get_base(adap);
+	void __iomem *i2c_base = omap24_get_base(adap);
+	int ip_rev = omap24_get_ip_rev();
 
-	return __omap24_i2c_init(i2c_base, speed, slaveadd, &adap->waitdelay);
+	return __omap24_i2c_init(i2c_base, ip_rev, speed, slaveadd,
+				 &adap->waitdelay);
 }
 
 static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip)
 {
-	struct i2c *i2c_base = omap24_get_base(adap);
+	void __iomem *i2c_base = omap24_get_base(adap);
+	int ip_rev = omap24_get_ip_rev();
 
-	return __omap24_i2c_probe(i2c_base, adap->waitdelay, chip);
+	return __omap24_i2c_probe(i2c_base, ip_rev, adap->waitdelay, chip);
 }
 
 #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED1)
@@ -793,6 +951,7 @@
 			 CONFIG_SYS_OMAP24_I2C_SPEED1,
 			 CONFIG_SYS_OMAP24_I2C_SLAVE1,
 			 1)
+
 #if (CONFIG_SYS_I2C_BUS_MAX > 2)
 #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED2)
 #define CONFIG_SYS_OMAP24_I2C_SPEED2 CONFIG_SYS_OMAP24_I2C_SPEED
@@ -847,11 +1006,13 @@
 	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 = __omap24_i2c_read(priv->regs, priv->waitdelay,
+			ret = __omap24_i2c_read(priv->regs, priv->ip_rev,
+						priv->waitdelay,
 						msg->addr, 0, 0, msg->buf,
 						msg->len);
 		} else {
-			ret = __omap24_i2c_write(priv->regs, priv->waitdelay,
+			ret = __omap24_i2c_write(priv->regs, priv->ip_rev,
+						 priv->waitdelay,
 						 msg->addr, 0, 0, msg->buf,
 						 msg->len);
 		}
@@ -870,7 +1031,8 @@
 
 	priv->speed = speed;
 
-	return __omap24_i2c_setspeed(priv->regs, speed, &priv->waitdelay);
+	return __omap24_i2c_setspeed(priv->regs, priv->ip_rev, speed,
+				     &priv->waitdelay);
 }
 
 static int omap_i2c_probe_chip(struct udevice *bus, uint chip_addr,
@@ -878,14 +1040,22 @@
 {
 	struct omap_i2c *priv = dev_get_priv(bus);
 
-	return __omap24_i2c_probe(priv->regs, priv->waitdelay, chip_addr);
+	return __omap24_i2c_probe(priv->regs, priv->ip_rev, priv->waitdelay,
+				  chip_addr);
 }
 
 static int omap_i2c_probe(struct udevice *bus)
 {
 	struct omap_i2c *priv = dev_get_priv(bus);
+	struct omap_i2c_platdata *plat = dev_get_platdata(bus);
 
-	__omap24_i2c_init(priv->regs, priv->speed, 0, &priv->waitdelay);
+	priv->speed = plat->speed;
+	priv->regs = map_physmem(plat->base, sizeof(void *),
+				 MAP_NOCACHE);
+	priv->ip_rev = plat->ip_rev;
+
+	__omap24_i2c_init(priv->regs, priv->ip_rev, priv->speed, 0,
+			  &priv->waitdelay);
 
 	return 0;
 }
@@ -893,18 +1063,18 @@
 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 static int omap_i2c_ofdata_to_platdata(struct udevice *bus)
 {
-	struct omap_i2c *priv = dev_get_priv(bus);
+	struct omap_i2c_platdata *plat = dev_get_platdata(bus);
 
-	priv->regs = map_physmem(devfdt_get_addr(bus), sizeof(void *),
-				 MAP_NOCACHE);
-	priv->speed = CONFIG_SYS_OMAP24_I2C_SPEED;
+	plat->base = devfdt_get_addr(bus);
+	plat->speed = dev_read_u32_default(bus, "clock-frequency", 100000);
+	plat->ip_rev = dev_get_driver_data(bus);
 
 	return 0;
 }
 
 static const struct udevice_id omap_i2c_ids[] = {
-	{ .compatible = "ti,omap3-i2c" },
-	{ .compatible = "ti,omap4-i2c" },
+	{ .compatible = "ti,omap3-i2c", .data = OMAP_I2C_REV_V1 },
+	{ .compatible = "ti,omap4-i2c", .data = OMAP_I2C_REV_V2 },
 	{ }
 };
 #endif
@@ -921,6 +1091,7 @@
 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 	.of_match = omap_i2c_ids,
 	.ofdata_to_platdata = omap_i2c_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct omap_i2c_platdata),
 #endif
 	.probe	= omap_i2c_probe,
 	.priv_auto_alloc_size = sizeof(struct omap_i2c),
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 14d82b9..3921e39 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -155,4 +155,13 @@
 
 	  This PHY is found on qualcomm dragonboard410c development board.
 
+config OMAP_USB2_PHY
+	bool "Support OMAP's USB2 PHY"
+	depends on PHY
+	depends on SYSCON
+	help
+	  Support for the OMAP's USB2 PHY.
+
+	  This PHY is found on OMAP devices supporting USB2.
+
 endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 8030d59..53dd5bd 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -17,3 +17,4 @@
 obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o
 obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o
 obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
+obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o
diff --git a/drivers/phy/omap-usb2-phy.c b/drivers/phy/omap-usb2-phy.c
new file mode 100644
index 0000000..fd20e8c
--- /dev/null
+++ b/drivers/phy/omap-usb2-phy.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * OMAP USB2 PHY LAYER
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
+ * Written by Jean-Jacques Hiblot <jjhiblot@ti.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <dm.h>
+#include <errno.h>
+#include <generic-phy.h>
+#include <regmap.h>
+#include <syscon.h>
+
+#define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT	BIT(0)
+
+#define OMAP_DEV_PHY_PD		BIT(0)
+#define OMAP_USB2_PHY_PD	BIT(28)
+
+#define USB2PHY_DISCON_BYP_LATCH	BIT(31)
+#define USB2PHY_ANA_CONFIG1		(0x4c)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct omap_usb2_phy {
+	struct regmap *pwr_regmap;
+	ulong flags;
+	void *phy_base;
+	u32 pwr_reg_offset;
+};
+
+struct usb_phy_data {
+	const char *label;
+	u8 flags;
+	u32 mask;
+	u32 power_on;
+	u32 power_off;
+};
+
+static const struct usb_phy_data omap5_usb2_data = {
+	.label = "omap5_usb2",
+	.flags = 0,
+	.mask = OMAP_DEV_PHY_PD,
+	.power_off = OMAP_DEV_PHY_PD,
+};
+
+static const struct usb_phy_data dra7x_usb2_data = {
+	.label = "dra7x_usb2",
+	.flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
+	.mask = OMAP_DEV_PHY_PD,
+	.power_off = OMAP_DEV_PHY_PD,
+};
+
+static const struct usb_phy_data dra7x_usb2_phy2_data = {
+	.label = "dra7x_usb2_phy2",
+	.flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
+	.mask = OMAP_USB2_PHY_PD,
+	.power_off = OMAP_USB2_PHY_PD,
+};
+
+static const struct udevice_id omap_usb2_id_table[] = {
+	{
+		.compatible = "ti,omap5-usb2",
+		.data = (ulong)&omap5_usb2_data,
+	},
+	{
+		.compatible = "ti,dra7x-usb2",
+		.data = (ulong)&dra7x_usb2_data,
+	},
+	{
+		.compatible = "ti,dra7x-usb2-phy2",
+		.data = (ulong)&dra7x_usb2_phy2_data,
+	},
+	{},
+};
+
+static int omap_usb_phy_power(struct phy *usb_phy, bool on)
+{
+	struct udevice *dev = usb_phy->dev;
+	const struct usb_phy_data *data;
+	const struct omap_usb2_phy *phy = dev_get_priv(dev);
+	u32 val;
+	int rc;
+
+	data = (const struct usb_phy_data *)dev_get_driver_data(dev);
+	if (!data)
+		return -EINVAL;
+
+	rc = regmap_read(phy->pwr_regmap, phy->pwr_reg_offset, &val);
+	if (rc)
+		return rc;
+	val &= ~data->mask;
+	if (on)
+		val |= data->power_on;
+	else
+		val |= data->power_off;
+	rc = regmap_write(phy->pwr_regmap, phy->pwr_reg_offset, val);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int omap_usb2_phy_init(struct phy *usb_phy)
+{
+	struct udevice *dev = usb_phy->dev;
+	struct omap_usb2_phy *priv = dev_get_priv(dev);
+	u32 val;
+
+	if (priv->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
+		/*
+		 *
+		 * Reduce the sensitivity of internal PHY by enabling the
+		 * DISCON_BYP_LATCH of the USB2PHY_ANA_CONFIG1 register. This
+		 * resolves issues with certain devices which can otherwise
+		 * be prone to false disconnects.
+		 *
+		 */
+		val = readl(priv->phy_base + USB2PHY_ANA_CONFIG1);
+		val |= USB2PHY_DISCON_BYP_LATCH;
+		writel(val, priv->phy_base + USB2PHY_ANA_CONFIG1);
+	}
+
+	return 0;
+}
+
+static int omap_usb2_phy_power_on(struct phy *usb_phy)
+{
+	return omap_usb_phy_power(usb_phy, true);
+}
+
+static int omap_usb2_phy_power_off(struct phy *usb_phy)
+{
+	return omap_usb_phy_power(usb_phy, false);
+}
+
+static int omap_usb2_phy_exit(struct phy *usb_phy)
+{
+	return omap_usb_phy_power(usb_phy, false);
+}
+
+struct phy_ops omap_usb2_phy_ops = {
+	.init = omap_usb2_phy_init,
+	.power_on = omap_usb2_phy_power_on,
+	.power_off = omap_usb2_phy_power_off,
+	.exit = omap_usb2_phy_exit,
+};
+
+int omap_usb2_phy_probe(struct udevice *dev)
+{
+	int rc;
+	struct regmap *regmap;
+	struct omap_usb2_phy *priv = dev_get_priv(dev);
+	const struct usb_phy_data *data;
+	u32 tmp[2];
+
+	data = (const struct usb_phy_data *)dev_get_driver_data(dev);
+	if (!data)
+		return -EINVAL;
+
+	if (data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
+		u32 base = dev_read_addr(dev);
+
+		if (base == FDT_ADDR_T_NONE)
+			return -EINVAL;
+		priv->phy_base = (void *)base;
+		priv->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT;
+	}
+
+	regmap = syscon_regmap_lookup_by_phandle(dev, "syscon-phy-power");
+	if (IS_ERR(regmap)) {
+		printf("can't get regmap (err %ld)\n", PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+	priv->pwr_regmap = regmap;
+
+	rc =  dev_read_u32_array(dev, "syscon-phy-power", tmp, 2);
+	if (rc) {
+		printf("couldn't get power reg. offset (err %d)\n", rc);
+		return rc;
+	}
+	priv->pwr_reg_offset = tmp[1];
+
+	return 0;
+}
+
+U_BOOT_DRIVER(omap_usb2_phy) = {
+	.name = "omap_usb2_phy",
+	.id = UCLASS_PHY,
+	.of_match = omap_usb2_id_table,
+	.probe = omap_usb2_phy_probe,
+	.ops = &omap_usb2_phy_ops,
+	.priv_auto_alloc_size = sizeof(struct omap_usb2_phy),
+};
diff --git a/drivers/phy/ti-pipe3-phy.c b/drivers/phy/ti-pipe3-phy.c
index b22bbaf..e7e78e3 100644
--- a/drivers/phy/ti-pipe3-phy.c
+++ b/drivers/phy/ti-pipe3-phy.c
@@ -141,7 +141,7 @@
 	omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION1, val);
 
 	val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION2);
-	val &= ~PLL_SELFREQDCO_MASK;
+	val &= ~(PLL_SELFREQDCO_MASK | PLL_IDLE);
 	val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
 	omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION2, val);
 
@@ -265,10 +265,13 @@
 		return -EBUSY;
 	}
 
-	val = readl(pipe3->pll_reset_reg);
-	writel(val | SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
-	mdelay(1);
-	writel(val & ~SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
+	if (pipe3->pll_reset_reg) {
+		val = readl(pipe3->pll_reset_reg);
+		writel(val | SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
+		mdelay(1);
+		writel(val & ~SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
+	}
+
 	return 0;
 }
 
@@ -331,9 +334,11 @@
 	if (!pipe3->power_reg)
 		return -EINVAL;
 
-	pipe3->pll_reset_reg = get_reg(dev, "syscon-pllreset");
-	if (!pipe3->pll_reset_reg)
-		return -EINVAL;
+	if (device_is_compatible(dev, "ti,phy-pipe3-sata")) {
+		pipe3->pll_reset_reg = get_reg(dev, "syscon-pllreset");
+		if (!pipe3->pll_reset_reg)
+			return -EINVAL;
+	}
 
 	pipe3->dpll_map = (struct pipe3_dpll_map *)dev_get_driver_data(dev);
 
@@ -350,8 +355,19 @@
 	{ },                                    /* Terminator */
 };
 
+static struct pipe3_dpll_map dpll_map_usb[] = {
+	{12000000, {1250, 5, 4, 20, 0} },	/* 12 MHz */
+	{16800000, {3125, 20, 4, 20, 0} },	/* 16.8 MHz */
+	{19200000, {1172, 8, 4, 20, 65537} },	/* 19.2 MHz */
+	{20000000, {1000, 7, 4, 10, 0} },	/* 20 MHz */
+	{26000000, {1250, 12, 4, 20, 0} },	/* 26 MHz */
+	{38400000, {3125, 47, 4, 20, 92843} },	/* 38.4 MHz */
+	{ },					/* Terminator */
+};
+
 static const struct udevice_id pipe3_phy_ids[] = {
 	{ .compatible = "ti,phy-pipe3-sata", .data = (ulong)&dpll_map_sata },
+	{ .compatible = "ti,omap-usb3", .data = (ulong)&dpll_map_usb},
 	{ }
 };
 
diff --git a/drivers/power/palmas.c b/drivers/power/palmas.c
index 6d5abba..2584bea 100644
--- a/drivers/power/palmas.c
+++ b/drivers/power/palmas.c
@@ -175,3 +175,42 @@
 		       val, err);
 	return err;
 }
+
+#ifdef CONFIG_DM_I2C
+int palmas_i2c_write_u8(u8 chip_no, u8 reg, u8 val)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev);
+	if (ret) {
+		pr_err("unable to get I2C bus. ret %d\n", ret);
+		return ret;
+	}
+	ret = dm_i2c_reg_write(dev, reg, val);
+	if (ret) {
+		pr_err("writing to palmas failed. ret %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+int palmas_i2c_read_u8(u8 chip_no, u8 reg, u8 *valp)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev);
+	if (ret) {
+		pr_err("unable to get I2C bus. ret %d\n", ret);
+		return ret;
+	}
+	ret = dm_i2c_reg_read(dev, reg);
+	if (ret < 0) {
+		pr_err("reading from palmas failed. ret %d\n", ret);
+		return ret;
+	}
+	*valp = (u8)ret;
+	return 0;
+}
+#endif
diff --git a/drivers/power/pmic/pmic_tps62362.c b/drivers/power/pmic/pmic_tps62362.c
index f2987de..c3977fc 100644
--- a/drivers/power/pmic/pmic_tps62362.c
+++ b/drivers/power/pmic/pmic_tps62362.c
@@ -10,6 +10,10 @@
 #include <power/pmic.h>
 #include <power/tps62362.h>
 
+#ifdef CONFIG_DM_I2C
+struct udevice *tps62362_dev __attribute__((section(".data"))) = NULL;
+#endif
+
 /**
  * tps62362_voltage_update() - Function to change a voltage level, as this
  *			       is a multi-step process.
@@ -22,9 +26,16 @@
 	if (reg > TPS62362_NUM_REGS)
 		return 1;
 
+#ifndef CONFIG_DM_I2C
 	return i2c_write(TPS62362_I2C_ADDR, reg, 1, &volt_sel, 1);
+#else
+	if (!tps62362_dev)
+		return -ENODEV;
+	return dm_i2c_reg_write(tps62362_dev, reg, volt_sel);
+#endif
 }
 
+#ifndef CONFIG_DM_I2C
 int power_tps62362_init(unsigned char bus)
 {
 	static const char name[] = "TPS62362";
@@ -44,3 +55,16 @@
 
 	return 0;
 }
+#else
+int power_tps62362_init(unsigned char bus)
+{
+	struct udevice *dev = NULL;
+	int rc;
+
+	rc = i2c_get_chip_for_busnum(bus, TPS62362_I2C_ADDR, 1, &dev);
+	if (rc)
+		return rc;
+	tps62362_dev = dev;
+	return 0;
+}
+#endif
diff --git a/drivers/power/pmic/pmic_tps65217.c b/drivers/power/pmic/pmic_tps65217.c
index 01c0ad1..c839e31 100644
--- a/drivers/power/pmic/pmic_tps65217.c
+++ b/drivers/power/pmic/pmic_tps65217.c
@@ -8,6 +8,8 @@
 #include <i2c.h>
 #include <power/tps65217.h>
 
+struct udevice *tps65217_dev __attribute__((section(".data"))) = NULL;
+
 /**
  * tps65217_reg_read() - Generic function that can read a TPS65217 register
  * @src_reg:		 Source register address
@@ -16,7 +18,11 @@
  */
 int tps65217_reg_read(uchar src_reg, uchar *src_val)
 {
+#ifndef CONFIG_DM_I2C
 	return i2c_read(TPS65217_CHIP_PM, src_reg, 1, src_val, 1);
+#else
+	return dm_i2c_read(tps65217_dev, src_reg,  src_val, 1);
+#endif
 }
 
 /**
@@ -46,9 +52,14 @@
 	 * mask
 	 */
 	if (mask != TPS65217_MASK_ALL_BITS) {
+#ifndef CONFIG_DM_I2C
 		ret = i2c_read(TPS65217_CHIP_PM, dest_reg, 1, &read_val, 1);
+#else
+		ret = dm_i2c_read(tps65217_dev, dest_reg, &read_val, 1);
+#endif
 		if (ret)
 			return ret;
+
 		read_val &= (~mask);
 		read_val |= (dest_val & mask);
 		dest_val = read_val;
@@ -56,23 +67,40 @@
 
 	if (prot_level > 0) {
 		xor_reg = dest_reg ^ TPS65217_PASSWORD_UNLOCK;
+#ifndef CONFIG_DM_I2C
 		ret = i2c_write(TPS65217_CHIP_PM, TPS65217_PASSWORD, 1,
 				&xor_reg, 1);
+#else
+		ret = dm_i2c_write(tps65217_dev, TPS65217_PASSWORD,
+				   &xor_reg, 1);
+#endif
 		if (ret)
 			return ret;
 	}
-
+#ifndef CONFIG_DM_I2C
 	ret = i2c_write(TPS65217_CHIP_PM, dest_reg, 1, &dest_val, 1);
+#else
+	ret = dm_i2c_write(tps65217_dev, dest_reg, &dest_val, 1);
+#endif
 	if (ret)
 		return ret;
 
 	if (prot_level == TPS65217_PROT_LEVEL_2) {
+#ifndef CONFIG_DM_I2C
 		ret = i2c_write(TPS65217_CHIP_PM, TPS65217_PASSWORD, 1,
 				&xor_reg, 1);
+#else
+		ret = dm_i2c_write(tps65217_dev, TPS65217_PASSWORD,
+				   &xor_reg, 1);
+#endif
 		if (ret)
 			return ret;
 
+#ifndef CONFIG_DM_I2C
 		ret = i2c_write(TPS65217_CHIP_PM, dest_reg, 1, &dest_val, 1);
+#else
+		ret = dm_i2c_write(tps65217_dev, dest_reg, &dest_val, 1);
+#endif
 		if (ret)
 			return ret;
 	}
@@ -106,3 +134,17 @@
 
 	return 0;
 }
+
+int power_tps65217_init(unsigned char bus)
+{
+#ifdef CONFIG_DM_I2C
+	struct udevice *dev = NULL;
+	int rc;
+
+	rc = i2c_get_chip_for_busnum(bus, TPS65217_CHIP_PM, 1, &dev);
+	if (rc)
+		return rc;
+	tps65217_dev = dev;
+#endif
+	return 0;
+}
diff --git a/drivers/power/pmic/pmic_tps65218.c b/drivers/power/pmic/pmic_tps65218.c
index b50953b..7c95e5e 100644
--- a/drivers/power/pmic/pmic_tps65218.c
+++ b/drivers/power/pmic/pmic_tps65218.c
@@ -10,6 +10,7 @@
 #include <power/pmic.h>
 #include <power/tps65218.h>
 
+#ifndef CONFIG_DM_I2C
 int tps65218_reg_read(uchar dest_reg, uchar *dest_val)
 {
 	uchar read_val;
@@ -84,6 +85,76 @@
 
 	return 0;
 }
+#else
+struct udevice *tps65218_dev __attribute__((section(".data"))) = NULL;
+
+int tps65218_reg_read(uchar dest_reg, uchar *dest_val)
+{
+	uchar read_val;
+	int ret;
+
+	if (!tps65218_dev)
+		return -ENODEV;
+
+	ret = dm_i2c_read(tps65218_dev, dest_reg,  &read_val, 1);
+	if (ret)
+		return ret;
+
+	*dest_val = read_val;
+
+	return 0;
+}
+
+int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
+		       uchar mask)
+{
+	uchar read_val;
+	uchar xor_reg;
+	int ret;
+
+	if (!tps65218_dev)
+		return -ENODEV;
+
+	/*
+	 * If we are affecting only a bit field, read dest_reg and apply the
+	 * mask
+	 */
+	if (mask != TPS65218_MASK_ALL_BITS) {
+		ret = dm_i2c_read(tps65218_dev, dest_reg, &read_val, 1);
+		if (ret)
+			return ret;
+
+		read_val &= (~mask);
+		read_val |= (dest_val & mask);
+		dest_val = read_val;
+	}
+
+	if (prot_level > 0) {
+		xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK;
+		ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg,
+				   1);
+		if (ret)
+			return ret;
+	}
+
+	ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1);
+	if (ret)
+		return ret;
+
+	if (prot_level == TPS65218_PROT_LEVEL_2) {
+		ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg,
+				   1);
+		if (ret)
+			return ret;
+
+		ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+#endif
 
 /**
  * tps65218_voltage_update() - Function to change a voltage level, as this
@@ -154,6 +225,7 @@
 	return 0;
 }
 
+#ifndef CONFIG_DM_I2C
 int power_tps65218_init(unsigned char bus)
 {
 	static const char name[] = "TPS65218_PMIC";
@@ -173,3 +245,16 @@
 
 	return 0;
 }
+#else
+int power_tps65218_init(unsigned char bus)
+{
+	struct udevice *dev = NULL;
+	int rc;
+
+	rc = i2c_get_chip_for_busnum(bus, TPS65218_CHIP_PM, 1, &dev);
+	if (rc)
+		return rc;
+	tps65218_dev = dev;
+	return 0;
+}
+#endif
diff --git a/drivers/power/pmic/pmic_tps65910.c b/drivers/power/pmic/pmic_tps65910.c
index f4d2aa1..4772de1 100644
--- a/drivers/power/pmic/pmic_tps65910.c
+++ b/drivers/power/pmic/pmic_tps65910.c
@@ -8,6 +8,47 @@
 #include <i2c.h>
 #include <power/tps65910.h>
 
+struct udevice *tps65910_dev __attribute__((section(".data"))) = NULL;
+
+static inline int tps65910_read_reg(int addr, uchar *buf)
+{
+#ifndef CONFIG_DM_I2C
+	return i2c_read(TPS65910_CTRL_I2C_ADDR, addr, 1, buf, 1);
+#else
+	int rc;
+
+	rc = dm_i2c_reg_read(tps65910_dev, addr);
+	if (rc < 0)
+		return rc;
+	*buf = (uchar)rc;
+	return 0;
+#endif
+}
+
+static inline int tps65910_write_reg(int addr, uchar *buf)
+{
+#ifndef CONFIG_DM_I2C
+	return i2c_write(TPS65910_CTRL_I2C_ADDR, addr, 1, buf, 1);
+#else
+	return dm_i2c_reg_write(tps65910_dev, addr, *buf);
+#endif
+}
+
+int power_tps65910_init(unsigned char bus)
+{
+#ifdef CONFIG_DM_I2C
+	struct udevice *dev = NULL;
+	int rc;
+
+	rc = i2c_get_chip_for_busnum(bus, TPS65910_CTRL_I2C_ADDR, 1, &dev);
+
+	if (rc)
+		return rc;
+	tps65910_dev = dev;
+#endif
+	return 0;
+}
+
 /*
  * tps65910_set_i2c_control() - Set the TPS65910 to be controlled via the I2C
  * 				interface.
@@ -19,16 +60,14 @@
 	uchar buf;
 
 	/* VDD1/2 voltage selection register access by control i/f */
-	ret = i2c_read(TPS65910_CTRL_I2C_ADDR, TPS65910_DEVCTRL_REG, 1,
-		       &buf, 1);
+	ret = tps65910_read_reg(TPS65910_DEVCTRL_REG, &buf);
 
 	if (ret)
 		return ret;
 
 	buf |= TPS65910_DEVCTRL_REG_SR_CTL_I2C_SEL_CTL_I2C;
 
-	return i2c_write(TPS65910_CTRL_I2C_ADDR, TPS65910_DEVCTRL_REG, 1,
-			 &buf, 1);
+	return tps65910_write_reg(TPS65910_DEVCTRL_REG, &buf);
 }
 
 /*
@@ -49,29 +88,29 @@
 		reg_offset = TPS65910_VDD2_OP_REG;
 
 	/* Select VDDx OP   */
-	ret = i2c_read(TPS65910_CTRL_I2C_ADDR, reg_offset, 1, &buf, 1);
+	ret = tps65910_read_reg(reg_offset, &buf);
 	if (ret)
 		return ret;
 
 	buf &= ~TPS65910_OP_REG_CMD_MASK;
 
-	ret = i2c_write(TPS65910_CTRL_I2C_ADDR, reg_offset, 1, &buf, 1);
+	ret = tps65910_write_reg(reg_offset, &buf);
 	if (ret)
 		return ret;
 
 	/* Configure VDDx OP  Voltage */
-	ret = i2c_read(TPS65910_CTRL_I2C_ADDR, reg_offset, 1, &buf, 1);
+	ret = tps65910_read_reg(reg_offset, &buf);
 	if (ret)
 		return ret;
 
 	buf &= ~TPS65910_OP_REG_SEL_MASK;
 	buf |= vddx_op_vol_sel;
 
-	ret = i2c_write(TPS65910_CTRL_I2C_ADDR, reg_offset, 1, &buf, 1);
+	ret = tps65910_write_reg(reg_offset, &buf);
 	if (ret)
 		return ret;
 
-	ret = i2c_read(TPS65910_CTRL_I2C_ADDR, reg_offset, 1, &buf, 1);
+	ret = tps65910_read_reg(reg_offset, &buf);
 	if (ret)
 		return ret;
 
diff --git a/drivers/power/twl4030.c b/drivers/power/twl4030.c
index 5246001..42c9001 100644
--- a/drivers/power/twl4030.c
+++ b/drivers/power/twl4030.c
@@ -179,3 +179,42 @@
 	return 0;
 }
 #endif
+
+#ifdef CONFIG_DM_I2C
+int twl4030_i2c_write_u8(u8 chip_no, u8 reg, u8 val)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev);
+	if (ret) {
+		pr_err("unable to get I2C bus. ret %d\n", ret);
+		return ret;
+	}
+	ret = dm_i2c_reg_write(dev, reg, val);
+	if (ret) {
+		pr_err("writing to twl4030 failed. ret %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+int twl4030_i2c_read_u8(u8 chip_no, u8 reg, u8 *valp)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev);
+	if (ret) {
+		pr_err("unable to get I2C bus. ret %d\n", ret);
+		return ret;
+	}
+	ret = dm_i2c_reg_read(dev, reg);
+	if (ret < 0) {
+		pr_err("reading from twl4030 failed. ret %d\n", ret);
+		return ret;
+	}
+	*valp = (u8)ret;
+	return 0;
+}
+#endif
diff --git a/drivers/power/twl6030.c b/drivers/power/twl6030.c
index e0cbda1..103960d 100644
--- a/drivers/power/twl6030.c
+++ b/drivers/power/twl6030.c
@@ -268,3 +268,42 @@
 	value &= ~TWL6030_MISC2_VUSB_IN_PMID;
 	twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_MISC2, value);
 }
+
+#ifdef CONFIG_DM_I2C
+int twl6030_i2c_write_u8(u8 chip_no, u8 reg, u8 val)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev);
+	if (ret) {
+		pr_err("unable to get I2C bus. ret %d\n", ret);
+		return ret;
+	}
+	ret = dm_i2c_reg_write(dev, reg, val);
+	if (ret) {
+		pr_err("writing to twl6030 failed. ret %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+int twl6030_i2c_read_u8(u8 chip_no, u8 reg, u8 *valp)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = i2c_get_chip_for_busnum(0, chip_no, 1, &dev);
+	if (ret) {
+		pr_err("unable to get I2C bus. ret %d\n", ret);
+		return ret;
+	}
+	ret = dm_i2c_reg_read(dev, reg);
+	if (ret < 0) {
+		pr_err("reading from twl6030 failed. ret %d\n", ret);
+		return ret;
+	}
+	*valp = (u8)ret;
+	return 0;
+}
+#endif
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index d456beb..98f8343 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -52,6 +52,20 @@
 	depends on DM_USB
 	default y
 
+config DM_USB_GADGET
+	bool "Enable driver model for USB Gadget"
+	depends on DM_USB
+	help
+	  Enable driver model for USB Gadget (Peripheral
+	  mode)
+
+config SPL_DM_USB_GADGET
+	bool "Enable driver model for USB Gadget in sPL"
+	depends on SPL_DM_USB
+	help
+	  Enable driver model for USB Gadget in SPL
+	  (Peripheral mode)
+
 source "drivers/usb/host/Kconfig"
 
 source "drivers/usb/dwc3/Kconfig"
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 943b763..bbd8105 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -38,10 +38,11 @@
 	  Say 'Y' here if you have one such device
 
 config USB_DWC3_GENERIC
-	bool "Xilinx ZynqMP and similar Platforms"
-	depends on DM_USB && USB_DWC3
+	bool "Generic implementation of a DWC3 wrapper (aka dwc3 glue)"
+	depends on DM_USB && USB_DWC3 && MISC
 	help
-	  Some platforms can reuse this DWC3 generic implementation.
+	  Select this for Xilinx ZynqMP and similar Platforms.
+	  This wrapper supports Host and Peripheral operation modes.
 
 config USB_DWC3_UNIPHIER
 	bool "DesignWare USB3 Host Support on UniPhier Platforms"
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index f1ca619..56e2a04 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -19,7 +19,7 @@
 #include <asm/dma-mapping.h>
 #include <linux/ioport.h>
 #include <dm.h>
-
+#include <generic-phy.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 
@@ -789,8 +789,92 @@
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
 
-#if CONFIG_IS_ENABLED(DM_USB)
+#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB)
+int dwc3_setup_phy(struct udevice *dev, struct phy **array, int *num_phys)
+{
+	int i, ret, count;
+	struct phy *usb_phys;
 
+	/* Return if no phy declared */
+	if (!dev_read_prop(dev, "phys", NULL))
+		return 0;
+	count = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
+	if (count <= 0)
+		return count;
+
+	usb_phys = devm_kcalloc(dev, count, sizeof(struct phy),
+				GFP_KERNEL);
+	if (!usb_phys)
+		return -ENOMEM;
+
+	for (i = 0; i < count; i++) {
+		ret = generic_phy_get_by_index(dev, i, &usb_phys[i]);
+		if (ret && ret != -ENOENT) {
+			pr_err("Failed to get USB PHY%d for %s\n",
+			       i, dev->name);
+			return ret;
+		}
+	}
+
+	for (i = 0; i < count; i++) {
+		ret = generic_phy_init(&usb_phys[i]);
+		if (ret) {
+			pr_err("Can't init USB PHY%d for %s\n",
+			       i, dev->name);
+			goto phys_init_err;
+		}
+	}
+
+	for (i = 0; i < count; i++) {
+		ret = generic_phy_power_on(&usb_phys[i]);
+		if (ret) {
+			pr_err("Can't power USB PHY%d for %s\n",
+			       i, dev->name);
+			goto phys_poweron_err;
+		}
+	}
+
+	*array = usb_phys;
+	*num_phys =  count;
+	return 0;
+
+phys_poweron_err:
+	for (i = count - 1; i >= 0; i--)
+		generic_phy_power_off(&usb_phys[i]);
+
+	for (i = 0; i < count; i++)
+		generic_phy_exit(&usb_phys[i]);
+
+	return ret;
+
+phys_init_err:
+	for (; i >= 0; i--)
+		generic_phy_exit(&usb_phys[i]);
+
+	return ret;
+}
+
+int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, int num_phys)
+{
+	int i, ret;
+
+	for (i = 0; i < num_phys; i++) {
+		if (!generic_phy_valid(&usb_phys[i]))
+			continue;
+
+		ret = generic_phy_power_off(&usb_phys[i]);
+		ret |= generic_phy_exit(&usb_phys[i]);
+		if (ret) {
+			pr_err("Can't shutdown USB PHY%d for %s\n",
+			       i, dev->name);
+		}
+	}
+
+	return 0;
+}
+#endif
+
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
 int dwc3_init(struct dwc3 *dwc)
 {
 	int ret;
@@ -841,5 +925,4 @@
 	dwc3_core_exit(dwc);
 	kfree(dwc->mem);
 }
-
 #endif
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 56c9fd6..bc6bba1 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -8,72 +8,89 @@
  */
 
 #include <common.h>
+#include <asm-generic/io.h>
 #include <dm.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
-#include <linux/usb/otg.h>
-#include <linux/compat.h>
+#include <dwc3-uboot.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <malloc.h>
 #include <usb.h>
 #include "core.h"
 #include "gadget.h"
-#include "linux-compat.h"
+#include <reset.h>
+#include <clk.h>
 
-DECLARE_GLOBAL_DATA_PTR;
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+struct dwc3_generic_peripheral {
+	struct dwc3 dwc3;
+	struct phy *phys;
+	int num_phys;
+	fdt_addr_t base;
+};
 
-int usb_gadget_handle_interrupts(int index)
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
 {
-	struct dwc3 *priv;
-	struct udevice *dev;
-	int ret;
+	struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+	struct dwc3 *dwc3 = &priv->dwc3;
 
-	ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev);
-	if (!dev || ret) {
-		pr_err("No USB device found\n");
-		return -ENODEV;
-	}
-
-	priv = dev_get_priv(dev);
-
-	dwc3_gadget_uboot_handle_interrupt(priv);
+	dwc3_gadget_uboot_handle_interrupt(dwc3);
 
 	return 0;
 }
 
 static int dwc3_generic_peripheral_probe(struct udevice *dev)
 {
-	struct dwc3 *priv = dev_get_priv(dev);
+	int rc;
+	struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+	struct dwc3 *dwc3 = &priv->dwc3;
 
-	return dwc3_init(priv);
+	rc = dwc3_setup_phy(dev, &priv->phys, &priv->num_phys);
+	if (rc)
+		return rc;
+
+	dwc3->regs = map_physmem(priv->base, DWC3_OTG_REGS_END, MAP_NOCACHE);
+	dwc3->regs += DWC3_GLOBALS_REGS_START;
+	dwc3->dev = dev;
+
+	rc =  dwc3_init(dwc3);
+	if (rc) {
+		unmap_physmem(dwc3->regs, MAP_NOCACHE);
+		return rc;
+	}
+
+	return 0;
 }
 
 static int dwc3_generic_peripheral_remove(struct udevice *dev)
 {
-	struct dwc3 *priv = dev_get_priv(dev);
+	struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+	struct dwc3 *dwc3 = &priv->dwc3;
 
-	dwc3_remove(priv);
+	dwc3_remove(dwc3);
+	dwc3_shutdown_phy(dev, priv->phys, priv->num_phys);
+	unmap_physmem(dwc3->regs, MAP_NOCACHE);
 
 	return 0;
 }
 
 static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev)
 {
-	struct dwc3 *priv = dev_get_priv(dev);
+	struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+	struct dwc3 *dwc3 = &priv->dwc3;
 	int node = dev_of_offset(dev);
 
-	priv->regs = (void *)devfdt_get_addr(dev);
-	priv->regs += DWC3_GLOBALS_REGS_START;
+	priv->base = devfdt_get_addr(dev);
 
-	priv->maximum_speed = usb_get_maximum_speed(node);
-	if (priv->maximum_speed == USB_SPEED_UNKNOWN) {
+	dwc3->maximum_speed = usb_get_maximum_speed(node);
+	if (dwc3->maximum_speed == USB_SPEED_UNKNOWN) {
 		pr_err("Invalid usb maximum speed\n");
 		return -ENODEV;
 	}
 
-	priv->dr_mode = usb_get_dr_mode(node);
-	if (priv->dr_mode == USB_DR_MODE_UNKNOWN) {
+	dwc3->dr_mode = usb_get_dr_mode(node);
+	if (dwc3->dr_mode == USB_DR_MODE_UNKNOWN) {
 		pr_err("Invalid usb mode setup\n");
 		return -ENODEV;
 	}
@@ -81,24 +98,112 @@
 	return 0;
 }
 
-static int dwc3_generic_peripheral_bind(struct udevice *dev)
-{
-	return device_probe(dev);
-}
-
 U_BOOT_DRIVER(dwc3_generic_peripheral) = {
 	.name	= "dwc3-generic-peripheral",
-	.id	= UCLASS_USB_DEV_GENERIC,
+	.id	= UCLASS_USB_GADGET_GENERIC,
 	.ofdata_to_platdata = dwc3_generic_peripheral_ofdata_to_platdata,
 	.probe = dwc3_generic_peripheral_probe,
 	.remove = dwc3_generic_peripheral_remove,
-	.bind = dwc3_generic_peripheral_bind,
-	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
-	.priv_auto_alloc_size = sizeof(struct dwc3),
-	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
+	.priv_auto_alloc_size = sizeof(struct dwc3_generic_peripheral),
+};
+#endif
+
+struct dwc3_glue_data {
+	struct clk_bulk		clks;
+	struct reset_ctl_bulk	resets;
+	fdt_addr_t regs;
 };
 
-static int dwc3_generic_bind(struct udevice *parent)
+struct dwc3_glue_ops {
+	void (*select_dr_mode)(struct udevice *dev, int index,
+			       enum usb_dr_mode mode);
+};
+
+void dwc3_ti_select_dr_mode(struct udevice *dev, int index,
+			    enum usb_dr_mode mode)
+{
+#define USBOTGSS_UTMI_OTG_STATUS		0x0084
+#define USBOTGSS_UTMI_OTG_OFFSET		0x0480
+
+/* UTMI_OTG_STATUS REGISTER */
+#define USBOTGSS_UTMI_OTG_STATUS_SW_MODE	BIT(31)
+#define USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT	BIT(9)
+#define USBOTGSS_UTMI_OTG_STATUS_TXBITSTUFFENABLE BIT(8)
+#define USBOTGSS_UTMI_OTG_STATUS_IDDIG		BIT(4)
+#define USBOTGSS_UTMI_OTG_STATUS_SESSEND	BIT(3)
+#define USBOTGSS_UTMI_OTG_STATUS_SESSVALID	BIT(2)
+#define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID	BIT(1)
+enum dwc3_omap_utmi_mode {
+	DWC3_OMAP_UTMI_MODE_UNKNOWN = 0,
+	DWC3_OMAP_UTMI_MODE_HW,
+	DWC3_OMAP_UTMI_MODE_SW,
+};
+
+	u32 use_id_pin;
+	u32 host_mode;
+	u32 reg;
+	u32 utmi_mode;
+	u32 utmi_status_offset = USBOTGSS_UTMI_OTG_STATUS;
+
+	struct dwc3_glue_data *glue = dev_get_platdata(dev);
+	void *base = map_physmem(glue->regs, 0x10000, MAP_NOCACHE);
+
+	if (device_is_compatible(dev, "ti,am437x-dwc3"))
+		utmi_status_offset += USBOTGSS_UTMI_OTG_OFFSET;
+
+	utmi_mode = dev_read_u32_default(dev, "utmi-mode",
+					 DWC3_OMAP_UTMI_MODE_UNKNOWN);
+	if (utmi_mode != DWC3_OMAP_UTMI_MODE_HW) {
+		debug("%s: OTG is not supported. defaulting to PERIPHERAL\n",
+		      dev->name);
+		mode = USB_DR_MODE_PERIPHERAL;
+	}
+
+	switch (mode)  {
+	case USB_DR_MODE_PERIPHERAL:
+		use_id_pin = 0;
+		host_mode = 0;
+		break;
+	case USB_DR_MODE_HOST:
+		use_id_pin = 0;
+		host_mode = 1;
+		break;
+	case USB_DR_MODE_OTG:
+	default:
+		use_id_pin = 1;
+		host_mode = 0;
+		break;
+	}
+
+	reg = readl(base + utmi_status_offset);
+
+	reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SW_MODE);
+	if (!use_id_pin)
+		reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+
+	writel(reg, base + utmi_status_offset);
+
+	reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSEND |
+		USBOTGSS_UTMI_OTG_STATUS_VBUSVALID |
+		USBOTGSS_UTMI_OTG_STATUS_IDDIG);
+
+	reg |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID |
+		USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
+
+	if (!host_mode)
+		reg |= USBOTGSS_UTMI_OTG_STATUS_IDDIG |
+			USBOTGSS_UTMI_OTG_STATUS_VBUSVALID;
+
+	writel(reg, base + utmi_status_offset);
+
+	unmap_physmem(base, MAP_NOCACHE);
+}
+
+struct dwc3_glue_ops ti_ops = {
+	.select_dr_mode = dwc3_ti_select_dr_mode,
+};
+
+static int dwc3_glue_bind(struct udevice *parent)
 {
 	const void *fdt = gd->fdt_blob;
 	int node;
@@ -109,29 +214,32 @@
 		const char *name = fdt_get_name(fdt, node, NULL);
 		enum usb_dr_mode dr_mode;
 		struct udevice *dev;
-		const char *driver;
+		const char *driver = NULL;
 
 		debug("%s: subnode name: %s\n", __func__, name);
-		if (strncmp(name, "dwc3@", 4))
-			continue;
 
 		dr_mode = usb_get_dr_mode(node);
 
 		switch (dr_mode) {
 		case USB_DR_MODE_PERIPHERAL:
 		case USB_DR_MODE_OTG:
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
 			debug("%s: dr_mode: OTG or Peripheral\n", __func__);
 			driver = "dwc3-generic-peripheral";
+#endif
 			break;
 		case USB_DR_MODE_HOST:
 			debug("%s: dr_mode: HOST\n", __func__);
-			driver = "dwc3-generic-host";
+			driver = "xhci-dwc3";
 			break;
 		default:
 			debug("%s: unsupported dr_mode\n", __func__);
 			return -ENODEV;
 		};
 
+		if (!driver)
+			continue;
+
 		ret = device_bind_driver_to_node(parent, driver, name,
 						 offset_to_ofnode(node), &dev);
 		if (ret) {
@@ -144,14 +252,107 @@
 	return 0;
 }
 
-static const struct udevice_id dwc3_generic_ids[] = {
+static int dwc3_glue_reset_init(struct udevice *dev,
+				struct dwc3_glue_data *glue)
+{
+	int ret;
+
+	ret = reset_get_bulk(dev, &glue->resets);
+	if (ret == -ENOTSUPP)
+		return 0;
+	else if (ret)
+		return ret;
+
+	ret = reset_deassert_bulk(&glue->resets);
+	if (ret) {
+		reset_release_bulk(&glue->resets);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dwc3_glue_clk_init(struct udevice *dev,
+			      struct dwc3_glue_data *glue)
+{
+	int ret;
+
+	ret = clk_get_bulk(dev, &glue->clks);
+	if (ret == -ENOSYS)
+		return 0;
+	if (ret)
+		return ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+	ret = clk_enable_bulk(&glue->clks);
+	if (ret) {
+		clk_release_bulk(&glue->clks);
+		return ret;
+	}
+#endif
+
+	return 0;
+}
+
+static int dwc3_glue_probe(struct udevice *dev)
+{
+	struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(dev);
+	struct dwc3_glue_data *glue = dev_get_platdata(dev);
+	struct udevice *child = NULL;
+	int index = 0;
+	int ret;
+
+	glue->regs = dev_read_addr(dev);
+
+	ret = dwc3_glue_clk_init(dev, glue);
+	if (ret)
+		return ret;
+
+	ret = dwc3_glue_reset_init(dev, glue);
+	if (ret)
+		return ret;
+
+	ret = device_find_first_child(dev, &child);
+	if (ret)
+		return ret;
+
+	while (child) {
+		enum usb_dr_mode dr_mode;
+
+		dr_mode = usb_get_dr_mode(dev_of_offset(child));
+		device_find_next_child(&child);
+		if (ops && ops->select_dr_mode)
+			ops->select_dr_mode(dev, index, dr_mode);
+		index++;
+	}
+
+	return 0;
+}
+
+static int dwc3_glue_remove(struct udevice *dev)
+{
+	struct dwc3_glue_data *glue = dev_get_platdata(dev);
+
+	reset_release_bulk(&glue->resets);
+
+	clk_release_bulk(&glue->clks);
+
+	return dm_scan_fdt_dev(dev);
+}
+
+static const struct udevice_id dwc3_glue_ids[] = {
 	{ .compatible = "xlnx,zynqmp-dwc3" },
+	{ .compatible = "ti,dwc3", .data = (ulong)&ti_ops },
 	{ }
 };
 
 U_BOOT_DRIVER(dwc3_generic_wrapper) = {
 	.name	= "dwc3-generic-wrapper",
 	.id	= UCLASS_MISC,
-	.of_match = dwc3_generic_ids,
-	.bind = dwc3_generic_bind,
+	.of_match = dwc3_glue_ids,
+	.bind = dwc3_glue_bind,
+	.probe = dwc3_glue_probe,
+	.remove = dwc3_glue_remove,
+	.platdata_auto_alloc_size = sizeof(struct dwc3_glue_data),
+
 };
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 4f68887..818efb3 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -12,7 +12,7 @@
  *
  * commit c00552ebaf : Merge 3.18-rc7 into usb-next
  */
-
+#include <common.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 193583b..3b3d9af 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -100,9 +100,6 @@
 	struct usb_gadget	*gadget;
 	struct usb_request	*req;		/* for control responses */
 	struct usb_request	*stat_req;	/* for cdc & rndis status */
-#if CONFIG_IS_ENABLED(DM_USB)
-	struct udevice		*usb_udev;
-#endif
 
 	u8			config;
 	struct usb_ep		*in_ep, *out_ep, *status_ep;
@@ -2336,40 +2333,17 @@
 }
 
 /*-------------------------------------------------------------------------*/
-
-#if CONFIG_IS_ENABLED(DM_USB)
-int dm_usb_init(struct eth_dev *e_dev)
-{
-	struct udevice *dev = NULL;
-	int ret;
-
-	ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev);
-	if (!dev || ret) {
-		pr_err("No USB device found\n");
-		return -ENODEV;
-	}
-
-	e_dev->usb_udev = dev;
-
-	return ret;
-}
-#endif
-
 static int _usb_eth_init(struct ether_priv *priv)
 {
 	struct eth_dev *dev = &priv->ethdev;
 	struct usb_gadget *gadget;
 	unsigned long ts;
+	int ret;
 	unsigned long timeout = USB_CONNECT_TIMEOUT;
 
-#if CONFIG_IS_ENABLED(DM_USB)
-	if (dm_usb_init(dev)) {
-		pr_err("USB ether not found\n");
-		return -ENODEV;
-	}
-#else
-	board_usb_init(0, USB_INIT_DEVICE);
-#endif
+	ret = usb_gadget_initialize(0);
+	if (ret)
+		return ret;
 
 	/* Configure default mac-addresses for the USB ethernet device */
 #ifdef CONFIG_USBNET_DEV_ADDR
@@ -2541,9 +2515,7 @@
 	}
 
 	usb_gadget_unregister_driver(&priv->eth_driver);
-#if !CONFIG_IS_ENABLED(DM_USB)
-	board_usb_cleanup(0, USB_INIT_DEVICE);
-#endif
+	usb_gadget_release(0);
 }
 
 #ifndef CONFIG_DM_ETH
@@ -2699,7 +2671,7 @@
 	struct udevice *usb_dev;
 	int ret;
 
-	ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &usb_dev);
+	ret = uclass_first_device(UCLASS_USB_GADGET_GENERIC, &usb_dev);
 	if (!usb_dev || ret) {
 		pr_err("No USB device found\n");
 		return ret;
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
index 449339f..38ac2dd 100644
--- a/drivers/usb/gadget/udc/Makefile
+++ b/drivers/usb/gadget/udc/Makefile
@@ -2,4 +2,8 @@
 #
 # USB peripheral controller drivers
 
+ifndef CONFIG_$(SPL_)DM_USB_GADGET
 obj-$(CONFIG_USB_DWC3_GADGET)	+= udc-core.o
+endif
+
+obj-$(CONFIG_$(SPL_)DM_USB_GADGET)	+= udc-uclass.o udc-core.o
diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
index f5c30dd..62b4778 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -18,7 +18,8 @@
 #include <asm/cache.h>
 #include <asm/dma-mapping.h>
 #include <common.h>
-
+#include <dm.h>
+#include <dm/device-internal.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 
diff --git a/drivers/usb/gadget/udc/udc-uclass.c b/drivers/usb/gadget/udc/udc-uclass.c
new file mode 100644
index 0000000..0620518
--- /dev/null
+++ b/drivers/usb/gadget/udc/udc-uclass.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
+ * Written by Jean-Jacques Hiblot <jjhiblot@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <linux/usb/gadget.h>
+
+#define MAX_UDC_DEVICES 4
+static struct udevice *dev_array[MAX_UDC_DEVICES];
+int usb_gadget_initialize(int index)
+{
+	int ret;
+	struct udevice *dev = NULL;
+
+	if (index < 0 || index >= ARRAY_SIZE(dev_array))
+		return -EINVAL;
+	if (dev_array[index])
+		return 0;
+	ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, index, &dev);
+	if (!dev || ret) {
+		pr_err("No USB device found\n");
+		return -ENODEV;
+	}
+	dev_array[index] = dev;
+	return 0;
+}
+
+int usb_gadget_release(int index)
+{
+#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
+	int ret;
+	if (index < 0 || index >= ARRAY_SIZE(dev_array))
+		return -EINVAL;
+
+	ret = device_remove(dev_array[index], DM_REMOVE_NORMAL);
+	if (!ret)
+		dev_array[index] = NULL;
+	return ret;
+#else
+	return -ENOTSUPP;
+#endif
+}
+
+int usb_gadget_handle_interrupts(int index)
+{
+	if (index < 0 || index >= ARRAY_SIZE(dev_array))
+		return -EINVAL;
+	return dm_usb_gadget_handle_interrupts(dev_array[index]);
+}
+
+UCLASS_DRIVER(usb_gadget_generic) = {
+	.id		= UCLASS_USB_GADGET_GENERIC,
+	.name		= "usb_gadget_generic",
+};
diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c
index dd0d156..83b9f11 100644
--- a/drivers/usb/host/xhci-dwc3.c
+++ b/drivers/usb/host/xhci-dwc3.c
@@ -12,6 +12,7 @@
 #include <fdtdec.h>
 #include <generic-phy.h>
 #include <usb.h>
+#include <dwc3-uboot.h>
 
 #include "xhci.h"
 #include <asm/io.h>
@@ -110,105 +111,21 @@
 }
 
 #if CONFIG_IS_ENABLED(DM_USB)
-static int xhci_dwc3_setup_phy(struct udevice *dev)
-{
-	struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
-	int i, ret, count;
-
-	/* Return if no phy declared */
-	if (!dev_read_prop(dev, "phys", NULL))
-		return 0;
-
-	count = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
-	if (count <= 0)
-		return count;
-
-	plat->usb_phys = devm_kcalloc(dev, count, sizeof(struct phy),
-				      GFP_KERNEL);
-	if (!plat->usb_phys)
-		return -ENOMEM;
-
-	for (i = 0; i < count; i++) {
-		ret = generic_phy_get_by_index(dev, i, &plat->usb_phys[i]);
-		if (ret && ret != -ENOENT) {
-			pr_err("Failed to get USB PHY%d for %s\n",
-			       i, dev->name);
-			return ret;
-		}
-
-		++plat->num_phys;
-	}
-
-	for (i = 0; i < plat->num_phys; i++) {
-		ret = generic_phy_init(&plat->usb_phys[i]);
-		if (ret) {
-			pr_err("Can't init USB PHY%d for %s\n",
-			       i, dev->name);
-			goto phys_init_err;
-		}
-	}
-
-	for (i = 0; i < plat->num_phys; i++) {
-		ret = generic_phy_power_on(&plat->usb_phys[i]);
-		if (ret) {
-			pr_err("Can't power USB PHY%d for %s\n",
-			       i, dev->name);
-			goto phys_poweron_err;
-		}
-	}
-
-	return 0;
-
-phys_poweron_err:
-	for (; i >= 0; i--)
-		generic_phy_power_off(&plat->usb_phys[i]);
-
-	for (i = 0; i < plat->num_phys; i++)
-		generic_phy_exit(&plat->usb_phys[i]);
-
-	return ret;
-
-phys_init_err:
-	for (; i >= 0; i--)
-		generic_phy_exit(&plat->usb_phys[i]);
-
-	return ret;
-}
-
-static int xhci_dwc3_shutdown_phy(struct udevice *dev)
-{
-	struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
-	int i, ret;
-
-	for (i = 0; i < plat->num_phys; i++) {
-		if (!generic_phy_valid(&plat->usb_phys[i]))
-			continue;
-
-		ret = generic_phy_power_off(&plat->usb_phys[i]);
-		ret |= generic_phy_exit(&plat->usb_phys[i]);
-		if (ret) {
-			pr_err("Can't shutdown USB PHY%d for %s\n",
-			       i, dev->name);
-		}
-	}
-
-	return 0;
-}
-
 static int xhci_dwc3_probe(struct udevice *dev)
 {
 	struct xhci_hcor *hcor;
 	struct xhci_hccr *hccr;
 	struct dwc3 *dwc3_reg;
 	enum usb_dr_mode dr_mode;
+	struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
 	int ret;
 
 	hccr = (struct xhci_hccr *)((uintptr_t)dev_read_addr(dev));
 	hcor = (struct xhci_hcor *)((uintptr_t)hccr +
 			HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
 
-	ret = xhci_dwc3_setup_phy(dev);
-	if (ret)
+	ret = dwc3_setup_phy(dev, &plat->usb_phys, &plat->num_phys);
+	if (ret && (ret != -ENOTSUPP))
 		return ret;
 
 	dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET);
@@ -227,7 +144,9 @@
 
 static int xhci_dwc3_remove(struct udevice *dev)
 {
-	xhci_dwc3_shutdown_phy(dev);
+	struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
+
+	dwc3_shutdown_phy(dev, plat->usb_phys, plat->num_phys);
 
 	return xhci_deregister(dev);
 }
diff --git a/drivers/usb/musb-new/omap2430.c b/drivers/usb/musb-new/omap2430.c
index 58aed72..32743aa 100644
--- a/drivers/usb/musb-new/omap2430.c
+++ b/drivers/usb/musb-new/omap2430.c
@@ -263,7 +263,7 @@
 #ifdef CONFIG_USB_MUSB_HOST
 	.id		= UCLASS_USB,
 #else
-	.id		= UCLASS_USB_DEV_GENERIC,
+	.id		= UCLASS_USB_GADGET_GENERIC,
 #endif
 	.of_match = omap2430_musb_ids,
 	.ofdata_to_platdata = omap2430_musb_ofdata_to_platdata,
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index 6cf9826..d7170a3 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -535,7 +535,7 @@
 #ifdef CONFIG_USB_MUSB_HOST
 	.id		= UCLASS_USB,
 #else
-	.id		= UCLASS_USB_DEV_GENERIC,
+	.id		= UCLASS_USB_GADGET_GENERIC,
 #endif
 	.of_match	= sunxi_musb_ids,
 	.probe		= musb_usb_probe,
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index dffd6b2..78dcf40 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -77,6 +77,10 @@
 #ifdef CONFIG_OF_LIVE
 	struct device_node *of_root;
 #endif
+
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+	const void *multi_dtb_fit;	/* uncompressed multi-dtb FIT image */
+#endif
 	struct jt_funcs *jt;		/* jump table */
 	char env_buf[32];		/* buffer for env_get() before reloc. */
 #ifdef CONFIG_TRACE
diff --git a/include/configs/am43xx_evm.h b/include/configs/am43xx_evm.h
index 9d0d342..ed71f4c 100644
--- a/include/configs/am43xx_evm.h
+++ b/include/configs/am43xx_evm.h
@@ -27,8 +27,10 @@
 #define CONFIG_SYS_I2C_EEPROM_ADDR_LEN	2
 
 /* Power */
+#ifndef CONFIG_DM_I2C
 #define CONFIG_POWER
 #define CONFIG_POWER_I2C
+#endif
 #define CONFIG_POWER_TPS65218
 #define CONFIG_POWER_TPS62362
 
diff --git a/include/configs/pdu001.h b/include/configs/pdu001.h
index 7b809e2..e4c2872 100644
--- a/include/configs/pdu001.h
+++ b/include/configs/pdu001.h
@@ -12,12 +12,6 @@
 
 #include <configs/ti_am335x_common.h>
 
-/* No more need for I2C legacy compatibility for this board.
- * CONFIG_DM_I2C_COMPAT is defined in ti_armv7_common.h. See the comment there
- * for the right moment to delete the following line.
- */
-#undef CONFIG_DM_I2C_COMPAT
-
 /* Using 32K of volatile storage for environment */
 #define CONFIG_ENV_SIZE		0x4000
 
diff --git a/include/configs/ti_armv7_common.h b/include/configs/ti_armv7_common.h
index 0f892e5..1e2a62d 100644
--- a/include/configs/ti_armv7_common.h
+++ b/include/configs/ti_armv7_common.h
@@ -74,24 +74,10 @@
 /* Timer information. */
 #define CONFIG_SYS_PTV			2	/* Divisor: 2^(PTV+1) => 8 */
 
-/*
- * Disable DM_* for SPL build and can be re-enabled after adding
- * DM support in SPL
- */
-#ifdef CONFIG_SPL_BUILD
-#undef CONFIG_DM_I2C
-#endif
-
-/* I2C IP block */
+/* If DM_I2C, enable non-DM I2C support */
+#if !defined(CONFIG_DM_I2C)
 #define CONFIG_I2C
-#ifndef CONFIG_DM_I2C
 #define CONFIG_SYS_I2C
-#else
-/*
- * Enable CONFIG_DM_I2C_COMPAT temporarily until all the i2c client
- * devices are adopted to DM
- */
-#define CONFIG_DM_I2C_COMPAT
 #endif
 
 /*
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index bbe842e..e960e48 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -95,6 +95,7 @@
 	UCLASS_USB,		/* USB bus */
 	UCLASS_USB_DEV_GENERIC,	/* USB generic device */
 	UCLASS_USB_HUB,		/* USB hub */
+	UCLASS_USB_GADGET_GENERIC,	/* USB generic device */
 	UCLASS_VIDEO,		/* Video or LCD device */
 	UCLASS_VIDEO_BRIDGE,	/* Video bridge, e.g. DisplayPort to LVDS */
 	UCLASS_VIDEO_CONSOLE,	/* Text console driver for video device */
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index 8a4839e..6977995 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -12,6 +12,19 @@
 #include <dm/ofnode.h>
 
 /**
+ * uclass_find_next_free_req_seq() - Get the next free req_seq number
+ *
+ * This returns the next free req_seq number. This is useful only if
+ * OF_CONTROL is not used. The next free req_seq number is simply the
+ * maximum req_seq of the uclass + 1.
+ * This allows assiging req_seq number in the binding order.
+ *
+ * @id:		Id number of the uclass
+ * @return	The next free req_seq number
+ */
+int uclass_find_next_free_req_seq(enum uclass_id id);
+
+/**
  * uclass_get_device_tail() - handle the end of a get_device call
  *
  * This handles returning an error or probing a device as needed.
diff --git a/include/dwc3-uboot.h b/include/dwc3-uboot.h
index 228ab3b..9941cc3 100644
--- a/include/dwc3-uboot.h
+++ b/include/dwc3-uboot.h
@@ -38,4 +38,23 @@
 int dwc3_uboot_init(struct dwc3_device *dev);
 void dwc3_uboot_exit(int index);
 void dwc3_uboot_handle_interrupt(int index);
+
+struct phy;
+#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB)
+int dwc3_setup_phy(struct udevice *dev, struct phy **array, int *num_phys);
+int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, int num_phys);
+#else
+static inline int dwc3_setup_phy(struct udevice *dev, struct phy **array,
+				 int *num_phys)
+{
+	return -ENOTSUPP;
+}
+
+static inline int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys,
+				    int num_phys)
+{
+	return -ENOTSUPP;
+}
+#endif
+
 #endif /* __DWC3_UBOOT_H_ */
diff --git a/include/fdtdec.h b/include/fdtdec.h
index b15da00..f1bcbf8 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -951,6 +951,27 @@
  */
 int fdtdec_setup(void);
 
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+/**
+ * fdtdec_resetup()  - Set up the device tree again
+ *
+ * The main difference with fdtdec_setup() is that it returns if the fdt has
+ * changed because a better match has been found.
+ * This is typically used for boards that rely on a DM driver to detect the
+ * board type. This function sould be called by the board code after the stuff
+ * needed by board_fit_config_name_match() to operate porperly is available.
+ * If this functions signals that a rescan is necessary, the board code must
+ * unbind all the drivers using dm_uninit() and then rescan the DT with
+ * dm_init_and_scan().
+ *
+ * @param rescan Returns a flag indicating that fdt has changed and rescanning
+ *               the fdt is required
+ *
+ * @return 0 if OK, -ve on error
+ */
+int fdtdec_resetup(int *rescan);
+#endif
+
 /**
  * Board-specific FDT initialization. Returns the address to a device tree blob.
  * Called when CONFIG_OF_BOARD is defined, or if CONFIG_OF_SEPARATE is defined
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index b824f13..497798a 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -19,6 +19,7 @@
 #define __LINUX_USB_GADGET_H
 
 #include <errno.h>
+#include <usb.h>
 #include <linux/compat.h>
 #include <linux/list.h>
 
@@ -926,4 +927,21 @@
 
 extern int usb_gadget_handle_interrupts(int index);
 
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+int usb_gadget_initialize(int index);
+int usb_gadget_release(int index);
+int dm_usb_gadget_handle_interrupts(struct udevice *dev);
+#else
+#include <usb.h>
+static inline int usb_gadget_initialize(int index)
+{
+	return board_usb_init(index, USB_INIT_DEVICE);
+}
+
+static inline int usb_gadget_release(int index)
+{
+	return board_usb_cleanup(index, USB_INIT_DEVICE);
+}
+#endif
+
 #endif	/* __LINUX_USB_GADGET_H */
diff --git a/include/palmas.h b/include/palmas.h
index 229de53..20c7e48 100644
--- a/include/palmas.h
+++ b/include/palmas.h
@@ -117,6 +117,7 @@
 #define BB_VSEL_VBAT		(3 << 1)
 #define BB_CHRG_EN		(1 << 0)
 
+#ifndef CONFIG_DM_I2C
 /*
  * Functions to read and write from TPS659038/TWL6035/TWL6037
  * or other Palmas family of TI PMICs
@@ -130,6 +131,10 @@
 {
 	return i2c_read(chip_no, reg, 1, val, 1);
 }
+#else
+int palmas_i2c_write_u8(u8 chip_no, u8 reg, u8 val);
+int palmas_i2c_read_u8(u8 chip_no, u8 reg, u8 *val);
+#endif
 
 void palmas_init_settings(void);
 int palmas_mmc1_poweron_ldo(uint ldo_volt, uint ldo_ctrl, uint voltage);
diff --git a/include/power/tps65217.h b/include/power/tps65217.h
index 00fbab8..669a94a 100644
--- a/include/power/tps65217.h
+++ b/include/power/tps65217.h
@@ -80,6 +80,8 @@
 #define TPS65217_PWR_SRC_USB_BITMASK		0x4
 #define TPS65217_PWR_SRC_AC_BITMASK		0x8
 
+int power_tps65217_init(unsigned char bus);
+
 int tps65217_reg_read(uchar src_reg, uchar *src_val);
 int tps65217_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
 		       uchar mask);
diff --git a/include/power/tps65910.h b/include/power/tps65910.h
index 48e0b2c..21b2a21 100644
--- a/include/power/tps65910.h
+++ b/include/power/tps65910.h
@@ -72,6 +72,7 @@
 #define TPS65910_DEVCTRL_REG_SR_CTL_I2C_SEL_SR_I2C	(0x0 << 4)
 #define TPS65910_DEVCTRL_REG_SR_CTL_I2C_SEL_CTL_I2C	(0x1 << 4)
 
+int power_tps65910_init(unsigned char bus);
 int tps65910_set_i2c_control(void);
 int tps65910_voltage_update(unsigned int module, unsigned char vddx_op_vol_sel);
 #endif	/* __POWER_TPS65910_H__ */
diff --git a/include/syscon.h b/include/syscon.h
index 2aa73e5..3df96e3 100644
--- a/include/syscon.h
+++ b/include/syscon.h
@@ -74,6 +74,19 @@
 struct regmap *syscon_get_regmap_by_driver_data(ulong driver_data);
 
 /**
+ * syscon_regmap_lookup_by_phandle() - Look up a controller by a phandle
+ *
+ * This operates by looking up the given name in the device (device
+ * tree property) of the device using the system controller.
+ *
+ * @dev:	Device using the system controller
+ * @name:	Name of property referring to the system controller
+ * @return	A pointer to the regmap if found, ERR_PTR(-ve) on error
+ */
+struct regmap *syscon_regmap_lookup_by_phandle(struct udevice *dev,
+					       const char *name);
+
+/**
  * syscon_get_first_range() - get the first memory range from a syscon regmap
  *
  * @driver_data:	Driver data value to look up
diff --git a/include/twl4030.h b/include/twl4030.h
index 46a9306..c27ad61 100644
--- a/include/twl4030.h
+++ b/include/twl4030.h
@@ -648,6 +648,7 @@
  *   examples are TWL4030_PM_RECEIVER_VMMC1_DEV_GRP and
  *   TWL4030_LED_LEDEN.
  */
+#ifndef CONFIG_DM_I2C
 static inline int twl4030_i2c_write_u8(u8 chip_no, u8 reg, u8 val)
 {
 	return i2c_write(chip_no, reg, 1, &val, 1);
@@ -657,7 +658,10 @@
 {
 	return i2c_read(chip_no, reg, 1, val, 1);
 }
-
+#else
+int twl4030_i2c_write_u8(u8 chip_no, u8 reg, u8 val);
+int twl4030_i2c_read_u8(u8 chip_no, u8 reg, u8 *val);
+#endif
 /*
  * Power
  */
diff --git a/include/twl6030.h b/include/twl6030.h
index 6685343..41f17de 100644
--- a/include/twl6030.h
+++ b/include/twl6030.h
@@ -186,6 +186,7 @@
 };
 
 /* Functions to read and write from TWL6030 */
+#ifndef CONFIG_DM_I2C
 static inline int twl6030_i2c_write_u8(u8 chip_no, u8 reg, u8 val)
 {
 	return i2c_write(chip_no, reg, 1, &val, 1);
@@ -195,6 +196,10 @@
 {
 	return i2c_read(chip_no, reg, 1, val, 1);
 }
+#else
+int twl6030_i2c_write_u8(u8 chip_no, u8 reg, u8 val);
+int twl6030_i2c_read_u8(u8 chip_no, u8 reg, u8 *val);
+#endif
 
 /*
  * Power
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index cbdc077..7bbc6d4 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1275,14 +1275,55 @@
 	 * If so, pick the most relevant
 	 */
 	fdt_blob = locate_dtb_in_fit(gd->fdt_blob);
-	if (fdt_blob)
+	if (fdt_blob) {
+		gd->multi_dtb_fit = gd->fdt_blob;
 		gd->fdt_blob = fdt_blob;
+	}
+
 # endif
 #endif
 
 	return fdtdec_prepare_fdt();
 }
 
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+int fdtdec_resetup(int *rescan)
+{
+	void *fdt_blob;
+
+	/*
+	 * If the current DTB is part of a compressed FIT image,
+	 * try to locate the best match from the uncompressed
+	 * FIT image stillpresent there. Save the time and space
+	 * required to uncompress it again.
+	 */
+	if (gd->multi_dtb_fit) {
+		fdt_blob = locate_dtb_in_fit(gd->multi_dtb_fit);
+
+		if (fdt_blob == gd->fdt_blob) {
+			/*
+			 * The best match did not change. no need to tear down
+			 * the DM and rescan the fdt.
+			 */
+			*rescan = 0;
+			return 0;
+		}
+
+		*rescan = 1;
+		gd->fdt_blob = fdt_blob;
+		return fdtdec_prepare_fdt();
+	}
+
+	/*
+	 * If multi_dtb_fit is NULL, it means that blob appended to u-boot is
+	 * not a FIT image containings DTB, but a single DTB. There is no need
+	 * to teard down DM and rescan the DT in this case.
+	 */
+	*rescan = 0;
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_NR_DRAM_BANKS
 int fdtdec_decode_ram_size(const void *blob, const char *area, int board_id,
 			   phys_addr_t *basep, phys_size_t *sizep, bd_t *bd)
diff --git a/test/dm/syscon.c b/test/dm/syscon.c
index 77c7928..a294dda 100644
--- a/test/dm/syscon.c
+++ b/test/dm/syscon.c
@@ -6,6 +6,7 @@
 #include <common.h>
 #include <dm.h>
 #include <syscon.h>
+#include <regmap.h>
 #include <asm/test.h>
 #include <dm/test.h>
 #include <test/ut.h>
@@ -43,3 +44,31 @@
 	return 0;
 }
 DM_TEST(dm_test_syscon_by_driver_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test system controller by phandle */
+static int dm_test_syscon_by_phandle(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct regmap *map;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_TEST_PROBE, "test4",
+					      &dev));
+
+	ut_assertok_ptr(syscon_regmap_lookup_by_phandle(dev, "first-syscon"));
+	map = syscon_regmap_lookup_by_phandle(dev, "first-syscon");
+	ut_assert(map);
+	ut_assert(!IS_ERR(map));
+	ut_asserteq(1, map->range_count);
+
+	ut_assertok_ptr(syscon_regmap_lookup_by_phandle(dev,
+							"second-sys-ctrl"));
+	map = syscon_regmap_lookup_by_phandle(dev, "second-sys-ctrl");
+	ut_assert(map);
+	ut_assert(!IS_ERR(map));
+	ut_asserteq(4, map->range_count);
+
+	ut_assert(IS_ERR(syscon_regmap_lookup_by_phandle(dev, "not-present")));
+
+	return 0;
+}
+DM_TEST(dm_test_syscon_by_phandle, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);