Merge patch series "FIX: Re-enable MUX_MMIO on J721E/J7200"

Siddharth Vadapalli <s-vadapalli@ti.com> says:

Hello,

This series re-enables MUX_MMIO at U-Boot proper on J721E and J7200
SoCs. The commits which introduced support for Hyperflash boot on both
of these SoCs disabled MUX_MMIO functionality at U-Boot proper, thereby
introducing a regression.

Series is based on commit
2b1c8d3b2d cmd: Fix Kconfig coding style
of the master branch of U-Boot.

Link: https://lore.kernel.org/r/20250201091809.1894892-1-s-vadapalli@ti.com
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index db471e6..bd197cd 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -89,6 +89,7 @@
       options: $(container_option)
     steps:
       - script: |
+          set -e
           virtualenv -p /usr/bin/python3 /tmp/venvhtml
           . /tmp/venvhtml/bin/activate
           pip install -r doc/sphinx/requirements.txt
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a93703f..8f386a8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -105,6 +105,7 @@
     paths:
       - "*.html"
       - "*.css"
+      - results.xml
     reports:
       junit: results.xml
     expire_in: 1 week
@@ -230,31 +231,47 @@
 
 # Test sandbox with test.py
 sandbox test.py:
+  parallel:
+    matrix:
+      - HOST: "fast arm64"
+      - HOST: "fast amd64"
   tags:
-    - ${DEFAULT_AMD64_TAG}
+    - ${HOST}
   variables:
     TEST_PY_BD: "sandbox"
     TEST_PY_EXTRA: "--timing"
   <<: *buildman_and_testpy_dfn
 
 sandbox with clang test.py:
+  parallel:
+    matrix:
+      - HOST: "fast arm64"
+      - HOST: "fast amd64"
   tags:
-    - ${DEFAULT_AMD64_TAG}
+    - ${HOST}
   variables:
     TEST_PY_BD: "sandbox"
     OVERRIDE: "-O clang-17"
   <<: *buildman_and_testpy_dfn
 
 sandbox64 test.py:
+  parallel:
+    matrix:
+      - HOST: "fast arm64"
+      - HOST: "fast amd64"
   tags:
-    - ${DEFAULT_AMD64_TAG}
+    - ${HOST}
   variables:
     TEST_PY_BD: "sandbox64"
   <<: *buildman_and_testpy_dfn
 
 sandbox64 with clang test.py:
+  parallel:
+    matrix:
+      - HOST: "fast arm64"
+      - HOST: "fast amd64"
   tags:
-    - ${DEFAULT_AMD64_TAG}
+    - ${HOST}
   variables:
     TEST_PY_BD: "sandbox64"
     OVERRIDE: "-O clang-17"
diff --git a/MAINTAINERS b/MAINTAINERS
index 247f525..10f7f1f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1806,6 +1806,13 @@
 S:	Maintained
 F:	test/lib/uuid.c
 
+VBE
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	boot/vbe*
+F:	common/spl_reloc.c
+F:	include/vbe.h
+
 VIDEO
 M:	Anatolij Gustschin <agust@denx.de>
 S:	Maintained
diff --git a/api/Kconfig b/api/Kconfig
index b5a7399..8cfd98a 100644
--- a/api/Kconfig
+++ b/api/Kconfig
@@ -19,24 +19,4 @@
 	  U-Boot provides an API for standalone applications. Examples are
 	  provided in directory examples/.
 
-config STANDALONE_LOAD_ADDR
-	depends on EXAMPLES
-	hex "Address in memory to link standalone applications to"
-	default 0xffffffff80200000 if MIPS && 64BIT
-	default 0x8c000000 if SH
-	default 0x82000000 if ARC
-	default 0x80f00000 if MICROBLAZE
-	default 0x80300000 if ARCH_OMAP2PLUS || FSL_LSCH2 || FSL_LSCH3
-	default 0x80200000 if MIPS && 32BIT
-	default 0x0c100000 if ARM
-	default 0x02000000 if NIOS2
-	default 0x00040000 if PPC || X86
-	default 0x00020000 if M68K
-	default 0x0 if RISCV
-	default SYS_LOAD_ADDR
-	help
-	  This option defines a board specific value for the address where
-	  standalone program gets loaded, thus overwriting the architecture
-	  dependent default settings.
-
 endmenu
diff --git a/api/api_platform.c b/api/api_platform.c
index 7a789bd..d5cbcd6 100644
--- a/api/api_platform.c
+++ b/api/api_platform.c
@@ -17,9 +17,15 @@
 {
 	int i;
 
+	si->clk_bus = gd->bus_clk;
+	si->clk_cpu = gd->cpu_clk;
+
 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
 		platform_set_mr(si, gd->bd->bi_dram[i].start,
 				gd->bd->bi_dram[i].size, MR_ATTR_DRAM);
 
+	platform_set_mr(si, gd->ram_base, gd->ram_size, MR_ATTR_DRAM);
+	platform_set_mr(si, gd->bd->bi_flashstart, gd->bd->bi_flashsize, MR_ATTR_FLASH);
+
 	return 1;
 }
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index f504d7d..da6f117 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -108,6 +108,9 @@
 	  The value subtracted from CONFIG_TEXT_BASE to calculate the
 	  TEXT_OFFSET value written to the Linux kernel image header.
 
+config NVIC
+	bool
+
 config GICV2
 	bool
 
@@ -117,6 +120,7 @@
 config DRIVER_GICV2
 	bool "ARM GICV2 driver"
 	select IRQ
+	depends on !NVIC
 	help
 	  ARM GICV2 driver.
 	  Basic support for parsing the GICV2 node and generate ACPI tables.
@@ -124,6 +128,7 @@
 config GIC_V3_ITS
 	bool "ARM GICV3 ITS"
 	select IRQ
+	depends on !NVIC
 	help
 	  ARM GICV3 Interrupt translation service (ITS).
 	  Basic support for programming locality specific peripheral
@@ -134,6 +139,7 @@
 
 config GICV3_SUPPORT_GIC600
 	bool "ARM GICV3 GIC600 SUPPORT"
+	depends on !NVIC
 	help
 	  ARM GIC-600 IP complies with ARM GICv3 architecture, but among others,
 	  implements a power control register in the Redistributor frame.This
@@ -193,6 +199,7 @@
 
 config SYS_ARM_CACHE_CP15
 	bool "CP15 based cache enabling support"
+	depends on !CPU_V7M
 	help
 	  Select this if your processor suports enabling caches by using
 	  CP15 registers.
@@ -200,6 +207,7 @@
 config SYS_ARM_MMU
 	bool "MMU-based Paged Memory Management Support"
 	select SYS_ARM_CACHE_CP15
+	depends on !CPU_V7M
 	help
 	  Select if you want MMU-based virtualised addressing space
 	  support via paged memory management.
@@ -350,6 +358,7 @@
 	select SYS_CACHE_SHIFT_5
 	select SYS_THUMB_BUILD
 	select THUMB2_KERNEL
+	select NVIC
 
 config CPU_V7R
 	bool
@@ -2193,6 +2202,7 @@
 config STATIC_MACH_TYPE
 	bool "Statically define the Machine ID number"
 	default y if TARGET_DS109 || TARGET_DS414 || DEFAULT_DEVICE_TREE = "sun7i-a20-icnova-swac"
+	depends on SUPPORT_PASSING_ATAGS
 	help
 	  When booting via ATAGs, enable this option if we know the correct
 	  machine ID number to use at compile time.  Some systems will be
diff --git a/arch/arm/dts/k3-am642-phyboard-electra-rdk-u-boot.dtsi b/arch/arm/dts/k3-am642-phyboard-electra-rdk-u-boot.dtsi
index 8f3c3a1..c68a486 100644
--- a/arch/arm/dts/k3-am642-phyboard-electra-rdk-u-boot.dtsi
+++ b/arch/arm/dts/k3-am642-phyboard-electra-rdk-u-boot.dtsi
@@ -72,6 +72,14 @@
 	bootph-all;
 };
 
+&main_i2c0 {
+	bootph-all;
+};
+
+&main_i2c0_pins_default {
+	bootph-all;
+};
+
 &main_mmc1_pins_default {
 	bootph-all;
 };
diff --git a/arch/arm/dts/mt7981-emmc-rfb.dts b/arch/arm/dts/mt7981-emmc-rfb.dts
index d6590f0..ebfcee5 100644
--- a/arch/arm/dts/mt7981-emmc-rfb.dts
+++ b/arch/arm/dts/mt7981-emmc-rfb.dts
@@ -47,8 +47,8 @@
 	status = "okay";
 	mediatek,gmac-id = <0>;
 	phy-mode = "2500base-x";
-	mediatek,switch = "mt7531";
-	reset-gpios = <&gpio 39 GPIO_ACTIVE_HIGH>;
+	mediatek,switch = "auto";
+	reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>;
 
 	fixed-link {
 		speed = <2500>;
@@ -56,7 +56,7 @@
 	};
 };
 
-&pinctrl {
+&pio {
 	spic_pins: spi1-pins-func-1 {
 		mux {
 			function = "spi";
diff --git a/arch/arm/dts/mt7981-rfb.dts b/arch/arm/dts/mt7981-rfb.dts
index d6ebd65..17e6b5a 100644
--- a/arch/arm/dts/mt7981-rfb.dts
+++ b/arch/arm/dts/mt7981-rfb.dts
@@ -38,8 +38,8 @@
 	status = "okay";
 	mediatek,gmac-id = <0>;
 	phy-mode = "2500base-x";
-	mediatek,switch = "mt7531";
-	reset-gpios = <&gpio 39 GPIO_ACTIVE_HIGH>;
+	mediatek,switch = "auto";
+	reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>;
 
 	fixed-link {
 		speed = <2500>;
@@ -47,7 +47,7 @@
 	};
 };
 
-&pinctrl {
+&pio {
 	spi_flash_pins: spi0-pins-func-1 {
 		mux {
 			function = "flash";
diff --git a/arch/arm/dts/mt7981-sd-rfb.dts b/arch/arm/dts/mt7981-sd-rfb.dts
index 2adbc37..6721246 100644
--- a/arch/arm/dts/mt7981-sd-rfb.dts
+++ b/arch/arm/dts/mt7981-sd-rfb.dts
@@ -47,8 +47,8 @@
 	status = "okay";
 	mediatek,gmac-id = <0>;
 	phy-mode = "2500base-x";
-	mediatek,switch = "mt7531";
-	reset-gpios = <&gpio 39 GPIO_ACTIVE_HIGH>;
+	mediatek,switch = "auto";
+	reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>;
 
 	fixed-link {
 		speed = <2500>;
@@ -56,7 +56,7 @@
 	};
 };
 
-&pinctrl {
+&pio {
 	spic_pins: spi1-pins-func-1 {
 		mux {
 			function = "spi";
diff --git a/arch/arm/dts/mt7981.dtsi b/arch/arm/dts/mt7981.dtsi
index 2844ab0..5b4cadc 100644
--- a/arch/arm/dts/mt7981.dtsi
+++ b/arch/arm/dts/mt7981.dtsi
@@ -6,6 +6,7 @@
 
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/phy/phy.h>
 #include <dt-bindings/clock/mt7981-clk.h>
 #include <dt-bindings/reset/mt7629-reset.h>
 #include <dt-bindings/pinctrl/mt65xx.h>
@@ -106,7 +107,7 @@
 		bootph-all;
 	};
 
-	pinctrl: pinctrl@11d00000 {
+	pio: pinctrl@11d00000 {
 		compatible = "mediatek,mt7981-pinctrl";
 		reg = <0x11d00000 0x1000>,
 		      <0x11c00000 0x1000>,
@@ -117,13 +118,11 @@
 		      <0x11f00000 0x1000>,
 		      <0x11f10000 0x1000>,
 		      <0x1000b000 0x1000>;
-		reg-names = "gpio_base", "iocfg_rt_base", "iocfg_rm_base",
-			    "iocfg_rb_base", "iocfg_lb_base", "iocfg_bl_base",
-			    "iocfg_tm_base", "iocfg_tl_base", "eint";
-		gpio: gpio-controller {
-			gpio-controller;
-			#gpio-cells = <2>;
-		};
+		reg-names = "gpio", "iocfg_rt", "iocfg_rm",
+			    "iocfg_rb", "iocfg_lb", "iocfg_bl",
+			    "iocfg_tm", "iocfg_tl", "eint";
+		gpio-controller;
+		#gpio-cells = <2>;
 	};
 
 	pwm: pwm@10048000 {
@@ -317,4 +316,86 @@
 		status = "disabled";
 	};
 
+	xhci: xhci@11200000 {
+		compatible = "mediatek,mt7981-xhci",
+			     "mediatek,mtk-xhci";
+		reg = <0x11200000 0x2e00>,
+		      <0x11203e00 0x0100>;
+		reg-names = "mac", "ippc";
+		interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+		phys = <&u2port0 PHY_TYPE_USB2>,
+		       <&u3port0 PHY_TYPE_USB3>;
+		clocks = <&infracfg CLK_INFRA_IUSB_SYS_CK>,
+			 <&infracfg CLK_INFRA_IUSB_CK>,
+			 <&infracfg CLK_INFRA_IUSB_133_CK>,
+			 <&infracfg CLK_INFRA_IUSB_66M_CK>,
+			 <&topckgen CLK_TOP_U2U3_XHCI_SEL>;
+		clock-names = "sys_ck",
+			      "ref_ck",
+			      "mcu_ck",
+			      "dma_ck",
+			      "xhci_ck";
+		mediatek,u3p-dis-msk = <0x1>;
+		status = "okay";
+	};
+
+	pcie: pcie@11280000 {
+		compatible = "mediatek,mt8192-pcie";
+		device_type = "pci";
+		reg = <0x11280000 0x4000>;
+		reg-names = "pcie-mac";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&infracfg CLK_INFRA_IPCIE_CK>,
+				<&infracfg CLK_INFRA_IPCIE_PIPE_CK>,
+				<&infracfg CLK_INFRA_IPCIER_CK>,
+				<&infracfg CLK_INFRA_IPCIEB_CK>;
+		clock-names = "pl_250m", "tl_26m", "peri_26m", "top_133m";
+		phys = <&u3port0 PHY_TYPE_PCIE>;
+		phy-names = "pcie-phy";
+		bus-range = <0x00 0xff>;
+		ranges = <0x82000000 0 0x20000000 0x20000000 0 0x10000000>;
+
+		#interrupt-cells = <1>;
+
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie_intc 0>,
+			<0 0 0 2 &pcie_intc 1>,
+			<0 0 0 3 &pcie_intc 2>,
+			<0 0 0 4 &pcie_intc 3>;
+
+		status = "disabled";
+
+		pcie_intc: interrupt-controller {
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			#address-cells = <0>;
+		};
+	};
+
+	usbtphy: usb-phy@11e10000 {
+		compatible = "mediatek,mt7981",
+			     "mediatek,generic-tphy-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		status = "okay";
+
+		u2port0: usb-phy@11e10000 {
+			reg = <0x11e10000 0x700>;
+			clocks = <&topckgen CLK_TOP_USB_FRMCNT_SEL>;
+			clock-names = "ref";
+			#phy-cells = <1>;
+			status = "okay";
+		};
+
+		u3port0: usb-phy@11e10700 {
+			reg = <0x11e10700 0x900>;
+			clocks = <&topckgen CLK_TOP_USB3_PHY_SEL>;
+			clock-names = "ref";
+			#phy-cells = <1>;
+			mediatek,syscon-type = <&topmisc 0x218 0>;
+			status = "okay";
+		};
+	};
 };
diff --git a/arch/arm/dts/mt7986-u-boot.dtsi b/arch/arm/dts/mt7986-u-boot.dtsi
index 096b973..71e8330 100644
--- a/arch/arm/dts/mt7986-u-boot.dtsi
+++ b/arch/arm/dts/mt7986-u-boot.dtsi
@@ -28,6 +28,6 @@
 	bootph-all;
 };
 
-&pinctrl {
+&pio {
 	bootph-all;
 };
diff --git a/arch/arm/dts/mt7986.dtsi b/arch/arm/dts/mt7986.dtsi
index f871f23..b2c5709 100644
--- a/arch/arm/dts/mt7986.dtsi
+++ b/arch/arm/dts/mt7986.dtsi
@@ -122,7 +122,7 @@
 		#clock-cells = <1>;
 	};
 
-	pinctrl: pinctrl@1001f000 {
+	pio: pinctrl@1001f000 {
 		compatible = "mediatek,mt7986-pinctrl";
 		reg = <0x1001f000 0x1000>,
 		      <0x11c30000 0x1000>,
@@ -132,13 +132,11 @@
 		      <0x11f00000 0x1000>,
 		      <0x11f10000 0x1000>,
 		      <0x1000b000 0x1000>;
-		reg-names = "gpio_base", "iocfg_rt_base", "iocfg_rb_base",
-			    "iocfg_lt_base", "iocfg_lb_base", "iocfg_tr_base",
-			    "iocfg_tl_base", "eint";
-		gpio: gpio-controller {
-			gpio-controller;
-			#gpio-cells = <2>;
-		};
+		reg-names = "gpio", "iocfg_rt", "iocfg_rb",
+			    "iocfg_lt", "iocfg_lb", "iocfg_tr",
+			    "iocfg_tl", "eint";
+		gpio-controller;
+		#gpio-cells = <2>;
 	};
 
 	pwm: pwm@10048000 {
diff --git a/arch/arm/dts/mt7986a-bpi-r3-sd.dts b/arch/arm/dts/mt7986a-bpi-r3-sd.dts
index c156a81..e01ae4c 100644
--- a/arch/arm/dts/mt7986a-bpi-r3-sd.dts
+++ b/arch/arm/dts/mt7986a-bpi-r3-sd.dts
@@ -38,12 +38,12 @@
 
 		factory {
 			label = "reset";
-			gpios = <&gpio 9 GPIO_ACTIVE_LOW>;
+			gpios = <&pio 9 GPIO_ACTIVE_LOW>;
 		};
 
 		wps {
 			label = "wps";
-			gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
+			gpios = <&pio 10 GPIO_ACTIVE_LOW>;
 		};
 	};
 
@@ -52,12 +52,12 @@
 
 		led_status_green: green {
 			label = "green:status";
-			gpios = <&gpio 69 GPIO_ACTIVE_HIGH>;
+			gpios = <&pio 69 GPIO_ACTIVE_HIGH>;
 		};
 
 		led_status_blue: blue {
 			label = "blue:status";
-			gpios = <&gpio 86 GPIO_ACTIVE_HIGH>;
+			gpios = <&pio 86 GPIO_ACTIVE_HIGH>;
 		};
 	};
 
@@ -78,7 +78,7 @@
 	mediatek,gmac-id = <0>;
 	phy-mode = "2500base-x";
 	mediatek,switch = "mt7531";
-	reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
+	reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>;
 
 	fixed-link {
 		speed = <2500>;
@@ -86,7 +86,7 @@
 	};
 };
 
-&pinctrl {
+&pio {
 	spic_pins: spi1-pins-func-1 {
 		mux {
 			function = "spi";
diff --git a/arch/arm/dts/mt7986a-rfb.dts b/arch/arm/dts/mt7986a-rfb.dts
index 67d14a9..d4bbb23 100644
--- a/arch/arm/dts/mt7986a-rfb.dts
+++ b/arch/arm/dts/mt7986a-rfb.dts
@@ -57,7 +57,7 @@
 	mediatek,gmac-id = <0>;
 	phy-mode = "2500base-x";
 	mediatek,switch = "mt7531";
-	reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
+	reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>;
 
 	fixed-link {
 		speed = <2500>;
@@ -65,7 +65,7 @@
 	};
 };
 
-&pinctrl {
+&pio {
 	spi_flash_pins: spi0-pins-func-1 {
 		mux {
 			function = "flash";
diff --git a/arch/arm/dts/mt7986a-sd-rfb.dts b/arch/arm/dts/mt7986a-sd-rfb.dts
index 4f8fa70..11823e0 100644
--- a/arch/arm/dts/mt7986a-sd-rfb.dts
+++ b/arch/arm/dts/mt7986a-sd-rfb.dts
@@ -49,7 +49,7 @@
 	mediatek,gmac-id = <0>;
 	phy-mode = "2500base-x";
 	mediatek,switch = "mt7531";
-	reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
+	reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>;
 
 	fixed-link {
 		speed = <2500>;
@@ -57,7 +57,7 @@
 	};
 };
 
-&pinctrl {
+&pio {
 	spi_flash_pins: spi0-pins-func-1 {
 		mux {
 			function = "flash";
diff --git a/arch/arm/dts/mt7986b-rfb.dts b/arch/arm/dts/mt7986b-rfb.dts
index f98b04a..0a731fe 100644
--- a/arch/arm/dts/mt7986b-rfb.dts
+++ b/arch/arm/dts/mt7986b-rfb.dts
@@ -48,7 +48,7 @@
 	mediatek,gmac-id = <0>;
 	phy-mode = "2500base-x";
 	mediatek,switch = "mt7531";
-	reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
+	reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>;
 
 	fixed-link {
 		speed = <2500>;
@@ -56,7 +56,7 @@
 	};
 };
 
-&pinctrl {
+&pio {
 	spi_flash_pins: spi0-pins-func-1 {
 		mux {
 			function = "flash";
diff --git a/arch/arm/dts/mt7986b-sd-rfb.dts b/arch/arm/dts/mt7986b-sd-rfb.dts
index ec80a2f..e5fb4d7 100644
--- a/arch/arm/dts/mt7986b-sd-rfb.dts
+++ b/arch/arm/dts/mt7986b-sd-rfb.dts
@@ -49,7 +49,7 @@
 	mediatek,gmac-id = <0>;
 	phy-mode = "2500base-x";
 	mediatek,switch = "mt7531";
-	reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
+	reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>;
 
 	fixed-link {
 		speed = <2500>;
@@ -57,7 +57,7 @@
 	};
 };
 
-&pinctrl {
+&pio {
 	spi_flash_pins: spi0-pins-func-1 {
 		mux {
 			function = "flash";
diff --git a/arch/arm/dts/mt7988-rfb.dts b/arch/arm/dts/mt7988-rfb.dts
index 2579d70..1694ef8d 100644
--- a/arch/arm/dts/mt7988-rfb.dts
+++ b/arch/arm/dts/mt7988-rfb.dts
@@ -80,7 +80,7 @@
 	status = "disabled";
 };
 
-&pinctrl {
+&pio {
 	i2c1_pins: i2c1-pins {
 		mux {
 			function = "i2c";
diff --git a/arch/arm/dts/mt7988-sd-rfb.dts b/arch/arm/dts/mt7988-sd-rfb.dts
index 38727a2..63e9231 100644
--- a/arch/arm/dts/mt7988-sd-rfb.dts
+++ b/arch/arm/dts/mt7988-sd-rfb.dts
@@ -53,7 +53,7 @@
 	};
 };
 
-&pinctrl {
+&pio {
 	i2c1_pins: i2c1-pins {
 		mux {
 			function = "i2c";
diff --git a/arch/arm/dts/mt7988.dtsi b/arch/arm/dts/mt7988.dtsi
index f2bfde5..2d57c6f 100644
--- a/arch/arm/dts/mt7988.dtsi
+++ b/arch/arm/dts/mt7988.dtsi
@@ -110,7 +110,7 @@
 		#clock-cells = <1>;
 	};
 
-	pinctrl: pinctrl@1001f000 {
+	pio: pinctrl@1001f000 {
 		compatible = "mediatek,mt7988-pinctrl";
 		reg = <0 0x1001f000 0 0x1000>,
 		      <0 0x11c10000 0 0x1000>,
@@ -119,13 +119,11 @@
 		      <0 0x11e00000 0 0x1000>,
 		      <0 0x11f00000 0 0x1000>,
 		      <0 0x1000b000 0 0x1000>;
-		reg-names = "gpio_base", "iocfg_tr_base", "iocfg_br_base",
-			    "iocfg_rb_base", "iocfg_lb_base", "iocfg_tl_base",
+		reg-names = "gpio", "iocfg_tr", "iocfg_br",
+			    "iocfg_rb", "iocfg_lb", "iocfg_tl",
 			    "eint";
-		gpio: gpio-controller {
-			gpio-controller;
-			#gpio-cells = <2>;
-		};
+		gpio-controller;
+		#gpio-cells = <2>;
 	};
 
 	sgmiisys0: syscon@10060000 {
diff --git a/arch/arm/dts/r8a779f4-s4sk-u-boot.dtsi b/arch/arm/dts/r8a779f4-s4sk-u-boot.dtsi
new file mode 100644
index 0000000..c2c743b
--- /dev/null
+++ b/arch/arm/dts/r8a779f4-s4sk-u-boot.dtsi
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot for the S4SK board
+ *
+ * Copyright (C) 2024-2025 Renesas Electronics Corp.
+ */
+
+#include "r8a779f0-u-boot.dtsi"
+
+/ {
+	aliases {
+		spi0 = &rpc;
+		/delete-property/ ethernet0;
+	};
+};
+
+&pfc {
+	qspi0_pins: qspi0 {
+		groups = "qspi0_ctrl", "qspi0_data4";
+		function = "qspi0";
+	};
+};
+
+&rpc {
+	pinctrl-0 = <&qspi0_pins>;
+	pinctrl-names = "default";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	spi-max-frequency = <40000000>;
+	status = "okay";
+
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "s25fs512s", "jedec,spi-nor";
+		reg = <0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <1>;
+		spi-max-frequency = <40000000>;
+	};
+};
diff --git a/arch/arm/dts/zynqmp-binman-som.dts b/arch/arm/dts/zynqmp-binman-som.dts
index 3d9d847..d5b63ef 100644
--- a/arch/arm/dts/zynqmp-binman-som.dts
+++ b/arch/arm/dts/zynqmp-binman-som.dts
@@ -13,6 +13,8 @@
 / {
 	binman: binman {
 		multiple-images;
+
+#ifdef CONFIG_SPL
 		fit-dtb.blob {
 			filename = "fit-dtb.blob";
 			pad-byte = <0>;
@@ -146,8 +148,11 @@
 						arch = "arm64";
 						compression = "none";
 						os = "tee";
-						load = /bits/ 64 <CONFIG_BL31_LOAD_ADDR>;
-						entry = /bits/ 64 <CONFIG_BL31_LOAD_ADDR>;
+						load = /bits/ 64 <CONFIG_BL32_LOAD_ADDR>;
+						entry = /bits/ 64 <CONFIG_BL32_LOAD_ADDR>;
+						hash {
+							algo = "md5";
+						};
 						tee-os {
 							optional;
 						};
@@ -157,7 +162,9 @@
 						type = "flat_dt";
 						arch = "arm64";
 						compression = "none";
-						load = <0x0 0x100000>;
+#if CONFIG_XILINX_OF_BOARD_DTB_ADDR
+						load = /bits/ 64 <CONFIG_XILINX_OF_BOARD_DTB_ADDR>;
+#endif
 						hash {
 							algo = "md5";
 						};
@@ -171,8 +178,13 @@
 					default = "conf-1";
 					conf-1 {
 						description = "Multi DTB with TF-A/TEE";
+#if CONFIG_BL31_LOAD_ADDR
 						firmware = "atf";
 						loadables = "tee", "uboot", "fdt";
+#else
+						firmware = "uboot";
+						loadables = "fdt";
+#endif
 					};
 				};
 			};
@@ -221,5 +233,6 @@
 			};
 		};
 #endif
+#endif
 	};
 };
diff --git a/arch/arm/dts/zynqmp-binman.dts b/arch/arm/dts/zynqmp-binman.dts
index 675f6bf..252c2ad 100644
--- a/arch/arm/dts/zynqmp-binman.dts
+++ b/arch/arm/dts/zynqmp-binman.dts
@@ -14,6 +14,7 @@
 	binman: binman {
 		multiple-images;
 
+#ifdef CONFIG_SPL
 		/* u-boot.itb generation in a static way */
 		itb {
 			filename = "u-boot.itb";
@@ -60,8 +61,11 @@
 						arch = "arm64";
 						compression = "none";
 						os = "tee";
-						load = /bits/ 64 <CONFIG_BL31_LOAD_ADDR>;
-						entry = /bits/ 64 <CONFIG_BL31_LOAD_ADDR>;
+						load = /bits/ 64 <CONFIG_BL32_LOAD_ADDR>;
+						entry = /bits/ 64 <CONFIG_BL32_LOAD_ADDR>;
+						hash {
+							algo = "md5";
+						};
 						tee-os {
 							optional;
 						};
@@ -71,8 +75,10 @@
 						type = "flat_dt";
 						arch = "arm64";
 						compression = "none";
-						load = <0x0 0x100000>;
-						hash-1 {
+#if CONFIG_XILINX_OF_BOARD_DTB_ADDR
+						load = /bits/ 64 <CONFIG_XILINX_OF_BOARD_DTB_ADDR>;
+#endif
+						hash {
 							algo = "md5";
 						};
 					};
@@ -81,9 +87,15 @@
 					default = "@conf-DEFAULT-SEQ";
 					@conf-SEQ {
 						description = "NAME";
+#if CONFIG_BL31_LOAD_ADDR
 						firmware = "atf";
 						loadables = "tee", "uboot";
 						fdt = "fdt-SEQ";
+#else
+						firmware = "uboot";
+						loadables = "fdt";
+#endif
+
 					};
 				};
 			};
@@ -134,8 +146,11 @@
 						arch = "arm64";
 						compression = "none";
 						os = "tee";
-						load = /bits/ 64 <CONFIG_BL31_LOAD_ADDR>;
-						entry = /bits/ 64 <CONFIG_BL31_LOAD_ADDR>;
+						load = /bits/ 64 <CONFIG_BL32_LOAD_ADDR>;
+						entry = /bits/ 64 <CONFIG_BL32_LOAD_ADDR>;
+						hash {
+							algo = "md5";
+						};
 						tee-os {
 							optional;
 						};
@@ -145,15 +160,16 @@
 						type = "flat_dt";
 						arch = "arm64";
 						compression = "none";
-						load = <0x0 0x100000>;
+#if CONFIG_XILINX_OF_BOARD_DTB_ADDR
+						load = /bits/ 64 <CONFIG_XILINX_OF_BOARD_DTB_ADDR>;
+#endif
+						hash {
+							algo = "md5";
+						};
 						uboot-fdt-blob {
 							filename = "u-boot.dtb";
 							type = "blob-ext";
 						};
-						hash-1 {
-							algo = "md5";
-						};
-
 					};
 				};
 				configurations {
@@ -202,5 +218,6 @@
 			};
 		};
 #endif
+#endif
 	};
 };
diff --git a/arch/arm/dts/zynqmp-sck-kd-g-revA.dtso b/arch/arm/dts/zynqmp-sck-kd-g-revA.dtso
index d56e863..02be5e1 100644
--- a/arch/arm/dts/zynqmp-sck-kd-g-revA.dtso
+++ b/arch/arm/dts/zynqmp-sck-kd-g-revA.dtso
@@ -22,6 +22,10 @@
 		     "xlnx,zynqmp-sk-kd240", "xlnx,zynqmp";
 	model = "ZynqMP KD240 revA/B/1";
 
+	aliases {
+		ethernet0 = "/axi/ethernet@ff0c0000"; /* &gem1 */
+	};
+
 	ina260-u3 {
 		compatible = "iio-hwmon";
 		io-channels = <&u3 0>, <&u3 1>, <&u3 2>;
diff --git a/arch/arm/dts/zynqmp-sck-kr-g-revA.dtso b/arch/arm/dts/zynqmp-sck-kr-g-revA.dtso
index 9d0c0c2..fbacfa9 100644
--- a/arch/arm/dts/zynqmp-sck-kr-g-revA.dtso
+++ b/arch/arm/dts/zynqmp-sck-kr-g-revA.dtso
@@ -20,6 +20,11 @@
 		     "xlnx,zynqmp-sk-kr260", "xlnx,zynqmp";
 	model = "ZynqMP KR260 revA";
 
+	aliases {
+		ethernet0 = "/axi/ethernet@ff0b0000"; /* &gem0 */
+		ethernet1 = "/axi/ethernet@ff0c0000"; /* &gem1 */
+	};
+
 	ina260-u14 {
 		compatible = "iio-hwmon";
 		io-channels = <&u14 0>, <&u14 1>, <&u14 2>;
diff --git a/arch/arm/dts/zynqmp-sck-kv-g-revA.dtso b/arch/arm/dts/zynqmp-sck-kv-g-revA.dtso
index a98a888..3c36eb5 100644
--- a/arch/arm/dts/zynqmp-sck-kv-g-revA.dtso
+++ b/arch/arm/dts/zynqmp-sck-kv-g-revA.dtso
@@ -28,6 +28,10 @@
 		     "xlnx,zynqmp-sk-kv260", "xlnx,zynqmp";
 	model = "ZynqMP KV260 revA";
 
+	aliases {
+		ethernet0 = "/axi/ethernet@ff0e0000"; /* &gem3 */
+	};
+
 	ina260-u14 {
 		compatible = "iio-hwmon";
 		io-channels = <&u14 0>, <&u14 1>, <&u14 2>;
diff --git a/arch/arm/dts/zynqmp-sck-kv-g-revB.dtso b/arch/arm/dts/zynqmp-sck-kv-g-revB.dtso
index 7490efe..078d98e 100644
--- a/arch/arm/dts/zynqmp-sck-kv-g-revB.dtso
+++ b/arch/arm/dts/zynqmp-sck-kv-g-revB.dtso
@@ -23,6 +23,10 @@
 		     "xlnx,zynqmp-sk-kv260", "xlnx,zynqmp";
 	model = "ZynqMP KV260 revB";
 
+	aliases {
+		ethernet0 = "/axi/ethernet@ff0e0000"; /* &gem3 */
+	};
+
 	ina260-u14 {
 		compatible = "iio-hwmon";
 		io-channels = <&u14 0>, <&u14 1>, <&u14 2>;
diff --git a/arch/arm/mach-renesas/Kconfig.rcar4 b/arch/arm/mach-renesas/Kconfig.rcar4
index c2812fd..c42bb97 100644
--- a/arch/arm/mach-renesas/Kconfig.rcar4
+++ b/arch/arm/mach-renesas/Kconfig.rcar4
@@ -54,6 +54,12 @@
 	help
 	  Support for Renesas R-Car Gen4 Spider platform
 
+config TARGET_S4SK
+	bool "S4SK board"
+	imply R8A779F0
+	help
+	  Support for Renesas R-Car Gen4 S4SK platform
+
 config TARGET_WHITEHAWK
 	bool "White Hawk board"
 	imply R8A779G0
@@ -70,6 +76,7 @@
 
 source "board/renesas/falcon/Kconfig"
 source "board/renesas/spider/Kconfig"
+source "board/renesas/s4sk/Kconfig"
 source "board/renesas/whitehawk/Kconfig"
 source "board/renesas/grayhawk/Kconfig"
 
diff --git a/arch/arm/mach-renesas/include/mach/boot0.h b/arch/arm/mach-renesas/include/mach/boot0.h
index fc68ffc..b71c157 100644
--- a/arch/arm/mach-renesas/include/mach/boot0.h
+++ b/arch/arm/mach-renesas/include/mach/boot0.h
@@ -34,7 +34,7 @@
 	.inst	0xe380070a	/* orr     r0, r0, #0x280000 */
 
 	/* APMU_RVBARPLC0 = (address of 'b reset' below) | CA_CORE0_VLD_RVBARP */
-	.inst	0xe28f3088	/* add     r3, pc, #0x88 */
+	.inst	0xe28f30a8	/* add     r3, pc, #0xa8 */
 	.inst	0xe3833001	/* orr     r3, r3, #1 */
 	.inst	0xe5843038	/* str     r3, [r4, #56]   @ 0x38 */
 
@@ -75,12 +75,22 @@
 	.inst	0xe20230ff	/* and     r3, r2, #255    @ 0xff */
 	.inst	0xe3530011	/* cmp     r3, #17 */
 	.inst	0x1afffffb	/* bne     78 <reset-0x28> */
+	/* Invalidate icache before jump to follow up software */
+	.inst	0xe3a00000	/* mov     r0, #0 */
+	.inst	0xee070f15	/* mcr     15, 0, r0, cr7, cr5, {0} */
+	.inst	0xf57ff04f	/* dsb     sy */
+	.inst	0xf57ff06f	/* isb     sy */
+	/* Jump to follow up software */
 	.inst	0xe1a02922	/* lsr     r2, r2, #18 */
 	.inst	0xe1a02902	/* lsl     r2, r2, #18 */
 	.inst	0xe1a0f002	/* mov     pc, r2 */
 	.inst	0xeafffffe	/* b       94 <reset-0xc> */
 	.inst	0xe1a00000	/* nop                     @ (mov r0, r0) */
 	.inst	0xe1a00000	/* nop                     @ (mov r0, r0) */
+	.inst	0xe1a00000	/* nop                     @ (mov r0, r0) */
+	.inst	0xe1a00000	/* nop                     @ (mov r0, r0) */
+	.inst	0xe1a00000	/* nop                     @ (mov r0, r0) */
+	.inst	0xe1a00000	/* nop                     @ (mov r0, r0) */
 	/* Offset 0xa0 */
 #endif
 	b	reset
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
index 265e9ce..376d1bc 100644
--- a/arch/arm/mach-zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -43,9 +43,6 @@
 config SYS_SOC
 	default "zynq"
 
-config SYS_MALLOC_F_LEN
-	default 0x800
-
 config SYS_MALLOC_LEN
 	default 0x1400000
 
diff --git a/arch/arm/mach-zynqmp-r5/Kconfig b/arch/arm/mach-zynqmp-r5/Kconfig
index b2ba896..45d8c05 100644
--- a/arch/arm/mach-zynqmp-r5/Kconfig
+++ b/arch/arm/mach-zynqmp-r5/Kconfig
@@ -19,7 +19,4 @@
 	help
 	  The value, in Hz, that the CPU clock is running at.
 
-config SYS_MALLOC_F_LEN
-	default 0x600
-
 endif
diff --git a/arch/arm/mach-zynqmp/Kconfig b/arch/arm/mach-zynqmp/Kconfig
index 92d61e8..151cfad 100644
--- a/arch/arm/mach-zynqmp/Kconfig
+++ b/arch/arm/mach-zynqmp/Kconfig
@@ -93,9 +93,6 @@
 	help
 	  Size in bytes of the DRAM ECC bank2. A null size takes no action.
 
-config SYS_MALLOC_F_LEN
-	default 0x600
-
 config DEFINE_TCM_OCM_MMAP
 	bool "Define TCM and OCM memory in MMU Table"
 	default y if MP
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index faf70cb..b246235 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -459,6 +459,7 @@
 
 config AVAILABLE_HARTS
 	bool "Send IPI by available harts"
+	depends on !XIP
 	default y
 	help
 	  By default, IPI sending mechanism will depend on available_harts.
@@ -587,4 +588,10 @@
 	  This is a shortcut boot flow, from u-boot SPL -> OpenSBI -> u-boot proper
 	  -> linux to u-boot SPL -> OpenSBI -> linux.
 
+config SPL_OPTEE_LOAD_ADDR
+	hex "OP-TEE Trusted OS image load address"
+	depends on OPTEE
+	help
+	  Load address of the OP-TEE binary.
+
 endmenu
diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
index 06ecd92..5b31da6 100644
--- a/arch/riscv/cpu/cpu.c
+++ b/arch/riscv/cpu/cpu.c
@@ -11,11 +11,13 @@
 #include <event.h>
 #include <hang.h>
 #include <init.h>
+#include <irq_func.h>
 #include <log.h>
 #include <asm/encoding.h>
 #include <asm/system.h>
 #include <asm/hwcap.h>
 #include <asm/cpufeature.h>
+#include <asm/cache.h>
 #include <dm/uclass-internal.h>
 #include <linux/bitops.h>
 #include <linux/log2.h>
@@ -729,3 +731,18 @@
 	hang();
 }
 #endif
+
+/*
+ * cleanup_before_linux() is called just before we call linux, which prepares
+ * the processor for linux.
+ * this weak implementation is used by default. we disable interrupts and flush
+ * the cache.
+ */
+__weak int cleanup_before_linux(void)
+{
+	disable_interrupts();
+
+	cache_flush();
+
+	return 0;
+}
diff --git a/arch/riscv/cpu/generic/Makefile b/arch/riscv/cpu/generic/Makefile
index 258e462..a9be44e 100644
--- a/arch/riscv/cpu/generic/Makefile
+++ b/arch/riscv/cpu/generic/Makefile
@@ -3,4 +3,3 @@
 # Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
 
 obj-y += dram.o
-obj-y += cpu.o
diff --git a/arch/riscv/cpu/generic/cpu.c b/arch/riscv/cpu/generic/cpu.c
deleted file mode 100644
index f13c189..0000000
--- a/arch/riscv/cpu/generic/cpu.c
+++ /dev/null
@@ -1,22 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
- */
-
-#include <irq_func.h>
-#include <asm/cache.h>
-
-/*
- * cleanup_before_linux() is called just before we call linux
- * it prepares the processor for linux
- *
- * we disable interrupt and caches.
- */
-int cleanup_before_linux(void)
-{
-	disable_interrupts();
-
-	cache_flush();
-
-	return 0;
-}
diff --git a/arch/riscv/cpu/jh7110/Makefile b/arch/riscv/cpu/jh7110/Makefile
index 0939c10..4f91aaf 100644
--- a/arch/riscv/cpu/jh7110/Makefile
+++ b/arch/riscv/cpu/jh7110/Makefile
@@ -5,6 +5,5 @@
 ifeq ($(CONFIG_XPL_BUILD),y)
 obj-y += spl.o
 else
-obj-y += cpu.o
 obj-y += dram.o
 endif
diff --git a/arch/riscv/cpu/jh7110/cpu.c b/arch/riscv/cpu/jh7110/cpu.c
deleted file mode 100644
index 1d7c026..0000000
--- a/arch/riscv/cpu/jh7110/cpu.c
+++ /dev/null
@@ -1,23 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2022 StarFive Technology Co., Ltd.
- * Author: Yanhong Wang <yanhong.wang@starfivetech.com>
- */
-
-#include <asm/cache.h>
-#include <irq_func.h>
-
-/*
- * cleanup_before_linux() is called just before we call linux
- * it prepares the processor for linux
- *
- * we disable interrupt and caches.
- */
-int cleanup_before_linux(void)
-{
-	disable_interrupts();
-
-	cache_flush();
-
-	return 0;
-}
diff --git a/arch/riscv/cpu/k1/dram.c b/arch/riscv/cpu/k1/dram.c
index c477c15..cc1e903 100644
--- a/arch/riscv/cpu/k1/dram.c
+++ b/arch/riscv/cpu/k1/dram.c
@@ -4,17 +4,53 @@
  */
 
 #include <asm/global_data.h>
+#include <asm/io.h>
 #include <config.h>
+#include <bitfield.h>
 #include <fdt_support.h>
 #include <linux/sizes.h>
 
+#define DDR_BASE 0xC0000000
 DECLARE_GLOBAL_DATA_PTR;
 
+static phys_size_t ddr_map_size(u32 val)
+{
+	u32 tmp;
+
+	if (!(val & 0x1))
+		return 0;
+
+	tmp = bitfield_extract(val, 16, 5);
+	switch (tmp) {
+	case 0xd:
+		return 512;
+	case 0xe:
+		return 1024;
+	case 0xf:
+		return 2048;
+	case 0x10:
+		return 4096;
+	case 0x11:
+		return 8192;
+	default:
+		pr_info("Invalid DRAM density %x\n", val);
+		return 0;
+	}
+}
+
+phys_size_t ddr_get_density(void)
+{
+	phys_size_t cs0_size = ddr_map_size(readl((void *)DDR_BASE + 0x200));
+	phys_size_t cs1_size = ddr_map_size(readl((void *)DDR_BASE + 0x208));
+	phys_size_t ddr_size = cs0_size + cs1_size;
+
+	return ddr_size;
+}
+
 int dram_init(void)
 {
 	gd->ram_base = CFG_SYS_SDRAM_BASE;
-	/* TODO get ram size from ddr controller */
-	gd->ram_size = SZ_4G;
+	gd->ram_size = ddr_get_density() * SZ_1M;
 	return 0;
 }
 
diff --git a/arch/riscv/dts/binman.dtsi b/arch/riscv/dts/binman.dtsi
index 9271de0..0405fac 100644
--- a/arch/riscv/dts/binman.dtsi
+++ b/arch/riscv/dts/binman.dtsi
@@ -53,6 +53,19 @@
 					};
 				};
 #endif
+#ifdef CONFIG_OPTEE
+				tee {
+					description = "OP-TEE";
+					type = "tee";
+					arch = "riscv";
+					compression = "none";
+					os = "tee";
+					load = /bits/ 64 <CONFIG_SPL_OPTEE_LOAD_ADDR>;
+					tee_blob: tee-os {
+						filename = "tee.bin";
+					};
+				};
+#endif
 
 				opensbi {
 					description = "OpenSBI fw_dynamic Firmware";
@@ -88,11 +101,20 @@
 #endif
 					description = "NAME";
 					firmware = "opensbi";
-#ifndef CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT
-					loadables = "uboot";
+#ifdef CONFIG_OPTEE
+#ifdef CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT
+					loadables = "linux", "tee";
 #else
+					loadables = "uboot", "tee";
+#endif
+#else /* !CONFIG_OPTEEE */
+#ifdef CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT
 					loadables = "linux";
+#else
+					loadables = "uboot";
 #endif
+#endif /* CONFIG_OPTEE */
+
 #ifndef CONFIG_OF_BOARD
 					fdt = "fdt-SEQ";
 #endif
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index ae52b37..b8f3012 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -13,6 +13,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/gpio/sandbox-gpio.h>
 #include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
 #include <dt-bindings/pinctrl/sandbox-pinmux.h>
 #include <dt-bindings/mux/mux.h>
 
@@ -820,7 +821,7 @@
 			gpio-controller;
 			#gpio-cells = <1>;
 			gpio-bank-name = "a";
-			sandbox,gpio-count = <20>;
+			sandbox,gpio-count = <25>;
 			hog_input_active_low {
 				gpio-hog;
 				input;
@@ -1010,6 +1011,40 @@
 			/* label intentionally omitted */
 			default-state = "off";
 		};
+
+		led-20 {
+			gpios = <&gpio_a 20 0>;
+			/* label intentionally omitted */
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_RED>;
+			function-enumerator = <20>;
+		};
+
+		led-21 {
+			gpios = <&gpio_a 21 0>;
+			/* label intentionally omitted */
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_GREEN>;
+		};
+
+		led-22 {
+			gpios = <&gpio_a 22 0>;
+			/* label intentionally omitted */
+			function = LED_FUNCTION_STATUS;
+		};
+
+		led-23 {
+			gpios = <&gpio_a 23 0>;
+			/* label intentionally omitted */
+			color = <LED_COLOR_ID_GREEN>;
+		};
+
+		led-24 {
+			gpios = <&gpio_a 24 0>;
+			label = "sandbox:function";
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_GREEN>;
+		};
 	};
 
 	wdt-gpio-toggle {
diff --git a/board/phytec/phycore_am64x/Kconfig b/board/phytec/phycore_am64x/Kconfig
index 829526c..a709b71 100644
--- a/board/phytec/phycore_am64x/Kconfig
+++ b/board/phytec/phycore_am64x/Kconfig
@@ -35,3 +35,28 @@
 source "board/phytec/common/Kconfig"
 
 endif
+
+config PHYCORE_AM64X_RAM_SIZE_FIX
+        bool "Set phyCORE-AM64x RAM size fix instead of detecting"
+        default false
+        help
+          RAM size is automatic being detected with the help of
+          the EEPROM introspection data. Set RAM size to a fix value
+          instead.
+
+choice
+        prompt "phyCORE-AM64x RAM size"
+        depends on PHYCORE_AM64X_RAM_SIZE_FIX
+        default PHYCORE_AM64X_RAM_SIZE_2GB
+
+config PHYCORE_AM64X_RAM_SIZE_1GB
+        bool "1GB RAM"
+        help
+          Set RAM size fix to 1GB for phyCORE-AM64x.
+
+config PHYCORE_AM64X_RAM_SIZE_2GB
+        bool "2GB RAM"
+        help
+          Set RAM size fix to 2GB for phyCORE-AM64x.
+
+endchoice
diff --git a/board/phytec/phycore_am64x/phycore-am64x.c b/board/phytec/phycore_am64x/phycore-am64x.c
index 8f3b226..f14c87f 100644
--- a/board/phytec/phycore_am64x/phycore-am64x.c
+++ b/board/phytec/phycore_am64x/phycore-am64x.c
@@ -11,9 +11,12 @@
 #include <env.h>
 #include <env_internal.h>
 #include <spl.h>
+#include <asm/arch/k3-ddr.h>
 #include <fdt_support.h>
 #include <asm/arch/hardware.h>
 
+#include "../common/am6_som_detection.h"
+
 DECLARE_GLOBAL_DATA_PTR;
 
 int board_init(void)
@@ -21,15 +24,113 @@
 	return 0;
 }
 
+static u8 phytec_get_am64_ddr_size_default(void)
+{
+	int ret;
+	struct phytec_eeprom_data data;
+
+	if (IS_ENABLED(CONFIG_PHYCORE_AM64X_RAM_SIZE_FIX)) {
+		if (IS_ENABLED(CONFIG_PHYCORE_AM64X_RAM_SIZE_1GB))
+			return EEPROM_RAM_SIZE_1GB;
+		else if (IS_ENABLED(CONFIG_PHYCORE_AM64X_RAM_SIZE_2GB))
+			return EEPROM_RAM_SIZE_2GB;
+	}
+
+	ret = phytec_eeprom_data_setup(&data, 0, EEPROM_ADDR);
+	if (!ret && data.valid)
+		return phytec_get_am6_ddr_size(&data);
+
+	/* Default DDR size is 2GB */
+	return EEPROM_RAM_SIZE_2GB;
+}
+
 int dram_init(void)
 {
-	return fdtdec_setup_mem_size_base();
+	u8 ram_size;
+
+	if (!IS_ENABLED(CONFIG_CPU_V7R))
+		return fdtdec_setup_mem_size_base();
+
+	ram_size = phytec_get_am64_ddr_size_default();
+
+	switch (ram_size) {
+	case EEPROM_RAM_SIZE_1GB:
+		gd->ram_size = 0x40000000;
+		break;
+	case EEPROM_RAM_SIZE_2GB:
+		gd->ram_size = 0x80000000;
+		break;
+	default:
+		gd->ram_size = 0x80000000;
+	}
+
+	return 0;
 }
 
 int dram_init_banksize(void)
 {
+	u8 ram_size;
+
+	memset(gd->bd->bi_dram, 0, sizeof(gd->bd->bi_dram[0]) * CONFIG_NR_DRAM_BANKS);
+
+	if (!IS_ENABLED(CONFIG_CPU_V7R))
+		return fdtdec_setup_memory_banksize();
+
+	ram_size = phytec_get_am64_ddr_size_default();
+	switch (ram_size) {
+	case EEPROM_RAM_SIZE_1GB:
+		gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
+		gd->bd->bi_dram[0].size = 0x40000000;
+		gd->ram_size = 0x40000000;
+		break;
+
+	case EEPROM_RAM_SIZE_2GB:
+		gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
+		gd->bd->bi_dram[0].size = 0x80000000;
+		gd->ram_size = 0x80000000;
+		break;
+
+	default:
+		/* Continue with default 2GB setup */
+		gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
+		gd->bd->bi_dram[0].size = 0x80000000;
+		gd->ram_size = 0x80000000;
+		printf("DDR size %d is not supported\n", ram_size);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_K3_DDRSS)
+int do_board_detect(void)
+{
+	void *fdt = (void *)gd->fdt_blob;
+	int bank;
+
+	u64 start[CONFIG_NR_DRAM_BANKS];
+	u64 size[CONFIG_NR_DRAM_BANKS];
+
+	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;
+	}
+
+	return fdt_fixup_memory_banks(fdt, start, size, CONFIG_NR_DRAM_BANKS);
+}
+#endif
+
+#if IS_ENABLED(CONFIG_XPL_BUILD)
+void spl_perform_fixups(struct spl_image_info *spl_image)
+{
-	return fdtdec_setup_memory_banksize();
+	if (IS_ENABLED(CONFIG_K3_DDRSS) && IS_ENABLED(CONFIG_K3_INLINE_ECC))
+		fixup_ddr_driver_for_ecc(spl_image);
+	else
+		fixup_memory_node(spl_image);
 }
+#endif
 
 #define CTRLMMR_USB0_PHY_CTRL	0x43004008
 #define CORE_VOLTAGE		0x80000000
diff --git a/board/renesas/s4sk/Kconfig b/board/renesas/s4sk/Kconfig
new file mode 100644
index 0000000..57013d2
--- /dev/null
+++ b/board/renesas/s4sk/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_S4SK
+
+config SYS_SOC
+	default "renesas"
+
+config SYS_BOARD
+	default "s4sk"
+
+config SYS_VENDOR
+	default "renesas"
+
+config SYS_CONFIG_NAME
+	default "s4sk"
+
+endif
diff --git a/board/renesas/s4sk/MAINTAINERS b/board/renesas/s4sk/MAINTAINERS
new file mode 100644
index 0000000..e64da07
--- /dev/null
+++ b/board/renesas/s4sk/MAINTAINERS
@@ -0,0 +1,7 @@
+S4SK BOARD
+M:	Marek Vasut <marek.vasut+renesas@mailbox.org>
+S:	Maintained
+F:	arch/arm/dts/r8a779f4*
+F:	board/renesas/s4sk/
+F:	configs/r8a779f4_s4sk_defconfig
+F:	include/configs/s4sk.h
diff --git a/board/renesas/s4sk/Makefile b/board/renesas/s4sk/Makefile
new file mode 100644
index 0000000..f03e523
--- /dev/null
+++ b/board/renesas/s4sk/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2025 Renesas Electronics Corp.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y	:= s4sk.o
diff --git a/board/renesas/s4sk/s4sk.c b/board/renesas/s4sk/s4sk.c
new file mode 100644
index 0000000..d2beb71
--- /dev/null
+++ b/board/renesas/s4sk/s4sk.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2025 Marek Vasut <marek.vasut+renesas@mailbox.org>
+ */
+
+#include <dm.h>
+#include <i2c.h>
+#include <malloc.h>
+#include <net-common.h>
+
+#define S4SK_FPGA_I2C_BUS			"i2c5"
+#define S4SK_FPGA_I2C_DEV_ADDR			0x70
+#define S4SK_FPGA_I2C_DEV_WIDTH			2
+#define S4SK_FPGA_I2C_MAC_COUNT			4
+#define S4SK_FPGA_I2C_MAC_OFFSET		0x58
+#define S4SK_FPGA_I2C_MAC_WIDTH			8
+
+int board_late_init(void)
+{
+	/*
+	 * Extract AVB and TSN0,1,2 MAC addresses from FPGA via I2C.
+	 *
+	 * In case a matching ethaddr/ethNaddr environment variable
+	 * is not set, set it, otherwise do not override it. This
+	 * allows users to set their own MAC addresses via ethaddr
+	 * and ethNaddr environment variables.
+	 *
+	 * The ethaddr/ethNaddr mapping follows Linux kernel DT aliases
+	 * ethernetN property assignment:
+	 * - ethaddr ..... TSN0 (IC104 connector)
+	 * - eth1addr .... TSN1 (IC101 connector)
+	 * - eth2addr .... TSN2 (Expansion connector)
+	 * - eth3addr .... AVB (CN1 connector)
+	 */
+	ofnode i2c_node = ofnode_path(S4SK_FPGA_I2C_BUS);
+	struct udevice *bus, *dev;
+	unsigned char enetaddr[6];
+	unsigned char macs[32];	/* Four MAC addresses in FPGA in total. */
+	int i, idx, j, ret;
+
+	ret = uclass_get_device_by_ofnode(UCLASS_I2C, i2c_node, &bus);
+	if (ret < 0) {
+		printf("s4sk: cannot find i2c bus (%d)\n", ret);
+		return 0;
+	}
+
+	ret = i2c_get_chip(bus, S4SK_FPGA_I2C_DEV_ADDR,
+			   S4SK_FPGA_I2C_DEV_WIDTH, &dev);
+	if (ret < 0) {
+		printf("s4sk: cannot find i2c chip (%d)\n", ret);
+		return 0;
+	}
+
+	ret = dm_i2c_read(dev, S4SK_FPGA_I2C_MAC_OFFSET, macs, sizeof(macs));
+	if (ret < 0) {
+		printf("s4sk: failed to read MAC addresses via i2c (%d)\n", ret);
+		return 0;
+	}
+
+	for (i = 0; i < S4SK_FPGA_I2C_MAC_COUNT; i++) {
+		/*
+		 * Remap TSN0,1,2 to ethaddr,eth1addr,eth2addr and
+		 * AVB to eth3addr to match Linux /aliases ethernetN
+		 * assignment, which starts with ethernet0 for TSN.
+		 */
+		idx = (i + 3) % 4;
+		ret = eth_env_get_enetaddr_by_index("eth", idx, enetaddr);
+		if (ret)	/* ethaddr is already set */
+			continue;
+
+		/* Byte-wise reverse the MAC address */
+		for (j = 0; j < sizeof(enetaddr); j++)
+			enetaddr[j] = macs[i * S4SK_FPGA_I2C_MAC_WIDTH + (5 - j)];
+
+		if (!is_valid_ethaddr(enetaddr)) {
+			printf("s4sk: MAC address %d in FPGA not valid (%pM)\n",
+			       i, enetaddr);
+			continue;
+		}
+
+		eth_env_set_enetaddr_by_index("eth", idx, enetaddr);
+	}
+
+	return 0;
+}
diff --git a/board/samsung/e850-96/e850-96.c b/board/samsung/e850-96/e850-96.c
index c5cef6f..0bef68d 100644
--- a/board/samsung/e850-96/e850-96.c
+++ b/board/samsung/e850-96/e850-96.c
@@ -19,6 +19,11 @@
 
 int board_init(void)
 {
-	load_ldfw();
+	int err;
+
+	err = load_ldfw();
+	if (err)
+		printf("ERROR: LDFW loading failed (%d)\n", err);
+
 	return 0;
 }
diff --git a/board/samsung/e850-96/e850-96.env b/board/samsung/e850-96/e850-96.env
index f36f90b..5ac76bc 100644
--- a/board/samsung/e850-96/e850-96.env
+++ b/board/samsung/e850-96/e850-96.env
@@ -1,26 +1,11 @@
-partitions=
-	uuid_disk=${uuid_gpt_disk};
-	name=efs,start=512K,size=20M,uuid=${uuid_gpt_efs};
-	name=env,size=16K,uuid=${uuid_gpt_env};
-	name=kernel,size=30M,uuid=${uuid_gpt_kernel};
-	name=ramdisk,size=26M,uuid=${uuid_gpt_ramdisk};
-	name=dtbo,size=1M,uuid=${uuid_gpt_dtbo};
-	name=ldfw,size=4016K,uuid=${uuid_gpt_ldfw};
-	name=keystorage,size=8K,uuid=${uuid_gpt_keystorage};
-	name=tzsw,size=1M,uuid=${uuid_gpt_tzsw};
-	name=harx,size=2M,uuid=${uuid_gpt_harx};
-	name=harx_rkp,size=2M,uuid=${uuid_gpt_harx_rkp};
-	name=logo,size=40M,uuid=${uuid_gpt_logo};
-	name=super,size=3600M,uuid=${uuid_gpt_super};
-	name=cache,size=300M,uuid=${uuid_gpt_cache};
-	name=modem,size=100M,uuid=${uuid_gpt_modem};
-	name=boot,size=100M,uuid=${uuid_gpt_boot};
-	name=persist,size=30M,uuid=${uuid_gpt_persist};
-	name=recovery,size=40M,uuid=${uuid_gpt_recovery};
-	name=misc,size=40M,uuid=${uuid_gpt_misc};
-	name=mnv,size=20M,uuid=${uuid_gpt_mnv};
-	name=frp,size=512K,uuid=${uuid_gpt_frp};
-	name=vbmeta,size=64K,uuid=${uuid_gpt_vbmeta};
-	name=metadata,size=16M,uuid=${uuid_gpt_metadata};
-	name=dtb,size=1M,uuid=${uuid_gpt_dtb};
-	name=userdata,size=-,uuid=${uuid_gpt_userdata}
+kernel_addr_r=0x80000000
+kernel_comp_addr_r=0x88000000
+kernel_comp_size=0x4000000
+fdt_addr_r=0x8c000000
+scriptaddr=0x8c100000
+pxefile_addr_r=0x8c200000
+ramdisk_addr_r=0x8c300000
+fdtfile=CONFIG_DEFAULT_FDT_FILE
+
+partitions=name=esp,start=512K,size=128M,bootable,type=system;
+partitions+=name=rootfs,size=-,bootable,type=linux
diff --git a/board/samsung/e850-96/fw.c b/board/samsung/e850-96/fw.c
index 82a0b22..8f64e75 100644
--- a/board/samsung/e850-96/fw.c
+++ b/board/samsung/e850-96/fw.c
@@ -7,14 +7,16 @@
  */
 
 #include <part.h>
+#include <fs.h>
 #include <linux/arm-smccc.h>
 #include "fw.h"
 
 #define EMMC_IFACE		"mmc"
 #define EMMC_DEV_NUM		0
+#define LDFW_RAW_PART		"ldfw"
+#define LDFW_FAT_PART		"esp"
+#define LDFW_FAT_PATH		"/EFI/firmware/ldfw.bin"
 
-/* LDFW constants */
-#define LDFW_PART_NAME		"ldfw"
 #define LDFW_NWD_ADDR		0x88000000
 #define LDFW_MAGIC		0x10adab1e
 #define SMC_CMD_LOAD_LDFW	-0x500
@@ -36,7 +38,33 @@
 	char fw_name[16];
 };
 
-static int read_fw(const char *part_name, void *buf)
+/* Load LDFW binary as a file from FAT partition */
+static int read_fw_from_fat(const char *part_name, const char *path, void *buf)
+{
+	char dev_part_str[8];
+	loff_t len_read;
+	int err;
+
+	snprintf(dev_part_str, sizeof(dev_part_str), "%d#%s", EMMC_DEV_NUM,
+		 LDFW_FAT_PART);
+
+	err = fs_set_blk_dev(EMMC_IFACE, dev_part_str, FS_TYPE_FAT);
+	if (err) {
+		debug("%s: Can't set block device\n", __func__);
+		return -ENODEV;
+	}
+
+	err = fs_read(path, (ulong)buf, 0, 0, &len_read);
+	if (err) {
+		debug("%s: Can't read LDFW file\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/* Load LDFW binary from raw partition on block device into RAM buffer */
+static int read_fw_from_raw(const char *part_name, void *buf)
 {
 	struct blk_desc *blk_desc;
 	struct disk_partition part;
@@ -73,10 +101,13 @@
 	u64 size = 0;
 	int err, i;
 
-	/* Load LDFW from the block device partition into RAM buffer */
-	err = read_fw(LDFW_PART_NAME, buf);
-	if (err)
-		return err;
+	/* First try to read LDFW from EFI partition, then from the raw one */
+	err = read_fw_from_fat(LDFW_FAT_PART, LDFW_FAT_PATH, buf);
+	if (err) {
+		err = read_fw_from_raw(LDFW_RAW_PART, buf);
+		if (err)
+			return err;
+	}
 
 	/* Validate LDFW by magic number in its header */
 	hdr = buf;
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index 8cdd9d8..820fb25 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -488,7 +488,7 @@
 		if (bootseq >= 0) {
 			bootseq_len = snprintf(NULL, 0, "%i", bootseq);
 			debug("Bootseq len: %x\n", bootseq_len);
-			env_set_hex("bootseq", bootseq);
+			env_set_ulong("bootseq", (unsigned long)bootseq);
 		}
 
 		/*
diff --git a/board/xilinx/zynqmp/zynqmp_kria.env b/board/xilinx/zynqmp/zynqmp_kria.env
index b0c2ac6..75b604a 100644
--- a/board/xilinx/zynqmp/zynqmp_kria.env
+++ b/board/xilinx/zynqmp/zynqmp_kria.env
@@ -43,6 +43,7 @@
 scriptaddr=0x20000000
 usb_boot=usb start; if usb dev ${devnum}; then devtype=usb; run scan_dev_for_boot_part; fi
 preboot=setenv boot_targets; setenv modeboot; run board_setup
+usb_pgood_delay=1000
 
 # SOM specific boot methods
 usb_boot_devices='usb0 usb1 usb2 usb3 usb4'
diff --git a/boot/Kconfig b/boot/Kconfig
index 20935a2..c09a98c 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -711,6 +711,20 @@
 	  firmware image in boot media such as MMC. It does not support any sort
 	  of rollback, recovery or A/B boot.
 
+config BOOTMETH_VBE_ABREC
+	bool "Bootdev support for VBE 'a/b/recovery' method"
+	imply SPL_CRC8
+	imply VPL_CRC8
+	help
+	  Enables support for VBE 'abrec' boot. This allows updating one of an
+	  A or B firmware image in boot media such as MMC. The new firmware is
+	  tried and if it boots, it is copied to the other image, so that both
+	  A and B have the same version. If neither firmware image passes the
+	  verification step, a recovery image is booted. This method will
+	  eventually provide rollback protection as well.
+
+if BOOTMETH_VBE_SIMPLE
+
 config BOOTMETH_VBE_SIMPLE_OS
 	bool "Bootdev support for VBE 'simple' method OS phase"
 	default y
@@ -769,6 +783,65 @@
 
 endif # BOOTMETH_VBE_SIMPLE
 
+if BOOTMETH_VBE_ABREC
+
+config SPL_BOOTMETH_VBE_ABREC
+	bool "Bootdev support for VBE 'abrec' method (SPL)"
+	depends on SPL
+	default y if VPL
+	help
+	  Enables support for VBE 'abrec' boot. The SPL part of this
+	  implementation simply loads U-Boot from the image selected by the
+	  VPL phase.
+
+config TPL_BOOTMETH_VBE_ABREC
+	bool "Bootdev support for VBE 'abrec' method (TPL)"
+	depends on TPL
+	select TPL_FIT
+	default y
+	help
+	  Enables support for VBE 'abrec' boot. The TPL part of this
+	  implementation simply jumps to VPL after device init is completed.
+
+config VPL_BOOTMETH_VBE_ABREC
+	bool "Bootdev support for VBE 'abrec' method (VPL)"
+	depends on VPL
+	default y
+	help
+	  Enables support for VBE 'abrec' boot. The VPL part of this
+	  implementation selects which SPL to use (A, B or recovery) and then
+	  boots into SPL.
+
+config SPL_BOOTMETH_VBE_ABREC_FW
+	bool "Bootdev support for VBE 'abrec' method firmware phase (SPL)"
+	depends on SPL
+	default y if VPL
+	help
+	  Enables support for VBE 'abrec' boot. The SPL part of this
+	  implementation simply loads U-Boot from the image selected by the
+	  VPL phase.
+
+config TPL_BOOTMETH_VBE_ABREC_FW
+	bool "Bootdev support for VBE 'abrec' method firmware phase (TPL)"
+	depends on TPL
+	default y if VPL
+	help
+	  Enables support for VBE 'abrec' boot. The TPL part of this
+	  implementation simply jumps to VPL after device init is completed.
+
+config VPL_BOOTMETH_VBE_ABREC_FW
+	bool "Bootdev support for VBE 'abrec' method firmware phase (VPL)"
+	depends on VPL
+	default y
+	help
+	  Enables support for VBE 'abrec' boot. The VPL part of this
+	  implementation selects which SPL to use (A, B or recovery) and then
+	  boots into SPL.
+
+endif # BOOTMETH_VBE_ABREC
+
+endif # BOOTMETH_VBE
+
 config EXPO
 	bool "Support for expos - groups of scenes displaying a UI"
 	depends on VIDEO
diff --git a/boot/Makefile b/boot/Makefile
index c2753de..34bac26 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -70,3 +70,7 @@
 obj-$(CONFIG_$(PHASE_)BOOTMETH_VBE_SIMPLE_OS) += vbe_simple_os.o
 
 obj-$(CONFIG_$(PHASE_)BOOTMETH_ANDROID) += bootmeth_android.o
+
+obj-$(CONFIG_$(PHASE_)BOOTMETH_VBE_ABREC) += vbe_abrec.o vbe_common.o
+obj-$(CONFIG_$(PHASE_)BOOTMETH_VBE_ABREC_FW) += vbe_abrec_fw.o
+obj-$(CONFIG_$(PHASE_)BOOTMETH_VBE_ABREC_OS) += vbe_abrec_os.o
diff --git a/boot/image-fit.c b/boot/image-fit.c
index 70080d1..aa139da 100644
--- a/boot/image-fit.c
+++ b/boot/image-fit.c
@@ -1907,24 +1907,30 @@
 	count = fit_conf_get_prop_node_count(fit, noffset, prop_name);
 	if (count < 0)
 		return count;
+	log_debug("looking for %s (%s, image-count %d):\n", prop_name,
+		  genimg_get_phase_name(image_ph_phase(sel_phase)), count);
 
 	/* check each image in the list */
 	for (i = 0; i < count; i++) {
-		enum image_phase_t phase;
+		enum image_phase_t phase = IH_PHASE_NONE;
 		int ret, node;
 
 		node = fit_conf_get_prop_node_index(fit, noffset, prop_name, i);
 		ret = fit_image_get_phase(fit, node, &phase);
+		log_debug("- %s (%s): ", fdt_get_name(fit, node, NULL),
+			  genimg_get_phase_name(phase));
 
 		/* if the image is for any phase, let's use it */
-		if (ret == -ENOENT)
+		if (ret == -ENOENT || phase == sel_phase) {
+			log_debug("found\n");
 			return node;
-		else if (ret < 0)
+		} else if (ret < 0) {
+			log_debug("err=%d\n", ret);
 			return ret;
-
-		if (phase == sel_phase)
-			return node;
+		}
+		log_debug("no match\n");
 	}
+	log_debug("- not found\n");
 
 	return -ENOENT;
 }
@@ -2012,13 +2018,15 @@
 }
 
 /**
- * fit_get_image_type_property() - get property name for IH_TYPE_...
+ * fit_get_image_type_property() - get property name for sel_phase
  *
  * Return: the properly name where we expect to find the image in the
  * config node
  */
-static const char *fit_get_image_type_property(int type)
+static const char *fit_get_image_type_property(int ph_type)
 {
+	int type = image_ph_type(ph_type);
+
 	/*
 	 * This is sort-of available in the uimage_type[] table in image.c
 	 * but we don't have access to the short name, and "fdt" is different
@@ -2070,8 +2078,9 @@
 	fit_uname = fit_unamep ? *fit_unamep : NULL;
 	fit_uname_config = fit_uname_configp ? *fit_uname_configp : NULL;
 	fit_base_uname_config = NULL;
-	prop_name = fit_get_image_type_property(image_type);
-	printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr);
+	prop_name = fit_get_image_type_property(ph_type);
+	printf("## Loading %s (%s) from FIT Image at %08lx ...\n",
+	       prop_name, genimg_get_phase_name(image_ph_phase(ph_type)), addr);
 
 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT);
 	ret = fit_check_format(fit, IMAGE_SIZE_INVAL);
@@ -2346,10 +2355,17 @@
 	char *next_config = NULL;
 	ulong load, len;
 #ifdef CONFIG_OF_LIBFDT_OVERLAY
-	ulong image_start, image_end;
 	ulong ovload, ovlen, ovcopylen;
 	const char *uconfig;
 	const char *uname;
+	/*
+	 * of_flat_tree is storing the void * returned by map_sysmem, then its
+	 * address is passed to boot_relocate_fdt which expects a char ** and it
+	 * is then cast into a ulong. Setting its type to void * would require
+	 * to cast its address to char ** when passing it to boot_relocate_fdt.
+	 * Instead, let's be lazy and use void *.
+	 */
+	char *of_flat_tree;
 	void *base, *ov, *ovcopy = NULL;
 	int i, err, noffset, ov_noffset;
 #endif
@@ -2393,17 +2409,18 @@
 	/* we need to apply overlays */
 
 #ifdef CONFIG_OF_LIBFDT_OVERLAY
-	image_start = addr;
-	image_end = addr + fit_get_size(fit);
-	/* verify that relocation took place by load address not being in fit */
-	if (load >= image_start && load < image_end) {
-		/* check is simplified; fit load checks for overlaps */
-		printf("Overlayed FDT requires relocation\n");
+	/* Relocate FDT so resizing does not overwrite other data in FIT. */
+	of_flat_tree = map_sysmem(load, len);
+	len = ALIGN(fdt_totalsize(load), SZ_4K);
+	err = boot_relocate_fdt(&of_flat_tree, &len);
+	if (err) {
+		printf("Required FDT relocation for applying DTOs failed: %d\n",
+		       err);
 		fdt_noffset = -EBADF;
 		goto out;
 	}
 
-	base = map_sysmem(load, len);
+	load = (ulong)of_flat_tree;
 
 	/* apply extra configs in FIT first, followed by args */
 	for (i = 1; ; i++) {
diff --git a/boot/vbe_abrec.c b/boot/vbe_abrec.c
new file mode 100644
index 0000000..6d0f622
--- /dev/null
+++ b/boot/vbe_abrec.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Verified Boot for Embedded (VBE) 'simple' method
+ *
+ * Copyright 2024 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY LOGC_BOOT
+
+#include <dm.h>
+#include <memalign.h>
+#include <mmc.h>
+#include <dm/ofnode.h>
+#include "vbe_abrec.h"
+
+int abrec_read_priv(ofnode node, struct abrec_priv *priv)
+{
+	memset(priv, '\0', sizeof(*priv));
+	if (ofnode_read_u32(node, "area-start", &priv->area_start) ||
+	    ofnode_read_u32(node, "area-size", &priv->area_size) ||
+	    ofnode_read_u32(node, "version-offset", &priv->version_offset) ||
+	    ofnode_read_u32(node, "version-size", &priv->version_size) ||
+	    ofnode_read_u32(node, "state-offset", &priv->state_offset) ||
+	    ofnode_read_u32(node, "state-size", &priv->state_size))
+		return log_msg_ret("read", -EINVAL);
+	ofnode_read_u32(node, "skip-offset", &priv->skip_offset);
+	priv->storage = strdup(ofnode_read_string(node, "storage"));
+	if (!priv->storage)
+		return log_msg_ret("str", -EINVAL);
+
+	return 0;
+}
+
+int abrec_read_nvdata(struct abrec_priv *priv, struct udevice *blk,
+		      struct abrec_state *state)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(u8, buf, MMC_MAX_BLOCK_LEN);
+	const struct vbe_nvdata *nvd = (struct vbe_nvdata *)buf;
+	uint flags;
+	int ret;
+
+	ret = vbe_read_nvdata(blk, priv->area_start + priv->state_offset,
+			      priv->state_size, buf);
+	if (ret == -EPERM) {
+		memset(buf, '\0', MMC_MAX_BLOCK_LEN);
+		log_warning("Starting with empty state\n");
+	} else if (ret) {
+		return log_msg_ret("nv", ret);
+	}
+
+	state->fw_vernum = nvd->fw_vernum;
+	flags = nvd->flags;
+	state->try_count = flags & VBEF_TRY_COUNT_MASK;
+	state->try_b = flags & VBEF_TRY_B;
+	state->recovery = flags & VBEF_RECOVERY;
+	state->pick = (flags & VBEF_PICK_MASK) >> VBEF_PICK_SHIFT;
+
+	return 0;
+}
+
+int abrec_read_state(struct udevice *dev, struct abrec_state *state)
+{
+	struct abrec_priv *priv = dev_get_priv(dev);
+	struct udevice *blk;
+	int ret;
+
+	ret = vbe_get_blk(priv->storage, &blk);
+	if (ret)
+		return log_msg_ret("blk", ret);
+
+	ret = vbe_read_version(blk, priv->area_start + priv->version_offset,
+			       state->fw_version, MAX_VERSION_LEN);
+	if (ret)
+		return log_msg_ret("ver", ret);
+	log_debug("version=%s\n", state->fw_version);
+
+	ret = abrec_read_nvdata(priv, blk, state);
+	if (ret)
+		return log_msg_ret("nvd", ret);
+
+	return 0;
+}
diff --git a/boot/vbe_abrec.h b/boot/vbe_abrec.h
new file mode 100644
index 0000000..63c7329
--- /dev/null
+++ b/boot/vbe_abrec.h
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Verified Boot for Embedded (VBE) vbe-abrec common file
+ *
+ * Copyright 2024 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __VBE_ABREC_H
+#define __VBE_ABREC_H
+
+#include <vbe.h>
+#include <dm/ofnode_decl.h>
+
+#include "vbe_common.h"
+
+struct bootflow;
+struct udevice;
+
+/**
+ * struct abrec_priv - information read from the device tree
+ *
+ * @area_start: Start offset of the VBE area in the device, in bytes
+ * @area_size: Total size of the VBE area
+ * @skip_offset: Size of an initial part of the device to skip, when using
+ *	area_start. This is effectively added to area_start to calculate the
+ *	actual start position on the device
+ * @state_offset: Offset from area_start of the VBE state, in bytes
+ * @state_size: Size of the state information
+ * @version_offset: Offset from from area_start of the VBE version info
+ * @version_size: Size of the version info
+ * @storage: Storage device to use, in the form <uclass><devnum>, e.g. "mmc1"
+ */
+struct abrec_priv {
+	u32 area_start;
+	u32 area_size;
+	u32 skip_offset;
+	u32 state_offset;
+	u32 state_size;
+	u32 version_offset;
+	u32 version_size;
+	const char *storage;
+};
+
+/** struct abrec_state - state information read from media
+ *
+ * The state on the media is converted into this more code-friendly structure.
+ *
+ * @fw_version: Firmware version string
+ * @fw_vernum: Firmware version number
+ * @try_count: Number of times the B firmware has been tried
+ * @try_b: true to try B firmware on the next boot
+ * @recovery: true to enter recovery firmware on the next boot
+ * @try_result: Result of trying to boot with the last firmware
+ * @pick: Firmware which was chosen in this boot
+ */
+struct abrec_state {
+	char fw_version[MAX_VERSION_LEN];
+	u32 fw_vernum;
+	u8 try_count;
+	bool try_b;
+	bool recovery;
+	enum vbe_try_result try_result;
+	enum vbe_pick_t pick;
+};
+
+/**
+ * abrec_read_fw_bootflow() - Read a bootflow for firmware
+ *
+ * Locates and loads the firmware image (FIT) needed for the next phase. The FIT
+ * should ideally use external data, to reduce the amount of it that needs to be
+ * read.
+ *
+ * @bdev: bootdev device containing the firmwre
+ * @bflow: Place to put the created bootflow, on success
+ * @return 0 if OK, -ve on error
+ */
+int abrec_read_bootflow_fw(struct udevice *dev, struct bootflow *bflow);
+
+/**
+ * vbe_simple_read_state() - Read the VBE simple state information
+ *
+ * @dev: VBE bootmeth
+ * @state: Place to put the state
+ * @return 0 if OK, -ve on error
+ */
+int abrec_read_state(struct udevice *dev, struct abrec_state *state);
+
+/**
+ * abrec_read_nvdata() - Read non-volatile data from a block device
+ *
+ * Reads the ABrec VBE nvdata from a device. This function reads a single block
+ * from the device, so the nvdata cannot be larger than that.
+ *
+ * @blk: Device to read from
+ * @offset: Offset to read, in bytes
+ * @size: Number of bytes to read
+ * @buf: Buffer to hold the data
+ * Return: 0 if OK, -E2BIG if @size > block size, -EBADF if the offset is not
+ * block-aligned, -EIO if an I/O error occurred, -EPERM if the header version is
+ * incorrect, the header size is invalid or the data fails its CRC check
+ */
+int abrec_read_nvdata(struct abrec_priv *priv, struct udevice *blk,
+		      struct abrec_state *state);
+
+/**
+ * abrec_read_priv() - Read info from the devicetree
+ *
+ * @node: Node to read from
+ * @priv: Information to fill in
+ * Return 0 if OK, -EINVAL if something is wrong with the devicetree node
+ */
+int abrec_read_priv(ofnode node, struct abrec_priv *priv);
+
+#endif /* __VBE_ABREC_H */
diff --git a/boot/vbe_abrec_fw.c b/boot/vbe_abrec_fw.c
new file mode 100644
index 0000000..d52bd9d
--- /dev/null
+++ b/boot/vbe_abrec_fw.c
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Verified Boot for Embedded (VBE) loading firmware phases
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY LOGC_BOOT
+
+#include <binman_sym.h>
+#include <bloblist.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootmeth.h>
+#include <bootstage.h>
+#include <display_options.h>
+#include <dm.h>
+#include <image.h>
+#include <log.h>
+#include <mapmem.h>
+#include <memalign.h>
+#include <mmc.h>
+#include <spl.h>
+#include <vbe.h>
+#include <dm/device-internal.h>
+#include "vbe_abrec.h"
+#include "vbe_common.h"
+
+binman_sym_declare(ulong, spl_a, image_pos);
+binman_sym_declare(ulong, spl_b, image_pos);
+binman_sym_declare(ulong, spl_recovery, image_pos);
+
+binman_sym_declare(ulong, spl_a, size);
+binman_sym_declare(ulong, spl_b, size);
+binman_sym_declare(ulong, spl_recovery, size);
+
+binman_sym_declare(ulong, u_boot_a, image_pos);
+binman_sym_declare(ulong, u_boot_b, image_pos);
+binman_sym_declare(ulong, u_boot_recovery, image_pos);
+
+binman_sym_declare(ulong, u_boot_a, size);
+binman_sym_declare(ulong, u_boot_b, size);
+binman_sym_declare(ulong, u_boot_recovery, size);
+
+binman_sym_declare(ulong, vpl, image_pos);
+binman_sym_declare(ulong, vpl, size);
+
+static const char *const pick_names[] = {"A", "B", "Recovery"};
+
+/**
+ * abrec_read_bootflow_fw() - Create a bootflow for firmware
+ *
+ * Locates and loads the firmware image (FIT) needed for the next phase. The FIT
+ * should ideally use external data, to reduce the amount of it that needs to be
+ * read.
+ *
+ * @bdev: bootdev device containing the firmwre
+ * @meth: VBE abrec bootmeth
+ * @blow: Place to put the created bootflow, on success
+ * @return 0 if OK, -ve on error
+ */
+int abrec_read_bootflow_fw(struct udevice *dev, struct bootflow *bflow)
+{
+	struct udevice *media = dev_get_parent(bflow->dev);
+	struct udevice *meth = bflow->method;
+	struct abrec_priv *priv = dev_get_priv(meth);
+	ulong len, load_addr;
+	struct udevice *blk;
+	int ret;
+
+	log_debug("media=%s\n", media->name);
+	ret = blk_get_from_parent(media, &blk);
+	if (ret)
+		return log_msg_ret("med", ret);
+
+	ret = vbe_read_fit(blk, priv->area_start + priv->skip_offset,
+			   priv->area_size, NULL, &load_addr, &len, &bflow->name);
+	if (ret)
+		return log_msg_ret("vbe", ret);
+
+	/* set up the bootflow with the info we obtained */
+	bflow->blk = blk;
+	bflow->buf = map_sysmem(load_addr, len);
+	bflow->size = len;
+
+	return 0;
+}
+
+static int abrec_run_vpl(struct udevice *blk, struct spl_image_info *image,
+			 struct vbe_handoff *handoff)
+{
+	uint flags, tries, prev_result;
+	struct abrec_priv priv;
+	struct abrec_state state;
+	enum vbe_pick_t pick;
+	uint try_count;
+	ulong offset, size;
+	ulong ub_offset, ub_size;
+	ofnode node;
+	int ret;
+
+	node = vbe_get_node();
+	if (!ofnode_valid(node))
+		return log_msg_ret("nod", -EINVAL);
+
+	ret = abrec_read_priv(node, &priv);
+	if (ret)
+		return log_msg_ret("pri", ret);
+
+	ret = abrec_read_nvdata(&priv, blk, &state);
+	if (ret)
+		return log_msg_ret("sta", ret);
+
+	prev_result = state.try_result;
+	try_count = state.try_count;
+
+	if (state.recovery) {
+		pick = VBEP_RECOVERY;
+
+	/* if we are trying B but ran out of tries, use A */
+	} else if ((prev_result == VBETR_TRYING) && !tries) {
+		pick = VBEP_A;
+		state.try_result = VBETR_BAD;
+
+	/* if requested, try B */
+	} else if (flags & VBEF_TRY_B) {
+		pick = VBEP_B;
+
+		/* decrement the try count if not already zero */
+		if (try_count)
+			try_count--;
+		state.try_result = VBETR_TRYING;
+	} else {
+		pick = VBEP_A;
+	}
+	state.try_count = try_count;
+
+	switch (pick) {
+	case VBEP_A:
+		offset = binman_sym(ulong, spl_a, image_pos);
+		size = binman_sym(ulong, spl_a, size);
+		ub_offset = binman_sym(ulong, u_boot_a, image_pos);
+		ub_size = binman_sym(ulong, u_boot_a, size);
+		break;
+	case VBEP_B:
+		offset = binman_sym(ulong, spl_b, image_pos);
+		size = binman_sym(ulong, spl_b, size);
+		ub_offset = binman_sym(ulong, u_boot_b, image_pos);
+		ub_size = binman_sym(ulong, u_boot_b, size);
+		break;
+	case VBEP_RECOVERY:
+		offset = binman_sym(ulong, spl_recovery, image_pos);
+		size = binman_sym(ulong, spl_recovery, size);
+		ub_offset = binman_sym(ulong, u_boot_recovery, image_pos);
+		ub_size = binman_sym(ulong, u_boot_recovery, size);
+		break;
+	}
+	log_debug("pick=%d, offset=%lx size=%lx\n", pick, offset, size);
+	log_info("VBE: Firmware pick %s at %lx\n", pick_names[pick], offset);
+
+	ret = vbe_read_fit(blk, offset, size, image, NULL, NULL, NULL);
+	if (ret)
+		return log_msg_ret("vbe", ret);
+	handoff->offset = ub_offset;
+	handoff->size = ub_size;
+	handoff->pick = pick;
+	image->load_addr = spl_get_image_text_base();
+	image->entry_point = image->load_addr;
+
+	return 0;
+}
+
+static int abrec_run_spl(struct udevice *blk, struct spl_image_info *image,
+			 struct vbe_handoff *handoff)
+{
+	int ret;
+
+	log_info("VBE: Firmware pick %s at %lx\n", pick_names[handoff->pick],
+		 handoff->offset);
+	ret = vbe_read_fit(blk, handoff->offset, handoff->size, image, NULL,
+			   NULL, NULL);
+	if (ret)
+		return log_msg_ret("vbe", ret);
+	image->load_addr = spl_get_image_text_base();
+	image->entry_point = image->load_addr;
+
+	return 0;
+}
+
+static int abrec_load_from_image(struct spl_image_info *image,
+				 struct spl_boot_device *bootdev)
+{
+	struct vbe_handoff *handoff;
+	int ret;
+
+	printf("load: %s\n", ofnode_read_string(ofnode_root(), "model"));
+	if (xpl_phase() != PHASE_VPL && xpl_phase() != PHASE_SPL &&
+	    xpl_phase() != PHASE_TPL)
+		return -ENOENT;
+
+	ret = bloblist_ensure_size(BLOBLISTT_VBE, sizeof(struct vbe_handoff),
+				   0, (void **)&handoff);
+	if (ret)
+		return log_msg_ret("ro", ret);
+
+	if (USE_BOOTMETH) {
+		struct udevice *meth, *bdev;
+		struct abrec_priv *priv;
+		struct bootflow bflow;
+
+		vbe_find_first_device(&meth);
+		if (!meth)
+			return log_msg_ret("vd", -ENODEV);
+		log_debug("vbe dev %s\n", meth->name);
+		ret = device_probe(meth);
+		if (ret)
+			return log_msg_ret("probe", ret);
+
+		priv = dev_get_priv(meth);
+		log_debug("abrec %s\n", priv->storage);
+		ret = bootdev_find_by_label(priv->storage, &bdev, NULL);
+		if (ret)
+			return log_msg_ret("bd", ret);
+		log_debug("bootdev %s\n", bdev->name);
+
+		bootflow_init(&bflow, bdev, meth);
+		ret = bootmeth_read_bootflow(meth, &bflow);
+		log_debug("\nfw ret=%d\n", ret);
+		if (ret)
+			return log_msg_ret("rd", ret);
+
+		/* jump to the image */
+		image->flags = SPL_SANDBOXF_ARG_IS_BUF;
+		image->arg = bflow.buf;
+		image->size = bflow.size;
+		log_debug("Image: %s at %p size %x\n", bflow.name, bflow.buf,
+			  bflow.size);
+
+		/* this is not used from now on, so free it */
+		bootflow_free(&bflow);
+	} else {
+		struct udevice *media;
+		struct udevice *blk;
+
+		ret = uclass_get_device_by_seq(UCLASS_MMC, 1, &media);
+		if (ret)
+			return log_msg_ret("vdv", ret);
+		ret = blk_get_from_parent(media, &blk);
+		if (ret)
+			return log_msg_ret("med", ret);
+
+		if (xpl_phase() == PHASE_TPL) {
+			ulong offset, size;
+
+			offset = binman_sym(ulong, vpl, image_pos);
+			size = binman_sym(ulong, vpl, size);
+			log_debug("VPL at offset %lx size %lx\n", offset, size);
+			ret = vbe_read_fit(blk, offset, size, image, NULL,
+					   NULL, NULL);
+			if (ret)
+				return log_msg_ret("vbe", ret);
+		} else if (xpl_phase() == PHASE_VPL) {
+			ret = abrec_run_vpl(blk, image, handoff);
+		} else {
+			ret = abrec_run_spl(blk, image, handoff);
+		}
+	}
+
+	/* Record that VBE was used in this phase */
+	handoff->phases |= 1 << xpl_phase();
+
+	return 0;
+}
+SPL_LOAD_IMAGE_METHOD("vbe_abrec", 5, BOOT_DEVICE_VBE,
+		      abrec_load_from_image);
diff --git a/boot/vbe_common.c b/boot/vbe_common.c
index 0d51fe7..a86986d 100644
--- a/boot/vbe_common.c
+++ b/boot/vbe_common.c
@@ -202,29 +202,30 @@
 	phase = IS_ENABLED(CONFIG_TPL_BUILD) ? IH_PHASE_NONE :
 		IS_ENABLED(CONFIG_VPL_BUILD) ? IH_PHASE_SPL : IH_PHASE_U_BOOT;
 
-	/*
-	 * Load the image from the FIT. We ignore any load-address information
-	 * so in practice this simply locates the image in the external-data
-	 * region and returns its address and size. Since we only loaded the FIT
-	 * itself, only a part of the image will be present, at best.
-	 */
-	fit_uname = NULL;
-	fit_uname_config = NULL;
 	log_debug("loading FIT\n");
 
 	if (xpl_phase() == PHASE_SPL && !IS_ENABLED(CONFIG_SANDBOX)) {
 		struct spl_load_info info;
 
 		spl_load_init(&info, h_vbe_load_read, desc, desc->blksz);
+		xpl_set_fdt_update(&info, false);
 		xpl_set_phase(&info, IH_PHASE_U_BOOT);
 		log_debug("doing SPL from %s blksz %lx log2blksz %x area_offset %lx + fdt_size %lx\n",
 			  blk->name, desc->blksz, desc->log2blksz, area_offset, ALIGN(size, 4));
 		ret = spl_load_simple_fit(image, &info, area_offset, buf);
-		log_debug("spl_load_abrec_fit() ret=%d\n", ret);
+		log_debug("spl_load_simple_fit() ret=%d\n", ret);
 
 		return ret;
 	}
 
+	/*
+	 * Load the image from the FIT. We ignore any load-address information
+	 * so in practice this simply locates the image in the external-data
+	 * region and returns its address and size. Since we only loaded the FIT
+	 * itself, only a part of the image will be present, at best.
+	 */
+	fit_uname = NULL;
+	fit_uname_config = NULL;
 	ret = fit_image_load(&images, addr, &fit_uname, &fit_uname_config,
 			     IH_ARCH_DEFAULT, image_ph(phase, IH_TYPE_FIRMWARE),
 			     BOOTSTAGE_ID_FIT_SPL_START, FIT_LOAD_IGNORED,
@@ -373,3 +374,8 @@
 
 	return 0;
 }
+
+ofnode vbe_get_node(void)
+{
+	return ofnode_path("/bootstd/firmware0");
+}
diff --git a/boot/vbe_common.h b/boot/vbe_common.h
index 8411781..493cbdc 100644
--- a/boot/vbe_common.h
+++ b/boot/vbe_common.h
@@ -9,6 +9,8 @@
 #ifndef __VBE_COMMON_H
 #define __VBE_COMMON_H
 
+#include <dm/ofnode_decl.h>
+#include <linux/bitops.h>
 #include <linux/types.h>
 
 struct spl_image_info;
@@ -39,6 +41,40 @@
 };
 
 /**
+ * enum vbe_try_result - result of trying a firmware pick
+ *
+ * @VBETR_UNKNOWN: Unknown / invalid result
+ * @VBETR_TRYING: Firmware pick is being tried
+ * @VBETR_OK: Firmware pick is OK and can be used from now on
+ * @VBETR_BAD: Firmware pick is bad and should be removed
+ */
+enum vbe_try_result {
+	VBETR_UNKNOWN,
+	VBETR_TRYING,
+	VBETR_OK,
+	VBETR_BAD,
+};
+
+/**
+ * enum vbe_flags - flags controlling operation
+ *
+ * @VBEF_TRY_COUNT_MASK: mask for the 'try count' value
+ * @VBEF_TRY_B: Try the B slot
+ * @VBEF_RECOVERY: Use recovery slot
+ */
+enum vbe_flags {
+	VBEF_TRY_COUNT_MASK	= 0x3,
+	VBEF_TRY_B		= BIT(2),
+	VBEF_RECOVERY		= BIT(3),
+
+	VBEF_RESULT_SHIFT	= 4,
+	VBEF_RESULT_MASK	= 3 << VBEF_RESULT_SHIFT,
+
+	VBEF_PICK_SHIFT		= 6,
+	VBEF_PICK_MASK		= 3 << VBEF_PICK_SHIFT,
+};
+
+/**
  * struct vbe_nvdata - basic storage format for non-volatile data
  *
  * This is used for all VBE methods
@@ -134,4 +170,11 @@
 		 struct spl_image_info *image, ulong *load_addrp, ulong *lenp,
 		 char **namep);
 
+/**
+ * vbe_get_node() - Get the node containing the VBE settings
+ *
+ * Return: VBE node (typically "/bootstd/firmware0")
+ */
+ofnode vbe_get_node(void);
+
 #endif /* __VBE_ABREC_H */
diff --git a/cmd/Kconfig b/cmd/Kconfig
index e62817b..1f9b269 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1178,16 +1178,30 @@
 	help
 	  FPGA support.
 
-config CMD_FPGA_LOADBP
-	bool "fpga loadbp - load partial bitstream (Xilinx only)"
+config CMD_FPGA_LOADB
+	bool "fpga loadb - load bitstream file"
+	default y
+	depends on CMD_FPGA && FPGA_XILINX
+	help
+	  Supports loading an FPGA device from a bitstream file (.BIT)
+
+config CMD_FPGA_LOADP
+	bool "fpga loadp - load partial bitstream"
 	depends on CMD_FPGA
 	help
+	  Supports loading an FPGA device from a bitstream buffer (.BIN)
+	  containing a partial bitstream.
+
+config CMD_FPGA_LOADBP
+	bool "fpga loadbp - load partial bitstream file"
+	depends on CMD_FPGA && FPGA_XILINX
+	help
-	  Supports loading an FPGA device from a bitstream buffer containing
-	  a partial bitstream.
+	  Supports loading an FPGA device from a bitstream file (.BIT)
+	  containing a partial bitstream.
 
 config CMD_FPGA_LOADFS
-	bool "fpga loadfs - load bitstream from FAT filesystem (Xilinx only)"
-	depends on CMD_FPGA
+	bool "fpga loadfs - load bitstream from FAT filesystem"
+	depends on CMD_FPGA && FPGA_XILINX
 	help
 	  Supports loading an FPGA device from a FAT filesystem.
 
@@ -1197,16 +1211,9 @@
 	help
 	  Supports loading an FPGA device from a image generated by mkimage.
 
-config CMD_FPGA_LOADP
-	bool "fpga loadp - load partial bitstream"
-	depends on CMD_FPGA
-	help
-	  Supports loading an FPGA device from a bitstream buffer containing
-	  a partial bitstream.
-
 config CMD_FPGA_LOAD_SECURE
 	bool "fpga loads - loads secure bitstreams"
-	depends on CMD_FPGA
+	depends on CMD_FPGA && FPGA_XILINX
 	select FPGA_LOAD_SECURE
 	help
 	  Enables the fpga loads command which is used to load secure
diff --git a/cmd/fpga.c b/cmd/fpga.c
index 93f1409..9dc7b63 100644
--- a/cmd/fpga.c
+++ b/cmd/fpga.c
@@ -67,7 +67,8 @@
 }
 
 #if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
-int do_fpga_loads(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+static int do_fpga_loads(struct cmd_tbl *cmdtp, int flag, int argc,
+			 char *const argv[])
 {
 	size_t data_size = 0;
 	long fpga_data, dev;
@@ -180,6 +181,7 @@
 	return fpga_load(dev, (void *)fpga_data, data_size, BIT_FULL, 0);
 }
 
+#if defined(CONFIG_CMD_FPGA_LOADB)
 static int do_fpga_loadb(struct cmd_tbl *cmdtp, int flag, int argc,
 			 char *const argv[])
 {
@@ -194,7 +196,7 @@
 
 	return fpga_loadbitstream(dev, (void *)fpga_data, data_size, BIT_FULL);
 }
-
+#endif
 #if defined(CONFIG_CMD_FPGA_LOADP)
 static int do_fpga_loadp(struct cmd_tbl *cmdtp, int flag, int argc,
 			 char *const argv[])
@@ -356,7 +358,9 @@
 	U_BOOT_CMD_MKENT(info, 1, 1, do_fpga_info, "", ""),
 	U_BOOT_CMD_MKENT(dump, 3, 1, do_fpga_dump, "", ""),
 	U_BOOT_CMD_MKENT(load, 3, 1, do_fpga_load, "", ""),
+#if defined(CONFIG_CMD_FPGA_LOADB)
 	U_BOOT_CMD_MKENT(loadb, 3, 1, do_fpga_loadb, "", ""),
+#endif
 #if defined(CONFIG_CMD_FPGA_LOADP)
 	U_BOOT_CMD_MKENT(loadp, 3, 1, do_fpga_loadp, "", ""),
 #endif
@@ -408,49 +412,40 @@
 #else
 U_BOOT_CMD(fpga, 6, 1, do_fpga_wrapper,
 #endif
+	 "loadable FPGA image support",
+	 "info   [dev]                  List known device information\n"
+	 "fpga dump   <dev> <address> <size> Load device to memory buffer\n"
+	 "fpga load   <dev> <address> <size> Load device from memory buffer\n"
+#if defined(CONFIG_CMD_FPGA_LOADP)
+	 "fpga loadb  <dev> <address> <size> Load device from bitstream buffer\n"
+#endif
-	   "loadable FPGA image support",
-	   "[operation type] [device number] [image address] [image size]\n"
-	   "fpga operations:\n"
-	   "  dump\t[dev] [address] [size]\tLoad device to memory buffer\n"
-	   "  info\t[dev]\t\t\tlist known device information\n"
-	   "  load\t[dev] [address] [size]\tLoad device from memory buffer\n"
 #if defined(CONFIG_CMD_FPGA_LOADP)
-	   "  loadp\t[dev] [address] [size]\t"
-	   "Load device from memory buffer with partial bitstream\n"
+	 "fpga loadp  <dev> <address> <size> Load device from memory buffer\n"
+	 "            with partial bitstream\n"
 #endif
-	   "  loadb\t[dev] [address] [size]\t"
-	   "Load device from bitstream buffer (Xilinx only)\n"
 #if defined(CONFIG_CMD_FPGA_LOADBP)
-	   "  loadbp\t[dev] [address] [size]\t"
-	   "Load device from bitstream buffer with partial bitstream"
-	   "(Xilinx only)\n"
+	 "fpga loadbp <dev> <address> <size> Load device from bitstream buffer\n"
+	 "             with partial bitstream\n"
 #endif
 #if defined(CONFIG_CMD_FPGA_LOADFS)
-	   "Load device from filesystem (FAT by default) (Xilinx only)\n"
-	   "  loadfs [dev] [address] [image size] [blocksize] <interface>\n"
-	   "        [<dev[:part]>] <filename>\n"
+	 "fpga loadfs <dev> <address> <size> <blocksize> <interface> [<dev[:part]>] <filename>\n"
+	 "            Load device from filesystem (FAT by default)\n"
 #endif
 #if defined(CONFIG_CMD_FPGA_LOADMK)
-	   "  loadmk [dev] [address]\tLoad device generated with mkimage"
+	 "fpga loadmk <dev> <address>        Load device generated with mkimage\n"
 #if defined(CONFIG_FIT)
-	   "\n"
-	   "\tFor loadmk operating on FIT format uImage address must include\n"
-	   "\tsubimage unit name in the form of addr:<subimg_uname>"
+	 "            NOTE: loadmk operating on FIT must include subimage unit\n"
+	 "            name in the form of addr:<subimg_uname>\n"
 #endif
 #endif
 #if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
-	   "Load encrypted bitstream (Xilinx only)\n"
-	   "  loads [dev] [address] [size] [auth-OCM-0/DDR-1/noauth-2]\n"
-	   "        [enc-devkey(0)/userkey(1)/nenc(2) [Userkey address]\n"
-	   "Loads the secure bistreams(authenticated/encrypted/both\n"
-	   "authenticated and encrypted) of [size] from [address].\n"
-	   "The auth-OCM/DDR flag specifies to perform authentication\n"
-	   "in OCM or in DDR. 0 for OCM, 1 for DDR, 2 for no authentication.\n"
-	   "The enc flag specifies which key to be used for decryption\n"
-	   "0-device key, 1-user key, 2-no encryption.\n"
-	   "The optional Userkey address specifies from which address key\n"
-	   "has to be used for decryption if user key is selected.\n"
-	   "NOTE: the secure bitstream has to be created using Xilinx\n"
-	   "bootgen tool only.\n"
+	 "fpga loads  <dev> <address> <size> <authflag> <encflag> [Userkey address]\n"
+	 "            Load device from memory buffer with secure bistream\n"
+	 "            (authenticated/encrypted/both)\n"
+	 "            -authflag: 0 for OCM, 1 for DDR, 2 for no authentication\n"
+	 "            (specifies where to perform authentication)\n"
+	 "            -encflag: 0 for device key, 1 for user key, 2 for no encryption\n"
+	 "            -Userkey address: address where user key is stored\n"
+	 "            NOTE: secure bitstream has to be created using Xilinx bootgen tool\n"
 #endif
 );
diff --git a/cmd/riscv/sbi.c b/cmd/riscv/sbi.c
index 5ecf567..b013c8c 100644
--- a/cmd/riscv/sbi.c
+++ b/cmd/riscv/sbi.c
@@ -30,6 +30,7 @@
 	{ 8, "PolarFire Hart Software Services" },
 	{ 9, "coreboot" },
 	{ 10, "oreboot" },
+	{ 11, "bhyve" },
 };
 
 static struct sbi_ext extensions[] = {
diff --git a/cmd/setexpr.c b/cmd/setexpr.c
index e111b8b..c45fa85 100644
--- a/cmd/setexpr.c
+++ b/cmd/setexpr.c
@@ -35,9 +35,37 @@
 	};
 };
 
+/**
+ * arg_set_str() - copy string to expression argument
+ *
+ * The string is truncated to 64 KiB plus NUL terminator.
+ *
+ * @p:		pointer to string
+ * @argp:	pointer to expression argument
+ * Return:	0 on success, -ENOMEM if out of memory
+ */
+static int arg_set_str(void *p, struct expr_arg *argp)
+{
+	int len;
+	char *str;
+
+	/* Maximum string length of 64 KiB plus NUL terminator */
+	len = strnlen((char *)p, SZ_64K) + 1;
+	str = malloc(len);
+	if (!str) {
+		printf("Out of memory\n");
+		return -ENOMEM;
+	}
+	memcpy(str, p, len);
+	str[len - 1] = '\0';
+	argp->sval = str;
+	return 0;
+}
+
 static int get_arg(char *s, int w, struct expr_arg *argp)
 {
 	struct expr_arg arg;
+	int ret;
 
 	/*
 	 * If the parameter starts with a '*' then assume it is a pointer to
@@ -47,8 +75,6 @@
 		ulong *p;
 		ulong addr;
 		ulong val;
-		int len;
-		char *str;
 
 		addr = hextoul(&s[1], NULL);
 		switch (w) {
@@ -66,18 +92,10 @@
 			break;
 		case CMD_DATA_SIZE_STR:
 			p = map_sysmem(addr, SZ_64K);
-
-			/* Maximum string length of 64KB plus terminator */
-			len = strnlen((char *)p, SZ_64K) + 1;
-			str = malloc(len);
-			if (!str) {
-				printf("Out of memory\n");
-				return -ENOMEM;
-			}
-			memcpy(str, p, len);
-			str[len - 1] = '\0';
+			ret = arg_set_str(p, &arg);
 			unmap_sysmem(p);
-			arg.sval = str;
+			if (ret)
+				return ret;
 			break;
 		case 4:
 			p = map_sysmem(addr, sizeof(u32));
@@ -93,9 +111,13 @@
 			break;
 		}
 	} else {
-		if (w == CMD_DATA_SIZE_STR)
-			return -EINVAL;
-		arg.ival = hextoul(s, NULL);
+		if (w == CMD_DATA_SIZE_STR) {
+			ret = arg_set_str(s, &arg);
+			if (ret)
+				return ret;
+		} else {
+			arg.ival = hextoul(s, NULL);
+		}
 	}
 	*argp = arg;
 
diff --git a/common/hash.c b/common/hash.c
index 8dd9da8..0c45992 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -143,7 +143,8 @@
 	return 0;
 }
 
-static int hash_init_crc16_ccitt(struct hash_algo *algo, void **ctxp)
+static int __maybe_unused hash_init_crc16_ccitt(struct hash_algo *algo,
+						void **ctxp)
 {
 	uint16_t *ctx = malloc(sizeof(uint16_t));
 	*ctx = 0;
@@ -151,16 +152,18 @@
 	return 0;
 }
 
-static int hash_update_crc16_ccitt(struct hash_algo *algo, void *ctx,
-				   const void *buf, unsigned int size,
-				   int is_last)
+static int __maybe_unused hash_update_crc16_ccitt(struct hash_algo *algo,
+						  void *ctx, const void *buf,
+						  unsigned int size,
+						  int is_last)
 {
 	*((uint16_t *)ctx) = crc16_ccitt(*((uint16_t *)ctx), buf, size);
 	return 0;
 }
 
-static int hash_finish_crc16_ccitt(struct hash_algo *algo, void *ctx,
-				   void *dest_buf, int size)
+static int __maybe_unused hash_finish_crc16_ccitt(struct hash_algo *algo,
+						  void *ctx, void *dest_buf,
+						  int size)
 {
 	if (size < algo->digest_size)
 		return -1;
@@ -295,6 +298,7 @@
 #endif
 	},
 #endif
+#if CONFIG_IS_ENABLED(CRC16)
 	{
 		.name		= "crc16-ccitt",
 		.digest_size	= 2,
@@ -304,6 +308,7 @@
 		.hash_update	= hash_update_crc16_ccitt,
 		.hash_finish	= hash_finish_crc16_ccitt,
 	},
+#endif
 #if CONFIG_IS_ENABLED(CRC8) && IS_ENABLED(CONFIG_HASH_CRC8)
 	{
 		.name		= "crc8",
diff --git a/common/spl/Kconfig.vpl b/common/spl/Kconfig.vpl
index 97dfc63..cf6b36c 100644
--- a/common/spl/Kconfig.vpl
+++ b/common/spl/Kconfig.vpl
@@ -9,6 +9,19 @@
 	  info. Disabling this option could be useful to reduce VPL boot time
 	  (e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud).
 
+config VPL_LDSCRIPT
+	string "Linker script for the VPL stage"
+	default "arch/arm/cpu/armv8/u-boot-spl.lds" if ARM64
+	default "arch/\$(ARCH)/cpu/u-boot-spl.lds"
+	help
+	  The TPL stage will usually require a different linker-script
+	  (as it runs from a different memory region) than the regular
+	  U-Boot stage.  Set this to the path of the linker-script to
+	  be used for TPL.
+
+	  May be left empty to trigger the Makefile infrastructure to
+	  fall back to the linker-script used for the SPL stage.
+
 config VPL_BOARD_INIT
 	bool "Call board-specific initialization in VPL"
 	help
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 9af0a49..76fd56d 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -50,8 +50,10 @@
 
 #if CONFIG_IS_ENABLED(BINMAN_UBOOT_SYMBOLS)
 /* See spl.h for information about this */
+#if defined(CONFIG_SPL_BUILD)
 binman_sym_declare(ulong, u_boot_any, image_pos);
 binman_sym_declare(ulong, u_boot_any, size);
+#endif
 
 #ifdef CONFIG_TPL
 binman_sym_declare(ulong, u_boot_spl_any, image_pos);
@@ -179,9 +181,15 @@
 	if (xpl_next_phase() == PHASE_VPL)
 		return binman_sym(ulong, u_boot_vpl_any, image_pos);
 #endif
-	return xpl_next_phase() == PHASE_SPL ?
-		binman_sym(ulong, u_boot_spl_any, image_pos) :
-		binman_sym(ulong, u_boot_any, image_pos);
+#if defined(CONFIG_TPL) && !defined(CONFIG_VPL)
+	if (xpl_next_phase() == PHASE_SPL)
+		return binman_sym(ulong, u_boot_spl_any, image_pos);
+#endif
+#if defined(CONFIG_SPL_BUILD)
+	return binman_sym(ulong, u_boot_any, image_pos);
+#endif
+
+	return BINMAN_SYM_MISSING;
 }
 
 ulong spl_get_image_size(void)
@@ -263,14 +271,20 @@
 	 */
 	if (u_boot_pos && u_boot_pos != BINMAN_SYM_MISSING) {
 		/* Binman does not support separated entry addresses */
-		spl_image->entry_point = u_boot_pos;
-		spl_image->load_addr = u_boot_pos;
+		spl_image->entry_point = spl_get_image_text_base();
+		spl_image->load_addr = spl_get_image_text_base();
+		spl_image->size = spl_get_image_size();
+		log_debug("Next load addr %lx\n", spl_image->load_addr);
 	} else {
 		spl_image->entry_point = CONFIG_SYS_UBOOT_START;
 		spl_image->load_addr = CONFIG_TEXT_BASE;
+		log_debug("Default load addr %x (u_boot_pos=%lx)\n",
+			  CONFIG_TEXT_BASE, u_boot_pos);
 	}
 	spl_image->os = IH_OS_U_BOOT;
-	spl_image->name = "U-Boot";
+	spl_image->name = xpl_name(xpl_next_phase());
+	log_debug("Next phase: %s at %lx size %lx\n", spl_image->name,
+		  spl_image->load_addr, (ulong)spl_image->size);
 }
 
 __weak int spl_parse_board_header(struct spl_image_info *spl_image,
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 64c4349..49b4df6 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -199,7 +199,9 @@
  *		the image gets loaded to the address pointed to by the
  *		load_addr member in this struct, if load_addr is not 0
  *
- * Return:	0 on success or a negative error number.
+ * Return:	0 on success, -EPERM if this image is not the correct phase
+ * (for CONFIG_BOOTMETH_VBE_SIMPLE_FW), or another negative error number on
+ * other error.
  */
 static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
 			   const struct spl_fit_info *ctx, int node,
@@ -218,6 +220,25 @@
 	const void *fit = ctx->fit;
 	bool external_data = false;
 
+	log_debug("starting\n");
+	if (CONFIG_IS_ENABLED(BOOTMETH_VBE) &&
+	    xpl_get_phase(info) != IH_PHASE_NONE) {
+		enum image_phase_t phase;
+		int ret;
+
+		ret = fit_image_get_phase(fit, node, &phase);
+		/* if the image is for any phase, let's use it */
+		if (ret == -ENOENT || phase == xpl_get_phase(info)) {
+			log_debug("found\n");
+		} else if (ret < 0) {
+			log_debug("err=%d\n", ret);
+			return ret;
+		} else {
+			log_debug("- phase mismatch, skipping this image\n");
+			return -EPERM;
+		}
+	}
+
 	if (IS_ENABLED(CONFIG_SPL_FPGA) ||
 	    (IS_ENABLED(CONFIG_SPL_OS_BOOT) && spl_decompression_enabled())) {
 		if (fit_image_get_type(fit, node, &type))
@@ -278,10 +299,7 @@
 		log_debug("reading from offset %x / %lx size %lx to %p: ",
 			  offset, read_offset, size, src_ptr);
 
-		if (info->read(info,
-			       fit_offset +
-			       get_aligned_image_offset(info, offset), size,
-			       src_ptr) < length)
+		if (info->read(info, read_offset, size, src_ptr) < length)
 			return -EIO;
 
 		debug("External data: dst=%p, offset=%x, size=%lx\n",
@@ -456,7 +474,9 @@
 			image_info.load_addr = (ulong)tmpbuffer;
 			ret = load_simple_fit(info, offset, ctx, node,
 					      &image_info);
-			if (ret < 0)
+			if (ret == -EPERM)
+				continue;
+			else if (ret < 0)
 				break;
 
 			/* Make room in FDT for changes from the overlay */
@@ -495,9 +515,6 @@
 	const char *name;
 	int node;
 
-	if (CONFIG_IS_ENABLED(FIT_IMAGE_TINY))
-		return 0;
-
 	ret = spl_fit_get_image_name(ctx, "loadables", index, &name);
 	if (ret < 0)
 		return ret;
@@ -817,7 +834,7 @@
 
 		image_info.load_addr = 0;
 		ret = load_simple_fit(info, offset, &ctx, node, &image_info);
-		if (ret < 0) {
+		if (ret < 0 && ret != -EPERM) {
 			printf("%s: can't load image loadables index %d (ret = %d)\n",
 			       __func__, index, ret);
 			return ret;
@@ -843,7 +860,8 @@
 			spl_image->entry_point = image_info.entry_point;
 
 		/* Record our loadables into the FDT */
-		if (spl_image->fdt_addr)
+		if (!CONFIG_IS_ENABLED(FIT_IMAGE_TINY) &&
+		    xpl_get_fdt_update(info) && spl_image->fdt_addr)
 			spl_fit_record_loadable(&ctx, index,
 						spl_image->fdt_addr,
 						&image_info);
diff --git a/common/spl/spl_reloc.c b/common/spl/spl_reloc.c
index be8349b..324b98e 100644
--- a/common/spl/spl_reloc.c
+++ b/common/spl/spl_reloc.c
@@ -154,7 +154,7 @@
 	rcode_func loader;
 	int ret;
 
-	log_debug("malloc usage %lx bytes (%ld KB of %d KB)\n", gd->malloc_ptr,
+	log_debug("malloc usage %x bytes (%d KB of %d KB)\n", gd->malloc_ptr,
 		  gd->malloc_ptr / 1024, CONFIG_VAL(SYS_MALLOC_F_LEN) / 1024);
 
 	if (*image->stack_prot != STACK_PROT_VALUE) {
diff --git a/config.mk b/config.mk
index e294be2..abed9cb 100644
--- a/config.mk
+++ b/config.mk
@@ -76,4 +76,3 @@
 export RELFLAGS
 export LDFLAGS_FINAL
 export LDFLAGS_STANDALONE
-export CONFIG_STANDALONE_LOAD_ADDR
diff --git a/configs/am62x_beagleplay_a53_defconfig b/configs/am62x_beagleplay_a53_defconfig
index af54f96..a8a7316 100644
--- a/configs/am62x_beagleplay_a53_defconfig
+++ b/configs/am62x_beagleplay_a53_defconfig
@@ -30,7 +30,6 @@
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SPL_LOAD_FIT_ADDRESS=0x81000000
 CONFIG_BOOTSTD_FULL=y
-CONFIG_SYS_BOOTM_LEN=0x800000
 CONFIG_AUTOBOOT_KEYED=y
 CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
 CONFIG_AUTOBOOT_DELAY_STR="d"
diff --git a/configs/am62x_evm_a53_defconfig b/configs/am62x_evm_a53_defconfig
index c77e09d..6527200 100644
--- a/configs/am62x_evm_a53_defconfig
+++ b/configs/am62x_evm_a53_defconfig
@@ -33,7 +33,6 @@
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SPL_LOAD_FIT_ADDRESS=0x81000000
 CONFIG_BOOTSTD_FULL=y
-CONFIG_SYS_BOOTM_LEN=0x800000
 CONFIG_BOOTCOMMAND="run findfdt; run envboot; bootflow scan -lb"
 CONFIG_BOARD_LATE_INIT=y
 CONFIG_SPL_MAX_SIZE=0x58000
diff --git a/configs/am65x_evm_r5_defconfig b/configs/am65x_evm_r5_defconfig
index 4bd5e8f..289c41c 100644
--- a/configs/am65x_evm_r5_defconfig
+++ b/configs/am65x_evm_r5_defconfig
@@ -24,7 +24,6 @@
 CONFIG_SPL_BSS_START_ADDR=0x41c7effc
 CONFIG_SPL_BSS_MAX_SIZE=0xc00
 CONFIG_SPL_STACK_R=y
-CONFIG_SYS_BOOTM_LEN=0x4000000
 CONFIG_SPL_SIZE_LIMIT=0x7ec00
 CONFIG_SPL_SIZE_LIMIT_PROVIDE_STACK=0x2000
 CONFIG_SPL_FS_FAT=y
diff --git a/configs/am65x_evm_r5_usbdfu_defconfig b/configs/am65x_evm_r5_usbdfu_defconfig
index ae57007..0b5eaeb 100644
--- a/configs/am65x_evm_r5_usbdfu_defconfig
+++ b/configs/am65x_evm_r5_usbdfu_defconfig
@@ -22,7 +22,6 @@
 CONFIG_SPL_BSS_START_ADDR=0x41c7effc
 CONFIG_SPL_BSS_MAX_SIZE=0xc00
 CONFIG_SPL_STACK_R=y
-CONFIG_SYS_BOOTM_LEN=0x4000000
 CONFIG_SPL_SIZE_LIMIT=0x7ec00
 CONFIG_SPL_SIZE_LIMIT_PROVIDE_STACK=0x2000
 CONFIG_SPL_LIBDISK_SUPPORT=y
diff --git a/configs/am65x_evm_r5_usbmsc_defconfig b/configs/am65x_evm_r5_usbmsc_defconfig
index 3aa17eb..ef2ff41 100644
--- a/configs/am65x_evm_r5_usbmsc_defconfig
+++ b/configs/am65x_evm_r5_usbmsc_defconfig
@@ -22,7 +22,6 @@
 CONFIG_SPL_BSS_START_ADDR=0x41c7effc
 CONFIG_SPL_BSS_MAX_SIZE=0xc00
 CONFIG_SPL_STACK_R=y
-CONFIG_SYS_BOOTM_LEN=0x4000000
 CONFIG_SPL_SIZE_LIMIT=0x7ec00
 CONFIG_SPL_SIZE_LIMIT_PROVIDE_STACK=0x2000
 CONFIG_SPL_FS_FAT=y
diff --git a/configs/amd_versal2_virt_defconfig b/configs/amd_versal2_virt_defconfig
index b4aebf3..8bee002 100644
--- a/configs/amd_versal2_virt_defconfig
+++ b/configs/amd_versal2_virt_defconfig
@@ -17,6 +17,7 @@
 CONFIG_SYS_MEMTEST_START=0x00000000
 CONFIG_SYS_MEMTEST_END=0x00001000
 CONFIG_REMAKE_ELF=y
+CONFIG_EFI_HTTP_BOOT=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_DISTRO_DEFAULTS=y
@@ -30,6 +31,8 @@
 CONFIG_CMD_BOOTMENU=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_NVEDIT_EFI=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMINFO_MAP=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_SYS_ALT_MEMTEST=y
 CONFIG_CMD_SHA1SUM=y
@@ -39,15 +42,13 @@
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_MMC_SPEED_MODE_SET=y
+CONFIG_CMD_OPTEE=y
 CONFIG_CMD_MTD=y
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_UFS=y
 CONFIG_CMD_USB=y
-CONFIG_BOOTP_MAY_FAIL=y
-CONFIG_BOOTP_BOOTFILESIZE=y
-CONFIG_CMD_TFTPPUT=y
-CONFIG_CMD_NFS=y
+CONFIG_WGET_HTTPS=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_EFIDEBUG=y
 CONFIG_CMD_TIME=y
@@ -67,9 +68,7 @@
 CONFIG_MULTI_DTB_FIT=y
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
-CONFIG_NETCONSOLE=y
-CONFIG_IP_DEFRAG=y
-CONFIG_SYS_FAULT_ECHO_LINK_DOWN=y
+CONFIG_NET_LWIP=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_TFTP_BLOCKSIZE=4096
 CONFIG_SIMPLE_PM_BUS=y
@@ -152,5 +151,7 @@
 CONFIG_VIRTIO_MMIO=y
 CONFIG_VIRTIO_NET=y
 CONFIG_VIRTIO_BLK=y
+CONFIG_MBEDTLS_LIB=y
 CONFIG_TPM=y
 # CONFIG_OPTEE_LIB is not set
+CONFIG_TOOLS_MKFWUMDATA=y
diff --git a/configs/e850-96_defconfig b/configs/e850-96_defconfig
index c36196c..5facd41 100644
--- a/configs/e850-96_defconfig
+++ b/configs/e850-96_defconfig
@@ -8,23 +8,40 @@
 CONFIG_ARCH_EXYNOS9=y
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xf8c00000
+CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x0
 CONFIG_DEFAULT_DEVICE_TREE="exynos/exynos850-e850-96"
 CONFIG_SYS_LOAD_ADDR=0x80000000
+CONFIG_ENV_OFFSET_REDUND=0x10000
 # CONFIG_PSCI_RESET is not set
+CONFIG_EFI_SET_TIME=y
 CONFIG_ANDROID_BOOT_IMAGE=y
-# CONFIG_AUTOBOOT is not set
+CONFIG_BOOTSTD_FULL=y
+CONFIG_DEFAULT_FDT_FILE="exynos850-e850-96.dtb"
 # CONFIG_DISPLAY_CPUINFO is not set
-CONFIG_HUSH_PARSER=y
+CONFIG_CMD_BOOTEFI_SELFTEST=y
 CONFIG_CMD_ABOOTIMG=y
+CONFIG_CMD_NVEDIT_EFI=y
 CONFIG_CMD_CLK=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_MMC=y
-CONFIG_CMD_PART=y
+CONFIG_CMD_EFIDEBUG=y
+# CONFIG_CMD_DATE is not set
+CONFIG_CMD_RTC=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_RNG=y
+CONFIG_PARTITION_TYPE_GUID=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_SYS_MMC_ENV_PART=2
 CONFIG_NO_NET=y
 CONFIG_CLK_EXYNOS850=y
+CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_MMC_DW=y
+CONFIG_DM_RTC=y
+CONFIG_RTC_EMULATION=y
 CONFIG_SOC_SAMSUNG=y
 CONFIG_EXYNOS_PMU=y
 CONFIG_EXYNOS_USI=y
diff --git a/configs/j721e_evm_r5_defconfig b/configs/j721e_evm_r5_defconfig
index 42000cc..c4e9f2d 100644
--- a/configs/j721e_evm_r5_defconfig
+++ b/configs/j721e_evm_r5_defconfig
@@ -26,7 +26,6 @@
 CONFIG_SPL_BSS_START_ADDR=0x41cf59f0
 CONFIG_SPL_BSS_MAX_SIZE=0xa000
 CONFIG_SPL_STACK_R=y
-CONFIG_SYS_BOOTM_LEN=0x4000000
 CONFIG_SPL_SIZE_LIMIT=0xf59f0
 CONFIG_SPL_SIZE_LIMIT_PROVIDE_STACK=0x4000
 CONFIG_SPL_FS_FAT=y
diff --git a/configs/j721s2_evm_r5_defconfig b/configs/j721s2_evm_r5_defconfig
index 23ae991..7ec9af8 100644
--- a/configs/j721s2_evm_r5_defconfig
+++ b/configs/j721s2_evm_r5_defconfig
@@ -26,7 +26,6 @@
 CONFIG_SPL_BSS_START_ADDR=0x41c76000
 CONFIG_SPL_BSS_MAX_SIZE=0xa000
 CONFIG_SPL_STACK_R=y
-CONFIG_SYS_BOOTM_LEN=0x4000000
 CONFIG_SPL_SIZE_LIMIT=0x80000
 CONFIG_SPL_SIZE_LIMIT_PROVIDE_STACK=0x4000
 CONFIG_SPL_FS_FAT=y
diff --git a/configs/microblaze-generic_defconfig b/configs/microblaze-generic_defconfig
index 2e618d8..87756cb 100644
--- a/configs/microblaze-generic_defconfig
+++ b/configs/microblaze-generic_defconfig
@@ -42,6 +42,8 @@
 CONFIG_CMD_SPL=y
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMINFO_MAP=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_SAVES=y
 CONFIG_BOOTP_BOOTFILESIZE=y
diff --git a/configs/phycore_am64x_r5_defconfig b/configs/phycore_am64x_r5_defconfig
index 6b0fd8d..d060a0f 100644
--- a/configs/phycore_am64x_r5_defconfig
+++ b/configs/phycore_am64x_r5_defconfig
@@ -7,6 +7,7 @@
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_SOC_K3_AM642=y
 CONFIG_TARGET_PHYCORE_AM64X_R5=y
+CONFIG_PHYTEC_SOM_DETECTION=y
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x7019b800
 CONFIG_SF_DEFAULT_SPEED=25000000
@@ -15,6 +16,7 @@
 CONFIG_DM_GPIO=y
 CONFIG_SPL_DM_SPI=y
 CONFIG_DEFAULT_DEVICE_TREE="k3-am642-r5-phycore-som-2gb"
+CONFIG_OF_LIBFDT_OVERLAY=y
 CONFIG_DM_RESET=y
 CONFIG_SPL_MMC=y
 CONFIG_SPL_SERIAL=y
diff --git a/configs/r8a779f0_spider_defconfig b/configs/r8a779f0_spider_defconfig
index 7274038..6b16ff5 100644
--- a/configs/r8a779f0_spider_defconfig
+++ b/configs/r8a779f0_spider_defconfig
@@ -1,32 +1,11 @@
-#include <configs/renesas_rcar4.config>
+#include <configs/renesas_rcar4_s4.config>
 
 CONFIG_ARM=y
 CONFIG_ARCH_RENESAS=y
 CONFIG_RCAR_GEN4=y
-CONFIG_ENV_SIZE=0x40000
-CONFIG_ENV_OFFSET=0xD00000
-CONFIG_ENV_SECT_SIZE=0x40000
-CONFIG_DEFAULT_DEVICE_TREE="renesas/r8a779f0-spider"
 CONFIG_TARGET_SPIDER=y
-CONFIG_SYS_CLK_FREQ=20000000
-CONFIG_SYS_BOOT_GET_CMDLINE=y
-CONFIG_SYS_BARGSIZE=2048
+CONFIG_DEFAULT_DEVICE_TREE="renesas/r8a779f0-spider"
 CONFIG_BOOTCOMMAND="tftp 0x48080000 Image && tftp 0x48000000 Image-r8a779f0-spider.dtb && booti 0x48080000 - 0x48000000"
 CONFIG_DEFAULT_FDT_FILE="r8a779f0-spider.dtb"
-CONFIG_SYS_CBSIZE=2048
-CONFIG_CMD_PART=y
-CONFIG_CMD_UFS=y
-CONFIG_ENV_IS_IN_SPI_FLASH=y
-CONFIG_LBA48=y
-CONFIG_SYS_64BIT_LBA=y
-CONFIG_CLK_GPIO=y
-CONFIG_DM_PCA953X=y
-CONFIG_PHYLIB_10G=y
-CONFIG_PHY_MARVELL_10G=y
-CONFIG_RENESAS_ETHER_SWITCH=y
-CONFIG_PHY_R8A779F0_ETHERNET_SERDES=y
-CONFIG_SCSI=y
 CONFIG_BAUDRATE=1843200
-CONFIG_UFS=y
-CONFIG_UFS_RENESAS=y
-CONFIG_FS_FAT_MAX_CLUSTSIZE=131072
+CONFIG_DM_PCA953X=y
diff --git a/configs/r8a779f4_s4sk_defconfig b/configs/r8a779f4_s4sk_defconfig
new file mode 100644
index 0000000..1b35349
--- /dev/null
+++ b/configs/r8a779f4_s4sk_defconfig
@@ -0,0 +1,11 @@
+#include <configs/renesas_rcar4_s4.config>
+
+CONFIG_ARM=y
+CONFIG_ARCH_RENESAS=y
+CONFIG_RCAR_GEN4=y
+CONFIG_TARGET_S4SK=y
+CONFIG_DEFAULT_DEVICE_TREE="renesas/r8a779f4-s4sk"
+CONFIG_BOOTCOMMAND="tftp 0x48080000 Image && tftp 0x48000000 Image-r8a779f4-s4sk.dtb && booti 0x48080000 - 0x48000000"
+CONFIG_DEFAULT_FDT_FILE="r8a779f4-s4sk.dtb"
+CONFIG_BAUDRATE=921600
+CONFIG_BOARD_LATE_INIT=y
diff --git a/configs/renesas_rcar4_s4.config b/configs/renesas_rcar4_s4.config
new file mode 100644
index 0000000..866e575
--- /dev/null
+++ b/configs/renesas_rcar4_s4.config
@@ -0,0 +1,23 @@
+#include <configs/renesas_rcar4.config>
+
+CONFIG_CLK_GPIO=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_UFS=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_OFFSET=0xD00000
+CONFIG_ENV_SECT_SIZE=0x40000
+CONFIG_ENV_SIZE=0x40000
+CONFIG_FS_FAT_MAX_CLUSTSIZE=131072
+CONFIG_LBA48=y
+CONFIG_PHYLIB_10G=y
+CONFIG_PHY_MARVELL_10G=y
+CONFIG_PHY_R8A779F0_ETHERNET_SERDES=y
+CONFIG_RENESAS_ETHER_SWITCH=y
+CONFIG_SCSI=y
+CONFIG_SYS_64BIT_LBA=y
+CONFIG_SYS_BARGSIZE=2048
+CONFIG_SYS_BOOT_GET_CMDLINE=y
+CONFIG_SYS_CBSIZE=2048
+CONFIG_SYS_CLK_FREQ=20000000
+CONFIG_UFS=y
+CONFIG_UFS_RENESAS=y
diff --git a/configs/sandbox_vpl_defconfig b/configs/sandbox_vpl_defconfig
index 4632939..f0315f6 100644
--- a/configs/sandbox_vpl_defconfig
+++ b/configs/sandbox_vpl_defconfig
@@ -252,6 +252,8 @@
 CONFIG_FS_CRAMFS=y
 # CONFIG_SPL_USE_TINY_PRINTF is not set
 CONFIG_CMD_DHRYSTONE=y
+CONFIG_VPL_SHA1_LEGACY=y
+CONFIG_VPL_SHA256_LEGACY=y
 CONFIG_RSA_VERIFY_WITH_PKEY=y
 CONFIG_TPM=y
 CONFIG_ZSTD=y
diff --git a/configs/xilinx_versal_mini_ospi_defconfig b/configs/xilinx_versal_mini_ospi_defconfig
index 9af3817..e1cdc18 100644
--- a/configs/xilinx_versal_mini_ospi_defconfig
+++ b/configs/xilinx_versal_mini_ospi_defconfig
@@ -7,7 +7,7 @@
 CONFIG_SYS_MALLOC_F_LEN=0x500
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
-CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xFFFE0000
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xFFFFFE00
 CONFIG_SF_DEFAULT_SPEED=30000000
 CONFIG_ENV_SIZE=0x80
 # CONFIG_DM_GPIO is not set
diff --git a/configs/xilinx_versal_net_virt_defconfig b/configs/xilinx_versal_net_virt_defconfig
index 30d79ab..5ef5fd4 100644
--- a/configs/xilinx_versal_net_virt_defconfig
+++ b/configs/xilinx_versal_net_virt_defconfig
@@ -32,6 +32,8 @@
 CONFIG_CMD_BOOTMENU=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_NVEDIT_EFI=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMINFO_MAP=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_SYS_ALT_MEMTEST=y
 CONFIG_CMD_SHA1SUM=y
@@ -44,10 +46,7 @@
 CONFIG_CMD_MTD=y
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_USB=y
-CONFIG_BOOTP_MAY_FAIL=y
-CONFIG_BOOTP_BOOTFILESIZE=y
-CONFIG_CMD_TFTPPUT=y
-CONFIG_CMD_NFS=y
+CONFIG_WGET_HTTPS=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_EFIDEBUG=y
 CONFIG_CMD_TIME=y
@@ -69,9 +68,7 @@
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
-CONFIG_NETCONSOLE=y
-CONFIG_IP_DEFRAG=y
-CONFIG_SYS_FAULT_ECHO_LINK_DOWN=y
+CONFIG_NET_LWIP=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_TFTP_BLOCKSIZE=4096
 CONFIG_SIMPLE_PM_BUS=y
@@ -102,6 +99,7 @@
 CONFIG_SPI_FLASH_ISSI=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_S28HX_T=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_MT35XU=y
 CONFIG_SPI_FLASH_SST=y
@@ -152,4 +150,5 @@
 CONFIG_VIRTIO_MMIO=y
 CONFIG_VIRTIO_NET=y
 CONFIG_VIRTIO_BLK=y
+CONFIG_MBEDTLS_LIB=y
 CONFIG_TPM=y
diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig
index fb757c1..f228eef 100644
--- a/configs/xilinx_versal_virt_defconfig
+++ b/configs/xilinx_versal_virt_defconfig
@@ -38,6 +38,8 @@
 CONFIG_CMD_BOOTMENU=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_NVEDIT_EFI=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMINFO_MAP=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_SYS_ALT_MEMTEST=y
 CONFIG_CMD_SHA1SUM=y
@@ -50,10 +52,7 @@
 CONFIG_CMD_MTD=y
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_USB=y
-CONFIG_BOOTP_MAY_FAIL=y
-CONFIG_BOOTP_BOOTFILESIZE=y
-CONFIG_CMD_TFTPPUT=y
-CONFIG_CMD_NFS=y
+CONFIG_WGET_HTTPS=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_EFIDEBUG=y
 CONFIG_CMD_TIME=y
@@ -73,9 +72,7 @@
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
-CONFIG_NETCONSOLE=y
-CONFIG_IP_DEFRAG=y
-CONFIG_SYS_FAULT_ECHO_LINK_DOWN=y
+CONFIG_NET_LWIP=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_TFTP_BLOCKSIZE=4096
 CONFIG_SIMPLE_PM_BUS=y
@@ -112,6 +109,7 @@
 CONFIG_SPI_FLASH_ISSI=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_S28HX_T=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_MT35XU=y
 CONFIG_SPI_FLASH_SST=y
@@ -167,4 +165,6 @@
 CONFIG_VIRTIO_MMIO=y
 CONFIG_VIRTIO_NET=y
 CONFIG_VIRTIO_BLK=y
+CONFIG_MBEDTLS_LIB=y
 CONFIG_TPM=y
+CONFIG_TOOLS_MKFWUMDATA=y
diff --git a/configs/xilinx_zynq_virt_defconfig b/configs/xilinx_zynq_virt_defconfig
index ed3d101..fdf8bb3 100644
--- a/configs/xilinx_zynq_virt_defconfig
+++ b/configs/xilinx_zynq_virt_defconfig
@@ -56,6 +56,8 @@
 CONFIG_CMD_THOR_DOWNLOAD=y
 CONFIG_THOR_RESET_OFF=y
 CONFIG_CMD_GREPENV=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMINFO_MAP=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_SYS_ALT_MEMTEST=y
 CONFIG_CMD_DFU=y
@@ -71,9 +73,6 @@
 CONFIG_CMD_NAND_LOCK_UNLOCK=y
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_USB=y
-CONFIG_BOOTP_MAY_FAIL=y
-CONFIG_CMD_TFTPPUT=y
-CONFIG_CMD_NFS=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_EFIDEBUG=y
 CONFIG_CMD_TIME=y
@@ -92,8 +91,7 @@
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
-CONFIG_NETCONSOLE=y
-CONFIG_SYS_FAULT_ECHO_LINK_DOWN=y
+CONFIG_NET_LWIP=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_SIMPLE_PM_BUS=y
@@ -158,4 +156,5 @@
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_SYS_TIMER_COUNTS_DOWN=y
+CONFIG_MBEDTLS_LIB=y
 CONFIG_SPL_GZIP=y
diff --git a/configs/xilinx_zynqmp_kria_defconfig b/configs/xilinx_zynqmp_kria_defconfig
index a68bd52..ad46c09 100644
--- a/configs/xilinx_zynqmp_kria_defconfig
+++ b/configs/xilinx_zynqmp_kria_defconfig
@@ -63,6 +63,8 @@
 CONFIG_CMD_BOOTMENU=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_NVEDIT_EFI=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMINFO_MAP=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_SYS_ALT_MEMTEST=y
 CONFIG_CMD_SHA1SUM=y
@@ -82,11 +84,7 @@
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
-CONFIG_CMD_USB_MASS_STORAGE=y
-CONFIG_BOOTP_MAY_FAIL=y
-CONFIG_BOOTP_BOOTFILESIZE=y
-CONFIG_CMD_TFTPPUT=y
-CONFIG_CMD_NFS=y
+CONFIG_WGET_HTTPS=y
 CONFIG_CMD_BMP=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_EFIDEBUG=y
@@ -118,8 +116,7 @@
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
 CONFIG_ENV_FAT_DEVICE_AND_PART=":auto"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
-CONFIG_NETCONSOLE=y
-CONFIG_SYS_FAULT_ECHO_LINK_DOWN=y
+CONFIG_NET_LWIP=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_SIMPLE_PM_BUS=y
@@ -129,7 +126,6 @@
 CONFIG_BUTTON=y
 CONFIG_BUTTON_GPIO=y
 CONFIG_CLK_ZYNQMP=y
-CONFIG_DFU_TFTP=y
 CONFIG_DFU_TIMEOUT=y
 CONFIG_DFU_MMC=y
 CONFIG_DFU_MTD=y
@@ -138,10 +134,6 @@
 CONFIG_SYS_DFU_DATA_BUF_SIZE=0x1800000
 CONFIG_DMA=y
 CONFIG_XILINX_DPDMA=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_FASTBOOT_FLASH=y
-CONFIG_FASTBOOT_FLASH_MMC_DEV=0
-CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_ARM_FFA_TRANSPORT=y
 CONFIG_FPGA_XILINX=y
 CONFIG_FPGA_ZYNQMPPL=y
@@ -229,5 +221,6 @@
 # CONFIG_BINMAN_FDT is not set
 CONFIG_BINMAN_DTB="./arch/arm/dts/zynqmp-binman-som.dtb"
 CONFIG_PANIC_HANG=y
+CONFIG_MBEDTLS_LIB=y
 CONFIG_TPM=y
 CONFIG_SPL_GZIP=y
diff --git a/configs/xilinx_zynqmp_virt_defconfig b/configs/xilinx_zynqmp_virt_defconfig
index b13079c..036268c 100644
--- a/configs/xilinx_zynqmp_virt_defconfig
+++ b/configs/xilinx_zynqmp_virt_defconfig
@@ -59,10 +59,10 @@
 CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y
 CONFIG_CMD_SMBIOS=y
 CONFIG_CMD_BOOTMENU=y
-CONFIG_CMD_THOR_DOWNLOAD=y
-CONFIG_THOR_RESET_OFF=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_NVEDIT_EFI=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMINFO_MAP=y
 CONFIG_CMD_MEMTEST=y
 CONFIG_SYS_ALT_MEMTEST=y
 CONFIG_CMD_SHA1SUM=y
@@ -84,11 +84,7 @@
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
-CONFIG_CMD_USB_MASS_STORAGE=y
-CONFIG_BOOTP_MAY_FAIL=y
-CONFIG_BOOTP_BOOTFILESIZE=y
-CONFIG_CMD_TFTPPUT=y
-CONFIG_CMD_NFS=y
+CONFIG_WGET_HTTPS=y
 CONFIG_CMD_BMP=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_EFIDEBUG=y
@@ -119,8 +115,7 @@
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
 CONFIG_ENV_FAT_DEVICE_AND_PART=":auto"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
-CONFIG_NETCONSOLE=y
-CONFIG_SYS_FAULT_ECHO_LINK_DOWN=y
+CONFIG_NET_LWIP=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_SIMPLE_PM_BUS=y
@@ -130,7 +125,6 @@
 CONFIG_BUTTON=y
 CONFIG_BUTTON_GPIO=y
 CONFIG_CLK_ZYNQMP=y
-CONFIG_DFU_TFTP=y
 CONFIG_DFU_TIMEOUT=y
 CONFIG_DFU_MMC=y
 CONFIG_DFU_MTD=y
@@ -138,10 +132,6 @@
 CONFIG_DFU_RAM=y
 CONFIG_DFU_SF=y
 CONFIG_SYS_DFU_DATA_BUF_SIZE=0x1800000
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_FASTBOOT_FLASH=y
-CONFIG_FASTBOOT_FLASH_MMC_DEV=0
-CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_ARM_FFA_TRANSPORT=y
 CONFIG_FPGA_XILINX=y
 CONFIG_FPGA_ZYNQMPPL=y
@@ -245,5 +235,7 @@
 # CONFIG_BINMAN_FDT is not set
 CONFIG_BINMAN_DTB="./arch/arm/dts/zynqmp-binman.dtb"
 CONFIG_PANIC_HANG=y
+CONFIG_MBEDTLS_LIB=y
 CONFIG_TPM=y
 CONFIG_SPL_GZIP=y
+CONFIG_TOOLS_MKFWUMDATA=y
diff --git a/doc/board/renesas/renesas.rst b/doc/board/renesas/renesas.rst
index 7d961e8..0a38ff4 100644
--- a/doc/board/renesas/renesas.rst
+++ b/doc/board/renesas/renesas.rst
@@ -169,6 +169,12 @@
      - r8a779f0_spider_defconfig
 
    * -
+     - S4SK
+     - R8A779F4 (S4)
+     - arm64
+     - r8a779f4_s4sk_defconfig
+
+   * -
      - White Hawk
      - R8A779G0 (V4H)
      - arm64
diff --git a/doc/device-tree-bindings/leds/common.txt b/doc/device-tree-bindings/leds/common.txt
deleted file mode 100644
index 2d88816..0000000
--- a/doc/device-tree-bindings/leds/common.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-Common leds properties.
-
-Optional properties for child nodes:
-- label : The label for this LED.  If omitted, the label is
-  taken from the node name (excluding the unit address).
-
-- linux,default-trigger :  This parameter, if present, is a
-    string defining the trigger assigned to the LED.  Current triggers are:
-     "backlight" - LED will act as a back-light, controlled by the framebuffer
-		   system
-     "default-on" - LED will turn on (but for leds-gpio see "default-state"
-		    property in Documentation/devicetree/bindings/gpio/led.txt)
-     "heartbeat" - LED "double" flashes at a load average based rate
-     "ide-disk" - LED indicates disk activity
-     "timer" - LED flashes at a fixed, configurable rate
-
-Examples:
-
-system-status {
-	label = "Status";
-	linux,default-trigger = "heartbeat";
-	...
-};
diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c
index 1f67825..f88267e 100644
--- a/drivers/fpga/fpga.c
+++ b/drivers/fpga/fpga.c
@@ -33,9 +33,9 @@
 /* fpga_get_desc
  *	map a device number to a descriptor
  */
-const fpga_desc *const fpga_get_desc(int devnum)
+const fpga_desc *fpga_get_desc(int devnum)
 {
-	fpga_desc *desc = (fpga_desc *)NULL;
+	const fpga_desc *desc = NULL;
 
 	if ((devnum >= 0) && (devnum < next_desc)) {
 		desc = &desc_table[devnum];
@@ -50,8 +50,8 @@
  * fpga_validate
  *	generic parameter checking code
  */
-const fpga_desc *const fpga_validate(int devnum, const void *buf,
-				     size_t bsize, char *fn)
+const fpga_desc *fpga_validate(int devnum, const void *buf,
+			       size_t bsize, char *fn)
 {
 	const fpga_desc *desc = fpga_get_desc(devnum);
 
@@ -60,7 +60,7 @@
 
 	if (!buf) {
 		printf("%s: Null buffer.\n", fn);
-		return (fpga_desc * const)NULL;
+		return NULL;
 	}
 	return desc;
 }
@@ -72,7 +72,7 @@
 static int fpga_dev_info(int devnum)
 {
 	int ret_val = FPGA_FAIL; /* assume failure */
-	const fpga_desc * const desc = fpga_get_desc(devnum);
+	const fpga_desc *desc = fpga_get_desc(devnum);
 
 	if (desc) {
 		debug("%s: Device Descriptor @ 0x%p\n",
@@ -374,7 +374,7 @@
 #if CONFIG_IS_ENABLED(FPGA_LOAD_SECURE)
 int fpga_compatible2flag(int devnum, const char *compatible)
 {
-	const fpga_desc * const desc = fpga_get_desc(devnum);
+	const fpga_desc *desc = fpga_get_desc(devnum);
 
 	if (!desc)
 		return 0;
diff --git a/drivers/led/led-uclass.c b/drivers/led/led-uclass.c
index 7607505..27ef890 100644
--- a/drivers/led/led-uclass.c
+++ b/drivers/led/led-uclass.c
@@ -13,6 +13,25 @@
 #include <dm/lists.h>
 #include <dm/root.h>
 #include <dm/uclass-internal.h>
+#include <dt-bindings/leds/common.h>
+
+static const char * const led_colors[LED_COLOR_ID_MAX] = {
+	[LED_COLOR_ID_WHITE] = "white",
+	[LED_COLOR_ID_RED] = "red",
+	[LED_COLOR_ID_GREEN] = "green",
+	[LED_COLOR_ID_BLUE] = "blue",
+	[LED_COLOR_ID_AMBER] = "amber",
+	[LED_COLOR_ID_VIOLET] = "violet",
+	[LED_COLOR_ID_YELLOW] = "yellow",
+	[LED_COLOR_ID_IR] = "ir",
+	[LED_COLOR_ID_MULTI] = "multicolor",
+	[LED_COLOR_ID_RGB] = "rgb",
+	[LED_COLOR_ID_PURPLE] = "purple",
+	[LED_COLOR_ID_ORANGE] = "orange",
+	[LED_COLOR_ID_PINK] = "pink",
+	[LED_COLOR_ID_CYAN] = "cyan",
+	[LED_COLOR_ID_LIME] = "lime",
+};
 
 int led_bind_generic(struct udevice *parent, const char *driver_name)
 {
@@ -232,11 +251,54 @@
 #endif
 #endif
 
+static const char *led_get_function_name(struct udevice *dev)
+{
+	struct led_uc_plat *uc_plat;
+	const char *func;
+	u32 color;
+	u32 enumerator;
+	int ret;
+	int cp;
+
+	if (!dev)
+		return NULL;
+
+	uc_plat = dev_get_uclass_plat(dev);
+	if (!uc_plat)
+		return NULL;
+
-static const char *led_get_label(ofnode node)
+	if (uc_plat->label)
+		return uc_plat->label;
+
+	/* Now try to detect function label name */
+	func = dev_read_string(dev, "function");
+	cp = dev_read_u32(dev, "color", &color);
+	if (cp == 0 || func) {
+		ret = dev_read_u32(dev, "function-enumerator", &enumerator);
+		if (!ret) {
+			snprintf(uc_plat->name, LED_MAX_NAME_SIZE,
+				 "%s:%s-%d",
+				 cp ? "" : led_colors[color],
+				 func ? func : "", enumerator);
+		} else {
+			snprintf(uc_plat->name, LED_MAX_NAME_SIZE,
+				 "%s:%s",
+				 cp ? "" : led_colors[color],
+				 func ? func : "");
+		}
+		uc_plat->label = uc_plat->name;
+	}
+
+	return uc_plat->label;
+}
+
+static const char *led_get_label(struct udevice *dev, ofnode node)
 {
 	const char *label;
 
 	label = ofnode_read_string(node, "label");
+	if (!label)
+		label = led_get_function_name(dev);
 	if (!label && !ofnode_read_string(node, "compatible"))
 		label = ofnode_get_name(node);
 
@@ -249,7 +311,7 @@
 	const char *default_state;
 
 	if (!uc_plat->label)
-		uc_plat->label = led_get_label(dev_ofnode(dev));
+		uc_plat->label = led_get_label(dev, dev_ofnode(dev));
 
 	uc_plat->default_state = LEDST_COUNT;
 
@@ -314,14 +376,14 @@
 #ifdef CONFIG_LED_BOOT
 	ret = ofnode_options_get_by_phandle("boot-led", &led_node);
 	if (!ret)
-		priv->boot_led_label = led_get_label(led_node);
+		priv->boot_led_label = led_get_label(NULL, led_node);
 	priv->boot_led_period = ofnode_options_read_int("boot-led-period-ms", 250);
 #endif
 
 #ifdef CONFIG_LED_ACTIVITY
 	ret = ofnode_options_get_by_phandle("activity-led", &led_node);
 	if (!ret)
-		priv->activity_led_label = led_get_label(led_node);
+		priv->activity_led_label = led_get_label(NULL, led_node);
 	priv->activity_led_period = ofnode_options_read_int("activity-led-period-ms",
 							    250);
 #endif
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index e1110ca..a514943 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -724,7 +724,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_DM_MMC
+#if CONFIG_IS_ENABLED(DM_MMC)
 int dwmci_probe(struct udevice *dev)
 {
 	struct mmc *mmc = mmc_get_mmc_dev(dev);
@@ -749,7 +749,7 @@
 		     u32 max_clk, u32 min_clk)
 {
 	cfg->name = host->name;
-#ifndef CONFIG_DM_MMC
+#if !CONFIG_IS_ENABLED(DM_MMC)
 	cfg->ops = &dwmci_ops;
 #endif
 	cfg->f_min = min_clk;
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 94d8f1b..0a1fff3 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -741,6 +741,18 @@
 			puts("Error enabling phy supply\n");
 			return ret;
 		}
+#if IS_ENABLED(CONFIG_ARCH_NPCM8XX)
+		int phy_uv;
+
+		phy_uv = dev_read_u32_default(dev, "phy-supply-microvolt", 0);
+		if (phy_uv) {
+			ret = regulator_set_value(phy_supply, phy_uv);
+			if (ret) {
+				puts("Error setting phy voltage\n");
+				return ret;
+			}
+		}
+#endif
 	}
 #endif
 
diff --git a/drivers/net/phy/miiphybb.c b/drivers/net/phy/miiphybb.c
index 171c171..9f5f9b1 100644
--- a/drivers/net/phy/miiphybb.c
+++ b/drivers/net/phy/miiphybb.c
@@ -183,9 +183,7 @@
 	bus->set_mdc(bus, 1);
 	bus->delay(bus);
 
-#ifdef DEBUG
-	printf("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, rdreg);
-#endif
+	debug("%s[%s](0x%x) @ 0x%x = 0x%04x\n", __func__, miidev->name, reg, addr, rdreg);
 
 	return rdreg;
 }
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7981.c b/drivers/pinctrl/mediatek/pinctrl-mt7981.c
index 84c3996..6b97690 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c
@@ -1051,8 +1051,9 @@
 };
 
 static const char *const mt7981_pinctrl_register_base_names[] = {
-	"gpio_base", "iocfg_rt_base", "iocfg_rm_base", "iocfg_rb_base",
-	"iocfg_lb_base", "iocfg_bl_base", "iocfg_tm_base", "iocfg_tl_base",
+	"gpio", "iocfg_rt", "iocfg_rm", "iocfg_rb",
+	"iocfg_lb", "iocfg_bl", "iocfg_tm", "iocfg_tl",
+	"eint",
 };
 
 static const struct mtk_pinctrl_soc mt7981_data = {
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7988.c b/drivers/pinctrl/mediatek/pinctrl-mt7988.c
index 1f384e8..639e241 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt7988.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7988.c
@@ -1233,8 +1233,7 @@
 };
 
 static const char *const mt7988_pinctrl_register_base_names[] = {
-	"gpio_base", "iocfg_tr_base", "iocfg_br_base", "iocfg_rb_base",
-	"iocfg_lb_base", "iocfg_tl_base",
+	"gpio", "iocfg_tr", "iocfg_br", "iocfg_rb", "iocfg_lb", "iocfg_tl",
 };
 
 static const struct mtk_pinctrl_soc mt7988_data = {
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index 3760c46..4aecb84 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -816,7 +816,11 @@
 		nbase_names = 1;
 
 	for (i = 0; i < nbase_names; i++) {
-		addr = devfdt_get_addr_index(dev, i);
+		if (soc->base_names)
+			addr = dev_read_addr_name(dev, soc->base_names[i]);
+		else
+			addr = dev_read_addr_index(dev, i);
+
 		if (addr == FDT_ADDR_T_NONE)
 			return -EINVAL;
 		priv->base[i] = (void __iomem *)addr;
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive.c b/drivers/pinctrl/starfive/pinctrl-starfive.c
index 95b1a75..1b942e6 100644
--- a/drivers/pinctrl/starfive/pinctrl-starfive.c
+++ b/drivers/pinctrl/starfive/pinctrl-starfive.c
@@ -348,7 +348,7 @@
 	.set_value = starfive_gpio_set_value,
 };
 
-static struct driver starfive_gpio_driver = {
+U_BOOT_DRIVER(starfive_gpio) = {
 	.name = "starfive_gpio",
 	.id = UCLASS_GPIO,
 	.probe = starfive_gpio_probe,
@@ -367,7 +367,7 @@
 		return -ENOENT;
 
 	node = dev_ofnode(parent);
-	ret = device_bind_with_driver_data(parent, &starfive_gpio_driver,
+	ret = device_bind_with_driver_data(parent, DM_DRIVER_REF(starfive_gpio),
 					   "starfive_gpio", 0, node, &dev);
 
 	return (ret == 0) ? 0 : ret;
diff --git a/drivers/remoteproc/renesas_apmu.c b/drivers/remoteproc/renesas_apmu.c
index 32d138e..1a50cd3 100644
--- a/drivers/remoteproc/renesas_apmu.c
+++ b/drivers/remoteproc/renesas_apmu.c
@@ -68,6 +68,13 @@
 	flush_dcache_range(trampolineaddr,
 			   trampolineaddr +
 			   sizeof(renesas_apmu_rproc_trampoline));
+	invalidate_dcache_range(trampolineaddr,
+				trampolineaddr +
+				sizeof(renesas_apmu_rproc_trampoline));
+	flush_dcache_range(addr, addr + size);
+	invalidate_dcache_range(addr, addr + size);
+	asm volatile("dsb sy\n");
+	asm volatile("isb sy\n");
 
 	/* CR52 boot address set */
 	writel(trampolineaddr | APMU_CRBARP_CR_VLD_BARP,
diff --git a/drivers/rtc/emul_rtc.c b/drivers/rtc/emul_rtc.c
index 97a8d9b..6817daa 100644
--- a/drivers/rtc/emul_rtc.c
+++ b/drivers/rtc/emul_rtc.c
@@ -58,7 +58,7 @@
 	return 0;
 }
 
-int emul_rtc_probe(struct udevice *dev)
+static int emul_rtc_probe(struct udevice *dev)
 {
 	struct emul_rtc *priv = dev_get_priv(dev);
 	const char *epoch_str;
diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c
index dcf28c7..816916d 100644
--- a/drivers/spi/cadence_ospi_versal.c
+++ b/drivers/spi/cadence_ospi_versal.c
@@ -24,6 +24,13 @@
 	u8 opcode, addr_bytes, *rxbuf, dummy_cycles;
 
 	n_rx = op->data.nbytes;
+
+	if (op->addr.dtr && (op->addr.val % 2)) {
+		n_rx += 1;
+		writel(op->addr.val & ~0x1,
+		       priv->regbase + CQSPI_REG_INDIRECTRDSTARTADDR);
+	}
+
 	rxbuf = op->data.buf.in;
 	rx_rem = n_rx % 4;
 	bytes_to_dma = n_rx - rx_rem;
@@ -104,6 +111,11 @@
 		memcpy(rxbuf, &data, rx_rem);
 	}
 
+	if (op->addr.dtr && (op->addr.val % 2)) {
+		rxbuf -= bytes_to_dma;
+		memcpy(rxbuf, rxbuf + 1, n_rx - 1);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index 693474a..1f9125c 100644
--- a/drivers/spi/cadence_qspi.h
+++ b/drivers/spi/cadence_qspi.h
@@ -307,7 +307,7 @@
 			      const struct spi_mem_op *op);
 int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_priv *priv);
 int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg);
-int cadence_qspi_versal_flash_reset(struct udevice *dev);
+int cadence_qspi_flash_reset(struct udevice *dev);
 ofnode cadence_qspi_get_subnode(struct udevice *dev);
 void cadence_qspi_apb_enable_linear_mode(bool enable);
 
diff --git a/examples/api/Makefile b/examples/api/Makefile
index 722c7e4..be97b80 100644
--- a/examples/api/Makefile
+++ b/examples/api/Makefile
@@ -5,26 +5,9 @@
 # Provide symbol API_BUILD to signal that the API example is being built.
 KBUILD_CPPFLAGS += -DAPI_BUILD
 
-ifeq ($(ARCH),powerpc)
-LOAD_ADDR = 0x40000
-endif
-ifeq ($(ARCH),arm)
-ifdef CONFIG_64BIT
-LOAD_ADDR = 0x40400000
-else
-LOAD_ADDR = 0x1000000
-endif
-endif
-ifeq ($(ARCH),mips)
-ifdef CONFIG_64BIT
-LOAD_ADDR = 0xffffffff80200000
-else
-LOAD_ADDR = 0x80200000
-endif
-endif
-ifeq ($(ARCH),riscv)
-LOAD_ADDR = 0x84000000
-endif
+# Environment variable loadaddr is set from CONFIG_SYS_LOAD_ADDR.
+# Run the examples 4 MiB above this address.
+LOAD_ADDR:=${shell printf 0x%X $$(( $(CONFIG_SYS_LOAD_ADDR) + 0x400000 ))}
 
 # Resulting ELF and binary exectuables will be named demo and demo.bin
 extra-y = demo
diff --git a/examples/api/crt0.S b/examples/api/crt0.S
index d2a9755..6899ebf 100644
--- a/examples/api/crt0.S
+++ b/examples/api/crt0.S
@@ -29,15 +29,17 @@
 	.text
 	.globl _start
 _start:
-	ldr	ip, =search_hint
-	str	sp, [ip]
+	ldr	r4, =search_hint
+	mov	r5, sp
+	str	r5, [r4]
 	b	main
 
 
 	.globl syscall
 syscall:
-	ldr	ip, =syscall_ptr
-	ldr	pc, [ip]
+	ldr	r4, =syscall_ptr
+	ldr	r4, [r4]
+	bx	r4
 
 #elif defined(CONFIG_ARM64)
 
diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile
index 559170d..9b57f1c 100644
--- a/examples/standalone/Makefile
+++ b/examples/standalone/Makefile
@@ -7,6 +7,10 @@
 extra-$(CONFIG_SPI_FLASH_ATMEL)    += atmel_df_pow2
 extra-$(CONFIG_PPC)                += sched
 
+# Environment variable loadaddr is set from CONFIG_SYS_LOAD_ADDR.
+# Run the examples 4 MiB above this address.
+LOAD_ADDR:=${shell printf 0x%X $$(( $(CONFIG_SYS_LOAD_ADDR) + 0x400000 ))}
+
 #
 # Some versions of make do not handle trailing white spaces properly;
 # leading to build failures. The problem was found with GNU Make 3.80.
@@ -46,7 +50,7 @@
 # source file.
 ccflags-y += $(call cc-option,-fno-toplevel-reorder)
 
-LDFLAGS_STANDALONE	+= -Ttext $(CONFIG_STANDALONE_LOAD_ADDR)
+LDFLAGS_STANDALONE	+= -Ttext $(LOAD_ADDR)
 
 #########################################################################
 
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index b6bca53..3fd5c77 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -67,6 +67,9 @@
 /* This marks the text region which must be relocated */
 extern char __image_copy_start[], __image_copy_end[];
 
+/* This marks the rcode region used for SPL relocation */
+extern char _rcode_start[], _rcode_end[];
+
 extern char __bss_end[];
 extern char __rel_dyn_start[], __rel_dyn_end[];
 extern char _image_binary_end[];
@@ -77,4 +80,17 @@
  */
 extern void _start(void);
 
+#ifndef USE_HOSTCC
+#if CONFIG_IS_ENABLED(RELOC_LOADER)
+#define __rcode __section(".text.rcode")
+#define __rdata __section(".text.rdata")
+#else
+#define __rcode
+#define __rdata
+#endif
+#else
+#define __rcode
+#define __rdata
+#endif
+
 #endif /* _ASM_GENERIC_SECTIONS_H_ */
diff --git a/include/configs/s4sk.h b/include/configs/s4sk.h
new file mode 100644
index 0000000..a170735
--- /dev/null
+++ b/include/configs/s4sk.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * This file is S4SK board configuration.
+ *
+ * Copyright (C) 2024-2025 Renesas Electronics Corp.
+ */
+
+#ifndef __S4SK_H
+#define __S4SK_H
+
+#include "rcar-gen4-common.h"
+
+#endif /* __S4SK_H */
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index bb0db7c..13941ba 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -179,6 +179,7 @@
 #ifndef CFG_EXTRA_ENV_SETTINGS
 #define CFG_EXTRA_ENV_SETTINGS \
 	ENV_MEM_LAYOUT_SETTINGS \
+	"usb_pgood_delay=1000\0" \
 	BOOTENV
 #endif
 
diff --git a/include/fpga.h b/include/fpga.h
index 44f2755..4cc4416 100644
--- a/include/fpga.h
+++ b/include/fpga.h
@@ -58,7 +58,7 @@
 void fpga_init(void);
 int fpga_add(fpga_type devtype, void *desc);
 int fpga_count(void);
-const fpga_desc *const fpga_get_desc(int devnum);
+const fpga_desc *fpga_get_desc(int devnum);
 int fpga_is_partial_data(int devnum, size_t img_len);
 #if CONFIG_IS_ENABLED(FPGA)
 int fpga_load(int devnum, const void *buf, size_t bsize,
@@ -78,8 +78,8 @@
 		       bitstream_type bstype);
 int fpga_dump(int devnum, const void *buf, size_t bsize);
 int fpga_info(int devnum);
-const fpga_desc *const fpga_validate(int devnum, const void *buf,
-				     size_t bsize, char *fn);
+const fpga_desc *fpga_validate(int devnum, const void *buf,
+			       size_t bsize, char *fn);
 int fpga_compatible2flag(int devnum, const char *compatible);
 
 #endif	/* _FPGA_H_ */
diff --git a/include/led.h b/include/led.h
index 64247cd..2a7f38b 100644
--- a/include/led.h
+++ b/include/led.h
@@ -53,6 +53,11 @@
 
 struct udevice;
 
+/*
+ * value imported from linux:include/linux/uapi/linux/uleds.h
+ */
+#define LED_MAX_NAME_SIZE      64
+
 enum led_state_t {
 	LEDST_OFF = 0,
 	LEDST_ON = 1,
@@ -81,11 +86,14 @@
  *
  * @label:	LED label
  * @default_state:	LED default state
+ * @name:	LED name, derived from function, color or function-enumerator
+ *		property.
  * @sw_blink:	LED software blink struct
  */
 struct led_uc_plat {
 	const char *label;
 	enum led_state_t default_state;
+	char name[LED_MAX_NAME_SIZE];
 #ifdef CONFIG_LED_SW_BLINK
 	struct led_sw_blink *sw_blink;
 #endif
diff --git a/include/spl.h b/include/spl.h
index 7155e9c..850c64d 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -345,7 +345,7 @@
  * @priv: Private data for the device
  * @bl_len: Block length for reading in bytes
  * @phase: Image phase to load
- * @fit_loaded: true if the FIT has been loaded, except for external data
+ * @no_fdt_update: true to update the FDT with any loadables that are loaded
  */
 struct spl_load_info {
 	spl_load_reader read;
@@ -355,7 +355,7 @@
 #endif
 #if CONFIG_IS_ENABLED(BOOTMETH_VBE)
 	u8 phase;
-	u8 fit_loaded;
+	u8 fdt_update;
 #endif
 };
 
@@ -395,12 +395,20 @@
 #endif
 }
 
-static inline bool xpl_get_fit_loaded(struct spl_load_info *info)
+static inline void xpl_set_fdt_update(struct spl_load_info *info,
+				      bool fdt_update)
 {
 #if CONFIG_IS_ENABLED(BOOTMETH_VBE)
-	return info->fit_loaded;
+	info->fdt_update = fdt_update;
+#endif
+}
+
+static inline enum image_phase_t xpl_get_fdt_update(struct spl_load_info *info)
+{
+#if CONFIG_IS_ENABLED(BOOTMETH_VBE)
+	return info->fdt_update;
 #else
-	return false;
+	return true;
 #endif
 }
 
@@ -415,6 +423,7 @@
 	load->priv = priv;
 	spl_set_bl_len(load, bl_len);
 	xpl_set_phase(load, IH_PHASE_NONE);
+	xpl_set_fdt_update(load, true);
 }
 
 /*
diff --git a/include/spl_load.h b/include/spl_load.h
index 935f7d3..525e0c9 100644
--- a/include/spl_load.h
+++ b/include/spl_load.h
@@ -20,13 +20,15 @@
 	ulong base_offset, image_offset, overhead;
 	int read, ret;
 
+	log_debug("\nloading hdr from %lx to %p\n", (ulong)offset, header);
 	read = info->read(info, offset, ALIGN(sizeof(*header),
 					      spl_get_bl_len(info)), header);
 	if (read < (int)sizeof(*header))
 		return -EIO;
 
 	if (image_get_magic(header) == FDT_MAGIC) {
-		if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL)) {
+		log_debug("Found FIT\n");
+		if (CONFIG_IS_ENABLED(LOAD_FIT_FULL)) {
 			void *buf;
 
 			/*
@@ -48,9 +50,12 @@
 			return spl_parse_image_header(spl_image, bootdev, buf);
 		}
 
-		if (IS_ENABLED(CONFIG_SPL_LOAD_FIT))
+		if (CONFIG_IS_ENABLED(LOAD_FIT)) {
+			log_debug("Simple loading\n");
 			return spl_load_simple_fit(spl_image, info, offset,
 						   header);
+		}
+		log_debug("No FIT support\n");
 	}
 
 	if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
diff --git a/include/vbe.h b/include/vbe.h
index 56bff63..61bfa0e 100644
--- a/include/vbe.h
+++ b/include/vbe.h
@@ -10,6 +10,8 @@
 #ifndef __VBE_H
 #define __VBE_H
 
+#include <linux/types.h>
+
 /**
  * enum vbe_phase_t - current phase of VBE
  *
@@ -26,12 +28,31 @@
 };
 
 /**
+ * enum vbe_pick_t - indicates which firmware is picked
+ *
+ * @VBEFT_A: Firmware A
+ * @VBEFT_B: Firmware B
+ * @VBEFT_RECOVERY: Recovery firmware
+ */
+enum vbe_pick_t {
+	VBEP_A,
+	VBEP_B,
+	VBEP_RECOVERY,
+};
+
+/**
  * struct vbe_handoff - information about VBE progress
  *
+ * @offset: Offset of the FIT to use for SPL onwards
+ * @size: Size of the area containing the FIT
  * @phases: Indicates which phases used the VBE bootmeth (1 << PHASE_...)
+ * @pick: Indicates which firmware pick was used (enum vbe_pick_t)
  */
 struct vbe_handoff {
+	ulong offset;
+	ulong size;
 	u8 phases;
+	u8 pick;
 };
 
 /**
diff --git a/lib/Kconfig b/lib/Kconfig
index b27965f..1a683de 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -758,6 +758,16 @@
 	  checksum with feedback to produce an 8-bit result. The code is small
 	  and it does not require a lookup table (unlike CRC32).
 
+config CRC16
+	bool "Support CRC16"
+	default y
+	help
+	  Enables CRC16 support. This is normally required. Two algorithms are
+	  provided:
+
+	    - CCITT, with a polynomical x^16 + x^12 + x^5 + 1
+	    - standard, with polynomial x^16 + x^15 + x^2 + 1 (0x8005)
+
 config SPL_CRC16
 	bool "Support CRC16 in SPL"
 	depends on SPL
diff --git a/lib/Makefile b/lib/Makefile
index fc6e68c..a7bc2f3 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -35,8 +35,6 @@
 endif
 
 obj-y += crc8.o
-obj-y += crc16.o
-obj-y += crc16-ccitt.o
 obj-$(CONFIG_ERRNO_STR) += errno_str.o
 obj-$(CONFIG_FIT) += fdtdec_common.o
 obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
@@ -71,6 +69,7 @@
 
 obj-$(CONFIG_$(PHASE_)CRC8) += crc8.o
 obj-$(CONFIG_$(PHASE_)CRC16) += crc16.o
+obj-$(CONFIG_$(PHASE_)CRC16) += crc16-ccitt.o
 
 obj-y += crypto/
 
@@ -80,11 +79,11 @@
 obj-$(CONFIG_HASH) += hash-checksum.o
 obj-$(CONFIG_BLAKE2) += blake2/blake2b.o
 
-obj-$(CONFIG_$(XPL_)MD5_LEGACY) += md5.o
-obj-$(CONFIG_$(XPL_)SHA1_LEGACY) += sha1.o
-obj-$(CONFIG_$(XPL_)SHA256) += sha256_common.o
-obj-$(CONFIG_$(XPL_)SHA256_LEGACY) += sha256.o
-obj-$(CONFIG_$(XPL_)SHA512_LEGACY) += sha512.o
+obj-$(CONFIG_$(PHASE_)MD5_LEGACY) += md5.o
+obj-$(CONFIG_$(PHASE_)SHA1_LEGACY) += sha1.o
+obj-$(CONFIG_$(PHASE_)SHA256) += sha256_common.o
+obj-$(CONFIG_$(PHASE_)SHA256_LEGACY) += sha256.o
+obj-$(CONFIG_$(PHASE_)SHA512_LEGACY) += sha512.o
 
 obj-$(CONFIG_CRYPT_PW) += crypt/
 obj-$(CONFIG_$(XPL_)ASN1_DECODER_LEGACY) += asn1_decoder.o
diff --git a/lib/crc8.c b/lib/crc8.c
index 811e199..bbb229c 100644
--- a/lib/crc8.c
+++ b/lib/crc8.c
@@ -6,11 +6,12 @@
 #ifdef USE_HOSTCC
 #include <arpa/inet.h>
 #endif
+#include <asm/sections.h>
 #include <u-boot/crc.h>
 
 #define POLY	(0x1070U << 3)
 
-static unsigned char _crc8(unsigned short data)
+__rcode static unsigned char _crc8(unsigned short data)
 {
 	int i;
 
@@ -23,7 +24,7 @@
 	return (unsigned char)(data >> 8);
 }
 
-unsigned int crc8(unsigned int crc, const unsigned char *vptr, int len)
+__rcode unsigned int crc8(unsigned int crc, const unsigned char *vptr, int len)
 {
 	int i;
 
diff --git a/lib/gunzip.c b/lib/gunzip.c
index e71d8d0..5200771 100644
--- a/lib/gunzip.c
+++ b/lib/gunzip.c
@@ -15,6 +15,7 @@
 #include <u-boot/crc.h>
 #include <watchdog.h>
 #include <u-boot/zlib.h>
+#include <asm/sections.h>
 
 #define HEADER0			'\x1f'
 #define HEADER1			'\x8b'
@@ -43,7 +44,7 @@
 	free (addr);
 }
 
-int gzip_parse_header(const unsigned char *src, unsigned long len)
+__rcode int gzip_parse_header(const unsigned char *src, unsigned long len)
 {
 	int i, flags;
 
@@ -71,7 +72,7 @@
 	return i;
 }
 
-int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp)
+__rcode int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp)
 {
 	int offset = gzip_parse_header(src, *lenp);
 
@@ -274,8 +275,8 @@
 /*
  * Uncompress blocks compressed with zlib without headers
  */
-int zunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp,
-						int stoponerr, int offset)
+__rcode int zunzip(void *dst, int dstlen, unsigned char *src,
+		   unsigned long *lenp, int stoponerr, int offset)
 {
 	z_stream s;
 	int err = 0;
diff --git a/lib/lz4.c b/lib/lz4.c
index 63955a0..c718659 100644
--- a/lib/lz4.c
+++ b/lib/lz4.c
@@ -33,15 +33,16 @@
 #include <linux/bug.h>
 #include <asm/unaligned.h>
 #include <u-boot/lz4.h>
+#include <asm/sections.h>
 
 #define FORCE_INLINE inline __attribute__((always_inline))
 
-static FORCE_INLINE u16 LZ4_readLE16(const void *src)
+__rcode static FORCE_INLINE u16 LZ4_readLE16(const void *src)
 {
 	return get_unaligned_le16(src);
 }
 
-static FORCE_INLINE void LZ4_copy8(void *dst, const void *src)
+__rcode static FORCE_INLINE void LZ4_copy8(void *dst, const void *src)
 {
 	put_unaligned(get_unaligned((const u64 *)src), (u64 *)dst);
 }
@@ -53,7 +54,7 @@
 typedef uint64_t U64;
 typedef uintptr_t uptrval;
 
-static FORCE_INLINE void LZ4_write32(void *memPtr, U32 value)
+__rcode static FORCE_INLINE void LZ4_write32(void *memPtr, U32 value)
 {
 	put_unaligned(value, (U32 *)memPtr);
 }
@@ -63,7 +64,7 @@
 **************************************/
 
 /* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */
-static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
+__rcode static void LZ4_wildCopy(void *dstPtr, const void *srcPtr, void *dstEnd)
 {
     BYTE* d = (BYTE*)dstPtr;
     const BYTE* s = (const BYTE*)srcPtr;
@@ -112,13 +113,24 @@
 #endif
 
 /*
+ * spl_reloc needs all necessary data to be set up within its code, since the
+ * code is relocated at runtime. Unfortunately this increase code-size slightly
+ * so only do it if spl_reloc is enabled
+ */
+#if CONFIG_IS_ENABLED(RELOC_LOADER)
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+/*
  * LZ4_decompress_generic() :
  * This generic decompression function covers all use cases.
  * It shall be instantiated several times, using different sets of directives.
  * Note that it is important for performance that this function really get inlined,
  * in order to remove useless branches during compilation optimization.
  */
-static FORCE_INLINE int LZ4_decompress_generic(
+__rcode static FORCE_INLINE int LZ4_decompress_generic(
 	 const char * const src,
 	 char * const dst,
 	 int srcSize,
@@ -141,6 +153,8 @@
 	 const size_t dictSize
 	 )
 {
+	STATIC const unsigned int inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4};
+	STATIC const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3};
 	const BYTE *ip = (const BYTE *) src;
 	const BYTE * const iend = ip + srcSize;
 
@@ -149,8 +163,6 @@
 	BYTE *cpy;
 
 	const BYTE * const dictEnd = (const BYTE *)dictStart + dictSize;
-	static const unsigned int inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4};
-	static const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3};
 
 	const int safeDecode = (endOnInput == endOnInputSize);
 	const int checkOffset = ((safeDecode) && (dictSize < (int)(64 * KB)));
@@ -514,8 +526,9 @@
 	return (int) (-(((const char *)ip) - src)) - 1;
 }
 
-int LZ4_decompress_safe(const char *source, char *dest,
-	int compressedSize, int maxDecompressedSize)
+#ifndef CONFIG_SPL_BUILD
+__rcode int LZ4_decompress_safe(const char *source, char *dest,
+				int compressedSize, int maxDecompressedSize)
 {
 	return LZ4_decompress_generic(source, dest,
 				      compressedSize, maxDecompressedSize,
@@ -523,11 +536,13 @@
 				      noDict, (BYTE *)dest, NULL, 0);
 }
 
-int LZ4_decompress_safe_partial(const char *src, char *dst,
-	int compressedSize, int targetOutputSize, int dstCapacity)
+__rcode int LZ4_decompress_safe_partial(const char *src, char *dst,
+					int compressedSize,
+					int targetOutputSize, int dstCapacity)
 {
 	dstCapacity = min(targetOutputSize, dstCapacity);
 	return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity,
 				      endOnInputSize, partial_decode,
 				      noDict, (BYTE *)dst, NULL, 0);
 }
+#endif
diff --git a/lib/lz4_wrapper.c b/lib/lz4_wrapper.c
index 4d48e7b..b120451 100644
--- a/lib/lz4_wrapper.c
+++ b/lib/lz4_wrapper.c
@@ -15,7 +15,7 @@
 
 #define LZ4F_BLOCKUNCOMPRESSED_FLAG 0x80000000U
 
-int ulz4fn(const void *src, size_t srcn, void *dst, size_t *dstn)
+__rcode int ulz4fn(const void *src, size_t srcn, void *dst, size_t *dstn)
 {
 	const void *end = dst + *dstn;
 	const void *in = src;
diff --git a/lib/mbedtls/Kconfig b/lib/mbedtls/Kconfig
index aa82336..35d8c50 100644
--- a/lib/mbedtls/Kconfig
+++ b/lib/mbedtls/Kconfig
@@ -112,6 +112,46 @@
 
 endif # SPL
 
+if VPL
+
+config VPL_SHA1_LEGACY
+	bool "Enable SHA1 support in VPL with legacy crypto library"
+	depends on LEGACY_CRYPTO_BASIC && VPL_SHA1
+	help
+	  This option enables support of hashing using SHA1 algorithm
+	  with legacy crypto library.
+
+config VPL_SHA256_LEGACY
+	bool "Enable SHA256 support in VPL with legacy crypto library"
+	depends on LEGACY_CRYPTO_BASIC && VPL_SHA256
+	help
+	  This option enables support of hashing using SHA256 algorithm
+	  with legacy crypto library.
+
+config VPL_SHA512_LEGACY
+	bool "Enable SHA512 support in VPL with legacy crypto library"
+	depends on LEGACY_CRYPTO_BASIC && VPL_SHA512
+	help
+	  This option enables support of hashing using SHA512 algorithm
+	  with legacy crypto library.
+
+config VPL_SHA384_LEGACY
+	bool "Enable SHA384 support in VPL with legacy crypto library"
+	depends on LEGACY_CRYPTO_BASIC && VPL_SHA384
+	select VPL_SHA512_LEGACY
+	help
+	  This option enables support of hashing using SHA384 algorithm
+	  with legacy crypto library.
+
+config VPL_MD5_LEGACY
+	bool "Enable MD5 support in VPL with legacy crypto library"
+	depends on LEGACY_CRYPTO_BASIC && VPL_MD5
+	help
+	  This option enables support of hashing using MD5 algorithm
+	  with legacy crypto library.
+
+endif # VPL
+
 endif # LEGACY_CRYPTO_BASIC
 
 config LEGACY_CRYPTO_CERT
diff --git a/lib/string.c b/lib/string.c
index feae951..0e0900d 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -21,6 +21,7 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <malloc.h>
+#include <asm/sections.h>
 
 /**
  * strncasecmp - Case insensitive, length-limited string comparison
@@ -559,7 +560,7 @@
  * You should not use this function to access IO space, use memcpy_toio()
  * or memcpy_fromio() instead.
  */
-__used void * memcpy(void *dest, const void *src, size_t count)
+__rcode __used void *memcpy(void *dest, const void *src, size_t count)
 {
 	unsigned long *dl = (unsigned long *)dest, *sl = (unsigned long *)src;
 	char *d8, *s8;
@@ -593,7 +594,7 @@
  *
  * Unlike memcpy(), memmove() copes with overlapping areas.
  */
-__used void * memmove(void * dest,const void *src,size_t count)
+__rcode __used void *memmove(void *dest, const void *src, size_t count)
 {
 	char *tmp, *s;
 
diff --git a/lib/zlib/inflate.c b/lib/zlib/inflate.c
index f7e81fc..b4c72cc 100644
--- a/lib/zlib/inflate.c
+++ b/lib/zlib/inflate.c
@@ -2,10 +2,12 @@
  * Copyright (C) 1995-2005 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
+#include <asm/sections.h>
+
 local void fixedtables OF((struct inflate_state FAR *state));
 local int updatewindow OF((z_streamp strm, unsigned out));
 
-int ZEXPORT inflateReset(z_streamp strm)
+__rcode int ZEXPORT inflateReset(z_streamp strm)
 {
     struct inflate_state FAR *state;
 
@@ -30,8 +32,8 @@
     return Z_OK;
 }
 
-int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
-			  int stream_size)
+__rcode int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
+				  int stream_size)
 {
     struct inflate_state FAR *state;
 
@@ -67,12 +69,12 @@
     return inflateReset(strm);
 }
 
-int ZEXPORT inflateInit_(z_streamp strm, int stream_size)
+__rcode int ZEXPORT inflateInit_(z_streamp strm, int stream_size)
 {
     return inflateInit2_(strm, DEF_WBITS, stream_size);
 }
 
-local void fixedtables(struct inflate_state FAR *state)
+__rcode local void fixedtables(struct inflate_state FAR *state)
 {
     state->lencode = lenfix;
     state->lenbits = 9;
@@ -94,7 +96,7 @@
    output will fall in the output data, making match copies simpler and faster.
    The advantage may be dependent on the size of the processor's data caches.
  */
-local int updatewindow(z_streamp strm, unsigned out)
+__rcode local int updatewindow(z_streamp strm, unsigned int out)
 {
     struct inflate_state FAR *state;
     unsigned copy, dist;
@@ -322,7 +324,7 @@
    when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
    will return Z_BUF_ERROR if it has not reached the end of the stream.
  */
-int ZEXPORT inflate(z_streamp strm, int flush)
+__rcode int ZEXPORT inflate(z_streamp strm, int flush)
 {
     struct inflate_state FAR *state;
     unsigned char FAR *next;    /* next input */
@@ -924,7 +926,7 @@
     return ret;
 }
 
-int ZEXPORT inflateEnd(z_streamp strm)
+__rcode int ZEXPORT inflateEnd(z_streamp strm)
 {
     struct inflate_state FAR *state;
     if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
diff --git a/test/cmd/setexpr.c b/test/cmd/setexpr.c
index 7f318a42..5e9b577 100644
--- a/test/cmd/setexpr.c
+++ b/test/cmd/setexpr.c
@@ -297,31 +297,19 @@
 /* Test 'setexpr' command with setting strings */
 static int setexpr_test_str(struct unit_test_state *uts)
 {
-	ulong start_mem;
 	char *buf;
 
 	buf = map_sysmem(0, BUF_SIZE);
 	memset(buf, '\xff', BUF_SIZE);
 
-	/*
-	 * Set 'fred' to the same length as we expect to get below, to avoid a
-	 * new allocation in 'setexpr'. That way we can check for memory leaks.
-	 */
 	ut_assertok(env_set("fred", "x"));
-	start_mem = ut_check_free();
-	strcpy(buf, "hello");
-	ut_asserteq(1, run_command("setexpr.s fred 0", 0));
-	ut_assertok(ut_check_delta(start_mem));
+	ut_asserteq(0, run_command("setexpr.s fred 0", 0));
+	ut_asserteq_str("0", env_get("fred"));
 
+	strcpy(buf, "hello");
 	ut_assertok(env_set("fred", "12345"));
-	start_mem = ut_check_free();
 	ut_assertok(run_command("setexpr.s fred *0", 0));
 	ut_asserteq_str("hello", env_get("fred"));
-	/*
-	 * This fails in CI at present.
-	 *
-	 * ut_assertok(ut_check_delta(start_mem));
-	 */
 
 	unmap_sysmem(buf);
 
@@ -332,45 +320,25 @@
 /* Test 'setexpr' command with concatenating strings */
 static int setexpr_test_str_oper(struct unit_test_state *uts)
 {
-	ulong start_mem;
 	char *buf;
 
+	/* Test concatenation of strings */
+	ut_assertok(run_command("setexpr.s fred '1' + '3'", 0));
+	ut_asserteq_str("13", env_get("fred"));
+
 	buf = map_sysmem(0, BUF_SIZE);
 	memset(buf, '\xff', BUF_SIZE);
 	strcpy(buf, "hello");
 	strcpy(buf + 0x10, " there");
 
-	start_mem = ut_check_free();
 	ut_asserteq(1, run_command("setexpr.s fred *0 * *10", 0));
-	ut_assertok(ut_check_delta(start_mem));
 	ut_assert_nextline("invalid op");
 	ut_assert_console_end();
 
-	/*
-	 * Set 'fred' to the same length as we expect to get below, to avoid a
-	 * new allocation in 'setexpr'. That way we can check for memory leaks.
-	 */
 	ut_assertok(env_set("fred", "12345012345"));
-	start_mem = ut_check_free();
 	ut_assertok(run_command("setexpr.s fred *0 + *10", 0));
 	ut_asserteq_str("hello there", env_get("fred"));
 
-	/*
-	 * This check does not work with sandbox_flattree, apparently due to
-	 * memory allocations in env_set().
-	 *
-	 * The truetype console produces lots of memory allocations even though
-	 * the LCD display is not visible. But even without these, it does not
-	 * work.
-	 *
-	 * A better test would be for dlmalloc to record the allocs and frees
-	 * for a particular caller, but that is not supported.
-	 *
-	 * For now, drop this test.
-	 *
-	 * ut_assertok(ut_check_delta(start_mem));
-	 */
-
 	unmap_sysmem(buf);
 
 	return 0;
diff --git a/test/dm/led.c b/test/dm/led.c
index e5b8632..36652c2 100644
--- a/test/dm/led.c
+++ b/test/dm/led.c
@@ -20,7 +20,12 @@
 	ut_assertok(uclass_get_device(UCLASS_LED, 1, &dev));
 	ut_assertok(uclass_get_device(UCLASS_LED, 2, &dev));
 	ut_assertok(uclass_get_device(UCLASS_LED, 3, &dev));
-	ut_asserteq(-ENODEV, uclass_get_device(UCLASS_LED, 4, &dev));
+	ut_assertok(uclass_get_device(UCLASS_LED, 4, &dev));
+	ut_assertok(uclass_get_device(UCLASS_LED, 5, &dev));
+	ut_assertok(uclass_get_device(UCLASS_LED, 6, &dev));
+	ut_assertok(uclass_get_device(UCLASS_LED, 7, &dev));
+	ut_assertok(uclass_get_device(UCLASS_LED, 8, &dev));
+	ut_asserteq(-ENODEV, uclass_get_device(UCLASS_LED, 9, &dev));
 
 	return 0;
 }
@@ -110,6 +115,21 @@
 
 	ut_asserteq(-ENODEV, led_get_by_label("sandbox:blue", &dev));
 
+	/* Test if function, color and function-enumerator naming works */
+	ut_assertok(led_get_by_label("red:status-20", &dev));
+
+	/* Test if function, color naming works */
+	ut_assertok(led_get_by_label("green:status", &dev));
+
+	/* Test if function, without color naming works */
+	ut_assertok(led_get_by_label(":status", &dev));
+
+	/* Test if color without function naming works */
+	ut_assertok(led_get_by_label("green:", &dev));
+
+	/* Test if function, color naming is ignored if label is found */
+	ut_assertok(led_get_by_label("sandbox:function", &dev));
+
 	return 0;
 }
 DM_TEST(dm_test_led_label, UTF_SCAN_PDATA | UTF_SCAN_FDT);
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index 4a23a3c..cc8b444 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -1599,7 +1599,7 @@
 	ut_assert(!ofnode_valid(node));
 	ut_assert(!ofnode_valid(ofnode_path("/leds/default_on")));
 
-	ut_asserteq(2, ofnode_get_child_count(ofnode_path("/leds")));
+	ut_asserteq(7, ofnode_get_child_count(ofnode_path("/leds")));
 
 	return 0;
 }
diff --git a/test/py/tests/test_usb.py b/test/py/tests/test_usb.py
index e1f203b..566d73b 100644
--- a/test/py/tests/test_usb.py
+++ b/test/py/tests/test_usb.py
@@ -242,7 +242,7 @@
                     elif part_type == '83':
                         print('ext(2/4) detected')
                         output = u_boot_console.run_command(
-                            'fstype usb %d:%d' % i, part_id
+                            'fstype usb %d:%d' % (i, part_id)
                         )
                         if 'ext2' in output:
                             part_ext2.append(part_id)
diff --git a/tools/Kconfig b/tools/Kconfig
index 5c75af4..01ff0fc 100644
--- a/tools/Kconfig
+++ b/tools/Kconfig
@@ -9,6 +9,11 @@
 	  some cases the system dtc may not support all required features
 	  and the path to a different version should be given here.
 
+config TOOLS_CRC16
+	def_bool y
+	help
+	  Enable CRC32 support in the tools builds
+
 config TOOLS_CRC32
 	def_bool y
 	help
diff --git a/tools/mkenvimage.c b/tools/mkenvimage.c
index a8eebab..885cdb1 100644
--- a/tools/mkenvimage.c
+++ b/tools/mkenvimage.c
@@ -28,7 +28,7 @@
 
 static void usage(const char *exec_name)
 {
-	fprintf(stderr, "%s [-h] [-r] [-b] [-p <byte>] -s <environment partition size> -o <output> <input file>\n"
+	fprintf(stderr, "%s [-h] [-V] [-r] [-b] [-p <byte>] -s <environment partition size> -o <output> <input file>\n"
 	       "\n"
 	       "This tool takes a key=value input file (same as would a `printenv' show) and generates the corresponding environment image, ready to be flashed.\n"
 	       "\n"