Merge tag 'u-boot-imx-20190612' of git://git.denx.de/u-boot-imx

u-boot-imx-20190612
--------------------

- Board fixes:
	- imx6logic
	- wandboard
	- mx6sabre boots again
	- imx8qm_mek
	- pico-* boards
	- Toradex apalis / colibri
	- engicam imx6 (environment)
	- KP MX53
	- opos6ul
- Switch to DM:
	- vining2000
	- dh MX6
	- Toradex colibri i.MX7
	- Novena
- Security : fix CSF size for HAB
- Other:
      - imx: fix building for i.mx8 without spl
      - pcie and switch to DM

      mx6sabreauto: Enable SPL SDP support
diff --git a/Makefile b/Makefile
index 7e5fd23..c55ffa2 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
 VERSION = 2019
 PATCHLEVEL = 07
 SUBLEVEL =
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc4
 NAME =
 
 # *DOCUMENTATION*
diff --git a/arch/arm/dts/imx7-colibri-emmc.dts b/arch/arm/dts/imx7-colibri-emmc.dts
index deb5482..bc0d10c 100644
--- a/arch/arm/dts/imx7-colibri-emmc.dts
+++ b/arch/arm/dts/imx7-colibri-emmc.dts
@@ -11,8 +11,10 @@
 	compatible = "toradex,imx7d-colibri-emmc", "fsl,imx7d";
 
 	aliases {
+		u-boot,dm-pre-reloc;
 		mmc0 = &usdhc3;
 		mmc1 = &usdhc1;
+		display1 = &lcdif;
 		usb0 = &usbotg1; /* required for ums */
 	};
 
diff --git a/arch/arm/dts/imx7-colibri.dtsi b/arch/arm/dts/imx7-colibri.dtsi
index a85702f..81717c2 100644
--- a/arch/arm/dts/imx7-colibri.dtsi
+++ b/arch/arm/dts/imx7-colibri.dtsi
@@ -111,3 +111,31 @@
 		>;
 	};
 };
+
+&lcdif {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+
+	display-timings {
+		native-mode = <&timing_vga>;
+
+		/* Standard VGA timing */
+		timing_vga: 640x480 {
+			u-boot,dm-pre-reloc;
+			clock-frequency = <25175000>;
+			hactive = <640>;
+			vactive = <480>;
+			hback-porch = <48>;
+			hfront-porch = <16>;
+			vback-porch = <33>;
+			vfront-porch = <10>;
+			hsync-len = <96>;
+			vsync-len = <2>;
+
+			de-active = <1>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+			pixelclk-active = <0>;
+		};
+	};
+};
diff --git a/arch/arm/dts/tegra124-apalis.dts b/arch/arm/dts/tegra124-apalis.dts
index fe08d3e..a962c0a 100644
--- a/arch/arm/dts/tegra124-apalis.dts
+++ b/arch/arm/dts/tegra124-apalis.dts
@@ -77,7 +77,7 @@
 		reg = <0x0 0x80000000 0x0 0x80000000>;
 	};
 
-	pcie-controller@01003000 {
+	pcie@1003000 {
 		status = "okay";
 		avddio-pex-supply = <&vdd_1v05>;
 		avdd-pex-pll-supply = <&vdd_1v05>;
diff --git a/arch/arm/dts/tegra124-cei-tk1-som.dts b/arch/arm/dts/tegra124-cei-tk1-som.dts
index b1dd418..e5b41f3 100644
--- a/arch/arm/dts/tegra124-cei-tk1-som.dts
+++ b/arch/arm/dts/tegra124-cei-tk1-som.dts
@@ -29,7 +29,7 @@
 		reg = <0x80000000 0x80000000>;
 	};
 
-	pcie-controller@01003000 {
+	pcie@1003000 {
 		status = "okay";
 
 		avddio-pex-supply = <&vdd_1v05_run>;
diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts
index d642043..59e080a 100644
--- a/arch/arm/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/dts/tegra124-jetson-tk1.dts
@@ -29,7 +29,7 @@
 		reg = <0x80000000 0x80000000>;
 	};
 
-	pcie-controller@01003000 {
+	pcie@1003000 {
 		status = "okay";
 
 		avddio-pex-supply = <&vdd_1v05_run>;
diff --git a/arch/arm/dts/tegra124.dtsi b/arch/arm/dts/tegra124.dtsi
index 83d6348..f473ba2 100644
--- a/arch/arm/dts/tegra124.dtsi
+++ b/arch/arm/dts/tegra124.dtsi
@@ -14,7 +14,7 @@
 	interrupt-parent = <&lic>;
 
 
-	pcie-controller@01003000 {
+	pcie@1003000 {
 		compatible = "nvidia,tegra124-pcie";
 		device_type = "pci";
 		reg = <0x01003000 0x00000800   /* PADS registers */
diff --git a/arch/arm/dts/tegra186-p2771-0000-000.dts b/arch/arm/dts/tegra186-p2771-0000-000.dts
index d97c6fd..84e850d 100644
--- a/arch/arm/dts/tegra186-p2771-0000-000.dts
+++ b/arch/arm/dts/tegra186-p2771-0000-000.dts
@@ -11,7 +11,7 @@
 		power-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 5) GPIO_ACTIVE_HIGH>;
 	};
 
-	pcie-controller@10003000 {
+	pcie@10003000 {
 		status = "okay";
 
 		pci@1,0 {
diff --git a/arch/arm/dts/tegra186-p2771-0000-500.dts b/arch/arm/dts/tegra186-p2771-0000-500.dts
index 393a8b2..1ac8ab4 100644
--- a/arch/arm/dts/tegra186-p2771-0000-500.dts
+++ b/arch/arm/dts/tegra186-p2771-0000-500.dts
@@ -11,7 +11,7 @@
 		power-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 6) GPIO_ACTIVE_HIGH>;
 	};
 
-	pcie-controller@10003000 {
+	pcie@10003000 {
 		status = "okay";
 
 		pci@1,0 {
diff --git a/arch/arm/dts/tegra186-p2771-0000.dtsi b/arch/arm/dts/tegra186-p2771-0000.dtsi
index a1319dc..7cda0b4 100644
--- a/arch/arm/dts/tegra186-p2771-0000.dtsi
+++ b/arch/arm/dts/tegra186-p2771-0000.dtsi
@@ -9,6 +9,7 @@
 	};
 
 	aliases {
+		ethernet = "/ethernet@2490000";
 		mmc0 = "/sdhci@3460000";
 		mmc1 = "/sdhci@3400000";
 		i2c0 = "/bpmp/i2c";
@@ -28,6 +29,7 @@
 	ethernet@2490000 {
 		status = "okay";
 		phy-reset-gpios = <&gpio_main TEGRA_MAIN_GPIO(M, 4) GPIO_ACTIVE_LOW>;
+		local-mac-address = [ 00 00 00 00 00 00 ];
 	};
 
 	i2c@3160000 {
diff --git a/arch/arm/dts/tegra186.dtsi b/arch/arm/dts/tegra186.dtsi
index dd9e3b8..0a9db98 100644
--- a/arch/arm/dts/tegra186.dtsi
+++ b/arch/arm/dts/tegra186.dtsi
@@ -217,7 +217,7 @@
 		#interrupt-cells = <2>;
 	};
 
-	pcie-controller@10003000 {
+	pcie@10003000 {
 		compatible = "nvidia,tegra186-pcie";
 		device_type = "pci";
 		reg = <0x0 0x10003000 0x0 0x00000800   /* PADS registers */
diff --git a/arch/arm/dts/tegra20-harmony.dts b/arch/arm/dts/tegra20-harmony.dts
index 0c90705..7fe7d52 100644
--- a/arch/arm/dts/tegra20-harmony.dts
+++ b/arch/arm/dts/tegra20-harmony.dts
@@ -599,7 +599,7 @@
 		nvidia,sys-clock-req-active-high;
 	};
 
-	pcie-controller@80003000 {
+	pcie@80003000 {
 		status = "okay";
 
 		avdd-pex-supply = <&pci_vdd_reg>;
diff --git a/arch/arm/dts/tegra20-trimslice.dts b/arch/arm/dts/tegra20-trimslice.dts
index 31f509a..e19001e 100644
--- a/arch/arm/dts/tegra20-trimslice.dts
+++ b/arch/arm/dts/tegra20-trimslice.dts
@@ -30,7 +30,7 @@
 		spi-max-frequency = <25000000>;
 	};
 
-	pcie-controller@80003000 {
+	pcie@80003000 {
 		status = "okay";
 
 		avdd-pex-supply = <&pci_vdd_reg>;
diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi
index e21ee25..275b343 100644
--- a/arch/arm/dts/tegra20.dtsi
+++ b/arch/arm/dts/tegra20.dtsi
@@ -580,7 +580,7 @@
 		reset-names = "fuse";
 	};
 
-	pcie-controller@80003000 {
+	pcie@80003000 {
 		compatible = "nvidia,tegra20-pcie";
 		device_type = "pci";
 		reg = <0x80003000 0x00000800   /* PADS registers */
diff --git a/arch/arm/dts/tegra210-p2371-2180.dts b/arch/arm/dts/tegra210-p2371-2180.dts
index da4349b..c2f497c 100644
--- a/arch/arm/dts/tegra210-p2371-2180.dts
+++ b/arch/arm/dts/tegra210-p2371-2180.dts
@@ -21,7 +21,7 @@
 		reg = <0x0 0x80000000 0x0 0xc0000000>;
 	};
 
-	pcie-controller@01003000 {
+	pcie@1003000 {
 		status = "okay";
 
 		pci@1,0 {
diff --git a/arch/arm/dts/tegra210.dtsi b/arch/arm/dts/tegra210.dtsi
index 229fed0..3ec54b1 100644
--- a/arch/arm/dts/tegra210.dtsi
+++ b/arch/arm/dts/tegra210.dtsi
@@ -11,7 +11,7 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
-	pcie-controller@01003000 {
+	pcie@1003000 {
 		compatible = "nvidia,tegra210-pcie";
 		device_type = "pci";
 		reg = <0x0 0x01003000 0x0 0x00000800   /* PADS registers */
diff --git a/arch/arm/dts/tegra30-apalis.dts b/arch/arm/dts/tegra30-apalis.dts
index 1a9ce27..77502df 100644
--- a/arch/arm/dts/tegra30-apalis.dts
+++ b/arch/arm/dts/tegra30-apalis.dts
@@ -32,7 +32,7 @@
 		reg = <0x80000000 0x40000000>;
 	};
 
-	pcie-controller@00003000 {
+	pcie@3000 {
 		status = "okay";
 		avdd-pexa-supply = <&vdd2_reg>;
 		vdd-pexa-supply = <&vdd2_reg>;
diff --git a/arch/arm/dts/tegra30-beaver.dts b/arch/arm/dts/tegra30-beaver.dts
index f5fbbe8..9bb097b 100644
--- a/arch/arm/dts/tegra30-beaver.dts
+++ b/arch/arm/dts/tegra30-beaver.dts
@@ -28,7 +28,7 @@
 		reg = <0x80000000 0x7ff00000>;
 	};
 
-	pcie-controller@00003000 {
+	pcie@3000 {
 		status = "okay";
 
 		avdd-pexa-supply = <&ldo1_reg>;
diff --git a/arch/arm/dts/tegra30-cardhu.dts b/arch/arm/dts/tegra30-cardhu.dts
index 5b9798c..7534861 100644
--- a/arch/arm/dts/tegra30-cardhu.dts
+++ b/arch/arm/dts/tegra30-cardhu.dts
@@ -27,7 +27,7 @@
 		reg = <0x80000000 0x40000000>;
 	};
 
-	pcie-controller@00003000 {
+	pcie@3000 {
 		status = "okay";
 
 		/* AVDD_PEXA and VDD_PEXA inputs are grounded on Cardhu. */
diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi
index 5030065..f198bc0 100644
--- a/arch/arm/dts/tegra30.dtsi
+++ b/arch/arm/dts/tegra30.dtsi
@@ -10,7 +10,7 @@
 	compatible = "nvidia,tegra30";
 	interrupt-parent = <&lic>;
 
-	pcie-controller@00003000 {
+	pcie@3000 {
 		compatible = "nvidia,tegra30-pcie";
 		device_type = "pci";
 		reg = <0x00003000 0x00000800   /* PADS registers */
diff --git a/arch/arm/include/asm/arch-tegra/cboot.h b/arch/arm/include/asm/arch-tegra/cboot.h
new file mode 100644
index 0000000..021c246
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra/cboot.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2019 NVIDIA Corporation. All rights reserved.
+ */
+
+#ifndef _TEGRA_CBOOT_H_
+#define _TEGRA_CBOOT_H_
+
+#ifdef CONFIG_ARM64
+extern unsigned long cboot_boot_x0;
+
+void cboot_save_boot_params(unsigned long x0, unsigned long x1,
+			    unsigned long x2, unsigned long x3);
+int cboot_dram_init(void);
+int cboot_dram_init_banksize(void);
+ulong cboot_get_usable_ram_top(ulong total_size);
+int cboot_get_ethaddr(const void *fdt, uint8_t mac[ETH_ALEN]);
+#else
+static inline void cboot_save_boot_params(unsigned long x0, unsigned long x1,
+					  unsigned long x2, unsigned long x3)
+{
+}
+
+static inline int cboot_dram_init(void)
+{
+	return -ENOSYS;
+}
+
+static inline int cboot_dram_init_banksize(void)
+{
+	return -ENOSYS;
+}
+
+static inline ulong cboot_get_usable_ram_top(ulong total_size)
+{
+	return 0;
+}
+
+static inline int cboot_get_ethaddr(const void *fdt, uint8_t mac[ETH_ALEN])
+{
+	return -ENOSYS;
+}
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/arch-tegra/pmc.h b/arch/arm/include/asm/arch-tegra/pmc.h
index 34bbe75..1524bf2 100644
--- a/arch/arm/include/asm/arch-tegra/pmc.h
+++ b/arch/arm/include/asm/arch-tegra/pmc.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- *  (C) Copyright 2010-2015
+ *  (C) Copyright 2010-2019
  *  NVIDIA Corporation <www.nvidia.com>
  */
 
@@ -388,4 +388,22 @@
 /* APBDEV_PMC_CNTRL2_0 0x440 */
 #define HOLD_CKE_LOW_EN				(1 << 12)
 
+/* PMC read/write functions */
+u32 tegra_pmc_readl(unsigned long offset);
+void tegra_pmc_writel(u32 value, unsigned long offset);
+
+#define PMC_CNTRL		0x0
+#define  PMC_CNTRL_MAIN_RST	BIT(4)
+
+#if IS_ENABLED(CONFIG_TEGRA186)
+#  define PMC_SCRATCH0 0x32000
+#else
+#  define PMC_SCRATCH0 0x00050
+#endif
+
+/* for secure PMC */
+#define TEGRA_SMC_PMC		0xc2fffe00
+#define  TEGRA_SMC_PMC_READ	0xaa
+#define  TEGRA_SMC_PMC_WRITE	0xbb
+
 #endif	/* PMC_H */
diff --git a/arch/arm/include/asm/arch-tegra20/pmu.h b/arch/arm/include/asm/arch-tegra/pmu.h
similarity index 73%
rename from arch/arm/include/asm/arch-tegra20/pmu.h
rename to arch/arm/include/asm/arch-tegra/pmu.h
index 18766df..e850875 100644
--- a/arch/arm/include/asm/arch-tegra20/pmu.h
+++ b/arch/arm/include/asm/arch-tegra/pmu.h
@@ -4,10 +4,10 @@
  *  NVIDIA Corporation <www.nvidia.com>
  */
 
-#ifndef _ARCH_PMU_H_
-#define _ARCH_PMU_H_
+#ifndef _TEGRA_PMU_H_
+#define _TEGRA_PMU_H_
 
 /* Set core and CPU voltages to nominal levels */
 int pmu_set_nominal(void);
 
-#endif	/* _ARCH_PMU_H_ */
+#endif	/* _TEGRA_PMU_H_ */
diff --git a/arch/arm/include/asm/arch-tegra/tegra.h b/arch/arm/include/asm/arch-tegra/tegra.h
index 7ae0129..7a4e097 100644
--- a/arch/arm/include/asm/arch-tegra/tegra.h
+++ b/arch/arm/include/asm/arch-tegra/tegra.h
@@ -30,7 +30,13 @@
 #define NV_PA_SLINK5_BASE	(NV_PA_APB_MISC_BASE + 0xDC00)
 #define NV_PA_SLINK6_BASE	(NV_PA_APB_MISC_BASE + 0xDE00)
 #define TEGRA_DVC_BASE		(NV_PA_APB_MISC_BASE + 0xD000)
+#if defined(CONFIG_TEGRA20) || defined(CONFIG_TEGRA30) || \
+	defined(CONFIG_TEGRA114) || defined(CONFIG_TEGRA124) || \
+	defined(CONFIG_TEGRA132) || defined(CONFIG_TEGRA210)
 #define NV_PA_PMC_BASE		(NV_PA_APB_MISC_BASE + 0xE400)
+#else
+#define NV_PA_PMC_BASE		0xc360000
+#endif
 #define NV_PA_EMC_BASE		(NV_PA_APB_MISC_BASE + 0xF400)
 #define NV_PA_FUSE_BASE		(NV_PA_APB_MISC_BASE + 0xF800)
 #if defined(CONFIG_TEGRA20) || defined(CONFIG_TEGRA30) || \
diff --git a/arch/arm/include/asm/arch-tegra114/pmu.h b/arch/arm/include/asm/arch-tegra114/pmu.h
deleted file mode 100644
index 1e571ee..0000000
--- a/arch/arm/include/asm/arch-tegra114/pmu.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
- */
-
-#ifndef _TEGRA114_PMU_H_
-#define _TEGRA114_PMU_H_
-
-/* Set core and CPU voltages to nominal levels */
-int pmu_set_nominal(void);
-
-#endif	/* _TEGRA114_PMU_H_ */
diff --git a/arch/arm/include/asm/arch-tegra124/pmu.h b/arch/arm/include/asm/arch-tegra124/pmu.h
deleted file mode 100644
index c38393e..0000000
--- a/arch/arm/include/asm/arch-tegra124/pmu.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * (C) Copyright 2010-2013
- * NVIDIA Corporation <www.nvidia.com>
- */
-
-#ifndef _TEGRA124_PMU_H_
-#define _TEGRA124_PMU_H_
-
-/* Set core and CPU voltages to nominal levels */
-int pmu_set_nominal(void);
-
-#endif	/* _TEGRA124_PMU_H_ */
diff --git a/arch/arm/include/asm/arch-tegra210/pmu.h b/arch/arm/include/asm/arch-tegra210/pmu.h
deleted file mode 100644
index 6ea36aa..0000000
--- a/arch/arm/include/asm/arch-tegra210/pmu.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * (C) Copyright 2010-2015
- * NVIDIA Corporation <www.nvidia.com>
- */
-
-#ifndef _TEGRA210_PMU_H_
-#define _TEGRA210_PMU_H_
-
-/* Set core and CPU voltages to nominal levels */
-int pmu_set_nominal(void);
-
-#endif	/* _TEGRA210_PMU_H_ */
diff --git a/arch/arm/include/asm/arch-tegra30/pmu.h b/arch/arm/include/asm/arch-tegra30/pmu.h
deleted file mode 100644
index a823f0f..0000000
--- a/arch/arm/include/asm/arch-tegra30/pmu.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
- */
-
-#ifndef _TEGRA30_PMU_H_
-#define _TEGRA30_PMU_H_
-
-/* Set core and CPU voltages to nominal levels */
-int pmu_set_nominal(void);
-
-#endif	/* _TEGRA30_PMU_H_ */
diff --git a/arch/arm/mach-at91/spl_atmel.c b/arch/arm/mach-at91/spl_atmel.c
index ef745c9..85290be 100644
--- a/arch/arm/mach-at91/spl_atmel.c
+++ b/arch/arm/mach-at91/spl_atmel.c
@@ -44,7 +44,15 @@
 #endif
 
 	tmp = readl(&pmc->mor);
+/*
+ * some boards have an external oscillator with driving.
+ * in this case we need to disable the internal SoC driving (bypass mode)
+ */
+#if defined(CONFIG_SPL_AT91_MCK_BYPASS)
+	tmp |= AT91_PMC_MOR_OSCBYPASS;
+#else
 	tmp &= ~AT91_PMC_MOR_OSCBYPASS;
+#endif
 	tmp &= ~AT91_PMC_MOR_KEY(0xff);
 	tmp |= AT91_PMC_MOR_KEY(0x37);
 	writel(tmp, &pmc->mor);
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
index 93e60b2..d62ff6e 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -298,7 +298,7 @@
 	/* disable video before launching O/S */
 	ipuv3_fb_shutdown();
 #endif
-#if defined(CONFIG_VIDEO_MXS)
+#if defined(CONFIG_VIDEO_MXS) && !defined(CONFIG_DM_VIDEO)
 	lcdif_power_down();
 #endif
 }
diff --git a/arch/arm/mach-imx/mx7/soc.c b/arch/arm/mach-imx/mx7/soc.c
index ccfab82..1b4bbc5 100644
--- a/arch/arm/mach-imx/mx7/soc.c
+++ b/arch/arm/mach-imx/mx7/soc.c
@@ -382,7 +382,7 @@
 void reset_misc(void)
 {
 #ifndef CONFIG_SPL_BUILD
-#ifdef CONFIG_VIDEO_MXS
+#if defined(CONFIG_VIDEO_MXS) && !defined(CONFIG_DM_VIDEO)
 	lcdif_power_down();
 #endif
 #endif
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 86b1cd1..97e22ea 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -12,6 +12,12 @@
 config SPL_SERIAL_SUPPORT
 	default y
 
+config TEGRA_CLKRST
+	bool
+
+config TEGRA_GP_PADCTRL
+	bool
+
 config TEGRA_IVC
 	bool "Tegra IVC protocol"
 	help
@@ -20,6 +26,19 @@
 	  U-Boot, it is typically used for communication between the main CPU
 	  and various auxiliary processors.
 
+config TEGRA_MC
+	bool
+
+config TEGRA_PINCTRL
+	bool
+
+config TEGRA_PMC
+	bool
+
+config TEGRA_PMC_SECURE
+	bool
+	depends on TEGRA_PMC
+
 config TEGRA_COMMON
 	bool "Tegra common options"
 	select BINMAN
@@ -55,14 +74,20 @@
 	select SPL
 	select SPL_BOARD_INIT if SPL
 	select SUPPORT_SPL
+	select TEGRA_CLKRST
 	select TEGRA_COMMON
 	select TEGRA_GPIO
+	select TEGRA_GP_PADCTRL
+	select TEGRA_MC
 	select TEGRA_NO_BPMP
+	select TEGRA_PINCTRL
+	select TEGRA_PMC
 
 config TEGRA_ARMV8_COMMON
 	bool "Tegra 64-bit common options"
 	select ARM64
 	select LINUX_KERNEL_IMAGE_HEADER
+	select POSITION_INDEPENDENT
 	select TEGRA_COMMON
 
 if TEGRA_ARMV8_COMMON
@@ -100,8 +125,14 @@
 config TEGRA210
 	bool "Tegra210 family"
 	select TEGRA_ARMV8_COMMON
+	select TEGRA_CLKRST
 	select TEGRA_GPIO
+	select TEGRA_GP_PADCTRL
+	select TEGRA_MC
 	select TEGRA_NO_BPMP
+	select TEGRA_PINCTRL
+	select TEGRA_PMC
+	select TEGRA_PMC_SECURE
 
 config TEGRA186
 	bool "Tegra186 family"
@@ -118,6 +149,7 @@
 
 config TEGRA_DISCONNECT_UDC_ON_BOOT
 	bool "Disconnect USB device mode controller on boot"
+	depends on CI_UDC
 	default y
 	help
 	  When loading U-Boot into RAM over USB protocols using tools such as
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index d4b4666..7165d70 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -1,11 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
-# (C) Copyright 2010-2015 Nvidia Corporation.
+# (C) Copyright 2010-2019 Nvidia Corporation.
 #
 # (C) Copyright 2000-2008
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
-ifndef CONFIG_TEGRA186
 ifdef CONFIG_SPL_BUILD
 obj-y += spl.o
 obj-y += cpu.o
@@ -13,25 +12,24 @@
 obj-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.o
 endif
 
-obj-y += ap.o
+obj-$(CONFIG_TEGRA_GP_PADCTRL) += ap.o
 obj-y += board.o board2.o
 obj-y += cache.o
-obj-y += clock.o
-obj-y += pinmux-common.o
-obj-y += powergate.o
+obj-$(CONFIG_TEGRA_CLKRST) += clock.o
+obj-$(CONFIG_TEGRA_PINCTRL) += pinmux-common.o
+obj-$(CONFIG_TEGRA_PMC) += powergate.o
 obj-y += xusb-padctl-dummy.o
-endif
 
-obj-$(CONFIG_ARM64) += arm64-mmu.o
+obj-$(CONFIG_ARM64) += arm64-mmu.o cboot.o
 obj-y += dt-setup.o
 obj-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
 obj-$(CONFIG_TEGRA_GPU) += gpu.o
 obj-$(CONFIG_TEGRA_IVC) += ivc.o
-obj-y += lowlevel_init.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ARMV7_PSCI) += psci.o
 endif
 obj-$(CONFIG_DISPLAY_CPUINFO) += sys_info.o
+obj-y += pmc.o
 
 obj-$(CONFIG_TEGRA20) += tegra20/
 obj-$(CONFIG_TEGRA30) += tegra30/
diff --git a/arch/arm/mach-tegra/board.c b/arch/arm/mach-tegra/board.c
index 4e15907..abcae15 100644
--- a/arch/arm/mach-tegra/board.c
+++ b/arch/arm/mach-tegra/board.c
@@ -9,12 +9,19 @@
 #include <ns16550.h>
 #include <spl.h>
 #include <asm/io.h>
+#if IS_ENABLED(CONFIG_TEGRA_CLKRST)
 #include <asm/arch/clock.h>
+#endif
+#if IS_ENABLED(CONFIG_TEGRA_PINCTRL)
 #include <asm/arch/funcmux.h>
+#endif
+#if IS_ENABLED(CONFIG_TEGRA_MC)
 #include <asm/arch/mc.h>
+#endif
 #include <asm/arch/tegra.h>
 #include <asm/arch-tegra/ap.h>
 #include <asm/arch-tegra/board.h>
+#include <asm/arch-tegra/cboot.h>
 #include <asm/arch-tegra/pmc.h>
 #include <asm/arch-tegra/sys_proto.h>
 #include <asm/arch-tegra/warmboot.h>
@@ -36,9 +43,25 @@
 static bool from_spl __attribute__ ((section(".data")));
 
 #ifndef CONFIG_SPL_BUILD
-void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3)
+void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2,
+		      unsigned long r3)
 {
 	from_spl = r0 != UBOOT_NOT_LOADED_FROM_SPL;
+
+	/*
+	 * The logic for this is somewhat indirect. The purpose of the marker
+	 * (UBOOT_NOT_LOADED_FROM_SPL) is in fact used to determine if U-Boot
+	 * was loaded from a read-only instance of itself, which is something
+	 * that can happen in secure boot setups. So basically the presence
+	 * of the marker is an indication that U-Boot was loaded by one such
+	 * special variant of U-Boot. Conversely, the absence of the marker
+	 * indicates that this instance of U-Boot was loaded by something
+	 * other than a special U-Boot. This could be SPL, but it could just
+	 * as well be one of any number of other first stage bootloaders.
+	 */
+	if (from_spl)
+		cboot_save_boot_params(r0, r1, r2, r3);
+
 	save_boot_params_ret();
 }
 #endif
@@ -66,6 +89,7 @@
 }
 #endif
 
+#if IS_ENABLED(CONFIG_TEGRA_MC)
 /* Read the RAM size directly from the memory controller */
 static phys_size_t query_sdram_size(void)
 {
@@ -115,14 +139,26 @@
 
 	return size_bytes;
 }
+#endif
 
 int dram_init(void)
 {
+	int err;
+
+	/* try to initialize DRAM from cboot DTB first */
+	err = cboot_dram_init();
+	if (err == 0)
+		return 0;
+
+#if IS_ENABLED(CONFIG_TEGRA_MC)
 	/* We do not initialise DRAM here. We just query the size */
 	gd->ram_size = query_sdram_size();
+#endif
+
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_TEGRA_PINCTRL)
 static int uart_configs[] = {
 #if defined(CONFIG_TEGRA20)
  #if defined(CONFIG_TEGRA_UARTA_UAA_UAB)
@@ -190,9 +226,11 @@
 		}
 	}
 }
+#endif
 
 void board_init_uart_f(void)
 {
+#if IS_ENABLED(CONFIG_TEGRA_PINCTRL)
 	int uart_ids = 0;	/* bit mask of which UART ids to enable */
 
 #ifdef CONFIG_TEGRA_ENABLE_UARTA
@@ -211,6 +249,7 @@
 	uart_ids |= UARTE;
 #endif
 	setup_uarts(uart_ids);
+#endif
 }
 
 #if !CONFIG_IS_ENABLED(OF_CONTROL)
diff --git a/arch/arm/mach-tegra/board186.c b/arch/arm/mach-tegra/board186.c
deleted file mode 100644
index 80b5570..0000000
--- a/arch/arm/mach-tegra/board186.c
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2016, NVIDIA CORPORATION.
- */
-
-#include <common.h>
-#include <asm/arch/tegra.h>
-
-int board_early_init_f(void)
-{
-	return 0;
-}
-
-__weak int tegra_board_init(void)
-{
-	return 0;
-}
-
-int board_init(void)
-{
-	return tegra_board_init();
-}
-
-__weak int tegra_soc_board_init_late(void)
-{
-	return 0;
-}
-
-int board_late_init(void)
-{
-	return tegra_soc_board_init_late();
-}
diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c
index 12257a4..bbc487a 100644
--- a/arch/arm/mach-tegra/board2.c
+++ b/arch/arm/mach-tegra/board2.c
@@ -13,18 +13,23 @@
 #include <asm/io.h>
 #include <asm/arch-tegra/ap.h>
 #include <asm/arch-tegra/board.h>
+#include <asm/arch-tegra/cboot.h>
 #include <asm/arch-tegra/clk_rst.h>
 #include <asm/arch-tegra/pmc.h>
+#include <asm/arch-tegra/pmu.h>
 #include <asm/arch-tegra/sys_proto.h>
 #include <asm/arch-tegra/uart.h>
 #include <asm/arch-tegra/warmboot.h>
 #include <asm/arch-tegra/gpu.h>
 #include <asm/arch-tegra/usb.h>
 #include <asm/arch-tegra/xusb-padctl.h>
+#if IS_ENABLED(CONFIG_TEGRA_CLKRST)
 #include <asm/arch/clock.h>
+#endif
+#if IS_ENABLED(CONFIG_TEGRA_PINCTRL)
 #include <asm/arch/funcmux.h>
 #include <asm/arch/pinmux.h>
-#include <asm/arch/pmu.h>
+#endif
 #include <asm/arch/tegra.h>
 #ifdef CONFIG_TEGRA_CLOCK_SCALING
 #include <asm/arch/emc.h>
@@ -47,6 +52,7 @@
 __weak void gpio_early_init_uart(void) {}
 __weak void pin_mux_display(void) {}
 __weak void start_cpu_fan(void) {}
+__weak void cboot_late_init(void) {}
 
 #if defined(CONFIG_TEGRA_NAND)
 __weak void pin_mux_nand(void)
@@ -109,8 +115,10 @@
 	__maybe_unused int board_id;
 
 	/* Do clocks and UART first so that printf() works */
+#if IS_ENABLED(CONFIG_TEGRA_CLKRST)
 	clock_init();
 	clock_verify();
+#endif
 
 	tegra_gpu_config();
 
@@ -181,8 +189,10 @@
 
 int board_early_init_f(void)
 {
+#if IS_ENABLED(CONFIG_TEGRA_CLKRST)
 	if (!clock_early_init_done())
 		clock_early_init();
+#endif
 
 #if defined(CONFIG_TEGRA_DISCONNECT_UDC_ON_BOOT)
 #define USBCMD_FS2 (1 << 15)
@@ -193,10 +203,12 @@
 #endif
 
 	/* Do any special system timer/TSC setup */
-#if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
+#if IS_ENABLED(CONFIG_TEGRA_CLKRST)
+#  if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
 	if (!tegra_cpu_is_non_secure())
-#endif
+#  endif
 		arch_timer_init();
+#endif
 
 	pinmux_init();
 	board_init_uart_f();
@@ -233,6 +245,7 @@
 	}
 #endif
 	start_cpu_fan();
+	cboot_late_init();
 
 	return 0;
 }
@@ -327,6 +340,15 @@
  */
 int dram_init_banksize(void)
 {
+	int err;
+
+	/* try to compute DRAM bank size based on cboot DTB first */
+	err = cboot_dram_init_banksize();
+	if (err == 0)
+		return err;
+
+	/* fall back to default DRAM bank size computation */
+
 	gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
 	gd->bd->bi_dram[0].size = usable_ram_size_below_4g();
 
@@ -360,5 +382,14 @@
  */
 ulong board_get_usable_ram_top(ulong total_size)
 {
+	ulong ram_top;
+
+	/* try to get top of usable RAM based on cboot DTB first */
+	ram_top = cboot_get_usable_ram_top(total_size);
+	if (ram_top > 0)
+		return ram_top;
+
+	/* fall back to default usable RAM computation */
+
 	return CONFIG_SYS_SDRAM_BASE + usable_ram_size_below_4g();
 }
diff --git a/arch/arm/mach-tegra/cache.c b/arch/arm/mach-tegra/cache.c
index be414e4..d706349 100644
--- a/arch/arm/mach-tegra/cache.c
+++ b/arch/arm/mach-tegra/cache.c
@@ -8,7 +8,9 @@
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch-tegra/ap.h>
+#if IS_ENABLED(CONFIG_TEGRA_GP_PADCTRL)
 #include <asm/arch/gp_padctrl.h>
+#endif
 
 #ifndef CONFIG_ARM64
 void config_cache(void)
diff --git a/arch/arm/mach-tegra/cboot.c b/arch/arm/mach-tegra/cboot.c
new file mode 100644
index 0000000..a829ef7
--- /dev/null
+++ b/arch/arm/mach-tegra/cboot.c
@@ -0,0 +1,620 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2016-2018, NVIDIA CORPORATION.
+ */
+
+#include <common.h>
+#include <environment.h>
+#include <fdt_support.h>
+#include <fdtdec.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <linux/ctype.h>
+#include <linux/sizes.h>
+
+#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/cboot.h>
+#include <asm/armv8/mmu.h>
+
+/*
+ * Size of a region that's large enough to hold the relocated U-Boot and all
+ * other allocations made around it (stack, heap, page tables, etc.)
+ * In practice, running "bdinfo" at the shell prompt, the stack reaches about
+ * 5MB from the address selected for ram_top as of the time of writing,
+ * so a 16MB region should be plenty.
+ */
+#define MIN_USABLE_RAM_SIZE SZ_16M
+/*
+ * The amount of space we expect to require for stack usage. Used to validate
+ * that all reservations fit into the region selected for the relocation target
+ */
+#define MIN_USABLE_STACK_SIZE SZ_1M
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern struct mm_region tegra_mem_map[];
+
+/*
+ * These variables are written to before relocation, and hence cannot be
+ * in.bss, since .bss overlaps the DTB that's appended to the U-Boot binary.
+ * The section attribute forces this into .data and avoids this issue. This
+ * also has the nice side-effect of the content being valid after relocation.
+ */
+
+/* The number of valid entries in ram_banks[] */
+static int ram_bank_count __attribute__((section(".data")));
+
+/*
+ * The usable top-of-RAM for U-Boot. This is both:
+ * a) Below 4GB to avoid issues with peripherals that use 32-bit addressing.
+ * b) At the end of a region that has enough space to hold the relocated U-Boot
+ *    and all other allocations made around it (stack, heap, page tables, etc.)
+ */
+static u64 ram_top __attribute__((section(".data")));
+/* The base address of the region of RAM that ends at ram_top */
+static u64 region_base __attribute__((section(".data")));
+
+/*
+ * Explicitly put this in the .data section because it is written before the
+ * .bss section is zeroed out but it needs to persist.
+ */
+unsigned long cboot_boot_x0 __attribute__((section(".data")));
+
+void cboot_save_boot_params(unsigned long x0, unsigned long x1,
+			    unsigned long x2, unsigned long x3)
+{
+	cboot_boot_x0 = x0;
+}
+
+int cboot_dram_init(void)
+{
+	unsigned int na, ns;
+	const void *cboot_blob = (void *)cboot_boot_x0;
+	int node, len, i;
+	const u32 *prop;
+
+	if (!cboot_blob)
+		return -EINVAL;
+
+	na = fdtdec_get_uint(cboot_blob, 0, "#address-cells", 2);
+	ns = fdtdec_get_uint(cboot_blob, 0, "#size-cells", 2);
+
+	node = fdt_path_offset(cboot_blob, "/memory");
+	if (node < 0) {
+		pr_err("Can't find /memory node in cboot DTB");
+		hang();
+	}
+	prop = fdt_getprop(cboot_blob, node, "reg", &len);
+	if (!prop) {
+		pr_err("Can't find /memory/reg property in cboot DTB");
+		hang();
+	}
+
+	/* Calculate the true # of base/size pairs to read */
+	len /= 4;		/* Convert bytes to number of cells */
+	len /= (na + ns);	/* Convert cells to number of banks */
+	if (len > CONFIG_NR_DRAM_BANKS)
+		len = CONFIG_NR_DRAM_BANKS;
+
+	/* Parse the /memory node, and save useful entries */
+	gd->ram_size = 0;
+	ram_bank_count = 0;
+	for (i = 0; i < len; i++) {
+		u64 bank_start, bank_end, bank_size, usable_bank_size;
+
+		/* Extract raw memory region data from DTB */
+		bank_start = fdt_read_number(prop, na);
+		prop += na;
+		bank_size = fdt_read_number(prop, ns);
+		prop += ns;
+		gd->ram_size += bank_size;
+		bank_end = bank_start + bank_size;
+		debug("Bank %d: %llx..%llx (+%llx)\n", i,
+		      bank_start, bank_end, bank_size);
+
+		/*
+		 * Align the bank to MMU section size. This is not strictly
+		 * necessary, since the translation table construction code
+		 * handles page granularity without issue. However, aligning
+		 * the MMU entries reduces the size and number of levels in the
+		 * page table, so is worth it.
+		 */
+		bank_start = ROUND(bank_start, SZ_2M);
+		bank_end = bank_end & ~(SZ_2M - 1);
+		bank_size = bank_end - bank_start;
+		debug("  aligned: %llx..%llx (+%llx)\n",
+		      bank_start, bank_end, bank_size);
+		if (bank_end <= bank_start)
+			continue;
+
+		/* Record data used to create MMU translation tables */
+		ram_bank_count++;
+		/* Index below is deliberately 1-based to skip MMIO entry */
+		tegra_mem_map[ram_bank_count].virt = bank_start;
+		tegra_mem_map[ram_bank_count].phys = bank_start;
+		tegra_mem_map[ram_bank_count].size = bank_size;
+		tegra_mem_map[ram_bank_count].attrs =
+			PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE;
+
+		/* Determine best bank to relocate U-Boot into */
+		if (bank_end > SZ_4G)
+			bank_end = SZ_4G;
+		debug("  end  %llx (usable)\n", bank_end);
+		usable_bank_size = bank_end - bank_start;
+		debug("  size %llx (usable)\n", usable_bank_size);
+		if ((usable_bank_size >= MIN_USABLE_RAM_SIZE) &&
+		    (bank_end > ram_top)) {
+			ram_top = bank_end;
+			region_base = bank_start;
+			debug("ram top now %llx\n", ram_top);
+		}
+	}
+
+	/* Ensure memory map contains the desired sentinel entry */
+	tegra_mem_map[ram_bank_count + 1].virt = 0;
+	tegra_mem_map[ram_bank_count + 1].phys = 0;
+	tegra_mem_map[ram_bank_count + 1].size = 0;
+	tegra_mem_map[ram_bank_count + 1].attrs = 0;
+
+	/* Error out if a relocation target couldn't be found */
+	if (!ram_top) {
+		pr_err("Can't find a usable RAM top");
+		hang();
+	}
+
+	return 0;
+}
+
+int cboot_dram_init_banksize(void)
+{
+	int i;
+
+	if (ram_bank_count == 0)
+		return -EINVAL;
+
+	if ((gd->start_addr_sp - region_base) < MIN_USABLE_STACK_SIZE) {
+		pr_err("Reservations exceed chosen region size");
+		hang();
+	}
+
+	for (i = 0; i < ram_bank_count; i++) {
+		gd->bd->bi_dram[i].start = tegra_mem_map[1 + i].virt;
+		gd->bd->bi_dram[i].size = tegra_mem_map[1 + i].size;
+	}
+
+#ifdef CONFIG_PCI
+	gd->pci_ram_top = ram_top;
+#endif
+
+	return 0;
+}
+
+ulong cboot_get_usable_ram_top(ulong total_size)
+{
+	return ram_top;
+}
+
+/*
+ * The following few functions run late during the boot process and dynamically
+ * calculate the load address of various binaries. To keep track of multiple
+ * allocations, some writable list of RAM banks must be used. tegra_mem_map[]
+ * is used for this purpose to avoid making yet another copy of the list of RAM
+ * banks. This is safe because tegra_mem_map[] is only used once during very
+ * early boot to create U-Boot's page tables, long before this code runs. If
+ * this assumption becomes invalid later, we can just fix the code to copy the
+ * list of RAM banks into some private data structure before running.
+ */
+
+static char *gen_varname(const char *var, const char *ext)
+{
+	size_t len_var = strlen(var);
+	size_t len_ext = strlen(ext);
+	size_t len = len_var + len_ext + 1;
+	char *varext = malloc(len);
+
+	if (!varext)
+		return 0;
+	strcpy(varext, var);
+	strcpy(varext + len_var, ext);
+	return varext;
+}
+
+static void mark_ram_allocated(int bank, u64 allocated_start, u64 allocated_end)
+{
+	u64 bank_start = tegra_mem_map[bank].virt;
+	u64 bank_size = tegra_mem_map[bank].size;
+	u64 bank_end = bank_start + bank_size;
+	bool keep_front = allocated_start != bank_start;
+	bool keep_tail = allocated_end != bank_end;
+
+	if (keep_front && keep_tail) {
+		/*
+		 * There are CONFIG_NR_DRAM_BANKS DRAM entries in the array,
+		 * starting at index 1 (index 0 is MMIO). So, we are at DRAM
+		 * entry "bank" not "bank - 1" as for a typical 0-base array.
+		 * The number of remaining DRAM entries is therefore
+		 * "CONFIG_NR_DRAM_BANKS - bank". We want to duplicate the
+		 * current entry and shift up the remaining entries, dropping
+		 * the last one. Thus, we must copy one fewer entry than the
+		 * number remaining.
+		 */
+		memmove(&tegra_mem_map[bank + 1], &tegra_mem_map[bank],
+			CONFIG_NR_DRAM_BANKS - bank - 1);
+		tegra_mem_map[bank].size = allocated_start - bank_start;
+		bank++;
+		tegra_mem_map[bank].virt = allocated_end;
+		tegra_mem_map[bank].phys = allocated_end;
+		tegra_mem_map[bank].size = bank_end - allocated_end;
+	} else if (keep_front) {
+		tegra_mem_map[bank].size = allocated_start - bank_start;
+	} else if (keep_tail) {
+		tegra_mem_map[bank].virt = allocated_end;
+		tegra_mem_map[bank].phys = allocated_end;
+		tegra_mem_map[bank].size = bank_end - allocated_end;
+	} else {
+		/*
+		 * We could move all subsequent banks down in the array but
+		 * that's not necessary for subsequent allocations to work, so
+		 * we skip doing so.
+		 */
+		tegra_mem_map[bank].size = 0;
+	}
+}
+
+static void reserve_ram(u64 start, u64 size)
+{
+	int bank;
+	u64 end = start + size;
+
+	for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
+		u64 bank_start = tegra_mem_map[bank].virt;
+		u64 bank_size = tegra_mem_map[bank].size;
+		u64 bank_end = bank_start + bank_size;
+
+		if (end <= bank_start || start > bank_end)
+			continue;
+		mark_ram_allocated(bank, start, end);
+		break;
+	}
+}
+
+static u64 alloc_ram(u64 size, u64 align, u64 offset)
+{
+	int bank;
+
+	for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
+		u64 bank_start = tegra_mem_map[bank].virt;
+		u64 bank_size = tegra_mem_map[bank].size;
+		u64 bank_end = bank_start + bank_size;
+		u64 allocated = ROUND(bank_start, align) + offset;
+		u64 allocated_end = allocated + size;
+
+		if (allocated_end > bank_end)
+			continue;
+		mark_ram_allocated(bank, allocated, allocated_end);
+		return allocated;
+	}
+	return 0;
+}
+
+static void set_calculated_aliases(char *aliases, u64 address)
+{
+	char *tmp, *alias;
+	int err;
+
+	aliases = strdup(aliases);
+	if (!aliases) {
+		pr_err("strdup(aliases) failed");
+		return;
+	}
+
+	tmp = aliases;
+	while (true) {
+		alias = strsep(&tmp, " ");
+		if (!alias)
+			break;
+		debug("%s: alias: %s\n", __func__, alias);
+		err = env_set_hex(alias, address);
+		if (err)
+			pr_err("Could not set %s\n", alias);
+	}
+
+	free(aliases);
+}
+
+static void set_calculated_env_var(const char *var)
+{
+	char *var_size;
+	char *var_align;
+	char *var_offset;
+	char *var_aliases;
+	u64 size;
+	u64 align;
+	u64 offset;
+	char *aliases;
+	u64 address;
+	int err;
+
+	var_size = gen_varname(var, "_size");
+	if (!var_size)
+		return;
+	var_align = gen_varname(var, "_align");
+	if (!var_align)
+		goto out_free_var_size;
+	var_offset = gen_varname(var, "_offset");
+	if (!var_offset)
+		goto out_free_var_align;
+	var_aliases = gen_varname(var, "_aliases");
+	if (!var_aliases)
+		goto out_free_var_offset;
+
+	size = env_get_hex(var_size, 0);
+	if (!size) {
+		pr_err("%s not set or zero\n", var_size);
+		goto out_free_var_aliases;
+	}
+	align = env_get_hex(var_align, 1);
+	/* Handle extant variables, but with a value of 0 */
+	if (!align)
+		align = 1;
+	offset = env_get_hex(var_offset, 0);
+	aliases = env_get(var_aliases);
+
+	debug("%s: Calc var %s; size=%llx, align=%llx, offset=%llx\n",
+	      __func__, var, size, align, offset);
+	if (aliases)
+		debug("%s: Aliases: %s\n", __func__, aliases);
+
+	address = alloc_ram(size, align, offset);
+	if (!address) {
+		pr_err("Could not allocate %s\n", var);
+		goto out_free_var_aliases;
+	}
+	debug("%s: Address %llx\n", __func__, address);
+
+	err = env_set_hex(var, address);
+	if (err)
+		pr_err("Could not set %s\n", var);
+	if (aliases)
+		set_calculated_aliases(aliases, address);
+
+out_free_var_aliases:
+	free(var_aliases);
+out_free_var_offset:
+	free(var_offset);
+out_free_var_align:
+	free(var_align);
+out_free_var_size:
+	free(var_size);
+}
+
+#ifdef DEBUG
+static void dump_ram_banks(void)
+{
+	int bank;
+
+	for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
+		u64 bank_start = tegra_mem_map[bank].virt;
+		u64 bank_size = tegra_mem_map[bank].size;
+		u64 bank_end = bank_start + bank_size;
+
+		if (!bank_size)
+			continue;
+		printf("%d: %010llx..%010llx (+%010llx)\n", bank - 1,
+		       bank_start, bank_end, bank_size);
+	}
+}
+#endif
+
+static void set_calculated_env_vars(void)
+{
+	char *vars, *tmp, *var;
+
+#ifdef DEBUG
+	printf("RAM banks before any calculated env. var.s:\n");
+	dump_ram_banks();
+#endif
+
+	reserve_ram(cboot_boot_x0, fdt_totalsize(cboot_boot_x0));
+
+#ifdef DEBUG
+	printf("RAM after reserving cboot DTB:\n");
+	dump_ram_banks();
+#endif
+
+	vars = env_get("calculated_vars");
+	if (!vars) {
+		debug("%s: No env var calculated_vars\n", __func__);
+		return;
+	}
+
+	vars = strdup(vars);
+	if (!vars) {
+		pr_err("strdup(calculated_vars) failed");
+		return;
+	}
+
+	tmp = vars;
+	while (true) {
+		var = strsep(&tmp, " ");
+		if (!var)
+			break;
+		debug("%s: var: %s\n", __func__, var);
+		set_calculated_env_var(var);
+#ifdef DEBUG
+		printf("RAM banks after allocating %s:\n", var);
+		dump_ram_banks();
+#endif
+	}
+
+	free(vars);
+}
+
+static int set_fdt_addr(void)
+{
+	int ret;
+
+	ret = env_set_hex("fdt_addr", cboot_boot_x0);
+	if (ret) {
+		printf("Failed to set fdt_addr to point at DTB: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Attempt to use /chosen/nvidia,ether-mac in the cboot DTB to U-Boot's
+ * ethaddr environment variable if possible.
+ */
+static int cboot_get_ethaddr_legacy(const void *fdt, uint8_t mac[ETH_ALEN])
+{
+	const char *const properties[] = {
+		"nvidia,ethernet-mac",
+		"nvidia,ether-mac",
+	};
+	const char *prop;
+	unsigned int i;
+	int node, len;
+
+	node = fdt_path_offset(fdt, "/chosen");
+	if (node < 0) {
+		printf("Can't find /chosen node in cboot DTB\n");
+		return node;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(properties); i++) {
+		prop = fdt_getprop(fdt, node, properties[i], &len);
+		if (prop)
+			break;
+	}
+
+	if (!prop) {
+		printf("Can't find Ethernet MAC address in cboot DTB\n");
+		return -ENOENT;
+	}
+
+	eth_parse_enetaddr(prop, mac);
+
+	if (!is_valid_ethaddr(mac)) {
+		printf("Invalid MAC address: %s\n", prop);
+		return -EINVAL;
+	}
+
+	debug("Legacy MAC address: %pM\n", mac);
+
+	return 0;
+}
+
+int cboot_get_ethaddr(const void *fdt, uint8_t mac[ETH_ALEN])
+{
+	int node, len, err = 0;
+	const uchar *prop;
+	const char *path;
+
+	path = fdt_get_alias(fdt, "ethernet");
+	if (!path) {
+		err = -ENOENT;
+		goto out;
+	}
+
+	debug("ethernet alias found: %s\n", path);
+
+	node = fdt_path_offset(fdt, path);
+	if (node < 0) {
+		err = -ENOENT;
+		goto out;
+	}
+
+	prop = fdt_getprop(fdt, node, "local-mac-address", &len);
+	if (!prop) {
+		err = -ENOENT;
+		goto out;
+	}
+
+	if (len != ETH_ALEN) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	debug("MAC address: %pM\n", prop);
+	memcpy(mac, prop, ETH_ALEN);
+
+out:
+	if (err < 0)
+		err = cboot_get_ethaddr_legacy(fdt, mac);
+
+	return err;
+}
+
+static char *strip(const char *ptr)
+{
+	const char *end;
+
+	while (*ptr && isblank(*ptr))
+		ptr++;
+
+	/* empty string */
+	if (*ptr == '\0')
+		return strdup(ptr);
+
+	end = ptr;
+
+	while (end[1])
+		end++;
+
+	while (isblank(*end))
+		end--;
+
+	return strndup(ptr, end - ptr + 1);
+}
+
+static char *cboot_get_bootargs(const void *fdt)
+{
+	const char *args;
+	int offset, len;
+
+	offset = fdt_path_offset(fdt, "/chosen");
+	if (offset < 0)
+		return NULL;
+
+	args = fdt_getprop(fdt, offset, "bootargs", &len);
+	if (!args)
+		return NULL;
+
+	return strip(args);
+}
+
+int cboot_late_init(void)
+{
+	const void *fdt = (const void *)cboot_boot_x0;
+	uint8_t mac[ETH_ALEN];
+	char *bootargs;
+	int err;
+
+	set_calculated_env_vars();
+	/*
+	 * Ignore errors here; the value may not be used depending on
+	 * extlinux.conf or boot script content.
+	 */
+	set_fdt_addr();
+
+	/* Ignore errors here; not all cases care about Ethernet addresses */
+	err = cboot_get_ethaddr(fdt, mac);
+	if (!err) {
+		void *blob = (void *)gd->fdt_blob;
+
+		err = fdtdec_set_ethernet_mac_address(blob, mac, sizeof(mac));
+		if (err < 0)
+			printf("failed to set MAC address %pM: %d\n", mac, err);
+	}
+
+	bootargs = cboot_get_bootargs(fdt);
+	if (bootargs) {
+		env_set("cbootargs", bootargs);
+		free(bootargs);
+	}
+
+	return 0;
+}
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index dc5f16b..e539ad8 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2010-2015, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2019, NVIDIA CORPORATION.  All rights reserved.
  */
 
 /* Tegra SoC common clock control functions */
@@ -815,11 +815,16 @@
 
 int clock_external_output(int clk_id)
 {
-	struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+	u32 val;
 
 	if (clk_id >= 1 && clk_id <= 3) {
-		setbits_le32(&pmc->pmc_clk_out_cntrl,
-			     1 << (2 + (clk_id - 1) * 8));
+		val = tegra_pmc_readl(offsetof(struct pmc_ctlr,
+				      pmc_clk_out_cntrl));
+		val |= 1 << (2 + (clk_id - 1) * 8);
+		tegra_pmc_writel(val,
+				 offsetof(struct pmc_ctlr,
+				 pmc_clk_out_cntrl));
+
 	} else {
 		printf("%s: Unknown output clock id %d\n", __func__, clk_id);
 		return -EINVAL;
diff --git a/arch/arm/mach-tegra/cmd_enterrcm.c b/arch/arm/mach-tegra/cmd_enterrcm.c
index 4e6beb3..4a889f0 100644
--- a/arch/arm/mach-tegra/cmd_enterrcm.c
+++ b/arch/arm/mach-tegra/cmd_enterrcm.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2012-2019, NVIDIA CORPORATION. All rights reserved.
  *
  * Derived from code (arch/arm/lib/reset.c) that is:
  *
@@ -31,12 +31,10 @@
 static int do_enterrcm(cmd_tbl_t *cmdtp, int flag, int argc,
 		       char * const argv[])
 {
-	struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
-
 	puts("Entering RCM...\n");
 	udelay(50000);
 
-	pmc->pmc_scratch0 = 2;
+	tegra_pmc_writel(2, PMC_SCRATCH0);
 	disable_interrupts();
 	reset_cpu(0);
 
diff --git a/arch/arm/mach-tegra/cpu.c b/arch/arm/mach-tegra/cpu.c
index 1b6ad07..3d14076 100644
--- a/arch/arm/mach-tegra/cpu.c
+++ b/arch/arm/mach-tegra/cpu.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2010-2015, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2019, NVIDIA CORPORATION.  All rights reserved.
  */
 
 #include <common.h>
@@ -299,21 +299,19 @@
 
 static int is_cpu_powered(void)
 {
-	struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
-
-	return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0;
+	return (tegra_pmc_readl(offsetof(struct pmc_ctlr,
+				pmc_pwrgate_status)) & CPU_PWRED) ? 1 : 0;
 }
 
 static void remove_cpu_io_clamps(void)
 {
-	struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
 	u32 reg;
 	debug("%s entry\n", __func__);
 
 	/* Remove the clamps on the CPU I/O signals */
-	reg = readl(&pmc->pmc_remove_clamping);
+	reg = tegra_pmc_readl(offsetof(struct pmc_ctlr, pmc_remove_clamping));
 	reg |= CPU_CLMP;
-	writel(reg, &pmc->pmc_remove_clamping);
+	tegra_pmc_writel(reg, offsetof(struct pmc_ctlr, pmc_remove_clamping));
 
 	/* Give I/O signals time to stabilize */
 	udelay(IO_STABILIZATION_DELAY);
@@ -321,17 +319,19 @@
 
 void powerup_cpu(void)
 {
-	struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
 	u32 reg;
 	int timeout = IO_STABILIZATION_DELAY;
 	debug("%s entry\n", __func__);
 
 	if (!is_cpu_powered()) {
 		/* Toggle the CPU power state (OFF -> ON) */
-		reg = readl(&pmc->pmc_pwrgate_toggle);
+		reg = tegra_pmc_readl(offsetof(struct pmc_ctlr,
+				      pmc_pwrgate_toggle));
 		reg &= PARTID_CP;
 		reg |= START_CP;
-		writel(reg, &pmc->pmc_pwrgate_toggle);
+		tegra_pmc_writel(reg,
+				 offsetof(struct pmc_ctlr,
+				 pmc_pwrgate_toggle));
 
 		/* Wait for the power to come up */
 		while (!is_cpu_powered()) {
diff --git a/arch/arm/mach-tegra/emc.c b/arch/arm/mach-tegra/emc.c
index 6697909..6662893 100644
--- a/arch/arm/mach-tegra/emc.c
+++ b/arch/arm/mach-tegra/emc.c
@@ -8,10 +8,10 @@
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/emc.h>
-#include <asm/arch/pmu.h>
 #include <asm/arch/tegra.h>
 #include <asm/arch-tegra/ap.h>
 #include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/pmu.h>
 #include <asm/arch-tegra/sys_proto.h>
 
 DECLARE_GLOBAL_DATA_PTR;
diff --git a/arch/arm/mach-tegra/lowlevel_init.S b/arch/arm/mach-tegra/lowlevel_init.S
deleted file mode 100644
index 626f1b6..0000000
--- a/arch/arm/mach-tegra/lowlevel_init.S
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * SoC-specific setup info
- *
- * (C) Copyright 2010,2011
- * NVIDIA Corporation <www.nvidia.com>
- */
-
-#include <config.h>
-#include <linux/linkage.h>
-
-#ifdef CONFIG_ARM64
-	.align	5
-ENTRY(reset_cpu)
-	/* get address for global reset register */
-	ldr	x1, =PRM_RSTCTRL
-	ldr	w3, [x1]
-	/* force reset */
-	orr	w3, w3, #0x10
-	str	w3, [x1]
-	mov	w0, w0
-1:
-	b	1b
-ENDPROC(reset_cpu)
-#else
-	.align	5
-ENTRY(reset_cpu)
-	ldr	r1, rstctl			@ get addr for global reset
-						@ reg
-	ldr	r3, [r1]
-	orr	r3, r3, #0x10
-	str	r3, [r1]			@ force reset
-	mov	r0, r0
-_loop_forever:
-	b	_loop_forever
-rstctl:
-	.word	PRM_RSTCTRL
-ENDPROC(reset_cpu)
-#endif
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
new file mode 100644
index 0000000..afd3c54
--- /dev/null
+++ b/arch/arm/mach-tegra/pmc.c
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
+ */
+
+#include <common.h>
+
+#include <linux/arm-smccc.h>
+
+#include <asm/io.h>
+#include <asm/arch-tegra/pmc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if IS_ENABLED(CONFIG_TEGRA_PMC_SECURE)
+static bool tegra_pmc_detect_tz_only(void)
+{
+	static bool initialized = false;
+	static bool is_tz_only = false;
+	u32 value, saved;
+
+	if (!initialized) {
+		saved = readl(NV_PA_PMC_BASE + PMC_SCRATCH0);
+		value = saved ^ 0xffffffff;
+
+		if (value == 0xffffffff)
+			value = 0xdeadbeef;
+
+		/* write pattern and read it back */
+		writel(value, NV_PA_PMC_BASE + PMC_SCRATCH0);
+		value = readl(NV_PA_PMC_BASE + PMC_SCRATCH0);
+
+		/* if we read all-zeroes, access is restricted to TZ only */
+		if (value == 0) {
+			debug("access to PMC is restricted to TZ\n");
+			is_tz_only = true;
+		} else {
+			/* restore original value */
+			writel(saved, NV_PA_PMC_BASE + PMC_SCRATCH0);
+		}
+
+		initialized = true;
+	}
+
+	return is_tz_only;
+}
+#endif
+
+uint32_t tegra_pmc_readl(unsigned long offset)
+{
+#if IS_ENABLED(CONFIG_TEGRA_PMC_SECURE)
+	if (tegra_pmc_detect_tz_only()) {
+		struct arm_smccc_res res;
+
+		arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_READ, offset, 0, 0,
+			      0, 0, 0, &res);
+		if (res.a0)
+			printf("%s(): SMC failed: %lu\n", __func__, res.a0);
+
+		return res.a1;
+	}
+#endif
+
+	return readl(NV_PA_PMC_BASE + offset);
+}
+
+void tegra_pmc_writel(u32 value, unsigned long offset)
+{
+#if IS_ENABLED(CONFIG_TEGRA_PMC_SECURE)
+	if (tegra_pmc_detect_tz_only()) {
+		struct arm_smccc_res res;
+
+		arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_WRITE, offset,
+			      value, 0, 0, 0, 0, &res);
+		if (res.a0)
+			printf("%s(): SMC failed: %lu\n", __func__, res.a0);
+
+		return;
+	}
+#endif
+
+	writel(value, NV_PA_PMC_BASE + offset);
+}
+
+void reset_cpu(ulong addr)
+{
+	u32 value;
+
+	value = tegra_pmc_readl(PMC_CNTRL);
+	value |= PMC_CNTRL_MAIN_RST;
+	tegra_pmc_writel(value, PMC_CNTRL);
+}
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index e45f096..761c9ef 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2019, NVIDIA CORPORATION.  All rights reserved.
  */
 
 #include <common.h>
@@ -11,6 +11,7 @@
 
 #include <asm/arch/powergate.h>
 #include <asm/arch/tegra.h>
+#include <asm/arch-tegra/pmc.h>
 
 #define PWRGATE_TOGGLE 0x30
 #define  PWRGATE_TOGGLE_START (1 << 8)
@@ -24,18 +25,18 @@
 	u32 value, mask = state ? (1 << id) : 0, old_mask;
 	unsigned long start, timeout = 25;
 
-	value = readl(NV_PA_PMC_BASE + PWRGATE_STATUS);
+	value = tegra_pmc_readl(PWRGATE_STATUS);
 	old_mask = value & (1 << id);
 
 	if (mask == old_mask)
 		return 0;
 
-	writel(PWRGATE_TOGGLE_START | id, NV_PA_PMC_BASE + PWRGATE_TOGGLE);
+	tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
 
 	start = get_timer(0);
 
 	while (get_timer(start) < timeout) {
-		value = readl(NV_PA_PMC_BASE + PWRGATE_STATUS);
+		value = tegra_pmc_readl(PWRGATE_STATUS);
 		if ((value & (1 << id)) == mask)
 			return 0;
 	}
@@ -69,7 +70,7 @@
 	else
 		value = 1 << id;
 
-	writel(value, NV_PA_PMC_BASE + REMOVE_CLAMPING);
+	tegra_pmc_writel(value, REMOVE_CLAMPING);
 
 	return 0;
 }
diff --git a/arch/arm/mach-tegra/tegra186/Makefile b/arch/arm/mach-tegra/tegra186/Makefile
index 56f3378..3a24050 100644
--- a/arch/arm/mach-tegra/tegra186/Makefile
+++ b/arch/arm/mach-tegra/tegra186/Makefile
@@ -2,8 +2,4 @@
 #
 # SPDX-License-Identifier: GPL-2.0
 
-obj-y += ../board186.o
 obj-y += cache.o
-obj-y += nvtboot_board.o
-obj-y += nvtboot_ll.o
-obj-y += nvtboot_mem.o
diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_board.c b/arch/arm/mach-tegra/tegra186/nvtboot_board.c
deleted file mode 100644
index 83c0e93..0000000
--- a/arch/arm/mach-tegra/tegra186/nvtboot_board.c
+++ /dev/null
@@ -1,332 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2016-2018, NVIDIA CORPORATION.
- */
-
-#include <stdlib.h>
-#include <common.h>
-#include <fdt_support.h>
-#include <fdtdec.h>
-#include <asm/arch/tegra.h>
-#include <asm/armv8/mmu.h>
-
-extern unsigned long nvtboot_boot_x0;
-
-/*
- * The following few functions run late during the boot process and dynamically
- * calculate the load address of various binaries. To keep track of multiple
- * allocations, some writable list of RAM banks must be used. tegra_mem_map[]
- * is used for this purpose to avoid making yet another copy of the list of RAM
- * banks. This is safe because tegra_mem_map[] is only used once during very
- * early boot to create U-Boot's page tables, long before this code runs. If
- * this assumption becomes invalid later, we can just fix the code to copy the
- * list of RAM banks into some private data structure before running.
- */
-
-extern struct mm_region tegra_mem_map[];
-
-static char *gen_varname(const char *var, const char *ext)
-{
-	size_t len_var = strlen(var);
-	size_t len_ext = strlen(ext);
-	size_t len = len_var + len_ext + 1;
-	char *varext = malloc(len);
-
-	if (!varext)
-		return 0;
-	strcpy(varext, var);
-	strcpy(varext + len_var, ext);
-	return varext;
-}
-
-static void mark_ram_allocated(int bank, u64 allocated_start, u64 allocated_end)
-{
-	u64 bank_start = tegra_mem_map[bank].virt;
-	u64 bank_size = tegra_mem_map[bank].size;
-	u64 bank_end = bank_start + bank_size;
-	bool keep_front = allocated_start != bank_start;
-	bool keep_tail = allocated_end != bank_end;
-
-	if (keep_front && keep_tail) {
-		/*
-		 * There are CONFIG_NR_DRAM_BANKS DRAM entries in the array,
-		 * starting at index 1 (index 0 is MMIO). So, we are at DRAM
-		 * entry "bank" not "bank - 1" as for a typical 0-base array.
-		 * The number of remaining DRAM entries is therefore
-		 * "CONFIG_NR_DRAM_BANKS - bank". We want to duplicate the
-		 * current entry and shift up the remaining entries, dropping
-		 * the last one. Thus, we must copy one fewer entry than the
-		 * number remaining.
-		 */
-		memmove(&tegra_mem_map[bank + 1], &tegra_mem_map[bank],
-			CONFIG_NR_DRAM_BANKS - bank - 1);
-		tegra_mem_map[bank].size = allocated_start - bank_start;
-		bank++;
-		tegra_mem_map[bank].virt = allocated_end;
-		tegra_mem_map[bank].phys = allocated_end;
-		tegra_mem_map[bank].size = bank_end - allocated_end;
-	} else if (keep_front) {
-		tegra_mem_map[bank].size = allocated_start - bank_start;
-	} else if (keep_tail) {
-		tegra_mem_map[bank].virt = allocated_end;
-		tegra_mem_map[bank].phys = allocated_end;
-		tegra_mem_map[bank].size = bank_end - allocated_end;
-	} else {
-		/*
-		 * We could move all subsequent banks down in the array but
-		 * that's not necessary for subsequent allocations to work, so
-		 * we skip doing so.
-		 */
-		tegra_mem_map[bank].size = 0;
-	}
-}
-
-static void reserve_ram(u64 start, u64 size)
-{
-	int bank;
-	u64 end = start + size;
-
-	for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
-		u64 bank_start = tegra_mem_map[bank].virt;
-		u64 bank_size = tegra_mem_map[bank].size;
-		u64 bank_end = bank_start + bank_size;
-
-		if (end <= bank_start || start > bank_end)
-			continue;
-		mark_ram_allocated(bank, start, end);
-		break;
-	}
-}
-
-static u64 alloc_ram(u64 size, u64 align, u64 offset)
-{
-	int bank;
-
-	for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
-		u64 bank_start = tegra_mem_map[bank].virt;
-		u64 bank_size = tegra_mem_map[bank].size;
-		u64 bank_end = bank_start + bank_size;
-		u64 allocated = ROUND(bank_start, align) + offset;
-		u64 allocated_end = allocated + size;
-
-		if (allocated_end > bank_end)
-			continue;
-		mark_ram_allocated(bank, allocated, allocated_end);
-		return allocated;
-	}
-	return 0;
-}
-
-static void set_calculated_aliases(char *aliases, u64 address)
-{
-	char *tmp, *alias;
-	int err;
-
-	aliases = strdup(aliases);
-	if (!aliases) {
-		pr_err("strdup(aliases) failed");
-		return;
-	}
-
-	tmp = aliases;
-	while (true) {
-		alias = strsep(&tmp, " ");
-		if (!alias)
-			break;
-		debug("%s: alias: %s\n", __func__, alias);
-		err = env_set_hex(alias, address);
-		if (err)
-			pr_err("Could not set %s\n", alias);
-	}
-
-	free(aliases);
-}
-
-static void set_calculated_env_var(const char *var)
-{
-	char *var_size;
-	char *var_align;
-	char *var_offset;
-	char *var_aliases;
-	u64 size;
-	u64 align;
-	u64 offset;
-	char *aliases;
-	u64 address;
-	int err;
-
-	var_size = gen_varname(var, "_size");
-	if (!var_size)
-		return;
-	var_align = gen_varname(var, "_align");
-	if (!var_align)
-		goto out_free_var_size;
-	var_offset = gen_varname(var, "_offset");
-	if (!var_offset)
-		goto out_free_var_align;
-	var_aliases = gen_varname(var, "_aliases");
-	if (!var_aliases)
-		goto out_free_var_offset;
-
-	size = env_get_hex(var_size, 0);
-	if (!size) {
-		pr_err("%s not set or zero\n", var_size);
-		goto out_free_var_aliases;
-	}
-	align = env_get_hex(var_align, 1);
-	/* Handle extant variables, but with a value of 0 */
-	if (!align)
-		align = 1;
-	offset = env_get_hex(var_offset, 0);
-	aliases = env_get(var_aliases);
-
-	debug("%s: Calc var %s; size=%llx, align=%llx, offset=%llx\n",
-	      __func__, var, size, align, offset);
-	if (aliases)
-		debug("%s: Aliases: %s\n", __func__, aliases);
-
-	address = alloc_ram(size, align, offset);
-	if (!address) {
-		pr_err("Could not allocate %s\n", var);
-		goto out_free_var_aliases;
-	}
-	debug("%s: Address %llx\n", __func__, address);
-
-	err = env_set_hex(var, address);
-	if (err)
-		pr_err("Could not set %s\n", var);
-	if (aliases)
-		set_calculated_aliases(aliases, address);
-
-out_free_var_aliases:
-	free(var_aliases);
-out_free_var_offset:
-	free(var_offset);
-out_free_var_align:
-	free(var_align);
-out_free_var_size:
-	free(var_size);
-}
-
-#ifdef DEBUG
-static void dump_ram_banks(void)
-{
-	int bank;
-
-	for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
-		u64 bank_start = tegra_mem_map[bank].virt;
-		u64 bank_size = tegra_mem_map[bank].size;
-		u64 bank_end = bank_start + bank_size;
-
-		if (!bank_size)
-			continue;
-		printf("%d: %010llx..%010llx (+%010llx)\n", bank - 1,
-		       bank_start, bank_end, bank_size);
-	}
-}
-#endif
-
-static void set_calculated_env_vars(void)
-{
-	char *vars, *tmp, *var;
-
-#ifdef DEBUG
-	printf("RAM banks before any calculated env. var.s:\n");
-	dump_ram_banks();
-#endif
-
-	reserve_ram(nvtboot_boot_x0, fdt_totalsize(nvtboot_boot_x0));
-
-#ifdef DEBUG
-	printf("RAM after reserving cboot DTB:\n");
-	dump_ram_banks();
-#endif
-
-	vars = env_get("calculated_vars");
-	if (!vars) {
-		debug("%s: No env var calculated_vars\n", __func__);
-		return;
-	}
-
-	vars = strdup(vars);
-	if (!vars) {
-		pr_err("strdup(calculated_vars) failed");
-		return;
-	}
-
-	tmp = vars;
-	while (true) {
-		var = strsep(&tmp, " ");
-		if (!var)
-			break;
-		debug("%s: var: %s\n", __func__, var);
-		set_calculated_env_var(var);
-#ifdef DEBUG
-		printf("RAM banks affter allocating %s:\n", var);
-		dump_ram_banks();
-#endif
-	}
-
-	free(vars);
-}
-
-static int set_fdt_addr(void)
-{
-	int ret;
-
-	ret = env_set_hex("fdt_addr", nvtboot_boot_x0);
-	if (ret) {
-		printf("Failed to set fdt_addr to point at DTB: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-/*
- * Attempt to use /chosen/nvidia,ether-mac in the nvtboot DTB to U-Boot's
- * ethaddr environment variable if possible.
- */
-static int set_ethaddr_from_nvtboot(void)
-{
-	const void *nvtboot_blob = (void *)nvtboot_boot_x0;
-	int ret, node, len;
-	const u32 *prop;
-
-	/* Already a valid address in the environment? If so, keep it */
-	if (env_get("ethaddr"))
-		return 0;
-
-	node = fdt_path_offset(nvtboot_blob, "/chosen");
-	if (node < 0) {
-		printf("Can't find /chosen node in nvtboot DTB\n");
-		return node;
-	}
-	prop = fdt_getprop(nvtboot_blob, node, "nvidia,ether-mac", &len);
-	if (!prop) {
-		printf("Can't find nvidia,ether-mac property in nvtboot DTB\n");
-		return -ENOENT;
-	}
-
-	ret = env_set("ethaddr", (void *)prop);
-	if (ret) {
-		printf("Failed to set ethaddr from nvtboot DTB: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-int tegra_soc_board_init_late(void)
-{
-	set_calculated_env_vars();
-	/*
-	 * Ignore errors here; the value may not be used depending on
-	 * extlinux.conf or boot script content.
-	 */
-	set_fdt_addr();
-	/* Ignore errors here; not all cases care about Ethernet addresses */
-	set_ethaddr_from_nvtboot();
-
-	return 0;
-}
diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_ll.S b/arch/arm/mach-tegra/tegra186/nvtboot_ll.S
deleted file mode 100644
index aa7a863..0000000
--- a/arch/arm/mach-tegra/tegra186/nvtboot_ll.S
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Save nvtboot-related boot-time CPU state
- *
- * (C) Copyright 2015-2016 NVIDIA Corporation <www.nvidia.com>
- */
-
-#include <config.h>
-#include <linux/linkage.h>
-
-.align 8
-.globl	nvtboot_boot_x0
-nvtboot_boot_x0:
-	.dword 0
-
-ENTRY(save_boot_params)
-	adr	x8, nvtboot_boot_x0
-	str	x0, [x8]
-	b	save_boot_params_ret
-ENDPROC(save_boot_params)
diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c
deleted file mode 100644
index 6214282..0000000
--- a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c
+++ /dev/null
@@ -1,172 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2016-2018, NVIDIA CORPORATION.
- */
-
-#include <common.h>
-#include <fdt_support.h>
-#include <fdtdec.h>
-#include <linux/sizes.h>
-#include <asm/arch/tegra.h>
-#include <asm/armv8/mmu.h>
-
-/*
- * Size of a region that's large enough to hold the relocated U-Boot and all
- * other allocations made around it (stack, heap, page tables, etc.)
- * In practice, running "bdinfo" at the shell prompt, the stack reaches about
- * 5MB from the address selected for ram_top as of the time of writing,
- * so a 16MB region should be plenty.
- */
-#define MIN_USABLE_RAM_SIZE SZ_16M
-/*
- * The amount of space we expect to require for stack usage. Used to validate
- * that all reservations fit into the region selected for the relocation target
- */
-#define MIN_USABLE_STACK_SIZE SZ_1M
-
-DECLARE_GLOBAL_DATA_PTR;
-
-extern unsigned long nvtboot_boot_x0;
-extern struct mm_region tegra_mem_map[];
-
-/*
- * These variables are written to before relocation, and hence cannot be
- * in.bss, since .bss overlaps the DTB that's appended to the U-Boot binary.
- * The section attribute forces this into .data and avoids this issue. This
- * also has the nice side-effect of the content being valid after relocation.
- */
-
-/* The number of valid entries in ram_banks[] */
-static int ram_bank_count __attribute__((section(".data")));
-
-/*
- * The usable top-of-RAM for U-Boot. This is both:
- * a) Below 4GB to avoid issues with peripherals that use 32-bit addressing.
- * b) At the end of a region that has enough space to hold the relocated U-Boot
- *    and all other allocations made around it (stack, heap, page tables, etc.)
- */
-static u64 ram_top __attribute__((section(".data")));
-/* The base address of the region of RAM that ends at ram_top */
-static u64 region_base __attribute__((section(".data")));
-
-int dram_init(void)
-{
-	unsigned int na, ns;
-	const void *nvtboot_blob = (void *)nvtboot_boot_x0;
-	int node, len, i;
-	const u32 *prop;
-
-	na = fdtdec_get_uint(nvtboot_blob, 0, "#address-cells", 2);
-	ns = fdtdec_get_uint(nvtboot_blob, 0, "#size-cells", 2);
-
-	node = fdt_path_offset(nvtboot_blob, "/memory");
-	if (node < 0) {
-		pr_err("Can't find /memory node in nvtboot DTB");
-		hang();
-	}
-	prop = fdt_getprop(nvtboot_blob, node, "reg", &len);
-	if (!prop) {
-		pr_err("Can't find /memory/reg property in nvtboot DTB");
-		hang();
-	}
-
-	/* Calculate the true # of base/size pairs to read */
-	len /= 4;		/* Convert bytes to number of cells */
-	len /= (na + ns);	/* Convert cells to number of banks */
-	if (len > CONFIG_NR_DRAM_BANKS)
-		len = CONFIG_NR_DRAM_BANKS;
-
-	/* Parse the /memory node, and save useful entries */
-	gd->ram_size = 0;
-	ram_bank_count = 0;
-	for (i = 0; i < len; i++) {
-		u64 bank_start, bank_end, bank_size, usable_bank_size;
-
-		/* Extract raw memory region data from DTB */
-		bank_start = fdt_read_number(prop, na);
-		prop += na;
-		bank_size = fdt_read_number(prop, ns);
-		prop += ns;
-		gd->ram_size += bank_size;
-		bank_end = bank_start + bank_size;
-		debug("Bank %d: %llx..%llx (+%llx)\n", i,
-		      bank_start, bank_end, bank_size);
-
-		/*
-		 * Align the bank to MMU section size. This is not strictly
-		 * necessary, since the translation table construction code
-		 * handles page granularity without issue. However, aligning
-		 * the MMU entries reduces the size and number of levels in the
-		 * page table, so is worth it.
-		 */
-		bank_start = ROUND(bank_start, SZ_2M);
-		bank_end = bank_end & ~(SZ_2M - 1);
-		bank_size = bank_end - bank_start;
-		debug("  aligned: %llx..%llx (+%llx)\n",
-		      bank_start, bank_end, bank_size);
-		if (bank_end <= bank_start)
-			continue;
-
-		/* Record data used to create MMU translation tables */
-		ram_bank_count++;
-		/* Index below is deliberately 1-based to skip MMIO entry */
-		tegra_mem_map[ram_bank_count].virt = bank_start;
-		tegra_mem_map[ram_bank_count].phys = bank_start;
-		tegra_mem_map[ram_bank_count].size = bank_size;
-		tegra_mem_map[ram_bank_count].attrs =
-			PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE;
-
-		/* Determine best bank to relocate U-Boot into */
-		if (bank_end > SZ_4G)
-			bank_end = SZ_4G;
-		debug("  end  %llx (usable)\n", bank_end);
-		usable_bank_size = bank_end - bank_start;
-		debug("  size %llx (usable)\n", usable_bank_size);
-		if ((usable_bank_size >= MIN_USABLE_RAM_SIZE) &&
-		    (bank_end > ram_top)) {
-			ram_top = bank_end;
-			region_base = bank_start;
-			debug("ram top now %llx\n", ram_top);
-		}
-	}
-
-	/* Ensure memory map contains the desired sentinel entry */
-	tegra_mem_map[ram_bank_count + 1].virt = 0;
-	tegra_mem_map[ram_bank_count + 1].phys = 0;
-	tegra_mem_map[ram_bank_count + 1].size = 0;
-	tegra_mem_map[ram_bank_count + 1].attrs = 0;
-
-	/* Error out if a relocation target couldn't be found */
-	if (!ram_top) {
-		pr_err("Can't find a usable RAM top");
-		hang();
-	}
-
-	return 0;
-}
-
-int dram_init_banksize(void)
-{
-	int i;
-
-	if ((gd->start_addr_sp - region_base) < MIN_USABLE_STACK_SIZE) {
-		pr_err("Reservations exceed chosen region size");
-		hang();
-	}
-
-	for (i = 0; i < ram_bank_count; i++) {
-		gd->bd->bi_dram[i].start = tegra_mem_map[1 + i].virt;
-		gd->bd->bi_dram[i].size = tegra_mem_map[1 + i].size;
-	}
-
-#ifdef CONFIG_PCI
-	gd->pci_ram_top = ram_top;
-#endif
-
-	return 0;
-}
-
-ulong board_get_usable_ram_top(ulong total_size)
-{
-	return ram_top;
-}
diff --git a/arch/arm/mach-tegra/tegra210/clock.c b/arch/arm/mach-tegra/tegra210/clock.c
index 06068c4..b240860 100644
--- a/arch/arm/mach-tegra/tegra210/clock.c
+++ b/arch/arm/mach-tegra/tegra210/clock.c
@@ -40,7 +40,7 @@
 	CLOCK_TYPE_PDCT,
 	CLOCK_TYPE_ACPT,
 	CLOCK_TYPE_ASPTE,
-	CLOCK_TYPE_PMDACD2T,
+	CLOCK_TYPE_PDD2T,
 	CLOCK_TYPE_PCST,
 	CLOCK_TYPE_DP,
 
@@ -97,8 +97,8 @@
 	{ CLK(AUDIO),	CLK(SFROM32KHZ),	CLK(PERIPH),	CLK(OSC),
 		CLK(EPCI),	CLK(NONE),	CLK(NONE),	CLK(NONE),
 		MASK_BITS_31_29},
-	{ CLK(PERIPH),	CLK(MEMORY),	CLK(DISPLAY),	CLK(AUDIO),
-		CLK(CGENERAL),	CLK(DISPLAY2),	CLK(OSC),	CLK(NONE),
+	{ CLK(PERIPH),	CLK(NONE),	CLK(DISPLAY),	CLK(NONE),
+		CLK(NONE),	CLK(DISPLAY2),	CLK(OSC),	CLK(NONE),
 		MASK_BITS_31_29},
 	{ CLK(PERIPH),	CLK(CGENERAL),	CLK(SFROM32KHZ),	CLK(OSC),
 		CLK(NONE),	CLK(NONE),	CLK(NONE),	CLK(NONE),
@@ -174,8 +174,8 @@
 	TYPE(PERIPHC_0bh,	CLOCK_TYPE_NONE),
 	TYPE(PERIPHC_0ch,	CLOCK_TYPE_NONE),
 	TYPE(PERIPHC_SBC1,	CLOCK_TYPE_PC2CC3M_T),
-	TYPE(PERIPHC_DISP1,	CLOCK_TYPE_PMDACD2T),
-	TYPE(PERIPHC_DISP2,	CLOCK_TYPE_PMDACD2T),
+	TYPE(PERIPHC_DISP1,	CLOCK_TYPE_PDD2T),
+	TYPE(PERIPHC_DISP2,	CLOCK_TYPE_PDD2T),
 
 	/* 0x10 */
 	TYPE(PERIPHC_10h,	CLOCK_TYPE_NONE),
@@ -1265,7 +1265,6 @@
 	{ PERIPH_ID_SBC5, CLOCK_ID_PERIPH },
 	{ PERIPH_ID_SBC6, CLOCK_ID_PERIPH },
 	{ PERIPH_ID_HOST1X, CLOCK_ID_PERIPH },
-	{ PERIPH_ID_DISP1, CLOCK_ID_CGENERAL },
 	{ PERIPH_ID_SDMMC1, CLOCK_ID_PERIPH },
 	{ PERIPH_ID_SDMMC2, CLOCK_ID_PERIPH },
 	{ PERIPH_ID_SDMMC3, CLOCK_ID_PERIPH },
diff --git a/board/atmel/sama5d2_icp/sama5d2_icp.c b/board/atmel/sama5d2_icp/sama5d2_icp.c
index 807cfcd..1593e2b 100644
--- a/board/atmel/sama5d2_icp/sama5d2_icp.c
+++ b/board/atmel/sama5d2_icp/sama5d2_icp.c
@@ -73,6 +73,36 @@
 /* SPL */
 #ifdef CONFIG_SPL_BUILD
 
+/* must set PB25 low to enable the CAN transceivers */
+static void board_can_stdby_dis(void)
+{
+	atmel_pio4_set_pio_output(AT91_PIO_PORTB, 25, 0);
+}
+
+static void board_leds_init(void)
+{
+	atmel_pio4_set_pio_output(AT91_PIO_PORTB, 0, 0); /* RED */
+	atmel_pio4_set_pio_output(AT91_PIO_PORTB, 1, 1); /* GREEN */
+	atmel_pio4_set_pio_output(AT91_PIO_PORTA, 31, 0); /* BLUE */
+}
+
+/* deassert reset lines for external periph in case of warm reboot */
+static void board_reset_additional_periph(void)
+{
+	atmel_pio4_set_pio_output(AT91_PIO_PORTB, 16, 0); /* LAN9252_RST */
+	atmel_pio4_set_pio_output(AT91_PIO_PORTC, 2, 0); /* HSIC_RST */
+	atmel_pio4_set_pio_output(AT91_PIO_PORTC, 17, 0); /* USB2534_RST */
+	atmel_pio4_set_pio_output(AT91_PIO_PORTD, 4, 0); /* KSZ8563_RST */
+}
+
+static void board_start_additional_periph(void)
+{
+	atmel_pio4_set_pio_output(AT91_PIO_PORTB, 16, 1); /* LAN9252_RST */
+	atmel_pio4_set_pio_output(AT91_PIO_PORTC, 2, 1); /* HSIC_RST */
+	atmel_pio4_set_pio_output(AT91_PIO_PORTC, 17, 1); /* USB2534_RST */
+	atmel_pio4_set_pio_output(AT91_PIO_PORTD, 4, 1); /* KSZ8563_RST */
+}
+
 #ifdef CONFIG_SD_BOOT
 void spl_mmc_init(void)
 {
@@ -93,12 +123,20 @@
 #ifdef CONFIG_SD_BOOT
 	spl_mmc_init();
 #endif
+	board_reset_additional_periph();
+	board_can_stdby_dis();
+	board_leds_init();
 }
 
 void spl_display_print(void)
 {
 }
 
+void spl_board_prepare_for_boot(void)
+{
+	board_start_additional_periph();
+}
+
 static void ddrc_conf(struct atmel_mpddrc_config *ddrc)
 {
 	ddrc->md = (ATMEL_MPDDRC_MD_DBW_32_BITS | ATMEL_MPDDRC_MD_DDR3_SDRAM);
diff --git a/board/nvidia/p2371-2180/p2371-2180.c b/board/nvidia/p2371-2180/p2371-2180.c
index 212037d..4985302 100644
--- a/board/nvidia/p2371-2180/p2371-2180.c
+++ b/board/nvidia/p2371-2180/p2371-2180.c
@@ -5,9 +5,13 @@
  */
 
 #include <common.h>
+#include <environment.h>
+#include <fdtdec.h>
 #include <i2c.h>
+#include <linux/libfdt.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/pinmux.h>
+#include <asm/arch-tegra/cboot.h>
 #include "../p2571/max77620_init.h"
 #include "pinmux-config-p2371-2180.h"
 
@@ -94,3 +98,96 @@
 	return 0;
 }
 #endif /* PCI */
+
+static void ft_mac_address_setup(void *fdt)
+{
+	const void *cboot_fdt = (const void *)cboot_boot_x0;
+	uint8_t mac[ETH_ALEN], local_mac[ETH_ALEN];
+	const char *path;
+	int offset, err;
+
+	err = cboot_get_ethaddr(cboot_fdt, local_mac);
+	if (err < 0)
+		memset(local_mac, 0, ETH_ALEN);
+
+	path = fdt_get_alias(fdt, "ethernet");
+	if (!path)
+		return;
+
+	debug("ethernet alias found: %s\n", path);
+
+	offset = fdt_path_offset(fdt, path);
+	if (offset < 0) {
+		printf("ethernet alias points to absent node %s\n", path);
+		return;
+	}
+
+	if (is_valid_ethaddr(local_mac)) {
+		err = fdt_setprop(fdt, offset, "local-mac-address", local_mac,
+				  ETH_ALEN);
+		if (!err)
+			debug("Local MAC address set: %pM\n", local_mac);
+	}
+
+	if (eth_env_get_enetaddr("ethaddr", mac)) {
+		if (memcmp(local_mac, mac, ETH_ALEN) != 0) {
+			err = fdt_setprop(fdt, offset, "mac-address", mac,
+					  ETH_ALEN);
+			if (!err)
+				debug("MAC address set: %pM\n", mac);
+		}
+	}
+}
+
+static int ft_copy_carveout(void *dst, const void *src, const char *node)
+{
+	struct fdt_memory fb;
+	int err;
+
+	err = fdtdec_get_carveout(src, node, "memory-region", 0, &fb);
+	if (err < 0) {
+		if (err != -FDT_ERR_NOTFOUND)
+			printf("failed to get carveout for %s: %d\n", node,
+			       err);
+
+		return err;
+	}
+
+	err = fdtdec_set_carveout(dst, node, "memory-region", 0, "framebuffer",
+				  &fb);
+	if (err < 0) {
+		printf("failed to set carveout for %s: %d\n", node, err);
+		return err;
+	}
+
+	return 0;
+}
+
+static void ft_carveout_setup(void *fdt)
+{
+	const void *cboot_fdt = (const void *)cboot_boot_x0;
+	static const char * const nodes[] = {
+		"/host1x@50000000/dc@54200000",
+		"/host1x@50000000/dc@54240000",
+	};
+	unsigned int i;
+	int err;
+
+	for (i = 0; i < ARRAY_SIZE(nodes); i++) {
+		err = ft_copy_carveout(fdt, cboot_fdt, nodes[i]);
+		if (err < 0) {
+			if (err != -FDT_ERR_NOTFOUND)
+				printf("failed to copy carveout for %s: %d\n",
+				       nodes[i], err);
+			continue;
+		}
+	}
+}
+
+int ft_board_setup(void *fdt, bd_t *bd)
+{
+	ft_mac_address_setup(fdt);
+	ft_carveout_setup(fdt);
+
+	return 0;
+}
diff --git a/board/nvidia/p2771-0000/p2771-0000.c b/board/nvidia/p2771-0000/p2771-0000.c
index 496e8a0..d294c7a 100644
--- a/board/nvidia/p2771-0000/p2771-0000.c
+++ b/board/nvidia/p2771-0000/p2771-0000.c
@@ -4,10 +4,14 @@
  */
 
 #include <common.h>
+#include <environment.h>
+#include <fdtdec.h>
 #include <i2c.h>
+#include <linux/libfdt.h>
+#include <asm/arch-tegra/cboot.h>
 #include "../p2571/max77620_init.h"
 
-int tegra_board_init(void)
+void pin_mux_mmc(void)
 {
 	struct udevice *dev;
 	uchar val;
@@ -18,19 +22,18 @@
 	ret = i2c_get_chip_for_busnum(0, MAX77620_I2C_ADDR_7BIT, 1, &dev);
 	if (ret) {
 		printf("%s: Cannot find MAX77620 I2C chip\n", __func__);
-		return ret;
+		return;
 	}
 	/* 0xF2 for 3.3v, enabled: bit7:6 = 11 = enable, bit5:0 = voltage */
 	val = 0xF2;
 	ret = dm_i2c_write(dev, MAX77620_CNFG1_L3_REG, &val, 1);
 	if (ret) {
 		printf("i2c_write 0 0x3c 0x27 failed: %d\n", ret);
-		return ret;
+		return;
 	}
-
-	return 0;
 }
 
+#ifdef CONFIG_PCI_TEGRA
 int tegra_pcie_board_init(void)
 {
 	struct udevice *dev;
@@ -52,3 +55,101 @@
 
 	return 0;
 }
+#endif
+
+static void ft_mac_address_setup(void *fdt)
+{
+	const void *cboot_fdt = (const void *)cboot_boot_x0;
+	uint8_t mac[ETH_ALEN], local_mac[ETH_ALEN];
+	const char *path;
+	int offset, err;
+
+	err = cboot_get_ethaddr(cboot_fdt, local_mac);
+	if (err < 0)
+		memset(local_mac, 0, ETH_ALEN);
+
+	path = fdt_get_alias(fdt, "ethernet");
+	if (!path)
+		return;
+
+	debug("ethernet alias found: %s\n", path);
+
+	offset = fdt_path_offset(fdt, path);
+	if (offset < 0) {
+		printf("ethernet alias points to absent node %s\n", path);
+		return;
+	}
+
+	if (is_valid_ethaddr(local_mac)) {
+		err = fdt_setprop(fdt, offset, "local-mac-address", local_mac,
+				  ETH_ALEN);
+		if (!err)
+			debug("Local MAC address set: %pM\n", local_mac);
+	}
+
+	if (eth_env_get_enetaddr("ethaddr", mac)) {
+		if (memcmp(local_mac, mac, ETH_ALEN) != 0) {
+			err = fdt_setprop(fdt, offset, "mac-address", mac,
+					  ETH_ALEN);
+			if (!err)
+				debug("MAC address set: %pM\n", mac);
+		}
+	}
+}
+
+static int ft_copy_carveout(void *dst, const void *src, const char *node)
+{
+	struct fdt_memory fb;
+	int err;
+
+	err = fdtdec_get_carveout(src, node, "memory-region", 0, &fb);
+	if (err < 0) {
+		if (err != -FDT_ERR_NOTFOUND)
+			printf("failed to get carveout for %s: %d\n", node,
+			       err);
+
+		return err;
+	}
+
+	err = fdtdec_set_carveout(dst, node, "memory-region", 0, "framebuffer",
+				  &fb);
+	if (err < 0) {
+		printf("failed to set carveout for %s: %d\n", node, err);
+		return err;
+	}
+
+	return 0;
+}
+
+static void ft_carveout_setup(void *fdt)
+{
+	const void *cboot_fdt = (const void *)cboot_boot_x0;
+	static const char * const nodes[] = {
+		"/host1x@13e00000/display-hub@15200000/display@15200000",
+		"/host1x@13e00000/display-hub@15200000/display@15210000",
+		"/host1x@13e00000/display-hub@15200000/display@15220000",
+	};
+	unsigned int i;
+	int err;
+
+	for (i = 0; i < ARRAY_SIZE(nodes); i++) {
+		printf("copying carveout for %s...\n", nodes[i]);
+
+		err = ft_copy_carveout(fdt, cboot_fdt, nodes[i]);
+		if (err < 0) {
+			if (err != -FDT_ERR_NOTFOUND)
+				printf("failed to copy carveout for %s: %d\n",
+				       nodes[i], err);
+
+			continue;
+		}
+	}
+}
+
+int ft_board_setup(void *fdt, bd_t *bd)
+{
+	ft_mac_address_setup(fdt);
+	ft_carveout_setup(fdt);
+
+	return 0;
+}
diff --git a/common/lcd.c b/common/lcd.c
index 95526b1..b34754f 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -171,8 +171,7 @@
 void lcd_clear(void)
 {
 	int bg_color;
-	char *s;
-	ulong addr;
+	__maybe_unused ulong addr;
 	static int do_splash = 1;
 #if LCD_BPP == LCD_COLOR8
 	/* Setting the palette */
@@ -222,14 +221,10 @@
 	/* Paint the logo and retrieve LCD base address */
 	debug("[LCD] Drawing the logo...\n");
 	if (do_splash) {
-		s = env_get("splashimage");
-		if (s) {
+		if (splash_display() == 0) {
 			do_splash = 0;
-			addr = simple_strtoul(s, NULL, 16);
-			if (lcd_splash(addr) == 0) {
-				lcd_sync();
-				return;
-			}
+			lcd_sync();
+			return;
 		}
 	}
 
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 48f6b39..52b0497 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1188,5 +1188,17 @@
 
 endif # TPL
 
+config SPL_AT91_MCK_BYPASS
+	bool "Use external clock signal as a source of main clock for AT91 platforms"
+	depends on ARCH_AT91
+	default n
+	help
+	  Use external 8 to 24 Mhz clock signal as source of main clock instead
+	  of an external crystal oscillator.
+	  This option disables the internal driving on the XOUT pin.
+	  The external source has to provide a stable clock on the XIN pin.
+	  If this option is disabled, the SoC expects a crystal oscillator
+	  that needs driving on both XIN and XOUT lines.
+
 endif # SPL
 endmenu
diff --git a/common/splash.c b/common/splash.c
index d251b3b..79d5057 100644
--- a/common/splash.c
+++ b/common/splash.c
@@ -80,11 +80,23 @@
 }
 #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
 
-#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_LCD)
-int lcd_splash(ulong addr)
+/*
+ * Common function to show a splash image if env("splashimage") is set.
+ * Is used for both dm_video and lcd video stacks. For additional
+ * details please refer to doc/README.splashprepare.
+ */
+#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_CMD_BMP)
+int splash_display(void)
 {
+	ulong addr;
+	char *s;
 	int x = 0, y = 0, ret;
 
+	s = env_get("splashimage");
+	if (!s)
+		return -EINVAL;
+
+	addr = simple_strtoul(s, NULL, 16);
 	ret = splash_screen_prepare();
 	if (ret)
 		return ret;
diff --git a/common/stdio.c b/common/stdio.c
index ee22c1f..54ecc9b 100644
--- a/common/stdio.c
+++ b/common/stdio.c
@@ -16,6 +16,7 @@
 #include <malloc.h>
 #include <stdio_dev.h>
 #include <serial.h>
+#include <splash.h>
 
 #if defined(CONFIG_SYS_I2C)
 #include <i2c.h>
@@ -366,6 +367,9 @@
 	if (ret)
 		printf("%s: Video device failed (ret=%d)\n", __func__, ret);
 #endif /* !CONFIG_SYS_CONSOLE_IS_IN_ENV */
+#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_CMD_BMP)
+	splash_display();
+#endif /* CONFIG_SPLASH_SCREEN && CONFIG_CMD_BMP */
 #else
 # if defined(CONFIG_LCD)
 	drv_lcd_init ();
diff --git a/configs/colibri_imx6_defconfig b/configs/colibri_imx6_defconfig
index f1decf8..59d4ab0 100644
--- a/configs/colibri_imx6_defconfig
+++ b/configs/colibri_imx6_defconfig
@@ -86,3 +86,4 @@
 CONFIG_VIDEO_IPUV3=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_SYS_WHITE_ON_BLACK=y
diff --git a/configs/colibri_imx7_emmc_defconfig b/configs/colibri_imx7_emmc_defconfig
index 2fa9f1f..bb11524 100644
--- a/configs/colibri_imx7_emmc_defconfig
+++ b/configs/colibri_imx7_emmc_defconfig
@@ -64,7 +64,7 @@
 CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_VIDEO=y
+CONFIG_DM_VIDEO=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT_OVERLAY=y
 CONFIG_DM_USB=y
diff --git a/configs/colibri_t20_defconfig b/configs/colibri_t20_defconfig
index 6b8a690..e652ebc 100644
--- a/configs/colibri_t20_defconfig
+++ b/configs/colibri_t20_defconfig
@@ -65,3 +65,4 @@
 CONFIG_VIDEO_TEGRA20=y
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_SYS_WHITE_ON_BLACK=y
diff --git a/configs/e2220-1170_defconfig b/configs/e2220-1170_defconfig
index 4d253c5..d650aca 100644
--- a/configs/e2220-1170_defconfig
+++ b/configs/e2220-1170_defconfig
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
 CONFIG_TEGRA=y
-CONFIG_SYS_TEXT_BASE=0x80110000
+CONFIG_SYS_TEXT_BASE=0x80080000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_TEGRA210=y
 CONFIG_OF_SYSTEM_SETUP=y
diff --git a/configs/gardena-smart-gateway-at91sam_defconfig b/configs/gardena-smart-gateway-at91sam_defconfig
index 577dceb..a25d378 100644
--- a/configs/gardena-smart-gateway-at91sam_defconfig
+++ b/configs/gardena-smart-gateway-at91sam_defconfig
@@ -36,6 +36,7 @@
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_MTD=y
 CONFIG_CMD_NAND=y
+CONFIG_CMD_WDT=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_PING=y
diff --git a/configs/ids8313_defconfig b/configs/ids8313_defconfig
index 43454a1..154a075 100644
--- a/configs/ids8313_defconfig
+++ b/configs/ids8313_defconfig
@@ -134,7 +134,6 @@
 CONFIG_CMD_I2C=y
 CONFIG_CMD_NAND=y
 CONFIG_CMD_NAND_TRIMFFS=y
-CONFIG_CMD_SPI=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
@@ -160,6 +159,4 @@
 CONFIG_TSEC_ENET=y
 # CONFIG_PCI is not set
 CONFIG_SYS_NS16550=y
-CONFIG_SPI=y
-CONFIG_MPC8XXX_SPI=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/p2371-0000_defconfig b/configs/p2371-0000_defconfig
index cdcb98a..aa9c1f6 100644
--- a/configs/p2371-0000_defconfig
+++ b/configs/p2371-0000_defconfig
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
 CONFIG_TEGRA=y
-CONFIG_SYS_TEXT_BASE=0x80110000
+CONFIG_SYS_TEXT_BASE=0x80080000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_TEGRA210=y
 CONFIG_TARGET_P2371_0000=y
diff --git a/configs/p2371-2180_defconfig b/configs/p2371-2180_defconfig
index 122b1b1..2a21ff1 100644
--- a/configs/p2371-2180_defconfig
+++ b/configs/p2371-2180_defconfig
@@ -1,10 +1,11 @@
 CONFIG_ARM=y
 CONFIG_TEGRA=y
-CONFIG_SYS_TEXT_BASE=0x80110000
+CONFIG_SYS_TEXT_BASE=0x80080000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_TEGRA210=y
 CONFIG_TARGET_P2371_2180=y
 CONFIG_OF_SYSTEM_SETUP=y
+CONFIG_OF_BOARD_SETUP=y
 CONFIG_CONSOLE_MUX=y
 CONFIG_SYS_STDIO_DEREGISTER=y
 CONFIG_SYS_PROMPT="Tegra210 (P2371-2180) # "
diff --git a/configs/p2571_defconfig b/configs/p2571_defconfig
index d28506b..1c47064 100644
--- a/configs/p2571_defconfig
+++ b/configs/p2571_defconfig
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
 CONFIG_TEGRA=y
-CONFIG_SYS_TEXT_BASE=0x80110000
+CONFIG_SYS_TEXT_BASE=0x80080000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_TEGRA210=y
 CONFIG_TARGET_P2571=y
diff --git a/configs/p2771-0000-000_defconfig b/configs/p2771-0000-000_defconfig
index 6d66cae..4ac810d 100644
--- a/configs/p2771-0000-000_defconfig
+++ b/configs/p2771-0000-000_defconfig
@@ -1,9 +1,10 @@
 CONFIG_ARM=y
 CONFIG_TEGRA=y
 CONFIG_SYS_TEXT_BASE=0x80080000
-CONFIG_NR_DRAM_BANKS=8
+CONFIG_NR_DRAM_BANKS=1026
 CONFIG_TEGRA186=y
 CONFIG_OF_SYSTEM_SETUP=y
+CONFIG_OF_BOARD_SETUP=y
 CONFIG_CONSOLE_MUX=y
 CONFIG_SYS_STDIO_DEREGISTER=y
 CONFIG_SYS_PROMPT="Tegra186 (P2771-0000-000) # "
diff --git a/configs/p2771-0000-500_defconfig b/configs/p2771-0000-500_defconfig
index b8ac94c..3ca8527 100644
--- a/configs/p2771-0000-500_defconfig
+++ b/configs/p2771-0000-500_defconfig
@@ -1,9 +1,10 @@
 CONFIG_ARM=y
 CONFIG_TEGRA=y
 CONFIG_SYS_TEXT_BASE=0x80080000
-CONFIG_NR_DRAM_BANKS=8
+CONFIG_NR_DRAM_BANKS=1026
 CONFIG_TEGRA186=y
 CONFIG_OF_SYSTEM_SETUP=y
+CONFIG_OF_BOARD_SETUP=y
 CONFIG_CONSOLE_MUX=y
 CONFIG_SYS_STDIO_DEREGISTER=y
 CONFIG_SYS_PROMPT="Tegra186 (P2771-0000-500) # "
diff --git a/configs/sama5d2_icp_mmc_defconfig b/configs/sama5d2_icp_mmc_defconfig
index 1fafb76..e047108 100644
--- a/configs/sama5d2_icp_mmc_defconfig
+++ b/configs/sama5d2_icp_mmc_defconfig
@@ -23,12 +23,12 @@
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTARGS=y
 # CONFIG_DISPLAY_BOARDINFO is not set
-CONFIG_SPL_TEXT_BASE=0x200000
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DISPLAY_PRINT=y
 # CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR is not set
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y
+CONFIG_SPL_AT91_MCK_BYPASS=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMI is not set
@@ -75,3 +75,4 @@
 CONFIG_SPL_TIMER=y
 CONFIG_ATMEL_PIT_TIMER=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+# CONFIG_EFI_LOADER_HII is not set
diff --git a/configs/sama5d2_ptc_ek_mmc_defconfig b/configs/sama5d2_ptc_ek_mmc_defconfig
index bf2b558..25b3aaf 100644
--- a/configs/sama5d2_ptc_ek_mmc_defconfig
+++ b/configs/sama5d2_ptc_ek_mmc_defconfig
@@ -51,6 +51,7 @@
 CONFIG_NAND=y
 CONFIG_NAND_ATMEL=y
 CONFIG_ATMEL_NAND_HW_PMECC=y
+CONFIG_PMECC_CAP=4
 CONFIG_DM_ETH=y
 CONFIG_MACB=y
 CONFIG_PINCTRL=y
diff --git a/configs/sama5d2_ptc_ek_nandflash_defconfig b/configs/sama5d2_ptc_ek_nandflash_defconfig
index 9608ecd..3f7e627 100644
--- a/configs/sama5d2_ptc_ek_nandflash_defconfig
+++ b/configs/sama5d2_ptc_ek_nandflash_defconfig
@@ -50,6 +50,7 @@
 CONFIG_MMC_SDHCI_ATMEL=y
 CONFIG_NAND_ATMEL=y
 CONFIG_ATMEL_NAND_HW_PMECC=y
+CONFIG_PMECC_CAP=4
 CONFIG_DM_ETH=y
 CONFIG_MACB=y
 CONFIG_PINCTRL=y
diff --git a/configs/sama5d4_xplained_mmc_defconfig b/configs/sama5d4_xplained_mmc_defconfig
index f673832..0504b4e 100644
--- a/configs/sama5d4_xplained_mmc_defconfig
+++ b/configs/sama5d4_xplained_mmc_defconfig
@@ -59,6 +59,8 @@
 CONFIG_GENERIC_ATMEL_MCI=y
 CONFIG_NAND=y
 CONFIG_NAND_ATMEL=y
+CONFIG_ATMEL_NAND_HW_PMECC=y
+CONFIG_PMECC_CAP=8
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SF_DEFAULT_SPEED=30000000
diff --git a/configs/tinker-rk3288_defconfig b/configs/tinker-rk3288_defconfig
index 4b48689..0e8cf73 100644
--- a/configs/tinker-rk3288_defconfig
+++ b/configs/tinker-rk3288_defconfig
@@ -20,7 +20,6 @@
 CONFIG_SPL_TEXT_BASE=0xff704000
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000
-CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
diff --git a/doc/driver-model/MIGRATION.txt b/doc/driver-model/MIGRATION.txt
index df659f3..d38be35 100644
--- a/doc/driver-model/MIGRATION.txt
+++ b/doc/driver-model/MIGRATION.txt
@@ -59,10 +59,7 @@
 	drivers/spi/cf_spi.c
 	drivers/spi/fsl_espi.c
 	drivers/spi/lpc32xx_ssp.c
-	drivers/spi/mpc8xx_spi.c
-	drivers/spi/mpc8xxx_spi.c
 	drivers/spi/mxs_spi.c
-	drivers/spi/sh_qspi.c
 	drivers/spi/sh_spi.c
 	drivers/spi/soft_spi_legacy.c
 
@@ -70,13 +67,12 @@
 	Deadline: 2019.04
 
 Partially converted:
-	drivers/spi/atcspi200_spi.c
 	drivers/spi/davinci_spi.c
 	drivers/spi/fsl_dspi.c
-	drivers/spi/fsl_qspi.c
 	drivers/spi/kirkwood_spi.c
 	drivers/spi/mxc_spi.c
 	drivers/spi/omap3_spi.c
+	drivers/spi/sh_qspi.c
 
 	Status: In progress
 	Deadline: 2019.07
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 7044da3..eb32f08 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -137,6 +137,11 @@
 	help
 	  Enable support for SPI on MPC8XX
 
+config MPC8XXX_SPI
+	bool "MPC8XXX SPI Driver"
+	help
+	  Enable support for SPI on the MPC8XXX PowerPC SoCs.
+
 config MT7621_SPI
 	bool "MediaTek MT7621 SPI driver"
 	depends on SOC_MT7628
@@ -370,11 +375,6 @@
 	help
 	  Enable support for SPI on LPC32xx
 
-config MPC8XXX_SPI
-	bool "MPC8XXX SPI Driver"
-	help
-	  Enable support for SPI on the MPC8XXX PowerPC SoCs.
-
 config MXC_SPI
 	bool "MXC SPI Driver"
 	help
diff --git a/drivers/spi/mpc8xxx_spi.c b/drivers/spi/mpc8xxx_spi.c
index 8d6d86d..1c7bf10 100644
--- a/drivers/spi/mpc8xxx_spi.c
+++ b/drivers/spi/mpc8xxx_spi.c
@@ -5,161 +5,258 @@
  */
 
 #include <common.h>
-
+#include <dm.h>
+#include <errno.h>
 #include <malloc.h>
 #include <spi.h>
 #include <asm/mpc8xxx_spi.h>
+#include <asm-generic/gpio.h>
 
-#define SPI_EV_NE	(0x80000000 >> 22)	/* Receiver Not Empty */
-#define SPI_EV_NF	(0x80000000 >> 23)	/* Transmitter Not Full */
+enum {
+	SPI_EV_NE = BIT(31 - 22),	/* Receiver Not Empty */
+	SPI_EV_NF = BIT(31 - 23),	/* Transmitter Not Full */
+};
 
-#define SPI_MODE_LOOP	(0x80000000 >> 1)	/* Loopback mode */
-#define SPI_MODE_REV	(0x80000000 >> 5)	/* Reverse mode - MSB first */
-#define SPI_MODE_MS	(0x80000000 >> 6)	/* Always master */
-#define SPI_MODE_EN	(0x80000000 >> 7)	/* Enable interface */
+enum {
+	SPI_MODE_LOOP  = BIT(31 - 1),	/* Loopback mode */
+	SPI_MODE_CI    = BIT(31 - 2),	/* Clock invert */
+	SPI_MODE_CP    = BIT(31 - 3),	/* Clock phase */
+	SPI_MODE_DIV16 = BIT(31 - 4),	/* Divide clock source by 16 */
+	SPI_MODE_REV   = BIT(31 - 5),	/* Reverse mode - MSB first */
+	SPI_MODE_MS    = BIT(31 - 6),	/* Always master */
+	SPI_MODE_EN    = BIT(31 - 7),	/* Enable interface */
+
+	SPI_MODE_LEN_MASK = 0xf00000,
+	SPI_MODE_PM_MASK = 0xf0000,
+
+	SPI_COM_LST = BIT(31 - 9),
+};
+
+struct mpc8xxx_priv {
+	spi8xxx_t *spi;
+	struct gpio_desc gpios[16];
+	int max_cs;
+};
+
+static inline u32 to_prescale_mod(u32 val)
+{
+	return (min(val, (u32)15) << 16);
+}
+
+static void set_char_len(spi8xxx_t *spi, u32 val)
+{
+	clrsetbits_be32(&spi->mode, SPI_MODE_LEN_MASK, (val << 20));
+}
 
 #define SPI_TIMEOUT	1000
 
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-		unsigned int max_hz, unsigned int mode)
+static int __spi_set_speed(spi8xxx_t *spi, uint speed)
 {
-	struct spi_slave *slave;
+	/* TODO(mario.six@gdsys.cc): This only ever sets one fixed speed */
 
-	if (!spi_cs_is_valid(bus, cs))
-		return NULL;
+	/* Use SYSCLK / 8 (16.67MHz typ.) */
+	clrsetbits_be32(&spi->mode, SPI_MODE_PM_MASK, to_prescale_mod(1));
 
-	slave = spi_alloc_slave_base(bus, cs);
-	if (!slave)
-		return NULL;
-
-	/*
-	 * TODO: Some of the code in spi_init() should probably move
-	 * here, or into spi_claim_bus() below.
-	 */
-
-	return slave;
+	return 0;
 }
 
-void spi_free_slave(struct spi_slave *slave)
+static int mpc8xxx_spi_ofdata_to_platdata(struct udevice *dev)
 {
-	free(slave);
+	struct mpc8xxx_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	priv->spi = (spi8xxx_t *)dev_read_addr(dev);
+
+	/* TODO(mario.six@gdsys.cc): Read clock and save the value */
+
+	ret = gpio_request_list_by_name(dev, "gpios", priv->gpios,
+					ARRAY_SIZE(priv->gpios), GPIOD_IS_OUT | GPIOD_ACTIVE_LOW);
+	if (ret < 0)
+		return -EINVAL;
+
+	priv->max_cs = ret;
+
+	return 0;
 }
 
-void spi_init(void)
+static int mpc8xxx_spi_probe(struct udevice *dev)
 {
-	volatile spi8xxx_t *spi = &((immap_t *) (CONFIG_SYS_IMMR))->spi;
+	struct mpc8xxx_priv *priv = dev_get_priv(dev);
 
 	/*
 	 * SPI pins on the MPC83xx are not muxed, so all we do is initialize
 	 * some registers
 	 */
-	spi->mode = SPI_MODE_REV | SPI_MODE_MS | SPI_MODE_EN;
-	spi->mode = (spi->mode & 0xfff0ffff) | BIT(16); /* Use SYSCLK / 8
-							     (16.67MHz typ.) */
-	spi->event = 0xffffffff;	/* Clear all SPI events */
-	spi->mask = 0x00000000;	/* Mask  all SPI interrupts */
-	spi->com = 0;		/* LST bit doesn't do anything, so disregard */
-}
+	out_be32(&priv->spi->mode, SPI_MODE_REV | SPI_MODE_MS | SPI_MODE_EN);
 
-int spi_claim_bus(struct spi_slave *slave)
-{
+	__spi_set_speed(priv->spi, 16666667);
+
+	/* Clear all SPI events */
+	setbits_be32(&priv->spi->event, 0xffffffff);
+	/* Mask  all SPI interrupts */
+	clrbits_be32(&priv->spi->mask, 0xffffffff);
+	/* LST bit doesn't do anything, so disregard */
+	out_be32(&priv->spi->com, 0);
+
 	return 0;
 }
 
-void spi_release_bus(struct spi_slave *slave)
+static void mpc8xxx_spi_cs_activate(struct udevice *dev)
 {
+	struct mpc8xxx_priv *priv = dev_get_priv(dev->parent);
+	struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
 
+	dm_gpio_set_dir_flags(&priv->gpios[platdata->cs], GPIOD_IS_OUT);
+	dm_gpio_set_value(&priv->gpios[platdata->cs], 0);
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
-		void *din, unsigned long flags)
+static void mpc8xxx_spi_cs_deactivate(struct udevice *dev)
 {
-	volatile spi8xxx_t *spi = &((immap_t *) (CONFIG_SYS_IMMR))->spi;
-	unsigned int tmpdout, tmpdin, event;
-	int numBlks = DIV_ROUND_UP(bitlen, 32);
-	int tm, isRead = 0;
-	unsigned char charSize = 32;
+	struct mpc8xxx_priv *priv = dev_get_priv(dev->parent);
+	struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
 
-	debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
-	      slave->bus, slave->cs, *(uint *) dout, *(uint *) din, bitlen);
+	dm_gpio_set_dir_flags(&priv->gpios[platdata->cs], GPIOD_IS_OUT);
+	dm_gpio_set_value(&priv->gpios[platdata->cs], 1);
+}
+
+static int mpc8xxx_spi_xfer(struct udevice *dev, uint bitlen,
+			    const void *dout, void *din, ulong flags)
+{
+	struct udevice *bus = dev->parent;
+	struct mpc8xxx_priv *priv = dev_get_priv(bus);
+	spi8xxx_t *spi = priv->spi;
+	struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
+	u32 tmpdin = 0;
+	int num_blks = DIV_ROUND_UP(bitlen, 32);
+
+	debug("%s: slave %s:%u dout %08X din %08X bitlen %u\n", __func__,
+	      bus->name, platdata->cs, *(uint *)dout, *(uint *)din, bitlen);
 
 	if (flags & SPI_XFER_BEGIN)
-		spi_cs_activate(slave);
+		mpc8xxx_spi_cs_activate(dev);
 
-	spi->event = 0xffffffff;	/* Clear all SPI events */
+	/* Clear all SPI events */
+	setbits_be32(&spi->event, 0xffffffff);
 
-	/* handle data in 32-bit chunks */
-	while (numBlks--) {
-		tmpdout = 0;
-		charSize = (bitlen >= 32 ? 32 : bitlen);
+	/* Handle data in 32-bit chunks */
+	while (num_blks--) {
+		u32 tmpdout = 0;
+		uchar xfer_bitlen = (bitlen >= 32 ? 32 : bitlen);
+		ulong start;
+
+		clrbits_be32(&spi->mode, SPI_MODE_EN);
+
+		/* Set up length for this transfer */
+
+		if (bitlen <= 4) /* 4 bits or less */
+			set_char_len(spi, 3);
+		else if (bitlen <= 16) /* at most 16 bits */
+			set_char_len(spi, bitlen - 1);
+		else /* more than 16 bits -> full 32 bit transfer */
+			set_char_len(spi, 0);
+
+		setbits_be32(&spi->mode, SPI_MODE_EN);
 
 		/* Shift data so it's msb-justified */
-		tmpdout = *(u32 *) dout >> (32 - charSize);
+		tmpdout = *(u32 *)dout >> (32 - xfer_bitlen);
 
-		/* The LEN field of the SPMODE register is set as follows:
-		 *
-		 * Bit length             setting
-		 * len <= 4               3
-		 * 4 < len <= 16          len - 1
-		 * len > 16               0
-		 */
-
-		spi->mode &= ~SPI_MODE_EN;
-
-		if (bitlen <= 16) {
-			if (bitlen <= 4)
-				spi->mode = (spi->mode & 0xff0fffff) |
-					    (3 << 20);
-			else
-				spi->mode = (spi->mode & 0xff0fffff) |
-					    ((bitlen - 1) << 20);
-		} else {
-			spi->mode = (spi->mode & 0xff0fffff);
+		if (bitlen > 32) {
 			/* Set up the next iteration if sending > 32 bits */
 			bitlen -= 32;
 			dout += 4;
 		}
 
-		spi->mode |= SPI_MODE_EN;
+		/* Write the data out */
+		out_be32(&spi->tx, tmpdout);
 
-		spi->tx = tmpdout;	/* Write the data out */
-		debug("*** spi_xfer: ... %08x written\n", tmpdout);
+		debug("*** %s: ... %08x written\n", __func__, tmpdout);
 
 		/*
 		 * Wait for SPI transmit to get out
 		 * or time out (1 second = 1000 ms)
 		 * The NE event must be read and cleared first
 		 */
-		for (tm = 0, isRead = 0; tm < SPI_TIMEOUT; ++tm) {
-			event = spi->event;
-			if (event & SPI_EV_NE) {
-				tmpdin = spi->rx;
-				spi->event |= SPI_EV_NE;
-				isRead = 1;
+		start = get_timer(0);
+		do {
+			u32 event = in_be32(&spi->event);
+			bool have_ne = event & SPI_EV_NE;
+			bool have_nf = event & SPI_EV_NF;
 
-				*(u32 *) din = (tmpdin << (32 - charSize));
-				if (charSize == 32) {
-					/* Advance output buffer by 32 bits */
-					din += 4;
-				}
+			if (!have_ne)
+				continue;
+
+			tmpdin = in_be32(&spi->rx);
+			setbits_be32(&spi->event, SPI_EV_NE);
+
+			*(u32 *)din = (tmpdin << (32 - xfer_bitlen));
+			if (xfer_bitlen == 32) {
+				/* Advance output buffer by 32 bits */
+				din += 4;
 			}
+
 			/*
 			 * Only bail when we've had both NE and NF events.
 			 * This will cause timeouts on RO devices, so maybe
 			 * in the future put an arbitrary delay after writing
 			 * the device.  Arbitrary delays suck, though...
 			 */
-			if (isRead && (event & SPI_EV_NF))
+			if (have_nf)
 				break;
-		}
-		if (tm >= SPI_TIMEOUT)
-			puts("*** spi_xfer: Time out during SPI transfer");
 
-		debug("*** spi_xfer: transfer ended. Value=%08x\n", tmpdin);
+			mdelay(1);
+		} while (get_timer(start) < SPI_TIMEOUT);
+
+		if (get_timer(start) >= SPI_TIMEOUT) {
+			debug("*** %s: Time out during SPI transfer\n",
+			      __func__);
+			return -ETIMEDOUT;
+		}
+
+		debug("*** %s: transfer ended. Value=%08x\n", __func__, tmpdin);
 	}
 
 	if (flags & SPI_XFER_END)
-		spi_cs_deactivate(slave);
+		mpc8xxx_spi_cs_deactivate(dev);
 
 	return 0;
 }
+
+static int mpc8xxx_spi_set_speed(struct udevice *dev, uint speed)
+{
+	struct mpc8xxx_priv *priv = dev_get_priv(dev);
+
+	return __spi_set_speed(priv->spi, speed);
+}
+
+static int mpc8xxx_spi_set_mode(struct udevice *dev, uint mode)
+{
+	/* TODO(mario.six@gdsys.cc): Using SPI_CPHA (for clock phase) and
+	 * SPI_CPOL (for clock polarity) should work
+	 */
+	return 0;
+}
+
+static const struct dm_spi_ops mpc8xxx_spi_ops = {
+	.xfer		= mpc8xxx_spi_xfer,
+	.set_speed	= mpc8xxx_spi_set_speed,
+	.set_mode	= mpc8xxx_spi_set_mode,
+	/*
+	 * cs_info is not needed, since we require all chip selects to be
+	 * in the device tree explicitly
+	 */
+};
+
+static const struct udevice_id mpc8xxx_spi_ids[] = {
+	{ .compatible = "fsl,spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(mpc8xxx_spi) = {
+	.name	= "mpc8xxx_spi",
+	.id	= UCLASS_SPI,
+	.of_match = mpc8xxx_spi_ids,
+	.ops	= &mpc8xxx_spi_ops,
+	.ofdata_to_platdata = mpc8xxx_spi_ofdata_to_platdata,
+	.probe	= mpc8xxx_spi_probe,
+	.priv_auto_alloc_size = sizeof(struct mpc8xxx_priv),
+};
diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c
index 7a1c060..483c93f 100644
--- a/drivers/video/meson/meson_dw_hdmi.c
+++ b/drivers/video/meson/meson_dw_hdmi.c
@@ -361,13 +361,19 @@
 	priv->hdmi.i2c_clk_high = 0x67;
 	priv->hdmi.i2c_clk_low = 0x78;
 
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
 	ret = device_get_supply_regulator(dev, "hdmi-supply", &supply);
-	if (ret)
+	if (ret && ret != -ENOENT) {
+		pr_err("Failed to get HDMI regulator\n");
 		return ret;
+	}
 
-	ret = regulator_set_enable(supply, true);
-	if (ret)
-		return ret;
+	if (!ret) {
+		ret = regulator_set_enable(supply, true);
+		if (ret)
+			return ret;
+	}
+#endif
 
 	ret = reset_get_bulk(dev, &resets);
 	if (ret)
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 02fde05..f02ba20 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -5,22 +5,26 @@
  * Copyright (C) 2011-2013 Marek Vasut <marex@denx.de>
  */
 #include <common.h>
+#include <dm.h>
+#include <linux/errno.h>
 #include <malloc.h>
+#include <video.h>
 #include <video_fb.h>
 
-#include <asm/arch/imx-regs.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
 #include <asm/arch/sys_proto.h>
-#include <linux/errno.h>
-#include <asm/io.h>
-
 #include <asm/mach-imx/dma.h>
+#include <asm/io.h>
 
 #include "videomodes.h"
 
 #define	PS2KHZ(ps)	(1000000000UL / (ps))
+#define HZ2PS(hz)	(1000000000UL / ((hz) / 1000))
 
-static GraphicDevice panel;
+#define BITS_PP		18
+#define BYTES_PP	4
+
 struct mxs_dma_desc desc;
 
 /**
@@ -46,8 +50,7 @@
  * 	 le:89,ri:164,up:23,lo:10,hs:10,vs:10,sync:0,vmode:0
  */
 
-static void mxs_lcd_init(GraphicDevice *panel,
-			struct ctfb_res_modes *mode, int bpp)
+static void mxs_lcd_init(u32 fb_addr, struct ctfb_res_modes *mode, int bpp)
 {
 	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
 	uint32_t word_len = 0, bus_width = 0;
@@ -112,8 +115,8 @@
 	writel((0 << LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET) | mode->xres,
 		&regs->hw_lcdif_vdctrl4);
 
-	writel(panel->frameAdrs, &regs->hw_lcdif_cur_buf);
-	writel(panel->frameAdrs, &regs->hw_lcdif_next_buf);
+	writel(fb_addr, &regs->hw_lcdif_cur_buf);
+	writel(fb_addr, &regs->hw_lcdif_next_buf);
 
 	/* Flush FIFO first */
 	writel(LCDIF_CTRL1_FIFO_CLEAR, &regs->hw_lcdif_ctrl1_set);
@@ -130,16 +133,47 @@
 	writel(LCDIF_CTRL_RUN, &regs->hw_lcdif_ctrl_set);
 }
 
-void lcdif_power_down(void)
+static int mxs_probe_common(struct ctfb_res_modes *mode, int bpp, u32 fb)
+{
+	/* Start framebuffer */
+	mxs_lcd_init(fb, mode, bpp);
+
+#ifdef CONFIG_VIDEO_MXS_MODE_SYSTEM
+	/*
+	 * If the LCD runs in system mode, the LCD refresh has to be triggered
+	 * manually by setting the RUN bit in HW_LCDIF_CTRL register. To avoid
+	 * having to set this bit manually after every single change in the
+	 * framebuffer memory, we set up specially crafted circular DMA, which
+	 * sets the RUN bit, then waits until it gets cleared and repeats this
+	 * infinitelly. This way, we get smooth continuous updates of the LCD.
+	 */
+	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
+
+	memset(&desc, 0, sizeof(struct mxs_dma_desc));
+	desc.address = (dma_addr_t)&desc;
+	desc.cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+			MXS_DMA_DESC_WAIT4END |
+			(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+	desc.cmd.pio_words[0] = readl(&regs->hw_lcdif_ctrl) | LCDIF_CTRL_RUN;
+	desc.cmd.next = (uint32_t)&desc.cmd;
+
+	/* Execute the DMA chain. */
+	mxs_dma_circ_start(MXS_DMA_CHANNEL_AHB_APBH_LCDIF, &desc);
+#endif
+
+	return 0;
+}
+
+static int mxs_remove_common(u32 fb)
 {
 	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
 	int timeout = 1000000;
 
-	if (!panel.frameAdrs)
-		return;
+	if (!fb)
+		return -EINVAL;
 
-	writel(panel.frameAdrs, &regs->hw_lcdif_cur_buf_reg);
-	writel(panel.frameAdrs, &regs->hw_lcdif_next_buf_reg);
+	writel(fb, &regs->hw_lcdif_cur_buf_reg);
+	writel(fb, &regs->hw_lcdif_next_buf_reg);
 	writel(LCDIF_CTRL1_VSYNC_EDGE_IRQ, &regs->hw_lcdif_ctrl1_clr);
 	while (--timeout) {
 		if (readl(&regs->hw_lcdif_ctrl1_reg) &
@@ -148,13 +182,25 @@
 		udelay(1);
 	}
 	mxs_reset_block((struct mxs_register_32 *)&regs->hw_lcdif_ctrl_reg);
+
+	return 0;
+}
+
+#ifndef CONFIG_DM_VIDEO
+
+static GraphicDevice panel;
+
+void lcdif_power_down(void)
+{
+	mxs_remove_common(panel.frameAdrs);
 }
 
 void *video_hw_init(void)
 {
 	int bpp = -1;
+	int ret = 0;
 	char *penv;
-	void *fb;
+	void *fb = NULL;
 	struct ctfb_res_modes mode;
 
 	puts("Video: ");
@@ -169,8 +215,7 @@
 	bpp = video_get_params(&mode, penv);
 
 	/* fill in Graphic device struct */
-	sprintf(panel.modeIdent, "%dx%dx%d",
-			mode.xres, mode.yres, bpp);
+	sprintf(panel.modeIdent, "%dx%dx%d", mode.xres, mode.yres, bpp);
 
 	panel.winSizeX = mode.xres;
 	panel.winSizeY = mode.yres;
@@ -213,31 +258,125 @@
 
 	printf("%s\n", panel.modeIdent);
 
-	/* Start framebuffer */
-	mxs_lcd_init(&panel, &mode, bpp);
-
-#ifdef CONFIG_VIDEO_MXS_MODE_SYSTEM
-	/*
-	 * If the LCD runs in system mode, the LCD refresh has to be triggered
-	 * manually by setting the RUN bit in HW_LCDIF_CTRL register. To avoid
-	 * having to set this bit manually after every single change in the
-	 * framebuffer memory, we set up specially crafted circular DMA, which
-	 * sets the RUN bit, then waits until it gets cleared and repeats this
-	 * infinitelly. This way, we get smooth continuous updates of the LCD.
-	 */
-	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
-
-	memset(&desc, 0, sizeof(struct mxs_dma_desc));
-	desc.address = (dma_addr_t)&desc;
-	desc.cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
-			MXS_DMA_DESC_WAIT4END |
-			(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
-	desc.cmd.pio_words[0] = readl(&regs->hw_lcdif_ctrl) | LCDIF_CTRL_RUN;
-	desc.cmd.next = (uint32_t)&desc.cmd;
-
-	/* Execute the DMA chain. */
-	mxs_dma_circ_start(MXS_DMA_CHANNEL_AHB_APBH_LCDIF, &desc);
-#endif
+	ret = mxs_probe_common(&mode, bpp, (u32)fb);
+	if (ret)
+		goto dealloc_fb;
 
 	return (void *)&panel;
+
+dealloc_fb:
+	free(fb);
+
+	return NULL;
 }
+#else /* ifndef CONFIG_DM_VIDEO */
+
+static int mxs_video_probe(struct udevice *dev)
+{
+	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	struct ctfb_res_modes mode;
+	struct display_timing timings;
+	int bpp = -1;
+	u32 fb_start, fb_end;
+	int ret;
+
+	debug("%s() plat: base 0x%lx, size 0x%x\n",
+	       __func__, plat->base, plat->size);
+
+	ret = ofnode_decode_display_timing(dev_ofnode(dev), 0, &timings);
+	if (ret) {
+		dev_err(dev, "failed to get any display timings\n");
+		return -EINVAL;
+	}
+
+	mode.xres = timings.hactive.typ;
+	mode.yres = timings.vactive.typ;
+	mode.left_margin = timings.hback_porch.typ;
+	mode.right_margin = timings.hfront_porch.typ;
+	mode.upper_margin = timings.vback_porch.typ;
+	mode.lower_margin = timings.vfront_porch.typ;
+	mode.hsync_len = timings.hsync_len.typ;
+	mode.vsync_len = timings.vsync_len.typ;
+	mode.pixclock = HZ2PS(timings.pixelclock.typ);
+
+	bpp = BITS_PP;
+
+	ret = mxs_probe_common(&mode, bpp, plat->base);
+	if (ret)
+		return ret;
+
+	switch (bpp) {
+	case 24:
+	case 18:
+		uc_priv->bpix = VIDEO_BPP32;
+		break;
+	case 16:
+		uc_priv->bpix = VIDEO_BPP16;
+		break;
+	case 8:
+		uc_priv->bpix = VIDEO_BPP8;
+		break;
+	default:
+		dev_err(dev, "invalid bpp specified (bpp = %i)\n", bpp);
+		return -EINVAL;
+	}
+
+	uc_priv->xsize = mode.xres;
+	uc_priv->ysize = mode.yres;
+
+	/* Enable dcache for the frame buffer */
+	fb_start = plat->base & ~(MMU_SECTION_SIZE - 1);
+	fb_end = plat->base + plat->size;
+	fb_end = ALIGN(fb_end, 1 << MMU_SECTION_SHIFT);
+	mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start,
+					DCACHE_WRITEBACK);
+	video_set_flush_dcache(dev, true);
+
+	return ret;
+}
+
+static int mxs_video_bind(struct udevice *dev)
+{
+	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+	struct display_timing timings;
+	int ret;
+
+	ret = ofnode_decode_display_timing(dev_ofnode(dev), 0, &timings);
+	if (ret) {
+		dev_err(dev, "failed to get any display timings\n");
+		return -EINVAL;
+	}
+
+	plat->size = timings.hactive.typ * timings.vactive.typ * BYTES_PP;
+
+	return 0;
+}
+
+static int mxs_video_remove(struct udevice *dev)
+{
+	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+
+	mxs_remove_common(plat->base);
+
+	return 0;
+}
+
+static const struct udevice_id mxs_video_ids[] = {
+	{ .compatible = "fsl,imx23-lcdif" },
+	{ .compatible = "fsl,imx28-lcdif" },
+	{ .compatible = "fsl,imx7ulp-lcdif" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mxs_video) = {
+	.name	= "mxs_video",
+	.id	= UCLASS_VIDEO,
+	.of_match = mxs_video_ids,
+	.bind	= mxs_video_bind,
+	.probe	= mxs_video_probe,
+	.remove = mxs_video_remove,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
+#endif /* ifndef CONFIG_DM_VIDEO */
diff --git a/include/configs/colibri_imx7.h b/include/configs/colibri_imx7.h
index 3e4f63e..545f506 100644
--- a/include/configs/colibri_imx7.h
+++ b/include/configs/colibri_imx7.h
@@ -234,7 +234,7 @@
 #define CONFIG_SYS_DFU_DATA_BUF_SIZE	SZ_16M
 #define DFU_DEFAULT_POLL_TIMEOUT	300
 
-#ifdef CONFIG_VIDEO
+#if defined(CONFIG_VIDEO) || defined(CONFIG_DM_VIDEO)
 #define CONFIG_VIDEO_MXS
 #define CONFIG_VIDEO_LOGO
 #define CONFIG_SPLASH_SCREEN
diff --git a/include/configs/tegra-common-post.h b/include/configs/tegra-common-post.h
index e54428b..9685ee5 100644
--- a/include/configs/tegra-common-post.h
+++ b/include/configs/tegra-common-post.h
@@ -21,12 +21,14 @@
 #define CONFIG_SYS_NONCACHED_MEMORY	(1 << 20)	/* 1 MiB */
 
 #ifndef CONFIG_SPL_BUILD
+#ifndef BOOT_TARGET_DEVICES
 #define BOOT_TARGET_DEVICES(func) \
 	func(MMC, mmc, 1) \
 	func(MMC, mmc, 0) \
 	func(USB, usb, 0) \
 	func(PXE, pxe, na) \
 	func(DHCP, dhcp, na)
+#endif
 #include <config_distro_bootcmd.h>
 #else
 #define BOOTENV
diff --git a/include/fdtdec.h b/include/fdtdec.h
index fa8e34f..e6c22dd 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -997,6 +997,30 @@
 int fdtdec_setup_memory_banksize(void);
 
 /**
+ * fdtdec_set_ethernet_mac_address() - set MAC address for default interface
+ *
+ * Looks up the default interface via the "ethernet" alias (in the /aliases
+ * node) and stores the given MAC in its "local-mac-address" property. This
+ * is useful on platforms that store the MAC address in a custom location.
+ * Board code can call this in the late init stage to make sure that the
+ * interface device tree node has the right MAC address configured for the
+ * Ethernet uclass to pick it up.
+ *
+ * Typically the FDT passed into this function will be U-Boot's control DTB.
+ * Given that a lot of code may be holding offsets to various nodes in that
+ * tree, this code will only set the "local-mac-address" property in-place,
+ * which means that it needs to exist and have space for the 6-byte address.
+ * This ensures that the operation is non-destructive and does not invalidate
+ * offsets that other drivers may be using.
+ *
+ * @param fdt FDT blob
+ * @param mac buffer containing the MAC address to set
+ * @param size size of MAC address
+ * @return 0 on success or a negative error code on failure
+ */
+int fdtdec_set_ethernet_mac_address(void *fdt, const u8 *mac, size_t size);
+
+/**
  * fdtdec_set_phandle() - sets the phandle of a given node
  *
  * @param blob		FDT blob
diff --git a/include/linux/string.h b/include/linux/string.h
index 3606620..5d63be4 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -94,6 +94,7 @@
 #ifndef __HAVE_ARCH_STRDUP
 extern char * strdup(const char *);
 #endif
+extern char * strndup(const char *, size_t);
 #ifndef __HAVE_ARCH_STRSWAB
 extern char * strswab(const char *);
 #endif
diff --git a/include/splash.h b/include/splash.h
index 228aff4..7fd2de8 100644
--- a/include/splash.h
+++ b/include/splash.h
@@ -66,10 +66,10 @@
 static inline void splash_get_pos(int *x, int *y) { }
 #endif
 
-#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_LCD)
-int lcd_splash(ulong addr);
+#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_CMD_BMP)
+int splash_display(void);
 #else
-static inline int lcd_splash(ulong addr)
+static inline int splash_display(void)
 {
 	return -ENOSYS;
 }
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index d0ba888..3ee786b 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1261,6 +1261,35 @@
 }
 #endif
 
+int fdtdec_set_ethernet_mac_address(void *fdt, const u8 *mac, size_t size)
+{
+	const char *path;
+	int offset, err;
+
+	if (!is_valid_ethaddr(mac))
+		return -EINVAL;
+
+	path = fdt_get_alias(fdt, "ethernet");
+	if (!path)
+		return 0;
+
+	debug("ethernet alias found: %s\n", path);
+
+	offset = fdt_path_offset(fdt, path);
+	if (offset < 0) {
+		debug("ethernet alias points to absent node %s\n", path);
+		return -ENOENT;
+	}
+
+	err = fdt_setprop_inplace(fdt, offset, "local-mac-address", mac, size);
+	if (err < 0)
+		return err;
+
+	debug("MAC address: %pM\n", mac);
+
+	return 0;
+}
+
 static int fdtdec_init_reserved_memory(void *blob)
 {
 	int na, ns, node, err;
diff --git a/lib/string.c b/lib/string.c
index af17c16..9b779dd 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -326,6 +326,29 @@
 }
 #endif
 
+char * strndup(const char *s, size_t n)
+{
+	size_t len;
+	char *new;
+
+	if (s == NULL)
+		return NULL;
+
+	len = strlen(s);
+
+	if (n < len)
+		len = n;
+
+	new = malloc(len + 1);
+	if (new == NULL)
+		return NULL;
+
+	strncpy(new, s, len);
+	new[len] = '\0';
+
+	return new;
+}
+
 #ifndef __HAVE_ARCH_STRSPN
 /**
  * strspn - Calculate the length of the initial substring of @s which only