Merge tag 'u-boot-imx-20201105' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx

u-boot-imx for 2021.1
---------------------

- new boards : GE (new B1x5v2), phytec phyCORE-i.MX8MM
- converted doc to reST
- fixes for verdin-imx8mm (Toradex)
- fixes for i.MX thermal driver
- mx7ulp: Align the PLL_USB frequency
- mx53: primary/secondary bmode

Travis: https://travis-ci.org/github/sbabic/u-boot-imx/builds/741465284
diff --git a/arch/Kconfig b/arch/Kconfig
index 683e384..3b9fcce 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -4,6 +4,9 @@
 config HAVE_ARCH_IOREMAP
 	bool
 
+config NEEDS_MANUAL_RELOC
+	bool
+
 choice
 	prompt "Architecture select"
 	default SANDBOX
@@ -26,12 +29,14 @@
 config M68K
 	bool "M68000 architecture"
 	select HAVE_PRIVATE_LIBGCC
+	select NEEDS_MANUAL_RELOC
 	select SYS_BOOT_GET_CMDLINE
 	select SYS_BOOT_GET_KBD
 	select SUPPORT_OF_CONTROL
 
 config MICROBLAZE
 	bool "MicroBlaze architecture"
+	select NEEDS_MANUAL_RELOC
 	select SUPPORT_OF_CONTROL
 	imply CMD_IRQ
 
diff --git a/arch/arm/dts/at91-vinco.dts b/arch/arm/dts/at91-vinco.dts
index 0ecb64e..bf17b0a 100644
--- a/arch/arm/dts/at91-vinco.dts
+++ b/arch/arm/dts/at91-vinco.dts
@@ -128,7 +128,7 @@
 			i2c2: i2c@f8024000 {
 				status = "okay";
 
-				rtc1: rtc@64 {
+				rtc1: rtc@32 {
 					compatible = "epson,rx8900";
 					reg = <0x32>;
 				};
diff --git a/arch/arm/dts/at91sam9260ek.dts b/arch/arm/dts/at91sam9260ek.dts
index 67a2660..47606cb 100644
--- a/arch/arm/dts/at91sam9260ek.dts
+++ b/arch/arm/dts/at91sam9260ek.dts
@@ -116,7 +116,7 @@
 
 			spi0: spi@fffc8000 {
 				cs-gpios = <0>, <&pioC 11 0>, <0>, <0>;
-				mtd_dataflash@0 {
+				mtd_dataflash@1 {
 					compatible = "atmel,at45", "atmel,dataflash";
 					spi-max-frequency = <15000000>;
 					reg = <1>;
diff --git a/arch/arm/dts/at91sam9261ek.dts b/arch/arm/dts/at91sam9261ek.dts
index 55bd51f..92fbdad 100644
--- a/arch/arm/dts/at91sam9261ek.dts
+++ b/arch/arm/dts/at91sam9261ek.dts
@@ -121,7 +121,7 @@
 					spi-max-frequency = <15000000>;
 				};
 
-				tsc2046@0 {
+				tsc2046@2 {
 					reg = <2>;
 					compatible = "ti,ads7843";
 					interrupts-extended = <&pioC 2 IRQ_TYPE_EDGE_BOTH>;
diff --git a/arch/arm/dts/at91sam9g20-taurus.dts b/arch/arm/dts/at91sam9g20-taurus.dts
index c00c5a8..ca982737 100644
--- a/arch/arm/dts/at91sam9g20-taurus.dts
+++ b/arch/arm/dts/at91sam9g20-taurus.dts
@@ -76,7 +76,7 @@
 
 &spi0 {
 	cs-gpios = <0>, <&pioC 11 0>, <0>, <0>;
-	mtd_dataflash@0 {
+	mtd_dataflash@1 {
 		compatible = "atmel,at45", "atmel,dataflash";
 		spi-max-frequency = <50000000>;
 		reg = <1>;
diff --git a/arch/arm/dts/at91sam9g20ek_common.dtsi b/arch/arm/dts/at91sam9g20ek_common.dtsi
index 9db245e..7195454 100644
--- a/arch/arm/dts/at91sam9g20ek_common.dtsi
+++ b/arch/arm/dts/at91sam9g20ek_common.dtsi
@@ -97,7 +97,7 @@
 
 			spi0: spi@fffc8000 {
 				cs-gpios = <0>, <&pioC 11 0>, <0>, <0>;
-				mtd_dataflash@0 {
+				mtd_dataflash@1 {
 					compatible = "atmel,at45", "atmel,dataflash";
 					spi-max-frequency = <15000000>;
 					reg = <1>;
diff --git a/arch/arm/dts/at91sam9g25ek.dts b/arch/arm/dts/at91sam9g25ek.dts
index 91a7177..31fecc2 100644
--- a/arch/arm/dts/at91sam9g25ek.dts
+++ b/arch/arm/dts/at91sam9g25ek.dts
@@ -25,7 +25,7 @@
 			};
 
 			i2c0: i2c@f8010000 {
-				ov2640: camera@0x30 {
+				ov2640: camera@30 {
 					compatible = "ovti,ov2640";
 					reg = <0x30>;
 					pinctrl-names = "default";
diff --git a/arch/arm/dts/at91sam9g45-gurnard.dts b/arch/arm/dts/at91sam9g45-gurnard.dts
index 75c1e99..2bc55f0 100644
--- a/arch/arm/dts/at91sam9g45-gurnard.dts
+++ b/arch/arm/dts/at91sam9g45-gurnard.dts
@@ -115,7 +115,7 @@
 
 			spi0: spi@fffa4000 {
 				cs-gpios = <0>, <&pioC 11 0>, <0>, <0>;
-				mtd_dataflash@0 {
+				mtd_dataflash@1 {
 					compatible = "atmel,at45", "atmel,dataflash";
 					spi-max-frequency = <50000000>;
 					reg = <1>;
diff --git a/arch/arm/dts/sama5d3xmb.dtsi b/arch/arm/dts/sama5d3xmb.dtsi
index c75b76a..906f3ce 100644
--- a/arch/arm/dts/sama5d3xmb.dtsi
+++ b/arch/arm/dts/sama5d3xmb.dtsi
@@ -61,7 +61,7 @@
 			};
 
 			i2c1: i2c@f0018000 {
-				ov2640: camera@0x30 {
+				ov2640: camera@30 {
 					compatible = "ovti,ov2640";
 					reg = <0x30>;
 					pinctrl-names = "default";
diff --git a/arch/arm/dts/sama5d3xmb_cmp.dtsi b/arch/arm/dts/sama5d3xmb_cmp.dtsi
index 5566fde..c6bf0f5 100644
--- a/arch/arm/dts/sama5d3xmb_cmp.dtsi
+++ b/arch/arm/dts/sama5d3xmb_cmp.dtsi
@@ -57,7 +57,7 @@
 			};
 
 			i2c1: i2c@f0018000 {
-				ov2640: camera@0x30 {
+				ov2640: camera@30 {
 					compatible = "ovti,ov2640";
 					reg = <0x30>;
 					pinctrl-names = "default";
diff --git a/arch/m68k/include/asm/config.h b/arch/m68k/include/asm/config.h
index c7363c0..7ea4436 100644
--- a/arch/m68k/include/asm/config.h
+++ b/arch/m68k/include/asm/config.h
@@ -6,8 +6,6 @@
 #ifndef _ASM_CONFIG_H_
 #define _ASM_CONFIG_H_
 
-#define CONFIG_NEEDS_MANUAL_RELOC
-
 #define CONFIG_LMB
 #define CONFIG_SYS_BOOT_RAMDISK_HIGH
 
diff --git a/arch/microblaze/include/asm/config.h b/arch/microblaze/include/asm/config.h
index 1124272..3ae71b3 100644
--- a/arch/microblaze/include/asm/config.h
+++ b/arch/microblaze/include/asm/config.h
@@ -8,10 +8,6 @@
 
 #define CONFIG_LMB
 
-#ifndef CONFIG_SPL_BUILD
-#define CONFIG_NEEDS_MANUAL_RELOC
-#endif
-
 #define CONFIG_SYS_BOOT_RAMDISK_HIGH
 
 #endif
diff --git a/common/Kconfig b/common/Kconfig
index 318d372..2bce8c9 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -599,9 +599,15 @@
 
 menu "Update support"
 
+config UPDATE_COMMON
+	bool
+	default n
+	select DFU_WRITE_ALT
+
 config UPDATE_TFTP
 	bool "Auto-update using fitImage via TFTP"
 	depends on FIT
+	select UPDATE_COMMON
 	help
 	  This option allows performing update of NOR with data in fitImage
 	  sent via TFTP boot.
@@ -616,6 +622,15 @@
 	default 100
 	depends on UPDATE_TFTP
 
+config UPDATE_FIT
+	bool "Firmware update using fitImage"
+	depends on FIT
+	depends on DFU
+	select UPDATE_COMMON
+	help
+	  This option allows performing update of DFU-capable storage with
+	  data in fitImage.
+
 config ANDROID_AB
 	bool "Android A/B updates"
 	default n
diff --git a/common/Makefile b/common/Makefile
index 2e7a090..bcf352d 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -53,8 +53,7 @@
 obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o
 obj-$(CONFIG_LYNXKDI) += lynxkdi.o
 obj-$(CONFIG_MENU) += menu.o
-obj-$(CONFIG_UPDATE_TFTP) += update.o
-obj-$(CONFIG_DFU_TFTP) += update.o
+obj-$(CONFIG_UPDATE_COMMON) += update.o
 obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
 obj-$(CONFIG_CMDLINE) += cli_readline.o cli_simple.o
 
diff --git a/common/board_r.c b/common/board_r.c
index 0829622..29dd7d2 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -73,6 +73,9 @@
 #if defined(CONFIG_GPIO_HOG)
 #include <asm/gpio.h>
 #endif
+#ifdef CONFIG_EFI_SETUP_EARLY
+#include <efi_loader.h>
+#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -889,6 +892,9 @@
 #if defined(CONFIG_PRAM)
 	initr_mem,
 #endif
+#ifdef CONFIG_EFI_SETUP_EARLY
+	(init_fnc_t)efi_init_obj_list,
+#endif
 	run_main_loop,
 };
 
diff --git a/common/update.c b/common/update.c
index 36b6b75..808be08 100644
--- a/common/update.c
+++ b/common/update.c
@@ -29,6 +29,7 @@
 #include <errno.h>
 #include <mtd/cfi_flash.h>
 
+#ifdef CONFIG_DFU_TFTP
 /* env variable holding the location of the update file */
 #define UPDATE_FILE_ENV		"updatefile"
 
@@ -98,6 +99,7 @@
 
 	return rv;
 }
+#endif /* CONFIG_DFU_TFTP */
 
 #ifdef CONFIG_MTD_NOR_FLASH
 static int update_flash_protect(int prot, ulong addr_first, ulong addr_last)
@@ -231,6 +233,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_DFU_TFTP
 int update_tftp(ulong addr, char *interface, char *devstring)
 {
 	char *filename, *env_addr, *fit_image_name;
@@ -324,8 +327,10 @@
 			}
 		} else if (fit_image_check_type(fit, noffset,
 						IH_TYPE_FIRMWARE)) {
-			ret = dfu_tftp_write(fit_image_name, update_addr,
-					     update_size, interface, devstring);
+			ret = dfu_write_by_name(fit_image_name,
+						(void *)update_addr,
+						update_size, interface,
+						devstring);
 			if (ret)
 				return ret;
 		}
@@ -335,3 +340,71 @@
 
 	return ret;
 }
+#endif /* CONFIG_DFU_UPDATE */
+
+#ifdef CONFIG_UPDATE_FIT
+/**
+ * fit_update - update storage with FIT image
+ * @fit:	Pointer to FIT image
+ *
+ * Update firmware on storage using FIT image as input.
+ * The storage area to be update will be identified by the name
+ * in FIT and matching it to "dfu_alt_info" variable.
+ *
+ * Return:      0 - on success, non-zero - otherwise
+ */
+int fit_update(const void *fit)
+{
+	char *fit_image_name;
+	ulong update_addr, update_fladdr, update_size;
+	int images_noffset, ndepth, noffset;
+	int ret = 0;
+
+	if (!fit)
+		return -EINVAL;
+
+	if (!fit_check_format((void *)fit)) {
+		printf("Bad FIT format of the update file, aborting auto-update\n");
+		return -EINVAL;
+	}
+
+	/* process updates */
+	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
+
+	ndepth = 0;
+	noffset = fdt_next_node(fit, images_noffset, &ndepth);
+	while (noffset >= 0 && ndepth > 0) {
+		if (ndepth != 1)
+			goto next_node;
+
+		fit_image_name = (char *)fit_get_name(fit, noffset, NULL);
+		printf("Processing update '%s' :", fit_image_name);
+
+		if (!fit_image_verify(fit, noffset)) {
+			printf("Error: invalid update hash, aborting\n");
+			ret = 1;
+			goto next_node;
+		}
+
+		printf("\n");
+		if (update_fit_getparams(fit, noffset, &update_addr,
+					 &update_fladdr, &update_size)) {
+			printf("Error: can't get update parameters, aborting\n");
+			ret = 1;
+			goto next_node;
+		}
+
+		if (fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE)) {
+			ret = dfu_write_by_name(fit_image_name,
+						(void *)update_addr,
+						update_size, NULL, NULL);
+			if (ret)
+				return ret;
+		}
+next_node:
+		noffset = fdt_next_node(fit, noffset, &ndepth);
+	}
+
+	return ret;
+}
+#endif /* CONFIG_UPDATE_FIT */
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig
index 0eec00b..b7427fc 100644
--- a/drivers/dfu/Kconfig
+++ b/drivers/dfu/Kconfig
@@ -14,9 +14,15 @@
 	depends on NET
 
 if DFU
+config DFU_WRITE_ALT
+	bool
+	default n
+
 config DFU_TFTP
 	bool "DFU via TFTP"
+	select DFU_WRITE_ALT
 	select DFU_OVER_TFTP
+	select UPDATE_COMMON
 	help
 	  This option allows performing update of DFU-managed medium with data
 	  sent via TFTP boot.
diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
index 0d7925c..dfbf64d 100644
--- a/drivers/dfu/Makefile
+++ b/drivers/dfu/Makefile
@@ -9,5 +9,5 @@
 obj-$(CONFIG_$(SPL_)DFU_NAND) += dfu_nand.o
 obj-$(CONFIG_$(SPL_)DFU_RAM) += dfu_ram.o
 obj-$(CONFIG_$(SPL_)DFU_SF) += dfu_sf.o
-obj-$(CONFIG_$(SPL_)DFU_TFTP) += dfu_tftp.o
+obj-$(CONFIG_$(SPL_)DFU_WRITE_ALT) += dfu_alt.o
 obj-$(CONFIG_$(SPL_)DFU_VIRT) += dfu_virt.o
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index a298c2c..501a60b 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -18,7 +18,7 @@
 #include <linux/list.h>
 #include <linux/compiler.h>
 
-static LIST_HEAD(dfu_list);
+LIST_HEAD(dfu_list);
 static int dfu_alt_num;
 static int alt_num_cnt;
 static struct hash_algo *dfu_hash_algo;
diff --git a/drivers/dfu/dfu_alt.c b/drivers/dfu/dfu_alt.c
new file mode 100644
index 0000000..ece3d22
--- /dev/null
+++ b/drivers/dfu/dfu_alt.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2015
+ * Lukasz Majewski <l.majewski@majess.pl>
+ */
+
+#include <common.h>
+#include <log.h>
+#include <malloc.h>
+#include <errno.h>
+#include <dfu.h>
+
+/**
+ * dfu_write_by_name() - write data to DFU medium
+ * @dfu_entity_name:    Name of DFU entity to write
+ * @addr:               Address of data buffer to write
+ * @len:                Number of bytes
+ * @interface:          Destination DFU medium (e.g. "mmc")
+ * @devstring:          Instance number of destination DFU medium (e.g. "1")
+ *
+ * This function is storing data received on DFU supported medium which
+ * is specified by @dfu_entity_name.
+ *
+ * Return:              0 - on success, error code - otherwise
+ */
+int dfu_write_by_name(char *dfu_entity_name, void *addr,
+		      unsigned int len, char *interface, char *devstring)
+{
+	char *s, *sb;
+	int alt_setting_num, ret;
+	struct dfu_entity *dfu;
+
+	debug("%s: name: %s addr: 0x%p len: %d device: %s:%s\n", __func__,
+	      dfu_entity_name, addr, len, interface, devstring);
+
+	ret = dfu_init_env_entities(interface, devstring);
+	if (ret)
+		goto done;
+
+	/*
+	 * We need to copy name pointed by *dfu_entity_name since this text
+	 * is the integral part of the FDT image.
+	 * Any implicit modification (i.e. done by strsep()) will corrupt
+	 * the FDT image and prevent other images to be stored.
+	 */
+	s = strdup(dfu_entity_name);
+	sb = s;
+	if (!s) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	strsep(&s, "@");
+	debug("%s: image name: %s strlen: %zd\n", __func__, sb, strlen(sb));
+
+	alt_setting_num = dfu_get_alt(sb);
+	free(sb);
+	if (alt_setting_num < 0) {
+		pr_err("Alt setting [%d] to write not found!",
+		       alt_setting_num);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	dfu = dfu_get_entity(alt_setting_num);
+	if (!dfu) {
+		pr_err("DFU entity for alt: %d not found!", alt_setting_num);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	ret = dfu_write_from_mem_addr(dfu, (void *)addr, len);
+
+done:
+	dfu_free_entities();
+
+	return ret;
+}
+
+/**
+ * dfu_write_by_alt() - write data to DFU medium
+ * @dfu_alt_num:        DFU alt setting number
+ * @addr:               Address of data buffer to write
+ * @len:                Number of bytes
+ * @interface:          Destination DFU medium (e.g. "mmc")
+ * @devstring:          Instance number of destination DFU medium (e.g. "1")
+ *
+ * This function is storing data received on DFU supported medium which
+ * is specified by @dfu_alt_name.
+ *
+ * Return:              0 - on success, error code - otherwise
+ */
+int dfu_write_by_alt(int dfu_alt_num, void *addr, unsigned int len,
+		     char *interface, char *devstring)
+{
+	struct dfu_entity *dfu;
+	int ret;
+
+	debug("%s: alt: %d addr: 0x%p len: %d device: %s:%s\n", __func__,
+	      dfu_alt_num, addr, len, interface, devstring);
+
+	ret = dfu_init_env_entities(interface, devstring);
+	if (ret)
+		goto done;
+
+	if (dfu_alt_num < 0) {
+		pr_err("Invalid alt number: %d", dfu_alt_num);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	dfu = dfu_get_entity(dfu_alt_num);
+	if (!dfu) {
+		pr_err("DFU entity for alt: %d not found!", dfu_alt_num);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	ret = dfu_write_from_mem_addr(dfu, (void *)(uintptr_t)addr, len);
+
+done:
+	dfu_free_entities();
+
+	return ret;
+}
diff --git a/drivers/dfu/dfu_tftp.c b/drivers/dfu/dfu_tftp.c
deleted file mode 100644
index ffae4bb..0000000
--- a/drivers/dfu/dfu_tftp.c
+++ /dev/null
@@ -1,65 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2015
- * Lukasz Majewski <l.majewski@majess.pl>
- */
-
-#include <common.h>
-#include <log.h>
-#include <malloc.h>
-#include <errno.h>
-#include <dfu.h>
-
-int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, unsigned int len,
-		   char *interface, char *devstring)
-{
-	char *s, *sb;
-	int alt_setting_num, ret;
-	struct dfu_entity *dfu;
-
-	debug("%s: name: %s addr: 0x%x len: %d device: %s:%s\n", __func__,
-	      dfu_entity_name, addr, len, interface, devstring);
-
-	ret = dfu_init_env_entities(interface, devstring);
-	if (ret)
-		goto done;
-
-	/*
-	 * We need to copy name pointed by *dfu_entity_name since this text
-	 * is the integral part of the FDT image.
-	 * Any implicit modification (i.e. done by strsep()) will corrupt
-	 * the FDT image and prevent other images to be stored.
-	 */
-	s = strdup(dfu_entity_name);
-	sb = s;
-	if (!s) {
-		ret = -ENOMEM;
-		goto done;
-	}
-
-	strsep(&s, "@");
-	debug("%s: image name: %s strlen: %zd\n", __func__, sb, strlen(sb));
-
-	alt_setting_num = dfu_get_alt(sb);
-	free(sb);
-	if (alt_setting_num < 0) {
-		pr_err("Alt setting [%d] to write not found!",
-		      alt_setting_num);
-		ret = -ENODEV;
-		goto done;
-	}
-
-	dfu = dfu_get_entity(alt_setting_num);
-	if (!dfu) {
-		pr_err("DFU entity for alt: %d not found!", alt_setting_num);
-		ret = -ENODEV;
-		goto done;
-	}
-
-	ret = dfu_write_from_mem_addr(dfu, (void *)(uintptr_t)addr, len);
-
-done:
-	dfu_free_entities();
-
-	return ret;
-}
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index d06d272..cad667a 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -68,11 +68,14 @@
 	depends on DM_RTC
 	help
 	  On a board without hardware clock this software real time clock can be
-	  used. The build time is used to initialize the RTC. So you will have
-	  to adjust the time either manually using the 'date' command  or use
-	  the 'sntp' to update the RTC with the time from a network time server.
-	  See CONFIG_CMD_SNTP and CONFIG_BOOTP_NTPSERVER. The RTC time is
-	  advanced according to CPU ticks.
+	  used. The initial time may be provided via the environment variable
+	  'rtc_emul_epoch' as a decimal string indicating seconds since
+	  1970-01-01. If the environment variable is missing, the build time is
+	  used to initialize the RTC. The time can be adjusted manually via the
+	  'date' command or the 'sntp' command can be used to update the RTC
+	  with the time from a network time server. See CONFIG_CMD_SNTP and
+	  CONFIG_BOOTP_NTPSERVER. The RTC time is advanced according to CPU
+	  ticks.
 
 config RTC_ISL1208
 	bool "Enable ISL1208 driver"
diff --git a/drivers/rtc/emul_rtc.c b/drivers/rtc/emul_rtc.c
index c98c24b..7e52210 100644
--- a/drivers/rtc/emul_rtc.c
+++ b/drivers/rtc/emul_rtc.c
@@ -8,6 +8,7 @@
 #include <common.h>
 #include <div64.h>
 #include <dm.h>
+#include <env.h>
 #include <generated/timestamp_autogenerated.h>
 #include <rtc.h>
 
@@ -30,12 +31,6 @@
 	struct emul_rtc *priv = dev_get_priv(dev);
 	u64 now;
 
-	if (!priv->offset_us) {
-		/* Use the build date as initial time */
-		priv->offset_us = U_BOOT_EPOCH * 1000000ULL - timer_get_us();
-		priv->isdst = -1;
-	}
-
 	now = timer_get_us() + priv->offset_us;
 	do_div(now, 1000000);
 	rtc_to_tm(now, time);
@@ -63,6 +58,26 @@
 	return 0;
 }
 
+int emul_rtc_probe(struct udevice *dev)
+{
+	struct emul_rtc *priv = dev_get_priv(dev);
+	const char *epoch_str;
+	u64 epoch;
+
+	epoch_str = env_get("rtc_emul_epoch");
+
+	if (epoch_str) {
+		epoch = simple_strtoull(epoch_str, NULL, 10);
+	} else {
+		/* Use the build date as initial time */
+		epoch = U_BOOT_EPOCH;
+	}
+	priv->offset_us = epoch * 1000000ULL - timer_get_us();
+	priv->isdst = -1;
+
+	return 0;
+}
+
 static const struct rtc_ops emul_rtc_ops = {
 	.get = emul_rtc_get,
 	.set = emul_rtc_set,
@@ -72,6 +87,7 @@
 	.name	= "rtc_emul",
 	.id	= UCLASS_RTC,
 	.ops	= &emul_rtc_ops,
+	.probe	= emul_rtc_probe,
 	.priv_auto_alloc_size = sizeof(struct emul_rtc),
 };
 
diff --git a/env/env.c b/env/env.c
index 42c7d81..37b4b54 100644
--- a/env/env.c
+++ b/env/env.c
@@ -329,6 +329,8 @@
 	for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) {
 		if (!drv->init || !(ret = drv->init()))
 			env_set_inited(drv->location);
+		if (ret == -ENOENT)
+			env_set_inited(drv->location);
 
 		debug("%s: Environment %s init done (ret=%d)\n", __func__,
 		      drv->name, ret);
diff --git a/env/sf.c b/env/sf.c
index 2eb2de1..91ed286 100644
--- a/env/sf.c
+++ b/env/sf.c
@@ -393,10 +393,12 @@
 	return env_sf_init_early();
 #endif
 	/*
-	 * we must return with 0 if there is nothing done,
-	 * else env_set_inited() get not called in env_init()
+	 * return here -ENOENT, so env_init()
+	 * can set the init bit and later if no
+	 * other Environment storage is defined
+	 * can set the default environment
 	 */
-	return 0;
+	return -ENOENT;
 }
 
 U_BOOT_ENV_LOCATION(sf) = {
diff --git a/include/charset.h b/include/charset.h
index 5564f3b..cc650a2 100644
--- a/include/charset.h
+++ b/include/charset.h
@@ -219,7 +219,7 @@
 size_t u16_strsize(const void *in);
 
 /**
- * u16_strlen - count non-zero words
+ * u16_strnlen() - count non-zero words
  *
  * This function matches wscnlen_s() if the -fshort-wchar compiler flag is set.
  * In the EFI context we explicitly need a function handling u16 strings.
diff --git a/include/dfu.h b/include/dfu.h
index 84abdc7..a767ade 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -158,6 +158,9 @@
 	unsigned int inited:1;
 };
 
+struct list_head;
+extern struct list_head dfu_list;
+
 #ifdef CONFIG_SET_DFU_ALT_INFO
 /**
  * set_dfu_alt_info() - set dfu_alt_info environment variable
@@ -493,28 +496,52 @@
 }
 #endif
 
+#if CONFIG_IS_ENABLED(DFU_WRITE_ALT)
 /**
- * dfu_tftp_write() - write TFTP data to DFU medium
+ * dfu_write_by_name() - write data to DFU medium
+ * @dfu_entity_name:	Name of DFU entity to write
+ * @addr:		Address of data buffer to write
+ * @len:		Number of bytes
+ * @interface:		Destination DFU medium (e.g. "mmc")
+ * @devstring:		Instance number of destination DFU medium (e.g. "1")
+ *
+ * This function is storing data received on DFU supported medium which
+ * is specified by @dfu_entity_name.
  *
- * This function is storing data received via TFTP on DFU supported medium.
+ * Return:		0 - on success, error code - otherwise
+ */
+int dfu_write_by_name(char *dfu_entity_name, void *addr,
+		      unsigned int len, char *interface, char *devstring);
+
+/**
+ * dfu_write_by_alt() - write data to DFU medium
+ * @dfu_alt_num:	DFU alt setting number
+ * @addr:		Address of data buffer to write
+ * @len:		Number of bytes
+ * @interface:		Destination DFU medium (e.g. "mmc")
+ * @devstring:		Instance number of destination DFU medium (e.g. "1")
  *
- * @dfu_entity_name:	name of DFU entity to write
- * @addr:		address of data buffer to write
- * @len:		number of bytes
- * @interface:		destination DFU medium (e.g. "mmc")
- * @devstring:		instance number of destination DFU medium (e.g. "1")
+ * This function is storing data received on DFU supported medium which
+ * is specified by @dfu_alt_name.
  *
- * Return:		0 on success, otherwise error code
+ * Return:		0 - on success, error code - otherwise
  */
-#if CONFIG_IS_ENABLED(DFU_TFTP)
-int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, unsigned int len,
-		   char *interface, char *devstring);
+int dfu_write_by_alt(int dfu_alt_num, void *addr, unsigned int len,
+		     char *interface, char *devstring);
 #else
-static inline int dfu_tftp_write(char *dfu_entity_name, unsigned int addr,
-				 unsigned int len, char *interface,
-				 char *devstring)
+static inline int dfu_write_by_name(char *dfu_entity_name, void *addr,
+				    unsigned int len, char *interface,
+				    char *devstring)
+{
+	puts("write support for DFU not available!\n");
+	return -ENOSYS;
+}
+
+static inline int dfu_write_by_alt(int dfu_alt_num, void *addr,
+				   unsigned int len, char *interface,
+				   char *devstring)
 {
-	puts("TFTP write support for DFU not available!\n");
+	puts("write support for DFU not available!\n");
 	return -ENOSYS;
 }
 #endif
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 7eea556..f550ced 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -804,6 +804,9 @@
 /* runtime implementation of memcpy() */
 void efi_memcpy_runtime(void *dest, const void *src, size_t n);
 
+/* commonly used helper function */
+u16 *efi_create_indexed_name(u16 *buffer, const char *name, unsigned int index);
+
 #else /* CONFIG_IS_ENABLED(EFI_LOADER) */
 
 /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
diff --git a/include/image.h b/include/image.h
index 4094ee5..00bc03b 100644
--- a/include/image.h
+++ b/include/image.h
@@ -1602,4 +1602,16 @@
 		.handler = _handler, \
 	}
 
+/**
+ * fit_update - update storage with FIT image
+ * @fit:        Pointer to FIT image
+ *
+ * Update firmware on storage using FIT image as input.
+ * The storage area to be update will be identified by the name
+ * in FIT and matching it to "dfu_alt_info" variable.
+ *
+ * Return:      0 on success, non-zero otherwise
+ */
+int fit_update(const void *fit);
+
 #endif	/* __IMAGE_H__ */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index ab42f3b..0754814 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -27,6 +27,10 @@
 
 if EFI_LOADER
 
+config EFI_SETUP_EARLY
+	bool
+	default n
+
 choice
 	prompt "Store for non-volatile UEFI variables"
 	default EFI_VARIABLE_FILE_STORE
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 9bad1d1..8892fb0 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -34,6 +34,7 @@
 obj-y += efi_root_node.o
 obj-y += efi_runtime.o
 obj-y += efi_setup.o
+obj-y += efi_string.o
 obj-$(CONFIG_EFI_UNICODE_COLLATION_PROTOCOL2) += efi_unicode_collation.o
 obj-y += efi_var_common.o
 obj-y += efi_var_mem.o
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index b26ac9f..dfa71b1 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -3523,6 +3523,7 @@
 	size_t number_of_children = 0;
 	efi_status_t r;
 	struct efi_object *efiobj;
+	bool sole_child;
 
 	EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle,
 		  child_handle);
@@ -3545,16 +3546,18 @@
 	}
 
 	/* Create list of child handles */
+	r = efi_get_child_controllers(efiobj,
+				      driver_image_handle,
+				      &number_of_children,
+				      &child_handle_buffer);
+	if (r != EFI_SUCCESS)
+		return r;
+	sole_child = (number_of_children == 1);
+
 	if (child_handle) {
 		number_of_children = 1;
+		free(child_handle_buffer);
 		child_handle_buffer = &child_handle;
-	} else {
-		r = efi_get_child_controllers(efiobj,
-					      driver_image_handle,
-					      &number_of_children,
-					      &child_handle_buffer);
-		if (r != EFI_SUCCESS)
-			return r;
 	}
 
 	/* Get the driver binding protocol */
@@ -3579,7 +3582,7 @@
 		}
 	}
 	/* Remove the driver */
-	if (!child_handle) {
+	if (!child_handle || sole_child) {
 		r = EFI_CALL(binding_protocol->stop(binding_protocol,
 						    controller_handle,
 						    0, NULL));
diff --git a/lib/efi_loader/efi_string.c b/lib/efi_loader/efi_string.c
new file mode 100644
index 0000000..3de721f
--- /dev/null
+++ b/lib/efi_loader/efi_string.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * String functions
+ *
+ * Copyright (c) 2020 AKASHI Takahiro, Linaro Limited
+ */
+
+#include <common.h>
+#include <charset.h>
+
+/**
+ * efi_create_indexed_name - create a string name with an index
+ * @buffer:	Buffer
+ * @name:	Name string
+ * @index:	Index
+ *
+ * Create a utf-16 string with @name, appending @index.
+ * For example, L"Capsule0001"
+ *
+ * The caller must ensure that the buffer has enough space for the resulting
+ * string including the trailing L'\0'.
+ *
+ * Return: A pointer to the next position after the created string
+ *	   in @buffer, or NULL otherwise
+ */
+u16 *efi_create_indexed_name(u16 *buffer, const char *name, unsigned int index)
+{
+	u16 *p = buffer;
+	char index_buf[5];
+
+	utf8_utf16_strcpy(&p, name);
+	sprintf(index_buf, "%04X", index);
+	utf8_utf16_strcpy(&p, index_buf);
+
+	return p;
+}
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index a950844..0aabe7a 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -1154,7 +1154,6 @@
 CONFIG_NCEMIC100_BASE
 CONFIG_NDS_DLM1_BASE
 CONFIG_NDS_DLM2_BASE
-CONFIG_NEEDS_MANUAL_RELOC
 CONFIG_NEO
 CONFIG_NET2BIG_V2
 CONFIG_NETCONSOLE_BUFFER_SIZE
diff --git a/test/unicode_ut.c b/test/unicode_ut.c
index 26d9633..33fc8b0 100644
--- a/test/unicode_ut.c
+++ b/test/unicode_ut.c
@@ -8,6 +8,7 @@
 #include <common.h>
 #include <charset.h>
 #include <command.h>
+#include <efi_loader.h>
 #include <errno.h>
 #include <log.h>
 #include <malloc.h>
@@ -594,6 +595,24 @@
 }
 UNICODE_TEST(unicode_test_u16_strsize);
 
+#ifdef CONFIG_EFI_LOADER
+static int unicode_test_efi_create_indexed_name(struct unit_test_state *uts)
+{
+	u16 buf[16];
+	u16 const expected[] = L"Capsule0AF9";
+	u16 *pos;
+
+	memset(buf, 0xeb, sizeof(buf));
+	pos = efi_create_indexed_name(buf, "Capsule", 0x0af9);
+
+	ut_asserteq_mem(expected, buf, sizeof(expected));
+	ut_asserteq(pos - buf, u16_strnlen(buf, SIZE_MAX));
+
+	return 0;
+}
+UNICODE_TEST(unicode_test_efi_create_indexed_name);
+#endif
+
 int do_ut_unicode(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
 	struct unit_test *tests = ll_entry_start(struct unit_test, unicode_test);