Merge git://git.denx.de/u-boot-mpc83xx

- Update MPC83xx platform support to current best practices, etc.
diff --git a/arch/arm/dts/armada-370-xp.dtsi b/arch/arm/dts/armada-370-xp.dtsi
index e4c35d4..50fc0be 100644
--- a/arch/arm/dts/armada-370-xp.dtsi
+++ b/arch/arm/dts/armada-370-xp.dtsi
@@ -102,6 +102,7 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
+			u-boot,dm-pre-reloc;
 
 			rtc: rtc@10300 {
 				compatible = "marvell,orion-rtc";
diff --git a/arch/arm/dts/imx53.dtsi b/arch/arm/dts/imx53.dtsi
index 5ba6174..211ff5f 100644
--- a/arch/arm/dts/imx53.dtsi
+++ b/arch/arm/dts/imx53.dtsi
@@ -31,6 +31,7 @@
 		i2c0 = &i2c1;
 		i2c1 = &i2c2;
 		i2c2 = &i2c3;
+		ipu0 = &ipu;
 		mmc0 = &esdhc1;
 		mmc1 = &esdhc2;
 		mmc2 = &esdhc3;
@@ -51,6 +52,7 @@
 		compatible = "simple-bus";
 		interrupt-parent = <&tzic>;
 		ranges;
+		u-boot,dm-pre-reloc;
 
 		aips@50000000 { /* AIPS1 */
 			compatible = "fsl,aips-bus", "simple-bus";
@@ -283,5 +285,140 @@
 				status = "disabled";
 			};
 		};
+
+		ipu: ipu@18000000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,imx53-ipu";
+			reg = <0x18000000 0x08000000>;
+			interrupts = <11 10>;
+			clocks = <&clks IMX5_CLK_IPU_GATE>,
+				 <&clks IMX5_CLK_IPU_DI0_GATE>,
+				 <&clks IMX5_CLK_IPU_DI1_GATE>;
+			clock-names = "bus", "di0", "di1";
+			resets = <&src 2>;
+			u-boot,dm-pre-reloc;
+
+			ipu_csi0: port@0 {
+				reg = <0>;
+			};
+
+			ipu_csi1: port@1 {
+				reg = <1>;
+			};
+
+			ipu_di0: port@2 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <2>;
+
+				ipu_di0_disp0: endpoint@0 {
+					reg = <0>;
+				};
+
+				ipu_di0_lvds0: endpoint@1 {
+					reg = <1>;
+					remote-endpoint = <&lvds0_in>;
+				};
+			};
+
+			ipu_di1: port@3 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <3>;
+
+				ipu_di1_disp1: endpoint@0 {
+					reg = <0>;
+				};
+
+				ipu_di1_lvds1: endpoint@1 {
+					reg = <1>;
+					remote-endpoint = <&lvds1_in>;
+				};
+
+				ipu_di1_tve: endpoint@2 {
+					reg = <2>;
+					remote-endpoint = <&tve_in>;
+				};
+			};
+		};
+
+		tve: tve@63ff0000 {
+				compatible = "fsl,imx53-tve";
+				reg = <0x63ff0000 0x1000>;
+				interrupts = <92>;
+				clocks = <&clks IMX5_CLK_TVE_GATE>,
+					 <&clks IMX5_CLK_IPU_DI1_SEL>;
+				clock-names = "tve", "di_sel";
+				status = "disabled";
+
+				port {
+					tve_in: endpoint {
+						remote-endpoint = <&ipu_di1_tve>;
+					};
+				};
+		};
+
+		src: src@53fd0000 {
+				compatible = "fsl,imx53-src", "fsl,imx51-src";
+				reg = <0x53fd0000 0x4000>;
+				#reset-cells = <1>;
+		};
+
+		ldb: ldb@53fa8008 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-ldb";
+				reg = <0x53fa8008 0x4>;
+				gpr = <&gpr>;
+				clocks = <&clks IMX5_CLK_LDB_DI0_SEL>,
+					 <&clks IMX5_CLK_LDB_DI1_SEL>,
+					 <&clks IMX5_CLK_IPU_DI0_SEL>,
+					 <&clks IMX5_CLK_IPU_DI1_SEL>,
+					 <&clks IMX5_CLK_LDB_DI0_GATE>,
+					 <&clks IMX5_CLK_LDB_DI1_GATE>;
+				clock-names = "di0_pll", "di1_pll",
+					      "di0_sel", "di1_sel",
+					      "di0", "di1";
+				status = "disabled";
+
+				lvds-channel@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+					status = "disabled";
+
+					port@0 {
+						reg = <0>;
+
+						lvds0_in: endpoint {
+							remote-endpoint = <&ipu_di0_lvds0>;
+						};
+					};
+
+					port@2 {
+						reg = <2>;
+					};
+				};
+
+				lvds-channel@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+					status = "disabled";
+
+					port@1 {
+						reg = <1>;
+
+						lvds1_in: endpoint {
+							remote-endpoint = <&ipu_di1_lvds1>;
+						};
+					};
+
+					port@2 {
+						reg = <2>;
+					};
+				};
+		};
 	};
 };
diff --git a/arch/arm/dts/imx6q.dtsi b/arch/arm/dts/imx6q.dtsi
index d038f41..71543a4 100644
--- a/arch/arm/dts/imx6q.dtsi
+++ b/arch/arm/dts/imx6q.dtsi
@@ -9,6 +9,7 @@
 / {
 	aliases {
 		ipu1 = &ipu2;
+		video1 = &ipu2;
 		spi4 = &ecspi5;
 	};
 
diff --git a/arch/arm/dts/imx6qdl.dtsi b/arch/arm/dts/imx6qdl.dtsi
index c0a9478..83eeb5c 100644
--- a/arch/arm/dts/imx6qdl.dtsi
+++ b/arch/arm/dts/imx6qdl.dtsi
@@ -33,6 +33,7 @@
 		i2c1 = &i2c2;
 		i2c2 = &i2c3;
 		ipu0 = &ipu1;
+		video0 = &ipu1;
 		mmc0 = &usdhc1;
 		mmc1 = &usdhc2;
 		mmc2 = &usdhc3;
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
index 41a9b0f..6392cb0 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
@@ -60,6 +60,7 @@
 #define SUNXI_RTC_BASE			0x07000000
 #define SUNXI_R_CPUCFG_BASE		0x07000400
 #define SUNXI_PRCM_BASE			0x07010000
+#define SUNXI_R_WDOG_BASE		0x07020400
 #define SUNXI_R_PIO_BASE		0x07022000
 #define SUNXI_R_UART_BASE		0x07080000
 #define SUNXI_R_TWI_BASE		0x07081400
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 7f5b633..8e9bb63 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -289,9 +289,14 @@
 		writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
 	}
 #elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
+#if defined(CONFIG_MACH_SUN50I_H6)
+	/* WDOG is broken for some H6 rev. use the R_WDOG instead */
+	static const struct sunxi_wdog *wdog =
+		(struct sunxi_wdog *)SUNXI_R_WDOG_BASE;
+#else
 	static const struct sunxi_wdog *wdog =
-		 ((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog;
-
+		((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog;
+#endif
 	/* Set the watchdog for its shortest interval (.5s) and wait */
 	writel(WDT_CFG_RESET, &wdog->cfg);
 	writel(WDT_MODE_EN, &wdog->mode);
diff --git a/board/beckhoff/mx53cx9020/Makefile b/board/beckhoff/mx53cx9020/Makefile
index 423a553..7f15fc5 100644
--- a/board/beckhoff/mx53cx9020/Makefile
+++ b/board/beckhoff/mx53cx9020/Makefile
@@ -4,4 +4,4 @@
 # Patrick Bruenn <p.bruenn@beckhoff.com>
 
 obj-y               += mx53cx9020.o
-obj-$(CONFIG_VIDEO) += mx53cx9020_video.o
+obj-$(CONFIG_DM_VIDEO) += mx53cx9020_video.o
diff --git a/board/beckhoff/mx53cx9020/mx53cx9020.c b/board/beckhoff/mx53cx9020/mx53cx9020.c
index 79d8a62..9450d92 100644
--- a/board/beckhoff/mx53cx9020/mx53cx9020.c
+++ b/board/beckhoff/mx53cx9020/mx53cx9020.c
@@ -8,26 +8,12 @@
  */
 
 #include <common.h>
-#include <dm.h>
-#include <asm/io.h>
-#include <asm/arch/imx-regs.h>
 #include <asm/arch/sys_proto.h>
-#include <asm/arch/crm_regs.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/iomux-mx53.h>
-#include <asm/arch/clock.h>
 #include <asm/mach-imx/mx5_video.h>
 #include <ACEX1K.h>
-#include <netdev.h>
-#include <i2c.h>
-#include <mmc.h>
-#include <fsl_esdhc.h>
 #include <asm/gpio.h>
-#include <linux/fb.h>
-#include <ipu_pixfmt.h>
-#include <input.h>
-#include <fs.h>
-#include <dm/platform_data/serial_mxc.h>
 
 enum LED_GPIOS {
 	GPIO_SD1_CD = IMX_GPIO_NR(1, 1),
@@ -91,6 +77,9 @@
 
 static void setup_gpio_eim(void)
 {
+	gpio_request(GPIO_C3_STATUS, "GPIO_C3_STATUS");
+	gpio_request(GPIO_C3_DONE, "GPIO_C3_DONE");
+	gpio_request(GPIO_C3_CONFIG, "GPIO_C3_CONFIG");
 	gpio_direction_input(GPIO_C3_STATUS);
 	gpio_direction_input(GPIO_C3_DONE);
 	gpio_direction_output(GPIO_C3_CONFIG, 1);
@@ -100,6 +89,7 @@
 
 static void setup_gpio_sups(void)
 {
+	gpio_request(GPIO_SUPS_INT, "GPIO_SUPS_INT");
 	gpio_direction_input(GPIO_SUPS_INT);
 
 	static const int BLINK_INTERVALL = 50000;
@@ -116,6 +106,16 @@
 
 static void setup_gpio_leds(void)
 {
+	gpio_request(GPIO_LED_SD2_R, "GPIO_LED_SD2_R");
+	gpio_request(GPIO_LED_SD2_B, "GPIO_LED_SD2_B");
+	gpio_request(GPIO_LED_SD2_G, "GPIO_LED_SD2_G");
+	gpio_request(GPIO_LED_SD1_R, "GPIO_LED_SD1_R");
+	gpio_request(GPIO_LED_SD1_B, "GPIO_LED_SD1_B");
+	gpio_request(GPIO_LED_SD1_G, "GPIO_LED_SD1_G");
+	gpio_request(GPIO_LED_PWR_R, "GPIO_LED_PWR_R");
+	gpio_request(GPIO_LED_PWR_B, "GPIO_LED_PWR_B");
+	gpio_request(GPIO_LED_PWR_G, "GPIO_LED_PWR_G");
+
 	gpio_direction_output(GPIO_LED_SD2_R, 0);
 	gpio_direction_output(GPIO_LED_SD2_B, 0);
 	gpio_direction_output(GPIO_LED_SD2_G, 0);
@@ -136,55 +136,6 @@
 }
 #endif
 
-#ifdef CONFIG_FSL_ESDHC
-struct fsl_esdhc_cfg esdhc_cfg[2] = {
-	{MMC_SDHC1_BASE_ADDR},
-	{MMC_SDHC2_BASE_ADDR},
-};
-
-int board_mmc_getcd(struct mmc *mmc)
-{
-	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
-	int ret;
-
-	gpio_direction_input(GPIO_SD1_CD);
-	gpio_direction_input(GPIO_SD2_CD);
-
-	if (cfg->esdhc_base == MMC_SDHC1_BASE_ADDR)
-		ret = !gpio_get_value(GPIO_SD1_CD);
-	else
-		ret = !gpio_get_value(GPIO_SD2_CD);
-
-	return ret;
-}
-
-int board_mmc_init(bd_t *bis)
-{
-	u32 index;
-	int ret;
-
-	esdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
-	esdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
-
-	for (index = 0; index < CONFIG_SYS_FSL_ESDHC_NUM; index++) {
-		switch (index) {
-		case 0:
-			break;
-		case 1:
-			break;
-		default:
-			printf("Warning: you configured more ESDHC controller(%d) as supported by the board(2)\n",
-			       CONFIG_SYS_FSL_ESDHC_NUM);
-			return -EINVAL;
-		}
-		ret = fsl_esdhc_initialize(bis, &esdhc_cfg[index]);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-#endif
 
 static int power_init(void)
 {
@@ -212,29 +163,21 @@
 
 int board_early_init_f(void)
 {
-	setup_gpio_leds();
-	setup_gpio_sups();
-	setup_gpio_eim();
-	setup_iomux_lcd();
 
 	return 0;
 }
 
-/*
- * Do not overwrite the console
- * Use always serial for U-Boot console
- */
-int overwrite_console(void)
-{
-	return 1;
-}
-
 int board_init(void)
 {
 	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
 
 	mxc_set_sata_internal_clock();
 
+	setup_gpio_leds();
+	setup_gpio_sups();
+	setup_gpio_eim();
+	setup_iomux_lcd();
+
 	return 0;
 }
 
diff --git a/board/beckhoff/mx53cx9020/mx53cx9020_video.c b/board/beckhoff/mx53cx9020/mx53cx9020_video.c
index 4055bcc..bf47290 100644
--- a/board/beckhoff/mx53cx9020/mx53cx9020_video.c
+++ b/board/beckhoff/mx53cx9020/mx53cx9020_video.c
@@ -8,41 +8,39 @@
  */
 
 #include <common.h>
-#include <linux/list.h>
-#include <asm/gpio.h>
 #include <asm/arch/iomux-mx53.h>
-#include <linux/fb.h>
-#include <ipu_pixfmt.h>
+#include <asm/gpio.h>
+#include <asm/mach-imx/video.h>
 
 #define CX9020_DVI_PWD	IMX_GPIO_NR(6, 1)
 
-static struct fb_videomode const vga_640x480 = {
-	.name = "VESA_VGA_640x480",
-	.refresh = 60,
-	.xres = 640,
-	.yres = 480,
-	.pixclock = 39721,	/* picosecond (25.175 MHz) */
-	.left_margin = 40,
-	.right_margin = 60,
-	.upper_margin = 10,
-	.lower_margin = 10,
-	.hsync_len = 20,
-	.vsync_len = 10,
-	.sync = 0,
-	.vmode = FB_VMODE_NONINTERLACED
-};
+struct display_info_t const displays[] = {{
+	.bus	= -1,
+	.addr	= 0,
+	.pixfmt	= IPU_PIX_FMT_RGB24,
+	.detect	= NULL,
+	.enable	= NULL,
+	.mode	= {
+		.name           = "DVI",
+		.refresh = 60,
+		.xres = 640,
+		.yres = 480,
+		.pixclock = 39721,	/* picosecond (25.175 MHz) */
+		.left_margin = 40,
+		.right_margin = 60,
+		.upper_margin = 10,
+		.lower_margin = 10,
+		.hsync_len = 20,
+		.vsync_len = 10,
+		.sync = 0,
+		.vmode = FB_VMODE_NONINTERLACED
+} } };
+size_t display_count = ARRAY_SIZE(displays);
 
 void setup_iomux_lcd(void)
 {
 	/* Turn on DVI_PWD */
 	imx_iomux_v3_setup_pad(MX53_PAD_CSI0_DAT15__GPIO6_1);
+	gpio_request(CX9020_DVI_PWD, "CX9020_DVI_PWD");
 	gpio_direction_output(CX9020_DVI_PWD, 1);
 }
-
-int board_video_skip(void)
-{
-	const int ret = ipuv3_fb_init(&vga_640x480, 0, IPU_PIX_FMT_RGB24);
-	if (ret)
-		printf("VESA VG 640x480 cannot be configured: %d\n", ret);
-	return ret;
-}
diff --git a/board/wandboard/wandboard.c b/board/wandboard/wandboard.c
index 69fbc8b..9d7a94f 100644
--- a/board/wandboard/wandboard.c
+++ b/board/wandboard/wandboard.c
@@ -46,6 +46,15 @@
 #define ETH_PHY_AR8035_POWER	IMX_GPIO_NR(7, 13)
 #define REV_DETECTION		IMX_GPIO_NR(2, 28)
 
+/* Speed defined in Kconfig is only applicable when not using DM_I2C.  */
+#ifdef CONFIG_DM_I2C
+#define I2C1_SPEED_NON_DM	0
+#define I2C2_SPEED_NON_DM	0
+#else
+#define I2C1_SPEED_NON_DM	CONFIG_SYS_MXC_I2C1_SPEED
+#define I2C2_SPEED_NON_DM	CONFIG_SYS_MXC_I2C2_SPEED
+#endif
+
 static bool with_pmic;
 
 int dram_init(void)
@@ -463,13 +472,13 @@
 	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 
 #if defined(CONFIG_VIDEO_IPUV3)
-	setup_i2c(1, CONFIG_SYS_MXC_I2C1_SPEED, 0x7f, &mx6dl_i2c2_pad_info);
+	setup_i2c(1, I2C1_SPEED_NON_DM, 0x7f, &mx6dl_i2c2_pad_info);
 	if (is_mx6dq() || is_mx6dqp()) {
-		setup_i2c(1, CONFIG_SYS_MXC_I2C1_SPEED, 0x7f, &mx6q_i2c2_pad_info);
-		setup_i2c(2, CONFIG_SYS_MXC_I2C2_SPEED, 0x7f, &mx6q_i2c3_pad_info);
+		setup_i2c(1, I2C1_SPEED_NON_DM, 0x7f, &mx6q_i2c2_pad_info);
+		setup_i2c(2, I2C2_SPEED_NON_DM, 0x7f, &mx6q_i2c3_pad_info);
 	} else {
-		setup_i2c(1, CONFIG_SYS_MXC_I2C1_SPEED, 0x7f, &mx6dl_i2c2_pad_info);
-		setup_i2c(2, CONFIG_SYS_MXC_I2C2_SPEED, 0x7f, &mx6dl_i2c3_pad_info);
+		setup_i2c(1, I2C1_SPEED_NON_DM, 0x7f, &mx6dl_i2c2_pad_info);
+		setup_i2c(2, I2C2_SPEED_NON_DM, 0x7f, &mx6dl_i2c3_pad_info);
 	}
 
 	setup_display();
diff --git a/common/splash_source.c b/common/splash_source.c
index 62763b9..8f276a3 100644
--- a/common/splash_source.c
+++ b/common/splash_source.c
@@ -303,8 +303,12 @@
 {
 	int res;
 	int node_offset;
-	int splash_offset;
-	int splash_size;
+	const char *splash_file;
+	const void *internal_splash_data;
+	size_t internal_splash_size;
+	int external_splash_addr;
+	int external_splash_size;
+	bool is_splash_external = false;
 	struct image_header *img_header;
 	const u32 *fit_header;
 	u32 fit_size;
@@ -335,35 +339,50 @@
 		return -EINVAL;
 	}
 
-	node_offset = fit_image_get_node(fit_header, location->name);
+	/* Get the splash image node */
+	splash_file = env_get("splashfile");
+	if (!splash_file)
+		splash_file = SPLASH_SOURCE_DEFAULT_FILE_NAME;
+
+	node_offset = fit_image_get_node(fit_header, splash_file);
 	if (node_offset < 0) {
 		debug("Could not find splash image '%s' in FIT\n",
-		      location->name);
+		      splash_file);
 		return -ENOENT;
 	}
 
-	res = fit_image_get_data_offset(fit_header, node_offset,
-					&splash_offset);
-	if (res < 0) {
-		printf("Failed to load splash image (err=%d)\n", res);
-		return res;
-	}
-
-	res = fit_image_get_data_size(fit_header, node_offset, &splash_size);
-	if (res < 0) {
-		printf("Failed to load splash image (err=%d)\n", res);
-		return res;
+	/* Extract the splash data from FIT */
+	/* 1. Test if splash is in FIT internal data. */
+	if (!fit_image_get_data(fit_header, node_offset, &internal_splash_data, &internal_splash_size))
+		memmove((void *)bmp_load_addr, internal_splash_data, internal_splash_size);
+	/* 2. Test if splash is in FIT external data with fixed position. */
+	else if (!fit_image_get_data_position(fit_header, node_offset, &external_splash_addr))
+		is_splash_external = true;
+	/* 3. Test if splash is in FIT external data with offset. */
+	else if (!fit_image_get_data_offset(fit_header, node_offset, &external_splash_addr)) {
+		/* Align data offset to 4-byte boundary */
+		fit_size = ALIGN(fdt_totalsize(fit_header), 4);
+		/* External splash offset means the offset by end of FIT header */
+		external_splash_addr += location->offset + fit_size;
+		is_splash_external = true;
+	} else {
+		printf("Failed to get splash image from FIT\n");
+		return -ENODATA;
 	}
 
-	/* Align data offset to 4-byte boundrary */
-	fit_size = fdt_totalsize(fit_header);
-	fit_size = (fit_size + 3) & ~3;
+	if (is_splash_external) {
+		res = fit_image_get_data_size(fit_header, node_offset, &external_splash_size);
+		if (res < 0) {
+			printf("Failed to get size of splash image (err=%d)\n", res);
+			return res;
+		}
 
-	/* Read in the splash data */
-	location->offset = (location->offset + fit_size + splash_offset);
-	res = splash_storage_read_raw(location, bmp_load_addr , splash_size);
-	if (res < 0)
-		return res;
+		/* Read in the splash data */
+		location->offset = external_splash_addr;
+		res = splash_storage_read_raw(location, bmp_load_addr, external_splash_size);
+		if (res < 0)
+			return res;
+	}
 
 	return 0;
 }
diff --git a/configs/beelink_gs1_defconfig b/configs/beelink_gs1_defconfig
index ef4dd29..437e2d9 100644
--- a/configs/beelink_gs1_defconfig
+++ b/configs/beelink_gs1_defconfig
@@ -7,6 +7,7 @@
 # CONFIG_PSCI_RESET is not set
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL_TEXT_BASE=0x20060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/mx53cx9020_defconfig b/configs/mx53cx9020_defconfig
index 90ea9a6..b809066 100644
--- a/configs/mx53cx9020_defconfig
+++ b/configs/mx53cx9020_defconfig
@@ -24,13 +24,14 @@
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_FPGA_ALTERA=y
 CONFIG_FPGA_CYCLON2=y
+CONFIG_DM=y
 CONFIG_DM_MMC=y
+CONFIG_DM_GPIO=y
 CONFIG_FSL_ESDHC=y
 CONFIG_FEC_MXC=y
 CONFIG_MII=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_IMX5=y
 CONFIG_MXC_UART=y
+CONFIG_DM_VIDEO=y
 CONFIG_VIDEO_IPUV3=y
-CONFIG_VIDEO=y
-# CONFIG_VIDEO_SW_CURSOR is not set
diff --git a/configs/mx6sabresd_defconfig b/configs/mx6sabresd_defconfig
index d3ed3c4..0fda6fc 100644
--- a/configs/mx6sabresd_defconfig
+++ b/configs/mx6sabresd_defconfig
@@ -4,13 +4,13 @@
 CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_TARGET_MX6SABRESD=y
 CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_SPL=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
-# CONFIG_SYS_MALLOC_F is not set
 CONFIG_FIT=y
 CONFIG_SPL_FIT_PRINT=y
 CONFIG_SPL_LOAD_FIT=y
@@ -63,6 +63,7 @@
 CONFIG_MULTI_DTB_FIT=y
 CONFIG_SPL_MULTI_DTB_FIT=y
 CONFIG_SPL_OF_LIST="imx6dl-sabresd imx6q-sabresd imx6qp-sabresd"
+CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
 CONFIG_SPL_DM=y
diff --git a/configs/nanopi_m1_plus_defconfig b/configs/nanopi_m1_plus_defconfig
index ad94d58..90edbd9 100644
--- a/configs/nanopi_m1_plus_defconfig
+++ b/configs/nanopi_m1_plus_defconfig
@@ -4,6 +4,7 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=408
+CONFIG_MACPWR="PD6"
 CONFIG_MMC0_CD_PIN="PH13"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
@@ -12,6 +13,7 @@
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-m1-plus"
+CONFIG_SUN8I_EMAC=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/teres_i_defconfig b/configs/teres_i_defconfig
index 421a8d3..1b57a48 100644
--- a/configs/teres_i_defconfig
+++ b/configs/teres_i_defconfig
@@ -7,6 +7,7 @@
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB1_VBUS_PIN="PL7"
 CONFIG_I2C0_ENABLE=y
+CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
diff --git a/doc/README.splashprepare b/doc/README.splashprepare
index f1418de..3cb5b5a 100644
--- a/doc/README.splashprepare
+++ b/doc/README.splashprepare
@@ -26,6 +26,9 @@
 controlled with the environment variable "splashfile".
 
 To enable loading the splash image from a FIT image, CONFIG_FIT must be
-enabled. Struct splash_location field 'name' should match the splash image
-name within the FIT and the FIT should start at the 'offset' field address in
-the specified storage.
+enabled. The FIT image has to start at the 'offset' field address in the
+selected splash location. The name of splash image within the FIT shall be
+specified by the environment variable "splashfile".
+
+In case the environment variable "splashfile" is not defined the default name
+'splash.bmp' will be used.
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 2156240..095a9bc 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -161,7 +161,10 @@
 	  channels and operating on standard mode up to 100 kbits/s and fast
 	  mode up to 400 kbits/s.
 
-if SYS_I2C_MXC
+# These settings are not used with DM_I2C, however SPL doesn't use
+# DM_I2C even if DM_I2C is enabled, and so might use these settings even
+# when main u-boot does not!
+if SYS_I2C_MXC && (!DM_I2C || SPL)
 config SYS_I2C_MXC_I2C1
 	bool "NXP MXC I2C1"
 	help
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index 5420afb..23119cc 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -482,8 +482,13 @@
 	return ret;
 }
 
+/* Will generate a STOP after the last byte if "last" is true, i.e. this is the
+ * final message of a transaction.  If not, it switches the bus back to TX mode
+ * and does not send a STOP, leaving the bus in a state where a repeated start
+ * and address can be sent for another message.
+ */
 static int i2c_read_data(struct mxc_i2c_bus *i2c_bus, uchar chip, uchar *buf,
-			 int len)
+			 int len, bool last)
 {
 	int ret;
 	unsigned int temp;
@@ -513,17 +518,31 @@
 			return ret;
 		}
 
-		/*
-		 * It must generate STOP before read I2DR to prevent
-		 * controller from generating another clock cycle
-		 */
 		if (i == (len - 1)) {
-			i2c_imx_stop(i2c_bus);
+			/* Final byte has already been received by master!  When
+			 * we read it from I2DR, the master will start another
+			 * cycle.  We must program it first to send a STOP or
+			 * switch to TX to avoid this.
+			 */
+			if (last) {
+				i2c_imx_stop(i2c_bus);
+			} else {
+				/* Final read, no stop, switch back to tx */
+				temp = readb(base + (I2CR << reg_shift));
+				temp |= I2CR_MTX | I2CR_TX_NO_AK;
+				writeb(temp, base + (I2CR << reg_shift));
+			}
 		} else if (i == (len - 2)) {
+			/* Master has already recevied penultimate byte.  When
+			 * we read it from I2DR, master will start RX of final
+			 * byte.  We must set TX_NO_AK now so it does not ACK
+			 * that final byte.
+			 */
 			temp = readb(base + (I2CR << reg_shift));
 			temp |= I2CR_TX_NO_AK;
 			writeb(temp, base + (I2CR << reg_shift));
 		}
+
 		writeb(I2SR_IIF_CLEAR, base + (I2SR << reg_shift));
 		buf[i] = readb(base + (I2DR << reg_shift));
 	}
@@ -533,13 +552,34 @@
 		debug(" 0x%02x", buf[ret]);
 	debug("\n");
 
-	i2c_imx_stop(i2c_bus);
+	/* It is not clear to me that this is necessary */
+	if (last)
+		i2c_imx_stop(i2c_bus);
 	return 0;
 }
 
 #ifndef CONFIG_DM_I2C
 /*
  * Read data from I2C device
+ *
+ * The transactions use the syntax defined in the Linux kernel I2C docs.
+ *
+ * If alen is > 0, then this function will send a transaction of the form:
+ *     S Chip Wr [A] Addr [A] S Chip Rd [A] [data] A ... NA P
+ * This is a normal I2C register read: writing the register address, then doing
+ * a repeated start and reading the data.
+ *
+ * If alen == 0, then we get this transaction:
+ *     S Chip Wr [A] S Chip Rd [A] [data] A ... NA P
+ * This is somewhat unusual, though valid, transaction.  It addresses the chip
+ * in write mode, but doesn't actually write any register address or data, then
+ * does a repeated start and reads data.
+ *
+ * If alen < 0, then we get this transaction:
+ *     S Chip Rd [A] [data] A ... NA P
+ * The chip is addressed in read mode and then data is read.  No register
+ * address is written first.  This is perfectly valid on most devices and
+ * required on some (usually those that don't act like an array of registers).
  */
 static int bus_i2c_read(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr,
 			int alen, u8 *buf, int len)
@@ -566,7 +606,7 @@
 		return ret;
 	}
 
-	ret = i2c_read_data(i2c_bus, chip, buf, len);
+	ret = i2c_read_data(i2c_bus, chip, buf, len, true);
 
 	i2c_imx_stop(i2c_bus);
 	return ret;
@@ -574,6 +614,20 @@
 
 /*
  * Write data to I2C device
+ *
+ * If alen > 0, we get this transaction:
+ *    S Chip Wr [A] addr [A] data [A] ... [A] P
+ * An ordinary write register command.
+ *
+ * If alen == 0, then we get this:
+ *    S Chip Wr [A] data [A] ... [A] P
+ * This is a simple I2C write.
+ *
+ * If alen < 0, then we get this:
+ *    S data [A] ... [A] P
+ * This is most likely NOT something that should be used.  It doesn't send the
+ * chip address first, so in effect, the first byte of data will be used as the
+ * address.
  */
 static int bus_i2c_write(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr,
 			 int alen, const u8 *buf, int len)
@@ -881,6 +935,7 @@
 	return 0;
 }
 
+/* Sends: S Addr Wr [A|NA] P */
 static int mxc_i2c_probe_chip(struct udevice *bus, u32 chip_addr,
 			      u32 chip_flags)
 {
@@ -905,42 +960,54 @@
 	ulong base = i2c_bus->base;
 	int reg_shift = i2c_bus->driver_data & I2C_QUIRK_FLAG ?
 		VF610_I2C_REGSHIFT : IMX_I2C_REGSHIFT;
+	int read_mode;
 
-	/*
-	 * Here the 3rd parameter addr and the 4th one alen are set to 0,
-	 * because here we only want to send out chip address. The register
-	 * address is wrapped in msg.
+	/* Here address len is set to -1 to not send any address at first.
+	 * Otherwise i2c_init_transfer will send the chip address with write
+	 * mode set.  This is wrong if the 1st message is read.
 	 */
-	ret = i2c_init_transfer(i2c_bus, msg->addr, 0, 0);
+	ret = i2c_init_transfer(i2c_bus, msg->addr, 0, -1);
 	if (ret < 0) {
 		debug("i2c_init_transfer error: %d\n", ret);
 		return ret;
 	}
 
+	read_mode = -1; /* So it's always different on the first message */
 	for (; nmsgs > 0; nmsgs--, msg++) {
-		bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
-		debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
-		if (msg->flags & I2C_M_RD)
-			ret = i2c_read_data(i2c_bus, msg->addr, msg->buf,
-					    msg->len);
-		else {
-			ret = i2c_write_data(i2c_bus, msg->addr, msg->buf,
-					     msg->len);
-			if (ret)
-				break;
-			if (next_is_read) {
-				/* Reuse ret */
+		const int msg_is_read = !!(msg->flags & I2C_M_RD);
+
+		debug("i2c_xfer: chip=0x%x, len=0x%x, dir=%c\n", msg->addr,
+		      msg->len, msg_is_read ? 'R' : 'W');
+
+		if (msg_is_read != read_mode) {
+			/* Send repeated start if not 1st message */
+			if (read_mode != -1) {
+				debug("i2c_xfer: [RSTART]\n");
 				ret = readb(base + (I2CR << reg_shift));
 				ret |= I2CR_RSTA;
 				writeb(ret, base + (I2CR << reg_shift));
-
-				ret = tx_byte(i2c_bus, (msg->addr << 1) | 1);
-				if (ret < 0) {
-					i2c_imx_stop(i2c_bus);
-					break;
-				}
 			}
+			debug("i2c_xfer: [ADDR %02x | %c]\n", msg->addr,
+			      msg_is_read ? 'R' : 'W');
+			ret = tx_byte(i2c_bus, (msg->addr << 1) | msg_is_read);
+			if (ret < 0) {
+				debug("i2c_xfer: [STOP]\n");
+				i2c_imx_stop(i2c_bus);
+				break;
+			}
+			read_mode = msg_is_read;
 		}
+
+		if (msg->flags & I2C_M_RD)
+			ret = i2c_read_data(i2c_bus, msg->addr, msg->buf,
+					    msg->len, nmsgs == 1 ||
+						      (msg->flags & I2C_M_STOP));
+		else
+			ret = i2c_write_data(i2c_bus, msg->addr, msg->buf,
+					     msg->len);
+
+		if (ret < 0)
+			break;
 	}
 
 	if (ret)
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 1b7de74..377b267 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -621,31 +621,18 @@
 #else
 	int pre_div = 2;
 #endif
+	int ddr_pre_div = mmc->ddr_mode ? 2 : 1;
 	int sdhc_clk = priv->sdhc_clk;
 	uint clk;
 
-	/*
-	 * For ddr mode, usdhc need to enable DDR mode first, after select
-	 * this DDR mode, usdhc will automatically divide the usdhc clock
-	 */
-	if (mmc->ddr_mode) {
-		writel(readl(&regs->mixctrl) | MIX_CTRL_DDREN, &regs->mixctrl);
-		sdhc_clk >>= 1;
-	}
-
 	if (clock < mmc->cfg->f_min)
 		clock = mmc->cfg->f_min;
 
-	if (sdhc_clk / 16 > clock) {
-		for (; pre_div < 256; pre_div *= 2)
-			if ((sdhc_clk / pre_div) <= (clock * 16))
-				break;
-	} else
-		pre_div = 1;
+	while (sdhc_clk / (16 * pre_div * ddr_pre_div) > clock && pre_div < 256)
+		pre_div *= 2;
 
-	for (div = 1; div <= 16; div++)
-		if ((sdhc_clk / (div * pre_div)) <= clock)
-			break;
+	while (sdhc_clk / (div * pre_div * ddr_pre_div) > clock && div < 16)
+		div++;
 
 	pre_div >>= 1;
 	div -= 1;
diff --git a/drivers/video/imx/mxc_ipuv3_fb.c b/drivers/video/imx/mxc_ipuv3_fb.c
index 3e38d4b..29ecac4 100644
--- a/drivers/video/imx/mxc_ipuv3_fb.c
+++ b/drivers/video/imx/mxc_ipuv3_fb.c
@@ -678,13 +678,14 @@
 	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
 
 	plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
-		     (1 << LCD_MAX_LOG2_BPP) / 8;
+		     (1 << VIDEO_BPP32) / 8;
 
 	return 0;
 }
 
 static const struct udevice_id ipuv3_video_ids[] = {
 	{ .compatible = "fsl,imx6q-ipu" },
+	{ .compatible = "fsl,imx53-ipu" },
 	{ }
 };
 
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index c31303b..af88588 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -529,6 +529,20 @@
 	return 0;
 }
 
+int vidconsole_put_string(struct udevice *dev, const char *str)
+{
+	const char *s;
+	int ret;
+
+	for (s = str; *s; s++) {
+		ret = vidconsole_put_char(dev, *s);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static void vidconsole_putc(struct stdio_dev *sdev, const char ch)
 {
 	struct udevice *dev = sdev->priv;
@@ -541,8 +555,7 @@
 {
 	struct udevice *dev = sdev->priv;
 
-	while (*s)
-		vidconsole_put_char(dev, *s++);
+	vidconsole_put_string(dev, s);
 	video_sync(dev->parent, false);
 }
 
diff --git a/include/configs/mx53cx9020.h b/include/configs/mx53cx9020.h
index 9bf5d91..ab61a07 100644
--- a/include/configs/mx53cx9020.h
+++ b/include/configs/mx53cx9020.h
@@ -159,11 +159,7 @@
 #define CONFIG_SYS_MMC_ENV_DEV 0
 
 /* Framebuffer and LCD */
+#define CONFIG_IMX_VIDEO_SKIP
 #define CONFIG_PREBOOT
-#define CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
-#define CONFIG_VIDEO_BMP_RLE8
-#define CONFIG_SPLASH_SCREEN
-#define CONFIG_BMP_16BPP
-#define CONFIG_VIDEO_LOGO
 
 #endif /* __CONFIG_H */
diff --git a/include/video_console.h b/include/video_console.h
index 52a41ac..0936cea 100644
--- a/include/video_console.h
+++ b/include/video_console.h
@@ -215,6 +215,22 @@
 int vidconsole_put_char(struct udevice *dev, char ch);
 
 /**
+ * vidconsole_put_string() - Output a string to the current console position
+ *
+ * Outputs a string to the console and advances the cursor. This function
+ * handles wrapping to new lines and scrolling the console. Special
+ * characters are handled also: \n, \r, \b and \t.
+ *
+ * The device always starts with the cursor at position 0,0 (top left). It
+ * can be adjusted manually using vidconsole_position_cursor().
+ *
+ * @dev:	Device to adjust
+ * @str:	String to write
+ * @return 0 if OK, -ve on error
+ */
+int vidconsole_put_string(struct udevice *dev, const char *str);
+
+/**
  * vidconsole_position_cursor() - Move the text cursor
  *
  * @dev:	Device to adjust
diff --git a/test/dm/video.c b/test/dm/video.c
index 6be5def..3151ebb 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -97,14 +97,6 @@
 	return 0;
 }
 
-static void vidconsole_put_string(struct udevice *dev, const char *str)
-{
-	const char *s;
-
-	for (s = str; *s; s++)
-		vidconsole_put_char(dev, *s);
-}
-
 /* Test text output works on the video console */
 static int dm_test_video_text(struct unit_test_state *uts)
 {