Merge branch '2022-04-04-platform-updates'

- Updates for exynos78x0 and TI K3 platforms
diff --git a/arch/arm/dts/k3-am64-ddr.dtsi b/arch/arm/dts/k3-am64-ddr.dtsi
index 026a547..8324b38 100644
--- a/arch/arm/dts/k3-am64-ddr.dtsi
+++ b/arch/arm/dts/k3-am64-ddr.dtsi
@@ -7,8 +7,9 @@
 	memorycontroller: memorycontroller@f300000 {
 		compatible = "ti,am64-ddrss";
 		reg = <0x00 0x0f308000 0x00 0x4000>,
-		      <0x00 0x43014000 0x00 0x100>;
-		reg-names = "cfg", "ctrl_mmr_lp4";
+		      <0x00 0x43014000 0x00 0x100>,
+		      <0x00 0x0f300000 0x00 0x200>;
+		reg-names = "cfg", "ctrl_mmr_lp4", "ss_cfg";
 		power-domains = <&k3_pds 138 TI_SCI_PD_SHARED>,
 			<&k3_pds 55 TI_SCI_PD_SHARED>;
 		clocks = <&k3_clks 138 0>, <&k3_clks 16 4>;
diff --git a/arch/arm/dts/k3-am64.dtsi b/arch/arm/dts/k3-am64.dtsi
index de6805b..7aa94d5 100644
--- a/arch/arm/dts/k3-am64.dtsi
+++ b/arch/arm/dts/k3-am64.dtsi
@@ -64,6 +64,7 @@
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges = <0x00 0x000f4000 0x00 0x000f4000 0x00 0x000002d0>, /* PINCTRL */
+			 <0x00 0x00420000 0x00 0x00420000 0x00 0x00001000>, /* ESM0 */
 			 <0x00 0x00600000 0x00 0x00600000 0x00 0x00001100>, /* GPIO */
 			 <0x00 0x00a40000 0x00 0x00a40000 0x00 0x00000800>, /* Timesync router */
 			 <0x00 0x01000000 0x00 0x01000000 0x00 0x02330400>, /* First peripheral window */
diff --git a/arch/arm/dts/k3-am642-evm-u-boot.dtsi b/arch/arm/dts/k3-am642-evm-u-boot.dtsi
index 03688a5..0c2d973 100644
--- a/arch/arm/dts/k3-am642-evm-u-boot.dtsi
+++ b/arch/arm/dts/k3-am642-evm-u-boot.dtsi
@@ -16,7 +16,7 @@
 		compatible = "ti,omap5430-timer";
 		reg = <0x0 0x2400000 0x0 0x80>;
 		ti,timer-alwon;
-		clock-frequency = <250000000>;
+		clock-frequency = <200000000>;
 		u-boot,dm-spl;
 	};
 };
diff --git a/arch/arm/dts/k3-am642-r5-evm.dts b/arch/arm/dts/k3-am642-r5-evm.dts
index cc48fd4..92a6bfd 100644
--- a/arch/arm/dts/k3-am642-r5-evm.dts
+++ b/arch/arm/dts/k3-am642-r5-evm.dts
@@ -25,6 +25,7 @@
 		/* 2G RAM */
 		reg = <0x00000000 0x80000000 0x00000000 0x80000000>;
 
+		u-boot,dm-spl;
 	};
 
 	a53_0: a53@0 {
@@ -82,6 +83,25 @@
 	};
 };
 
+&cbass_main {
+	main_esm: esm@420000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x0 0x420000 0x0 0x1000>;
+		ti,esm-pins = <160>, <161>;
+		u-boot,dm-spl;
+	};
+};
+
+&cbass_mcu {
+	u-boot,dm-spl;
+	mcu_esm: esm@4100000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x0 0x4100000 0x0 0x1000>;
+		ti,esm-pins = <0>, <1>;
+		u-boot,dm-spl;
+	};
+};
+
 &main_pmx0 {
 	u-boot,dm-spl;
 	main_uart0_pins_default: main-uart0-pins-default {
diff --git a/arch/arm/dts/k3-am642-r5-sk.dts b/arch/arm/dts/k3-am642-r5-sk.dts
index 7d1cb85..1f96e3f 100644
--- a/arch/arm/dts/k3-am642-r5-sk.dts
+++ b/arch/arm/dts/k3-am642-r5-sk.dts
@@ -75,6 +75,25 @@
 	};
 };
 
+&cbass_main {
+	main_esm: esm@420000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x0 0x420000 0x0 0x1000>;
+		ti,esm-pins = <160>, <161>;
+		u-boot,dm-spl;
+	};
+};
+
+&cbass_mcu {
+	u-boot,dm-spl;
+	mcu_esm: esm@4100000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x0 0x4100000 0x0 0x1000>;
+		ti,esm-pins = <0>, <1>;
+		u-boot,dm-spl;
+	};
+};
+
 &main_pmx0 {
 	u-boot,dm-spl;
 	main_uart0_pins_default: main-uart0-pins-default {
diff --git a/arch/arm/dts/k3-am642-sk-u-boot.dtsi b/arch/arm/dts/k3-am642-sk-u-boot.dtsi
index e5c26b8..afe5bab 100644
--- a/arch/arm/dts/k3-am642-sk-u-boot.dtsi
+++ b/arch/arm/dts/k3-am642-sk-u-boot.dtsi
@@ -20,7 +20,7 @@
 		compatible = "ti,omap5430-timer";
 		reg = <0x0 0x2400000 0x0 0x80>;
 		ti,timer-alwon;
-		clock-frequency = <250000000>;
+		clock-frequency = <200000000>;
 		u-boot,dm-spl;
 	};
 };
diff --git a/arch/arm/dts/sdm845.dtsi b/arch/arm/dts/sdm845.dtsi
index 1185b71..6f2fb20 100644
--- a/arch/arm/dts/sdm845.dtsi
+++ b/arch/arm/dts/sdm845.dtsi
@@ -48,10 +48,8 @@
 
 			/* DEBUG UART */
 			qup_uart9: qup-uart9-default {
-				pinmux {
-					pins = "GPIO_4", "GPIO_5";
-					function = "qup9";
-				};
+				pins = "GPIO_4", "GPIO_5";
+				function = "gpio";
 			};
 		};
 
diff --git a/arch/arm/dts/starqltechn-uboot.dtsi b/arch/arm/dts/starqltechn-uboot.dtsi
index d8d75e0..b55cccf 100644
--- a/arch/arm/dts/starqltechn-uboot.dtsi
+++ b/arch/arm/dts/starqltechn-uboot.dtsi
@@ -8,15 +8,18 @@
 
 /
 {
+	framebuffer@9D400000 {
+		u-boot,dm-pre-reloc;
+	};
 	soc {
 		u-boot,dm-pre-reloc;
+		serial@a84000 {
+			u-boot,dm-pre-reloc;
+		};
 		gcc {
 			clock-controller@100000 {
 				u-boot,dm-pre-reloc;
 			};
-			serial@0xa84000 {
-				u-boot,dm-pre-reloc;
-			};
 			gpio_north@3900000 {
 				u-boot,dm-pre-reloc;
 			};
diff --git a/arch/arm/dts/starqltechn.dts b/arch/arm/dts/starqltechn.dts
index 387420f..0261388 100644
--- a/arch/arm/dts/starqltechn.dts
+++ b/arch/arm/dts/starqltechn.dts
@@ -34,9 +34,18 @@
 		method = "smc";
 	};
 
+	framebuffer: framebuffer@9D400000 {
+		compatible = "simple-framebuffer";
+		reg = <0 0x9D400000 0 (2960 * 1440 * 4)>;//2400000
+		width = <1440>;
+		height = <2960>;
+		stride = <(1440 * 4)>;
+		format = "a8r8g8b8";
+	};
+
 	soc: soc {
-		serial@0xa84000 {
-			status = "ok";
+		serial@a84000 {
+			status = "okay";
 		};
 
 		pinctrl@3900000 {
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 594fc12..c603fe6 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -48,6 +48,11 @@
 endif
 obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
 
+ifneq ($(filter y,$(CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR) $(CONFIG_SAVE_PREV_BL_FDT_ADDR)),)
+obj-y += save_prev_bl_data.o
+endif
+
+# obj-$(CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR) += save_prev_bl_data.o
 obj-y	+= bdinfo.o
 obj-y	+= sections.o
 CFLAGS_REMOVE_sections.o := $(LTO_CFLAGS)
diff --git a/arch/arm/lib/save_prev_bl_data.c b/arch/arm/lib/save_prev_bl_data.c
new file mode 100644
index 0000000..f4ee86a
--- /dev/null
+++ b/arch/arm/lib/save_prev_bl_data.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * save_prev_bl_data - saving previous bootloader data
+ * to environment variables.
+ *
+ * Copyright (c) 2022 Dzmitry Sankouski (dsankouski@gmail.com)
+ */
+#include <init.h>
+#include <env.h>
+#include <fdtdec.h>
+#include <fdt_support.h>
+#include <fdt.h>
+#include <common.h>
+#include <linux/errno.h>
+#include <asm/system.h>
+#include <asm/armv8/mmu.h>
+
+static ulong reg0 __section(".data");
+
+/**
+ * Save x0 register value, assuming previous bootloader set it to
+ * point on loaded fdt or (for older linux kernels)atags.
+ */
+void save_boot_params(ulong r0)
+{
+	reg0 = r0;
+	save_boot_params_ret();
+}
+
+bool is_addr_accessible(phys_addr_t addr)
+{
+	struct mm_region *mem = mem_map;
+	phys_addr_t bank_start;
+	phys_addr_t bank_end;
+
+	while (mem->size) {
+		bank_start = mem->phys;
+		bank_end = bank_start + mem->size;
+		debug("check if block %pap - %pap includes %pap\n", &bank_start, &bank_end, &addr);
+		if (addr > bank_start && addr < bank_end)
+			return true;
+		mem++;
+	}
+
+	return false;
+}
+
+int save_prev_bl_data(void)
+{
+	struct fdt_header *fdt_blob;
+	int node;
+	u64 initrd_start_prop;
+
+	if (!is_addr_accessible((phys_addr_t)reg0))
+		return -ENODATA;
+
+	fdt_blob = (struct fdt_header *)reg0;
+	if (!fdt_valid(&fdt_blob)) {
+		pr_warn("%s: address 0x%lx is not a valid fdt\n", __func__, reg0);
+		return -ENODATA;
+	}
+
+	if (CONFIG_IS_ENABLED(SAVE_PREV_BL_FDT_ADDR))
+		env_set_addr("prevbl_fdt_addr", (void *)reg0);
+	if (!CONFIG_IS_ENABLED(SAVE_PREV_BL_INITRAMFS_START_ADDR))
+		return 0;
+
+	node = fdt_path_offset(fdt_blob, "/chosen");
+	if (!node) {
+		pr_warn("%s: chosen node not found in device tree at addr: 0x%lx\n",
+					__func__, reg0);
+		return -ENODATA;
+	}
+	/*
+	 * linux,initrd-start property might be either 64 or 32 bit,
+	 * depending on primary bootloader implementation.
+	 */
+	initrd_start_prop = fdtdec_get_uint64(fdt_blob, node, "linux,initrd-start", 0);
+	if (!initrd_start_prop) {
+		debug("%s: attempt to get uint64 linux,initrd-start property failed, trying uint\n",
+				__func__);
+		initrd_start_prop = fdtdec_get_uint(fdt_blob, node, "linux,initrd-start", 0);
+		if (!initrd_start_prop) {
+			debug("%s: attempt to get uint failed, too\n", __func__);
+			return -ENODATA;
+		}
+	}
+	env_set_addr("prevbl_initrd_start_addr", (void *)initrd_start_prop);
+
+	return 0;
+}
diff --git a/arch/arm/mach-k3/am642_init.c b/arch/arm/mach-k3/am642_init.c
index eabfd57..add7ea8 100644
--- a/arch/arm/mach-k3/am642_init.c
+++ b/arch/arm/mach-k3/am642_init.c
@@ -24,12 +24,22 @@
 #include <dm/root.h>
 
 #if defined(CONFIG_SPL_BUILD)
+#define MCU_CTRL_MMR0_BASE			0x04500000
+#define CTRLMMR_MCU_RST_CTRL			0x04518170
 
 static void ctrl_mmr_unlock(void)
 {
 	/* Unlock all PADCFG_MMR1 module registers */
 	mmr_unlock(PADCFG_MMR1_BASE, 1);
 
+	/* Unlock all MCU_CTRL_MMR0 module registers */
+	mmr_unlock(MCU_CTRL_MMR0_BASE, 0);
+	mmr_unlock(MCU_CTRL_MMR0_BASE, 1);
+	mmr_unlock(MCU_CTRL_MMR0_BASE, 2);
+	mmr_unlock(MCU_CTRL_MMR0_BASE, 3);
+	mmr_unlock(MCU_CTRL_MMR0_BASE, 4);
+	mmr_unlock(MCU_CTRL_MMR0_BASE, 6);
+
 	/* Unlock all CTRL_MMR0 module registers */
 	mmr_unlock(CTRL_MMR0_BASE, 0);
 	mmr_unlock(CTRL_MMR0_BASE, 1);
@@ -37,9 +47,6 @@
 	mmr_unlock(CTRL_MMR0_BASE, 3);
 	mmr_unlock(CTRL_MMR0_BASE, 5);
 	mmr_unlock(CTRL_MMR0_BASE, 6);
-
-	/* Unlock all MCU_PADCFG_MMR1 module registers */
-	mmr_unlock(MCU_PADCFG_MMR1_BASE, 1);
 }
 
 /*
@@ -142,9 +149,20 @@
 }
 #endif
 
+#if defined(CONFIG_ESM_K3)
+static void enable_mcu_esm_reset(void)
+{
+	/* Set CTRLMMR_MCU_RST_CTRL:MCU_ESM_ERROR_RST_EN_Z  to '0' (low active) */
+	u32 stat = readl(CTRLMMR_MCU_RST_CTRL);
+
+	stat &= 0xFFFDFFFF;
+	writel(stat, CTRLMMR_MCU_RST_CTRL);
+}
+#endif
+
 void board_init_f(ulong dummy)
 {
-#if defined(CONFIG_K3_LOAD_SYSFW) || defined(CONFIG_K3_AM64_DDRSS)
+#if defined(CONFIG_K3_LOAD_SYSFW) || defined(CONFIG_K3_AM64_DDRSS) || defined(CONFIG_ESM_K3)
 	struct udevice *dev;
 	int ret;
 #endif
@@ -194,6 +212,20 @@
 	/* Output System Firmware version info */
 	k3_sysfw_print_ver();
 
+#if defined(CONFIG_ESM_K3)
+	/* Probe/configure ESM0 */
+	ret = uclass_get_device_by_name(UCLASS_MISC, "esm@420000", &dev);
+	if (ret)
+		printf("esm main init failed: %d\n", ret);
+
+	/* Probe/configure MCUESM */
+	ret = uclass_get_device_by_name(UCLASS_MISC, "esm@4100000", &dev);
+	if (ret)
+		printf("esm mcu init failed: %d\n", ret);
+
+	enable_mcu_esm_reset();
+#endif
+
 #if defined(CONFIG_K3_AM64_DDRSS)
 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
 	if (ret)
diff --git a/board/ti/am64x/evm.c b/board/ti/am64x/evm.c
index 8373c76..c88139a 100644
--- a/board/ti/am64x/evm.c
+++ b/board/ti/am64x/evm.c
@@ -2,13 +2,15 @@
 /*
  * Board specific initialization for AM642 EVM
  *
- * Copyright (C) 2020-2021 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2020-2022 Texas Instruments Incorporated - https://www.ti.com/
  *	Keerthy <j-keerthy@ti.com>
  *
  */
 
 #include <common.h>
 #include <asm/io.h>
+#include <dm/uclass.h>
+#include <k3-ddrss.h>
 #include <spl.h>
 #include <fdt_support.h>
 #include <asm/arch/hardware.h>
@@ -29,19 +31,24 @@
 
 int dram_init(void)
 {
-	gd->ram_size = 0x80000000;
+	s32 ret;
 
-	return 0;
+	ret = fdtdec_setup_mem_size_base();
+	if (ret)
+		printf("Error setting up mem size and base. %d\n", ret);
+
+	return ret;
 }
 
 int dram_init_banksize(void)
 {
-	/* Bank 0 declares the memory available in the DDR low region */
-	gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
-	gd->bd->bi_dram[0].size = 0x80000000;
-	gd->ram_size = 0x80000000;
+	s32 ret;
 
-	return 0;
+	ret = fdtdec_setup_memory_banksize();
+	if (ret)
+		printf("Error setting up memory banksize. %d\n", ret);
+
+	return ret;
 }
 
 #if defined(CONFIG_SPL_LOAD_FIT)
@@ -61,7 +68,8 @@
 }
 #endif
 
-#if defined(CONFIG_SPL_BUILD) && CONFIG_IS_ENABLED(USB_STORAGE)
+#if defined(CONFIG_SPL_BUILD)
+#if CONFIG_IS_ENABLED(USB_STORAGE)
 static int fixup_usb_boot(const void *fdt_blob)
 {
 	int ret = 0;
@@ -85,10 +93,58 @@
 
 	return ret;
 }
+#endif
+
+#if defined(CONFIG_K3_AM64_DDRSS)
+static void fixup_ddr_driver_for_ecc(struct spl_image_info *spl_image)
+{
+	struct udevice *dev;
+	int ret;
+
+	dram_init_banksize();
+
+	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+	if (ret)
+		panic("Cannot get RAM device for ddr size fixup: %d\n", ret);
+
+	ret = k3_ddrss_ddr_fdt_fixup(dev, spl_image->fdt_addr, gd->bd);
+	if (ret)
+		printf("Error fixing up ddr node for ECC use! %d\n", ret);
+}
+#else
+static void fixup_memory_node(struct spl_image_info *spl_image)
+{
+	u64 start[CONFIG_NR_DRAM_BANKS];
+	u64 size[CONFIG_NR_DRAM_BANKS];
+	int bank;
+	int ret;
+
+	dram_init();
+	dram_init_banksize();
+
+	for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
+		start[bank] =  gd->bd->bi_dram[bank].start;
+		size[bank] = gd->bd->bi_dram[bank].size;
+	}
+
+	/* dram_init functions use SPL fdt, and we must fixup u-boot fdt */
+	ret = fdt_fixup_memory_banks(spl_image->fdt_addr, start, size, CONFIG_NR_DRAM_BANKS);
+	if (ret)
+		printf("Error fixing up memory node! %d\n", ret);
+}
+#endif
 
 void spl_perform_fixups(struct spl_image_info *spl_image)
 {
+#if defined(CONFIG_K3_AM64_DDRSS)
+	fixup_ddr_driver_for_ecc(spl_image);
+#else
+	fixup_memory_node(spl_image);
+#endif
+
+#if CONFIG_IS_ENABLED(USB_STORAGE)
 	fixup_usb_boot(spl_image->fdt_addr);
+#endif
 }
 #endif
 
diff --git a/boot/Kconfig b/boot/Kconfig
index 394b26f..ec5b956 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -1192,4 +1192,28 @@
 	help
 	  This option is used to set the default fdt file to boot OS.
 
+config SAVE_PREV_BL_FDT_ADDR
+	depends on ARM
+	bool "Saves fdt address, passed by the previous bootloader, to env var"
+	help
+	  When u-boot is used as a chain-loaded bootloader (replacing OS kernel),
+	  enable this option to save fdt address, passed by the
+	  previous bootloader for future use.
+	  Address is saved to `prevbl_fdt_addr` environment variable.
+
+	  If no fdt was provided by previous bootloader, no env variables
+	  will be created.
+
+config SAVE_PREV_BL_INITRAMFS_START_ADDR
+	depends on ARM
+	bool "Saves initramfs address, passed by the previous bootloader, to env var"
+	help
+	  When u-boot is used as a chain-loaded bootloader(replacing OS kernel),
+	  enable this option to save initramfs address, passed by the
+	  previous bootloader for future use.
+	  Address is saved to `prevbl_initrd_start_addr` environment variable.
+
+	  If no initramfs was provided by previous bootloader, no env variables
+	  will be created.
+
 endmenu		# Booting
diff --git a/common/board_r.c b/common/board_r.c
index b92c1bb..8dc87ed 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -445,6 +445,11 @@
 		env_set_hex("fdtcontroladdr",
 			    (unsigned long)map_to_sysmem(gd->fdt_blob));
 
+	#if (CONFIG_IS_ENABLED(SAVE_PREV_BL_INITRAMFS_START_ADDR) || \
+						CONFIG_IS_ENABLED(SAVE_PREV_BL_FDT_ADDR))
+		save_prev_bl_data();
+	#endif
+
 	/* Initialize from environment */
 	image_load_addr = env_get_ulong("loadaddr", 16, image_load_addr);
 
diff --git a/configs/a3y17lte_defconfig b/configs/a3y17lte_defconfig
index b433da3..7ca7ce0 100644
--- a/configs/a3y17lte_defconfig
+++ b/configs/a3y17lte_defconfig
@@ -11,8 +11,11 @@
 CONFIG_FIT=y
 CONFIG_USE_PREBOOT=y
 CONFIG_PREBOOT="echo Read pressed buttons status;KEY_VOLUMEUP=gpa20;KEY_HOME=gpa17;KEY_VOLUMEDOWN=gpa21;KEY_POWER=gpa00;PRESSED=0;RELEASED=1;if gpio input $KEY_VOLUMEUP; then setenv VOLUME_UP $PRESSED; else setenv VOLUME_UP $RELEASED; fi;if gpio input $KEY_VOLUMEDOWN; then setenv VOLUME_DOWN $PRESSED; else setenv VOLUME_DOWN $RELEASED; fi;if gpio input $KEY_HOME; then setenv HOME $PRESSED; else setenv HOME $RELEASED; fi;if gpio input $KEY_POWER; then setenv POWER $PRESSED; else setenv POWER $RELEASED; fi;"
+CONFIG_SAVE_PREV_BL_FDT_ADDR=y
+CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_DM_I2C_GPIO=y
+CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/a5y17lte_defconfig b/configs/a5y17lte_defconfig
index 2534ab0..793389e 100644
--- a/configs/a5y17lte_defconfig
+++ b/configs/a5y17lte_defconfig
@@ -11,8 +11,11 @@
 CONFIG_FIT=y
 CONFIG_USE_PREBOOT=y
 CONFIG_PREBOOT="echo Read pressed buttons status;KEY_VOLUMEUP=gpa20;KEY_HOME=gpa17;KEY_VOLUMEDOWN=gpa21;KEY_POWER=gpa00;PRESSED=0;RELEASED=1;if gpio input $KEY_VOLUMEUP; then setenv VOLUME_UP $PRESSED; else setenv VOLUME_UP $RELEASED; fi;if gpio input $KEY_VOLUMEDOWN; then setenv VOLUME_DOWN $PRESSED; else setenv VOLUME_DOWN $RELEASED; fi;if gpio input $KEY_HOME; then setenv HOME $PRESSED; else setenv HOME $RELEASED; fi;if gpio input $KEY_POWER; then setenv POWER $PRESSED; else setenv POWER $RELEASED; fi;"
+CONFIG_SAVE_PREV_BL_FDT_ADDR=y
+CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_DM_I2C_GPIO=y
+CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/a7y17lte_defconfig b/configs/a7y17lte_defconfig
index a2d7637..eaa448d 100644
--- a/configs/a7y17lte_defconfig
+++ b/configs/a7y17lte_defconfig
@@ -11,8 +11,11 @@
 CONFIG_FIT=y
 CONFIG_USE_PREBOOT=y
 CONFIG_PREBOOT="echo Read pressed buttons status;KEY_VOLUMEUP=gpa20;KEY_HOME=gpa17;KEY_VOLUMEDOWN=gpa21;KEY_POWER=gpa00;PRESSED=0;RELEASED=1;if gpio input $KEY_VOLUMEUP; then setenv VOLUME_UP $PRESSED; else setenv VOLUME_UP $RELEASED; fi;if gpio input $KEY_VOLUMEDOWN; then setenv VOLUME_DOWN $PRESSED; else setenv VOLUME_DOWN $RELEASED; fi;if gpio input $KEY_HOME; then setenv HOME $PRESSED; else setenv HOME $RELEASED; fi;if gpio input $KEY_POWER; then setenv POWER $PRESSED; else setenv POWER $RELEASED; fi;"
+CONFIG_SAVE_PREV_BL_FDT_ADDR=y
+CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_DM_I2C_GPIO=y
+CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/am64x_evm_a53_defconfig b/configs/am64x_evm_a53_defconfig
index 7397436..bceb35f 100644
--- a/configs/am64x_evm_a53_defconfig
+++ b/configs/am64x_evm_a53_defconfig
@@ -135,9 +135,6 @@
 CONFIG_SYSRESET=y
 CONFIG_SPL_SYSRESET=y
 CONFIG_SYSRESET_TI_SCI=y
-CONFIG_TIMER=y
-CONFIG_SPL_TIMER=y
-CONFIG_OMAP_TIMER=y
 CONFIG_USB=y
 CONFIG_DM_USB_GADGET=y
 CONFIG_SPL_DM_USB_GADGET=y
diff --git a/configs/am64x_evm_r5_defconfig b/configs/am64x_evm_r5_defconfig
index 61138dd..985e7df 100644
--- a/configs/am64x_evm_r5_defconfig
+++ b/configs/am64x_evm_r5_defconfig
@@ -9,6 +9,7 @@
 CONFIG_TARGET_AM642_R5_EVM=y
 CONFIG_ENV_SIZE=0x20000
 CONFIG_ENV_OFFSET=0x680000
+CONFIG_NR_DRAM_BANKS=2
 CONFIG_DM_GPIO=y
 CONFIG_SPL_DM_SPI=y
 CONFIG_DEFAULT_DEVICE_TREE="k3-am642-r5-evm"
@@ -103,6 +104,7 @@
 CONFIG_SYS_I2C_OMAP24XX=y
 CONFIG_DM_MAILBOX=y
 CONFIG_K3_SEC_PROXY=y
+CONFIG_ESM_K3=y
 CONFIG_SPL_MISC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ADMA=y
diff --git a/configs/starqltechn_defconfig b/configs/starqltechn_defconfig
index f57bb85..75e8409 100644
--- a/configs/starqltechn_defconfig
+++ b/configs/starqltechn_defconfig
@@ -2,16 +2,18 @@
 CONFIG_SKIP_LOWLEVEL_INIT=y
 CONFIG_POSITION_INDEPENDENT=y
 CONFIG_ARCH_SNAPDRAGON=y
-CONFIG_SYS_TEXT_BASE=0x80000000
-CONFIG_SYS_MALLOC_LEN=0x81f000
 CONFIG_DEFAULT_DEVICE_TREE="starqltechn"
+CONFIG_BOOTDELAY=0
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
 CONFIG_TARGET_STARQLTECHN=y
 CONFIG_IDENT_STRING="\nSamsung S9 SM-G9600"
 CONFIG_SYS_LOAD_ADDR=0x80000000
-CONFIG_USE_PREBOOT=y
+CONFIG_LMB_MAX_REGIONS=64
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_GPIO=y
+# CONFIG_REQUIRE_SERIAL_CONSOLE is not set
 # CONFIG_NET is not set
 # CONFIG_DM_STDIO is not set
 CONFIG_CLK=y
@@ -20,5 +22,16 @@
 CONFIG_PINCTRL=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_PM8916=y
-CONFIG_MSM_GENI_SERIAL=y
+# CONFIG_MSM_GENI_SERIAL is not set
 CONFIG_SPMI_MSM=y
+CONFIG_LINUX_KERNEL_IMAGE_HEADER=y
+CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR=y
+CONFIG_SAVE_PREV_BL_FDT_ADDR=y
+CONFIG_DM_VIDEO=y
+CONFIG_VIDEO_LOGO=y
+CONFIG_CMD_VIDCONSOLE=y
+CONFIG_CONSOLE_NORMAL=y
+CONFIG_SYS_WHITE_ON_BLACK=y
+CONFIG_VIDEO_DT_SIMPLEFB=y
+CONFIG_VIDEO_SIMPLE=y
+CONFIG_CMD_BMP=y
diff --git a/doc/board/qualcomm/sdm845.rst b/doc/board/qualcomm/sdm845.rst
index cd46cbe..b6642c9 100644
--- a/doc/board/qualcomm/sdm845.rst
+++ b/doc/board/qualcomm/sdm845.rst
@@ -17,7 +17,9 @@
 
 Installation
 ------------
-First, setup ``CROSS_COMPILE`` for aarch64. Then, build U-Boot for your board::
+Build
+^^^^^
+Setup ``CROSS_COMPILE`` for aarch64 and build U-Boot for your board::
 
 	$ export CROSS_COMPILE=<aarch64 toolchain prefix>
 	$ make <your board name here, see Boards section>_defconfig
@@ -25,6 +27,49 @@
 
 This will build ``u-boot.bin`` in the configured output directory.
 
+Generate FIT image
+^^^^^^^^^^^^^^^^^^
+See doc/uImage.FIT for more details
+
+Pack android boot image
+^^^^^^^^^^^^^^^^^^^^^^^
+We'll assemble android boot image with ``u-boot.bin`` instead of linux kernel,
+and FIT image instead of ``initramfs``. Android bootloader expect gzipped kernel
+with appended dtb, so let's mimic linux to satisfy stock bootloader:
+
+- create dump dtb::
+
+	workdir=/tmp/prepare_payload
+	mkdir -p "$workdir"
+	cd "$workdir"
+	mock_dtb="$workdir"/payload_mock.dtb
+
+	dtc -I dts -O dtb -o "$mock_dtb" << EOF
+	/dts-v1/;
+	/ {
+		memory {
+			/* We expect the bootloader to fill in the size */
+			reg = <0 0 0 0>;
+		};
+
+		chosen { };
+	};
+	EOF
+
+- gzip u-boot ``gzip u-boot.bin``
+- append dtb to gzipped u-boot: ``cat u-boot.bin.gz "$mock_dtb" > u-boot.bin.gz-dtb``
+
+Now we've got everything to build android boot image:::
+
+	mkbootimg --base 0x0 --kernel_offset 0x00008000 \
+	--ramdisk_offset 0x02000000 --tags_offset 0x01e00000 \
+	--pagesize 4096 --second_offset 0x00f00000 \
+	--ramdisk "$fit_image" \
+	--kernel u-boot.bin.gz-dtb \
+	-o boot.img
+
+Flash image with your phone's flashing method.
+
 Boards
 ------------
 starqlte
diff --git a/doc/board/samsung/axy17lte.rst b/doc/board/samsung/axy17lte.rst
index e84fefe..b7f299d 100644
--- a/doc/board/samsung/axy17lte.rst
+++ b/doc/board/samsung/axy17lte.rst
@@ -66,26 +66,17 @@
 It may be pure u-boot (with loading u-boot's payload from flash in mind),
 or u-boot + u-boot's payload.
 
-It should be kept in mind, that SBOOT binary patches it's payload after loading
-in address range 0x401f8550-0x401f9280. Given SBOOT loads payload to 0x40001000,
-a range of 0x1f7550-0x1f8280 (2061648-2065024) in a payload file
-will be corrupted after loading to RAM.
-
 Creating payload file
 """""""""""""""""""""
 - Assemble FIT image for your kernel
-- Create a file for u-boot payload ``touch sboot-payload``
-- Write zeroes till 0x200000 address to be sure SBOOT won't corrupt your info
-  ``dd if=/dev/zero of=sboot-payload bs=$((0x200000)) count=1``
-- Write u-boot to the start of the payload ``dd if=<u-boot.bin path> of=sboot-payload``
-- Write FIT image to payload from 0x200000 address
-  ``dd if=<FIT image path> of=sboot-payload seek=1 bs=2M``
 
 Creating android boot image
 """""""""""""""""""""""""""
 Once payload created, it's time for android image::
 
-  mkbootimg --base 0x40000000 --kernel_offset 0x00000000 --ramdisk_offset 0x01000000 --tags_offset 0x00000100 --pagesize 2048 --second_offset 0x00f00000 --kernel <sboot-payload path> -o uboot.img
+  uboot=<path to u-boot.bin file>
+  ramdisk=<path to FIT payload file>
+  mkbootimg --base 0x40000000 --kernel_offset 0x00000000 --ramdisk_offset 0x01000000 --tags_offset 0x00000100 --pagesize 2048 --second_offset 0x00f00000 --kernel "$uboot" --ramdisk "$ramdisk" -o uboot.img
 
 Note, that stock Samsung bootloader ignores offsets, set in mkbootimg.
 
diff --git a/doc/device-tree-bindings/memory-controller/k3-j721e-ddrss.txt b/doc/device-tree-bindings/memory-controller/k3-j721e-ddrss.txt
index dd0260b..df3290a 100644
--- a/doc/device-tree-bindings/memory-controller/k3-j721e-ddrss.txt
+++ b/doc/device-tree-bindings/memory-controller/k3-j721e-ddrss.txt
@@ -13,6 +13,7 @@
 				  "ti,am64-ddrss" for am642
 - reg-names		cfg - Map the controller configuration region
 			ctrl_mmr_lp4 - Map LP4 register region in ctrl mmr
+			ss - Map the DDRSS configuration region
 - reg:			Contains the register map per reg-names.
 - power-domains:	Should contain two entries:
 			- an entry to TISCI DDR CFG device
@@ -32,6 +33,13 @@
 - ti,pi-data:		An array containing the phy independent block settings
 - ti,phy-data:		An array containing the ddr phy settings.
 
+Optional properties:
+--------------------
+- reg-names 		ss - Map the DDRSS configuration region
+- reg:			Must add "ss" to list if the above ss region is included.
+- ti,ecc-enable:	Boolean flag to enable ECC. This will reduce available DDR
+			by 1/9.
+
 Example (J721E):
 ================
 
diff --git a/drivers/misc/k3_esm.c b/drivers/misc/k3_esm.c
index cc2a23d..41faeb3 100644
--- a/drivers/misc/k3_esm.c
+++ b/drivers/misc/k3_esm.c
@@ -16,17 +16,57 @@
 
 #define ESM_SFT_RST			0x0c
 #define ESM_SFT_RST_KEY			0x0f
+#define ESM_EN				0x08
+#define ESM_EN_KEY			0x0f
 
 #define ESM_STS(i)			(0x404 + (i) / 32 * 0x20)
+#define ESM_STS_MASK(i)			(1 << ((i) % 32))
 #define ESM_PIN_EN_SET_OFFSET(i)	(0x414 + (i) / 32 * 0x20)
-#define ESM_PIN_MASK(i)			BIT((i) & 0x1f)
+#define ESM_PIN_MASK(i)			(1 << ((i) % 32))
+#define ESM_INTR_EN_SET_OFFSET(i)	(0x408 + (i) / 32 * 0x20)
+#define ESM_INTR_MASK(i)		(1 << ((i) % 32))
+#define ESM_INTR_PRIO_SET_OFFSET(i)	(0x410 + (i) / 32 * 0x20)
+#define ESM_INTR_PRIO_MASK(i)		(1 << ((i) % 32))
 
 static void esm_pin_enable(void __iomem *base, int pin)
 {
+	u32 value;
+
+	value = readl(base + ESM_PIN_EN_SET_OFFSET(pin));
+	value |= ESM_PIN_MASK(pin);
 	/* Enable event */
-	writel(ESM_PIN_MASK(pin), base + ESM_PIN_EN_SET_OFFSET(pin));
+	writel(value, base + ESM_PIN_EN_SET_OFFSET(pin));
 }
 
+static void esm_intr_enable(void __iomem *base, int pin)
+{
+	u32 value;
+
+	value = readl(base + ESM_INTR_EN_SET_OFFSET(pin));
+	value |= ESM_INTR_MASK(pin);
+	/* Enable Interrupt event */
+	writel(value, base + ESM_INTR_EN_SET_OFFSET(pin));
+}
+
+static void esm_intr_prio_set(void __iomem *base, int pin)
+{
+	u32 value;
+
+	value = readl(base + ESM_INTR_PRIO_SET_OFFSET(pin));
+	value |= ESM_INTR_PRIO_MASK(pin);
+	/* Set to priority */
+	writel(value, base + ESM_INTR_PRIO_SET_OFFSET(pin));
+}
+
+static void esm_clear_raw_status(void __iomem *base, int pin)
+{
+	u32 value;
+
+	value = readl(base + ESM_STS(pin));
+	value |= ESM_STS_MASK(pin);
+	/* Clear Event status */
+	writel(value, base + ESM_STS(pin));
+}
 /**
  * k3_esm_probe: configures ESM based on DT data
  *
@@ -67,8 +107,15 @@
 	/* Clear any pending events */
 	writel(ESM_SFT_RST_KEY, base + ESM_SFT_RST);
 
-	for (i = 0; i < num_pins; i++)
+	for (i = 0; i < num_pins; i++) {
+		esm_intr_prio_set(base, pins[i]);
+		esm_clear_raw_status(base, pins[i]);
 		esm_pin_enable(base, pins[i]);
+		esm_intr_enable(base, pins[i]);
+	}
+
+	/* Enable ESM */
+	writel(ESM_EN_KEY, base + ESM_EN);
 
 free_pins:
 	kfree(pins);
diff --git a/drivers/ram/k3-am654-ddrss.c b/drivers/ram/k3-am654-ddrss.c
index 4ec12bf..4453c24 100644
--- a/drivers/ram/k3-am654-ddrss.c
+++ b/drivers/ram/k3-am654-ddrss.c
@@ -265,6 +265,16 @@
 	ddrss_phy_writel(DDRSS_DDRPHY_ACIOCR5, ioctl->ddrphy_aciocr5);
 	ddrss_phy_writel(DDRSS_DDRPHY_IOVCR0, ioctl->ddrphy_iovcr0);
 
+	ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR0, cfg->ddrphy_dx2gcr0);
+	ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR1, cfg->ddrphy_dx2gcr1);
+	ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR2, cfg->ddrphy_dx2gcr2);
+	ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR3, cfg->ddrphy_dx2gcr3);
+
+	ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR0, cfg->ddrphy_dx3gcr0);
+	ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR1, cfg->ddrphy_dx3gcr1);
+	ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR2, cfg->ddrphy_dx3gcr2);
+	ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR3, cfg->ddrphy_dx3gcr3);
+
 	ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR0, cfg->ddrphy_dx4gcr0);
 	ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR1, cfg->ddrphy_dx4gcr1);
 	ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR2, cfg->ddrphy_dx4gcr2);
@@ -874,9 +884,8 @@
 	device_get_supply_regulator(ddrss->dev, "vtt-supply",
 				    &ddrss->vtt_supply);
 	ret = regulator_set_value(ddrss->vtt_supply, 3300000);
-	if (ret)
-		return ret;
-	debug("VTT regulator enabled\n");
+	if (ret == 0)
+		debug("VTT regulator enabled\n");
 #endif
 
 	return 0;
diff --git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c
index 25e3976..2467f12 100644
--- a/drivers/ram/k3-ddrss/k3-ddrss.c
+++ b/drivers/ram/k3-ddrss/k3-ddrss.c
@@ -6,9 +6,12 @@
  */
 
 #include <common.h>
+#include <config.h>
 #include <clk.h>
+#include <div64.h>
 #include <dm.h>
 #include <dm/device_compat.h>
+#include <fdt_support.h>
 #include <ram.h>
 #include <hang.h>
 #include <log.h>
@@ -30,6 +33,19 @@
 #define DDRSS_V2A_R1_MAT_REG			0x0020
 #define DDRSS_ECC_CTRL_REG			0x0120
 
+#define DDRSS_ECC_CTRL_REG_ECC_EN		BIT(0)
+#define DDRSS_ECC_CTRL_REG_RMW_EN		BIT(1)
+#define DDRSS_ECC_CTRL_REG_ECC_CK		BIT(2)
+#define DDRSS_ECC_CTRL_REG_WR_ALLOC		BIT(4)
+
+#define DDRSS_ECC_R0_STR_ADDR_REG		0x0130
+#define DDRSS_ECC_R0_END_ADDR_REG		0x0134
+#define DDRSS_ECC_R1_STR_ADDR_REG		0x0138
+#define DDRSS_ECC_R1_END_ADDR_REG		0x013c
+#define DDRSS_ECC_R2_STR_ADDR_REG		0x0140
+#define DDRSS_ECC_R2_END_ADDR_REG		0x0144
+#define DDRSS_ECC_1B_ERR_CNT_REG		0x0150
+
 #define SINGLE_DDR_SUBSYSTEM	0x1
 #define MULTI_DDR_SUBSYSTEM	0x2
 
@@ -102,10 +118,18 @@
 	enum emif_active active;
 };
 
+#define K3_DDRSS_MAX_ECC_REGIONS		3
+
+struct k3_ddrss_ecc_region {
+	u32 start;
+	u32 range;
+};
+
 struct k3_ddrss_desc {
 	struct udevice *dev;
 	void __iomem *ddrss_ss_cfg;
 	void __iomem *ddrss_ctrl_mmr;
+	void __iomem *ddrss_ctl_cfg;
 	struct power_domain ddrcfg_pwrdmn;
 	struct power_domain ddrdata_pwrdmn;
 	struct clk ddr_clk;
@@ -118,6 +142,9 @@
 	lpddr4_obj *driverdt;
 	lpddr4_config config;
 	lpddr4_privatedata pd;
+	struct k3_ddrss_ecc_region ecc_regions[K3_DDRSS_MAX_ECC_REGIONS];
+	u64 ecc_reserved_space;
+	bool ti_ecc_enabled;
 };
 
 struct reginitdata {
@@ -319,7 +346,7 @@
 		dev_err(dev, "No reg property for DDRSS wrapper logic\n");
 		return -EINVAL;
 	}
-	ddrss->ddrss_ss_cfg = (void *)reg;
+	ddrss->ddrss_ctl_cfg = (void *)reg;
 
 	reg = dev_read_addr_name(dev, "ctrl_mmr_lp4");
 	if (reg == FDT_ADDR_T_NONE) {
@@ -328,6 +355,14 @@
 	}
 	ddrss->ddrss_ctrl_mmr = (void *)reg;
 
+	reg = dev_read_addr_name(dev, "ss_cfg");
+	if (reg == FDT_ADDR_T_NONE) {
+		dev_dbg(dev, "No reg property for SS Config region, but this is optional so continuing.\n");
+		ddrss->ddrss_ss_cfg = NULL;
+	} else {
+		ddrss->ddrss_ss_cfg = (void *)reg;
+	}
+
 	ret = power_domain_get_by_index(dev, &ddrss->ddrcfg_pwrdmn, 0);
 	if (ret) {
 		dev_err(dev, "power_domain_get() failed: %d\n", ret);
@@ -371,6 +406,8 @@
 	if (ret)
 		dev_err(dev, "ddr fhs cnt not populated %d\n", ret);
 
+	ddrss->ti_ecc_enabled = dev_read_bool(dev, "ti,ecc-enable");
+
 	return ret;
 }
 
@@ -403,7 +440,7 @@
 		hang();
 	}
 
-	config->ctlbase = (struct lpddr4_ctlregs_s *)ddrss->ddrss_ss_cfg;
+	config->ctlbase = (struct lpddr4_ctlregs_s *)ddrss->ddrss_ctl_cfg;
 	config->infohandler = (lpddr4_infocallback) k3_lpddr4_info_handler;
 
 	status = driverdt->init(pd, config);
@@ -512,6 +549,60 @@
 	}
 }
 
+static void k3_ddrss_set_ecc_range_r0(u32 base, u32 start_address, u32 size)
+{
+	writel((start_address) >> 16, base + DDRSS_ECC_R0_STR_ADDR_REG);
+	writel((start_address + size - 1) >> 16, base + DDRSS_ECC_R0_END_ADDR_REG);
+}
+
+static void k3_ddrss_preload_ecc_mem_region(u32 *addr, u32 size, u32 word)
+{
+	int i;
+
+	printf("ECC is enabled, priming DDR which will take several seconds.\n");
+
+	for (i = 0; i < (size / 4); i++)
+		addr[i] = word;
+}
+
+static void k3_ddrss_lpddr4_ecc_calc_reserved_mem(struct k3_ddrss_desc *ddrss)
+{
+	fdtdec_setup_mem_size_base_lowest();
+
+	ddrss->ecc_reserved_space = gd->ram_size;
+	do_div(ddrss->ecc_reserved_space, 9);
+
+	/* Round to clean number */
+	ddrss->ecc_reserved_space = 1ull << (fls(ddrss->ecc_reserved_space));
+}
+
+static void k3_ddrss_lpddr4_ecc_init(struct k3_ddrss_desc *ddrss)
+{
+	u32 ecc_region_start = ddrss->ecc_regions[0].start;
+	u32 ecc_range = ddrss->ecc_regions[0].range;
+	u32 base = (u32)ddrss->ddrss_ss_cfg;
+	u32 val;
+
+	/* Only Program region 0 which covers full ddr space */
+	k3_ddrss_set_ecc_range_r0(base, ecc_region_start - gd->ram_base, ecc_range);
+
+	/* Enable ECC, RMW, WR_ALLOC */
+	writel(DDRSS_ECC_CTRL_REG_ECC_EN | DDRSS_ECC_CTRL_REG_RMW_EN |
+	       DDRSS_ECC_CTRL_REG_WR_ALLOC, base + DDRSS_ECC_CTRL_REG);
+
+	/* Preload ECC Mem region with 0's */
+	k3_ddrss_preload_ecc_mem_region((u32 *)ecc_region_start, ecc_range,
+					0x00000000);
+
+	/* Clear Error Count Register */
+	writel(0x1, base + DDRSS_ECC_1B_ERR_CNT_REG);
+
+	/* Enable ECC Check */
+	val = readl(base + DDRSS_ECC_CTRL_REG);
+	val |= DDRSS_ECC_CTRL_REG_ECC_CK;
+	writel(val, base + DDRSS_ECC_CTRL_REG);
+}
+
 static int k3_ddrss_probe(struct udevice *dev)
 {
 	int ret;
@@ -546,9 +637,52 @@
 
 	k3_lpddr4_start(ddrss);
 
+	if (ddrss->ti_ecc_enabled) {
+		if (!ddrss->ddrss_ss_cfg) {
+			printf("%s: ss_cfg is required if ecc is enabled but not provided.",
+			       __func__);
+			return -EINVAL;
+		}
+
+		k3_ddrss_lpddr4_ecc_calc_reserved_mem(ddrss);
+
+		/* Always configure one region that covers full DDR space */
+		ddrss->ecc_regions[0].start = gd->ram_base;
+		ddrss->ecc_regions[0].range = gd->ram_size - ddrss->ecc_reserved_space;
+		k3_ddrss_lpddr4_ecc_init(ddrss);
+	}
+
 	return ret;
 }
 
+int k3_ddrss_ddr_fdt_fixup(struct udevice *dev, void *blob, struct bd_info *bd)
+{
+	struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
+	u64 start[CONFIG_NR_DRAM_BANKS];
+	u64 size[CONFIG_NR_DRAM_BANKS];
+	int bank;
+
+	if (ddrss->ecc_reserved_space == 0)
+		return 0;
+
+	for (bank = CONFIG_NR_DRAM_BANKS - 1; bank >= 0; bank--) {
+		if (ddrss->ecc_reserved_space > bd->bi_dram[bank].size) {
+			ddrss->ecc_reserved_space -= bd->bi_dram[bank].size;
+			bd->bi_dram[bank].size = 0;
+		} else {
+			bd->bi_dram[bank].size -= ddrss->ecc_reserved_space;
+			break;
+		}
+	}
+
+	for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
+		start[bank] =  bd->bi_dram[bank].start;
+		size[bank] = bd->bi_dram[bank].size;
+	}
+
+	return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
+}
+
 static int k3_ddrss_get_info(struct udevice *dev, struct ram_info *info)
 {
 	return 0;
diff --git a/include/configs/exynos78x0-common.h b/include/configs/exynos78x0-common.h
index 53396aa..457057c 100644
--- a/include/configs/exynos78x0-common.h
+++ b/include/configs/exynos78x0-common.h
@@ -35,6 +35,7 @@
 
 #define CONFIG_SYS_SDRAM_BASE		0x40000000
 #define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_TEXT_BASE + SZ_2M - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_BOOTM_LEN	SZ_32M
 /* DRAM Memory Banks */
 #define SDRAM_BANK_SIZE		(256UL << 20UL)	/* 256 MB */
 #define PHYS_SDRAM_1		CONFIG_SYS_SDRAM_BASE
@@ -79,7 +80,10 @@
 #define EXYNOS_FDTFILE_SETTING
 #endif
 
+/* Cannot use bootdelay > 0, because timer is not working */
 #define EXTRA_ENV_SETTINGS \
+	"bootdelay=0\0" \
+	"bootcmd=source $prevbl_initrd_start_addr:bootscript\0"	\
 	EXYNOS_DEVICE_SETTINGS \
 	EXYNOS_FDTFILE_SETTING \
 	MEM_LAYOUT_ENV_SETTINGS
diff --git a/include/configs/qemu-arm.h b/include/configs/qemu-arm.h
index 4f042e5..3ad1cf3 100644
--- a/include/configs/qemu-arm.h
+++ b/include/configs/qemu-arm.h
@@ -39,6 +39,12 @@
 # define BOOT_TARGET_VIRTIO(func)
 #endif
 
+#if CONFIG_IS_ENABLED(CMD_NVME)
+# define BOOT_TARGET_NVME(func) func(NVME, nvme, 0)
+#else
+# define BOOT_TARGET_NVME(func)
+#endif
+
 #if CONFIG_IS_ENABLED(CMD_DHCP)
 # define BOOT_TARGET_DHCP(func) func(DHCP, dhcp, na)
 #else
@@ -49,6 +55,7 @@
 	BOOT_TARGET_USB(func) \
 	BOOT_TARGET_SCSI(func) \
 	BOOT_TARGET_VIRTIO(func) \
+	BOOT_TARGET_NVME(func) \
 	BOOT_TARGET_DHCP(func)
 
 #include <config_distro_bootcmd.h>
diff --git a/include/configs/sdm845.h b/include/configs/sdm845.h
index af9ba19..ba57323 100644
--- a/include/configs/sdm845.h
+++ b/include/configs/sdm845.h
@@ -16,6 +16,14 @@
 /* Generic Timer Definitions */
 #define COUNTER_FREQUENCY	19000000
 
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"bootm_size=0x4000000\0"	\
+	"bootm_low=0x80000000\0"	\
+	"stdout=vidconsole\0"	\
+	"stderr=vidconsole\0"	\
+	"preboot=source $prevbl_initrd_start_addr:prebootscript\0" \
+	"bootcmd=source $prevbl_initrd_start_addr:bootscript\0"
+
 /* Size of malloc() pool */
 #define CONFIG_SYS_BOOTM_LEN	SZ_64M
 
diff --git a/include/init.h b/include/init.h
index 7449650..7b8f62c 100644
--- a/include/init.h
+++ b/include/init.h
@@ -155,6 +155,19 @@
  */
 int setup_bdinfo(void);
 
+#if defined(CONFIG_SAVE_PREV_BL_INITRAMFS_START_ADDR) || \
+defined(CONFIG_SAVE_PREV_BL_FDT_ADDR)
+/**
+ * save_prev_bl_data - Save prev bl data in env vars.
+ *
+ * When u-boot is chain-loaded, save previous bootloader data,
+ * like initramfs address to environment variables.
+ *
+ * Return: 0 if ok; -ENODATA on error
+ */
+int save_prev_bl_data(void);
+#endif
+
 /**
  * cpu_secondary_init_r() - CPU-specific secondary initialization
  *
diff --git a/include/k3-ddrss.h b/include/k3-ddrss.h
new file mode 100644
index 0000000..d7b3bf3
--- /dev/null
+++ b/include/k3-ddrss.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Texas Instruments' K3 DDRSS Driver
+ *
+ * Copyright (C) 2021-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#ifndef _K3_DDRSS_
+#define _K3_DDRSS_
+
+struct udevice;
+
+int k3_ddrss_ddr_fdt_fixup(struct udevice *dev, void *blob, struct bd_info *bd);
+
+#endif