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

u-boot-imx-next-20230331 for next
---------------------------------

CI: https://source.denx.de/u-boot/custodians/u-boot-imx/-/pipelines/15819

i.MX patches queued for next:

- Conversions to DM_SERIAL
- Fixes for Toradex boards
- Gateworks Boards
- i.MX8ULP
- EQoS support / fixes, changes in boards
diff --git a/Kconfig b/Kconfig
index b8f6558..7a8c190 100644
--- a/Kconfig
+++ b/Kconfig
@@ -427,16 +427,16 @@
 
 config BUILD_TARGET
 	string "Build target special images"
+	default "u-boot-elf.srec" if RCAR_GEN3
+	default "u-boot-with-spl.bin" if ARCH_AT91 && SPL_NAND_SUPPORT
+	default "u-boot-with-spl.bin" if MPC85xx && !E500MC && !E5500 && !E6500 && SPL
+	default "u-boot-with-spl.imx" if ARCH_MX6 && SPL
+	default "u-boot-with-spl.kwb" if ARMADA_32BIT && SPL
 	default "u-boot-with-spl.sfp" if TARGET_SOCFPGA_ARRIA10
 	default "u-boot-with-spl.sfp" if TARGET_SOCFPGA_GEN5
-	default "u-boot-with-spl.kwb" if ARMADA_32BIT && SPL
-	default "u-boot-elf.srec" if RCAR_GEN3
 	default "u-boot.itb" if !BINMAN && SPL_LOAD_FIT && (ARCH_ROCKCHIP || \
 				ARCH_SUNXI || RISCV || ARCH_ZYNQMP)
 	default "u-boot.kwb" if (ARCH_KIRKWOOD || ARMADA_32BIT) && !SPL
-	default "u-boot-with-spl.bin" if MPC85xx && !E500MC && !E5500 && !E6500 && SPL
-	default "u-boot-with-spl.bin" if ARCH_AT91 && SPL_NAND_SUPPORT
-	default "u-boot-with-spl.imx" if ARCH_MX6 && SPL
 	help
 	  Some SoCs need special image types (e.g. U-Boot binary
 	  with a special header) as build targets. By defining
@@ -575,14 +575,6 @@
 	  This provides an option to bringup different processors
 	  in multiprocessor cases.
 
-config EXAMPLES
-	bool "Compile API examples"
-	depends on !SANDBOX
-	default y if ARCH_QEMU
-	help
-	  U-Boot provides an API for standalone applications. Examples are
-	  provided in directory examples/.
-
 endmenu		# General setup
 
 source "api/Kconfig"
diff --git a/MAINTAINERS b/MAINTAINERS
index 91d40ea..d2e245e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1249,6 +1249,12 @@
 S:	Maintained
 F:	drivers/pci/pci_mpc85xx.c
 
+PCI MPS
+M:	Stephen Carlson <stcarlso@linux.microsoft.com>
+S:	Maintained
+F:	cmd/pci_mps.c
+F:	test/cmd/pci_mps.c
+
 POWER
 M:	Jaehoon Chung <jh80.chung@samsung.com>
 S:	Maintained
diff --git a/api/Kconfig b/api/Kconfig
index d936272..6072288 100644
--- a/api/Kconfig
+++ b/api/Kconfig
@@ -10,9 +10,16 @@
 	depends on API
 	default 1
 
-endmenu
+config EXAMPLES
+	bool "Compile API examples"
+	depends on !SANDBOX
+	default y if ARCH_QEMU
+	help
+	  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
@@ -30,3 +37,5 @@
 	  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/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index a8b55fe..97a4832 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -1260,7 +1260,10 @@
 	k3-am6528-iot2050-basic.dtb \
 	k3-am6528-iot2050-basic-pg2.dtb \
 	k3-am6548-iot2050-advanced.dtb \
-	k3-am6548-iot2050-advanced-pg2.dtb
+	k3-am6548-iot2050-advanced-pg2.dtb \
+	k3-am6548-iot2050-advanced-m2.dtb \
+	k3-am6548-iot2050-advanced-m2-bkey-usb3-overlay.dtbo \
+	k3-am6548-iot2050-advanced-m2-bkey-ekey-pcie-overlay.dtbo
 dtb-$(CONFIG_SOC_K3_J721E) += k3-j721e-common-proc-board.dtb \
 			      k3-j721e-r5-common-proc-board.dtb \
 			      k3-j7200-common-proc-board.dtb \
diff --git a/arch/arm/dts/armada-388-clearfog-u-boot.dtsi b/arch/arm/dts/armada-388-clearfog-u-boot.dtsi
index fb27a3b..906d8f2 100644
--- a/arch/arm/dts/armada-388-clearfog-u-boot.dtsi
+++ b/arch/arm/dts/armada-388-clearfog-u-boot.dtsi
@@ -10,6 +10,7 @@
 
 &sdhci {
 	bootph-pre-ram;
+	non-removable; /* assume that the card is always present, required for eMMC variant */
 };
 
 &gpio0 {
diff --git a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi
index 2705837..03ccc54 100644
--- a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi
+++ b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) Siemens AG, 2020-2021
+ * Copyright (c) Siemens AG, 2020-2022
  *
  * Authors:
  *   Jan Kiszka <jan.kiszka@siemens.com>
@@ -14,21 +14,27 @@
 		filename = "flash.bin";
 		pad-byte = <0xff>;
 		size = <0x8c0000>;
+		allow-repack;
 
 		blob-ext@0x000000 {
 			offset = <0x000000>;
-			filename = "tiboot3.bin";
+#ifdef CONFIG_TARGET_IOT2050_A53_PG1
+			filename = "seboot_pg1.bin";
+#else
+			filename = "seboot_pg2.bin";
+#endif
 			missing-msg = "iot2050-seboot";
 		};
 
-		blob@0x080000 {
-			offset = <0x080000>;
+		blob@0x180000 {
+			offset = <0x180000>;
 			filename = "tispl.bin";
 		};
 
-		fit@0x280000 {
+		fit@0x380000 {
 			description = "U-Boot for IOT2050";
-			offset = <0x280000>;
+			fit,fdt-list = "of-list";
+			offset = <0x380000>;
 			images {
 				u-boot {
 					description = "U-Boot";
@@ -40,47 +46,50 @@
 					entry = <0x80800000>;
 					u-boot-nodtb {
 					};
-				};
-
-				fdt-iot2050-basic {
-					description = "k3-am6528-iot2050-basic.dtb";
-					type = "flat_dt";
-					arch = "arm64";
-					compression = "none";
-					blob {
-						filename = "arch/arm/dts/k3-am6528-iot2050-basic.dtb";
+					hash {
+						algo = "sha256";
 					};
 				};
 
-				fdt-iot2050-basic-pg2 {
-					description = "k3-am6528-iot2050-basic-pg2.dtb";
+				@fdt-SEQ {
+					description = "fdt-NAME";
 					type = "flat_dt";
 					arch = "arm64";
 					compression = "none";
-					blob {
-						filename = "arch/arm/dts/k3-am6528-iot2050-basic-pg2.dtb";
+					hash {
+						algo = "sha256";
 					};
 				};
 
-				fdt-iot2050-advanced {
-					description = "k3-am6548-iot2050-advanced.dtb";
-					type = "flat_dt";
+#ifdef CONFIG_TARGET_IOT2050_A53_PG2
+				bkey-usb3-overlay {
+					description = "M.2-bkey-usb3-overlay";
+					type = "blob";
+					load = <0x82100000>;
 					arch = "arm64";
 					compression = "none";
-					blob {
-						filename = "arch/arm/dts/k3-am6548-iot2050-advanced.dtb";
+					blob-ext {
+						filename = "k3-am6548-iot2050-advanced-m2-bkey-usb3-overlay.dtbo";
+					};
+					hash {
+						algo = "sha256";
 					};
 				};
 
-				fdt-iot2050-advanced-pg2 {
-					description = "k3-am6548-iot2050-advanced-pg2.dtb";
-					type = "flat_dt";
+				bkey-ekey-pcie-overlay {
+					description = "M.2-bkey-ekey-pcie-overlay";
+					type = "blob";
+					load = <0x82110000>;
 					arch = "arm64";
 					compression = "none";
-					blob {
-						filename = "arch/arm/dts/k3-am6548-iot2050-advanced-pg2.dtb";
+					blob-ext {
+						filename = "k3-am6548-iot2050-advanced-m2-bkey-ekey-pcie-overlay.dtbo";
+					};
+					hash {
+						algo = "sha256";
 					};
 				};
+#endif
 
 #ifdef CONFIG_WDT_K3_RTI_FW_FILE
 				k3-rti-wdt-firmware {
@@ -92,51 +101,38 @@
 						filename = CONFIG_WDT_K3_RTI_FW_FILE;
 						missing-msg = "k3-rti-wdt-firmware";
 					};
+					hash {
+						algo = "sha256";
+					};
 				};
 #endif
 			};
 
 			configurations {
-				default = "conf-iot2050-basic";
-
-				conf-iot2050-basic {
-					description = "iot2050-basic";
-					firmware = "u-boot";
-					fdt = "fdt-iot2050-basic";
-#ifdef CONFIG_WDT_K3_RTI_FW_FILE
-					loadables = "k3-rti-wdt-firmware";
-#endif
-				};
-
-				conf-iot2050-basic-pg2 {
-					description = "iot2050-basic-pg2";
+				default = "@config-DEFAULT-SEQ";
+				@config-SEQ {
+					description = "NAME";
 					firmware = "u-boot";
-					fdt = "fdt-iot2050-basic-pg2";
-#ifdef CONFIG_WDT_K3_RTI_FW_FILE
-					loadables = "k3-rti-wdt-firmware";
+					fdt = "fdt-SEQ";
+					loadables =
+#ifdef CONFIG_TARGET_IOT2050_A53_PG2
+						"bkey-usb3-overlay",
+						"bkey-ekey-pcie-overlay",
 #endif
-				};
-
-				conf-iot2050-advanced {
-					description = "iot2050-advanced";
-					firmware = "u-boot";
-					fdt = "fdt-iot2050-advanced";
-#ifdef CONFIG_WDT_K3_RTI_FW_FILE
-					loadables = "k3-rti-wdt-firmware";
-#endif
-				};
-
-				conf-iot2050-advanced-pg2 {
-					description = "iot2050-advanced-pg2";
-					firmware = "u-boot";
-					fdt = "fdt-iot2050-advanced-pg2";
 #ifdef CONFIG_WDT_K3_RTI_FW_FILE
-					loadables = "k3-rti-wdt-firmware";
+						"k3-rti-wdt-firmware",
 #endif
+						<>;
+					signature {
+						sign-images = "firmware", "fdt", "loadables";
+					};
 				};
 			};
 		};
 
+		fdtmap {
+		};
+
 		/* primary env */
 		fill@0x680000 {
 			offset = <0x680000>;
@@ -150,29 +146,20 @@
 			fill-byte = [00];
 		};
 
-		/* PG1 sysfw, basic variant */
+		/* OTP update command block */
+#if CONFIG_IOT2050_EMBED_OTPCMD
 		blob-ext@0x6c0000 {
 			offset = <0x6c0000>;
-			filename = "sysfw.itb";
-			missing-msg = "iot2050-sysfw";
+			size   = <0x010000>;
+			filename = "otpcmd.bin";
+			missing-msg = "iot2050-otpcmd";
 		};
-		/* PG1 sysfw, advanced variant */
-		blob-ext@0x740000 {
-			offset = <0x740000>;
-			filename = "sysfw.itb_HS";
-			missing-msg = "iot2050-sysfw";
-		};
-		/* PG2 sysfw, basic variant */
-		blob-ext@0x7c0000 {
-			offset = <0x7c0000>;
-			filename = "sysfw_sr2.itb";
-			missing-msg = "iot2050-sysfw";
-		};
-		/* PG2 sysfw, advanced variant */
-		blob-ext@0x840000 {
-			offset = <0x840000>;
-			filename = "sysfw_sr2.itb_HS";
-			missing-msg = "iot2050-sysfw";
+#else
+		fill@0x6c0000 {
+			offset = <0x6c0000>;
+			size   = <0x010000>;
+			fill-byte = [ff];
 		};
+#endif
 	};
 };
diff --git a/arch/arm/dts/k3-am6548-iot2050-advanced-m2-bkey-ekey-pcie-overlay.dts b/arch/arm/dts/k3-am6548-iot2050-advanced-m2-bkey-ekey-pcie-overlay.dts
new file mode 100644
index 0000000..c9e7360
--- /dev/null
+++ b/arch/arm/dts/k3-am6548-iot2050-advanced-m2-bkey-ekey-pcie-overlay.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IOT2050 M.2 variant, overlay for B-key PCIE0_LANE0 + E-key PCIE1_LANE0
+ * Copyright (c) Siemens AG, 2022
+ *
+ * Authors:
+ *   Chao Zeng <chao.zeng@siemens.com>
+ *   Jan Kiszka <jan.kiszka@siemens.com>
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/gpio/gpio.h>
+
+&pcie0_rc {
+	num-lanes = <1>;
+	phys = <&serdes0 PHY_TYPE_PCIE 1>;
+	phy-names = "pcie-phy0";
+	reset-gpios = <&main_gpio1 15 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&pcie1_rc {
+	status = "okay";
+};
diff --git a/arch/arm/dts/k3-am6548-iot2050-advanced-m2-bkey-usb3-overlay.dts b/arch/arm/dts/k3-am6548-iot2050-advanced-m2-bkey-usb3-overlay.dts
new file mode 100644
index 0000000..72fc011
--- /dev/null
+++ b/arch/arm/dts/k3-am6548-iot2050-advanced-m2-bkey-usb3-overlay.dts
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IOT2050 M.2 variant, overlay for B-key USB3.0 + E-key PCIE1_LANE0
+ * Copyright (c) Siemens AG, 2022
+ *
+ * Authors:
+ *   Chao Zeng <chao.zeng@siemens.com>
+ *   Jan Kiszka <jan.kiszka@siemens.com>
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/gpio/gpio.h>
+
+&serdes0 {
+	assigned-clock-parents = <&k3_clks 153 7>, <&k3_clks 153 4>;
+};
+
+&pcie0_rc {
+	status = "disabled";
+};
+
+&pcie1_rc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&minipcie_pins_default>;
+
+	num-lanes = <1>;
+	phys = <&serdes1 PHY_TYPE_PCIE 0>;
+	phy-names = "pcie-phy0";
+	reset-gpios = <&wkup_gpio0 27 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&dwc3_0 {
+	assigned-clock-parents = <&k3_clks 151 4>,  /* set REF_CLK to 20MHz i.e. PER0_PLL/48 */
+				 <&k3_clks 151 8>;  /* set PIPE3_TXB_CLK to WIZ8B2M4VSB */
+	phys = <&serdes0 PHY_TYPE_USB3 0>;
+	phy-names = "usb3-phy";
+};
+
+&usb0 {
+	maximum-speed = "super-speed";
+	snps,dis-u1-entry-quirk;
+	snps,dis-u2-entry-quirk;
+};
diff --git a/arch/arm/dts/k3-am6548-iot2050-advanced-m2.dts b/arch/arm/dts/k3-am6548-iot2050-advanced-m2.dts
new file mode 100644
index 0000000..9400e35
--- /dev/null
+++ b/arch/arm/dts/k3-am6548-iot2050-advanced-m2.dts
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) Siemens AG, 2018-2023
+ *
+ * Authors:
+ *   Chao Zeng <chao.zeng@siemens.com>
+ *   Jan Kiszka <jan.kiszka@siemens.com>
+ *
+ * AM6548-based (quad-core) IOT2050 M.2 variant (based on Advanced Product
+ * Generation 2), 2 GB RAM, 16 GB eMMC, USB-serial converter on connector X30
+ *
+ * Product homepage:
+ * https://new.siemens.com/global/en/products/automation/pc-based/iot-gateways/simatic-iot2050.html
+ */
+
+#include "k3-am6548-iot2050-advanced-common.dtsi"
+#include "k3-am65-iot2050-common-pg2.dtsi"
+
+/ {
+	compatible = "siemens,iot2050-advanced-m2", "ti,am654";
+	model = "SIMATIC IOT2050 Advanced M2";
+};
+
+&mcu_r5fss0 {
+	/* lock-step mode not supported on this board */
+	ti,cluster-mode = <0>;
+};
+
+&main_pmx0 {
+	main_m2_enable_pins_default: main-m2-enable-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x01c4, PIN_INPUT_PULLUP, 7)  /* (AH13) GPIO1_17 */
+		>;
+	};
+
+	main_bkey_pcie_reset: main-bkey-pcie-reset {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x01bc, PIN_OUTPUT_PULLUP, 7)  /* (AG13) GPIO1_15 */
+		>;
+	};
+
+	main_pmx0_m2_config_pins_default: main-pmx0-m2-config-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x01c8, PIN_INPUT_PULLUP, 7)  /* (AE13) GPIO1_18 */
+			AM65X_IOPAD(0x01cc, PIN_INPUT_PULLUP, 7)  /* (AD13) GPIO1_19 */
+		>;
+	};
+
+	main_m2_pcie_mux_control: main-m2-pcie-mux-control {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x0148, PIN_INPUT_PULLUP, 7)  /* (AG22) GPIO0_82 */
+			AM65X_IOPAD(0x0160, PIN_INPUT_PULLUP, 7)  /* (AE20) GPIO0_88 */
+			AM65X_IOPAD(0x0164, PIN_INPUT_PULLUP, 7)  /* (AF19) GPIO0_89 */
+		>;
+	};
+};
+
+&main_pmx1 {
+	main_pmx1_m2_config_pins_default: main-pmx1-m2-config-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x0018, PIN_INPUT_PULLUP, 7)  /* (B22) GPIO1_88 */
+			AM65X_IOPAD(0x001c, PIN_INPUT_PULLUP, 7)  /* (C23) GPIO1_89 */
+		>;
+	};
+};
+
+&main_gpio0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <
+		&main_m2_pcie_mux_control
+		&arduino_io_d4_to_d9_pins_default
+	>;
+};
+
+&main_gpio1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <
+		&main_m2_enable_pins_default
+		&main_pmx0_m2_config_pins_default
+		&main_pmx1_m2_config_pins_default
+		&cp2102n_reset_pin_default
+	>;
+};
+
+/*
+ * Base configuration for B-key slot with PCIe x2, E-key with USB 2.0 only.
+ * Firmware switches to other modes via device tree overlays.
+ */
+
+&serdes0 {
+	assigned-clocks = <&k3_clks 153 4>, <&serdes0 AM654_SERDES_CMU_REFCLK>;
+	assigned-clock-parents = <&k3_clks 153 8>, <&k3_clks 153 4>;
+};
+
+&pcie0_rc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_bkey_pcie_reset>;
+
+	num-lanes = <2>;
+	phys = <&serdes0 PHY_TYPE_PCIE 1>, <&serdes1 PHY_TYPE_PCIE 1>;
+	phy-names = "pcie-phy0","pcie-phy1";
+	reset-gpios = <&main_gpio1 15 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&pcie1_rc {
+	status = "disabled";
+};
+
+&dwc3_0 {
+	assigned-clock-parents = <&k3_clks 151 4>,  /* set REF_CLK to 20MHz i.e. PER0_PLL/48 */
+				 <&k3_clks 151 9>;  /* set PIPE3_TXB_CLK to CLK_12M_RC/256 (for HS only) */
+	/delete-property/ phys;
+	/delete-property/ phy-names;
+};
+
+&usb0 {
+	maximum-speed = "high-speed";
+	/delete-property/ snps,dis-u1-entry-quirk;
+	/delete-property/ snps,dis-u2-entry-quirk;
+};
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig
index a8c3a59..7edbac2 100644
--- a/arch/arm/mach-k3/Kconfig
+++ b/arch/arm/mach-k3/Kconfig
@@ -187,6 +187,11 @@
 	help
 	  SWRV for X509 certificate used for boot images
 
+config K3_BOARD_DETECT
+	bool "Support for Board detection"
+	help
+	   Support for board detection.
+
 source "board/ti/am65x/Kconfig"
 source "board/ti/am64x/Kconfig"
 source "board/ti/am62x/Kconfig"
diff --git a/arch/arm/mach-k3/am642_init.c b/arch/arm/mach-k3/am642_init.c
index 96f292e..1bf7e16 100644
--- a/arch/arm/mach-k3/am642_init.c
+++ b/arch/arm/mach-k3/am642_init.c
@@ -100,7 +100,7 @@
 {
 	int ret, rescan;
 
-	if (IS_ENABLED(CONFIG_TI_I2C_BOARD_DETECT))
+	if (IS_ENABLED(CONFIG_K3_BOARD_DETECT))
 		do_board_detect();
 
 	/*
diff --git a/arch/arm/mach-k3/am654_init.c b/arch/arm/mach-k3/am654_init.c
index 768fdd6..70059ed 100644
--- a/arch/arm/mach-k3/am654_init.c
+++ b/arch/arm/mach-k3/am654_init.c
@@ -245,8 +245,7 @@
 	/* Output System Firmware version info */
 	k3_sysfw_print_ver();
 
-	/* Perform EEPROM-based board detection */
-	if (IS_ENABLED(CONFIG_TI_I2C_BOARD_DETECT))
+	if (IS_ENABLED(CONFIG_K3_BOARD_DETECT))
 		do_board_detect();
 
 #if defined(CONFIG_CPU_V7R) && defined(CONFIG_K3_AVS0)
diff --git a/arch/arm/mach-k3/j721e_init.c b/arch/arm/mach-k3/j721e_init.c
index 276cbb5..9cae3ac 100644
--- a/arch/arm/mach-k3/j721e_init.c
+++ b/arch/arm/mach-k3/j721e_init.c
@@ -140,7 +140,7 @@
 	int ret, rescan, mmc_dev = -1;
 	static struct mmc *mmc;
 
-	if (IS_ENABLED(CONFIG_TI_I2C_BOARD_DETECT))
+	if (IS_ENABLED(CONFIG_K3_BOARD_DETECT))
 		do_board_detect();
 
 	/*
@@ -267,8 +267,7 @@
 	/* Output System Firmware version info */
 	k3_sysfw_print_ver();
 
-	/* Perform EEPROM-based board detection */
-	if (IS_ENABLED(CONFIG_TI_I2C_BOARD_DETECT))
+	if (IS_ENABLED(CONFIG_K3_BOARD_DETECT))
 		do_board_detect();
 
 #if defined(CONFIG_CPU_V7R) && defined(CONFIG_K3_AVS0)
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 1f0dbef..b1f2e97 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -107,6 +107,7 @@
 	bool "Support ClearFog"
 	select 88F6820
 	select BOARD_LATE_INIT
+	select OF_BOARD_SETUP
 
 config TARGET_HELIOS4
 	bool "Support Helios4"
diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
index 56999f6..1676032 100644
--- a/arch/arm/mach-mvebu/cpu.c
+++ b/arch/arm/mach-mvebu/cpu.c
@@ -67,6 +67,10 @@
 {
 	u32 val;
 	u32 boot_device;
+	u32 boot_err_mode;
+#ifdef CONFIG_ARMADA_38X
+	u32 boot_err_code;
+#endif
 
 	/*
 	 * First check, if UART boot-mode is active. This can only
@@ -74,9 +78,9 @@
 	 * MSB marks if the UART mode is active.
 	 */
 	val = readl(BOOTROM_ERR_REG);
-	boot_device = (val & BOOTROM_ERR_MODE_MASK) >> BOOTROM_ERR_MODE_OFFS;
-	debug("BOOTROM_REG=0x%08x boot_device=0x%x\n", val, boot_device);
-	if (boot_device == BOOTROM_ERR_MODE_UART)
+	boot_err_mode = (val & BOOTROM_ERR_MODE_MASK) >> BOOTROM_ERR_MODE_OFFS;
+	debug("BOOTROM_ERR_REG=0x%08x boot_err_mode=0x%x\n", val, boot_err_mode);
+	if (boot_err_mode == BOOTROM_ERR_MODE_UART)
 		return BOOT_DEVICE_UART;
 
 #ifdef CONFIG_ARMADA_38X
@@ -84,8 +88,9 @@
 	 * If the bootrom error code contains any other than zeros it's an
 	 * error condition and the bootROM has fallen back to UART boot
 	 */
-	boot_device = (val & BOOTROM_ERR_CODE_MASK) >> BOOTROM_ERR_CODE_OFFS;
-	if (boot_device)
+	boot_err_code = (val & BOOTROM_ERR_CODE_MASK) >> BOOTROM_ERR_CODE_OFFS;
+	debug("boot_err_code=0x%x\n", boot_err_code);
+	if (boot_err_code)
 		return BOOT_DEVICE_UART;
 #endif
 
@@ -95,31 +100,27 @@
 	val = readl(CFG_SAR_REG);	/* SAR - Sample At Reset */
 	boot_device = (val & BOOT_DEV_SEL_MASK) >> BOOT_DEV_SEL_OFFS;
 	debug("SAR_REG=0x%08x boot_device=0x%x\n", val, boot_device);
-	switch (boot_device) {
 #ifdef BOOT_FROM_NAND
-	case BOOT_FROM_NAND:
+	if (BOOT_FROM_NAND(boot_device))
 		return BOOT_DEVICE_NAND;
 #endif
 #ifdef BOOT_FROM_MMC
-	case BOOT_FROM_MMC:
-	case BOOT_FROM_MMC_ALT:
+	if (BOOT_FROM_MMC(boot_device))
 		return BOOT_DEVICE_MMC1;
 #endif
-	case BOOT_FROM_UART:
-#ifdef BOOT_FROM_UART_ALT
-	case BOOT_FROM_UART_ALT:
-#endif
+#ifdef BOOT_FROM_UART
+	if (BOOT_FROM_UART(boot_device))
 		return BOOT_DEVICE_UART;
+#endif
 #ifdef BOOT_FROM_SATA
-	case BOOT_FROM_SATA:
-	case BOOT_FROM_SATA_ALT:
+	if (BOOT_FROM_SATA(boot_device))
 		return BOOT_DEVICE_SATA;
 #endif
-	case BOOT_FROM_SPI:
+#ifdef BOOT_FROM_SPI
+	if (BOOT_FROM_SPI(boot_device))
 		return BOOT_DEVICE_SPI;
-	default:
-		return BOOT_DEVICE_BOOTROM;
-	};
+#endif
+	return BOOT_DEVICE_BOOTROM;
 }
 
 #if defined(CONFIG_DISPLAY_CPUINFO)
diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h
index 6edd2e2..dc68d40 100644
--- a/arch/arm/mach-mvebu/include/mach/soc.h
+++ b/arch/arm/mach-mvebu/include/mach/soc.h
@@ -128,7 +128,14 @@
 #define BOOTROM_ERR_REG		(MVEBU_REGISTER(0x182d0))
 #define BOOTROM_ERR_MODE_OFFS	28
 #define BOOTROM_ERR_MODE_MASK	(0xf << BOOTROM_ERR_MODE_OFFS)
+#define BOOTROM_ERR_MODE_MAIN	0x2
+#define BOOTROM_ERR_MODE_EXEC	0x3
 #define BOOTROM_ERR_MODE_UART	0x6
+#define BOOTROM_ERR_MODE_PEX	0x8
+#define BOOTROM_ERR_MODE_NOR	0x9
+#define BOOTROM_ERR_MODE_NAND	0xA
+#define BOOTROM_ERR_MODE_SATA	0xB
+#define BOOTROM_ERR_MODE_MMC	0xE
 #define BOOTROM_ERR_CODE_OFFS	0
 #define BOOTROM_ERR_CODE_MASK	(0xf << BOOTROM_ERR_CODE_OFFS)
 
@@ -143,8 +150,8 @@
 #define BOOT_DEV_SEL_OFFS	3
 #define BOOT_DEV_SEL_MASK	(0x3f << BOOT_DEV_SEL_OFFS)
 
-#define BOOT_FROM_UART		0x30
-#define BOOT_FROM_SPI		0x38
+#define BOOT_FROM_UART(x)	(x == 0x30)
+#define BOOT_FROM_SPI(x)	(x == 0x38)
 
 #define CFG_SYS_TCLK		((readl(CFG_SAR_REG) & BIT(20)) ? \
 				 200000000 : 166000000)
@@ -160,14 +167,14 @@
 #define BOOT_DEV_SEL_OFFS	4
 #define BOOT_DEV_SEL_MASK	(0x3f << BOOT_DEV_SEL_OFFS)
 
-#define BOOT_FROM_NAND		0x0A
-#define BOOT_FROM_SATA		0x22
-#define BOOT_FROM_UART		0x28
-#define BOOT_FROM_SATA_ALT	0x2A
-#define BOOT_FROM_UART_ALT	0x3f
-#define BOOT_FROM_SPI		0x32
-#define BOOT_FROM_MMC		0x30
-#define BOOT_FROM_MMC_ALT	0x31
+#define BOOT_FROM_NOR(x)	((x >= 0x00 && x <= 0x07) || x == 0x16 || x == 0x17 || x == 0x2E || x == 0x2F || (x >= 0x3A && x <= 0x3C))
+#define BOOT_FROM_NAND(x)	((x >= 0x08 && x <= 0x15) || (x >= 0x18 && x <= 0x25))
+#define BOOT_FROM_SPINAND(x)	(x == 0x26 || x == 0x27)
+#define BOOT_FROM_UART(x)	(x == 0x28 || x == 0x29)
+#define BOOT_FROM_SATA(x)	(x == 0x2A || x == 0x2B)
+#define BOOT_FROM_PEX(x)	(x == 0x2C || x == 0x2D)
+#define BOOT_FROM_MMC(x)	(x == 0x30 || x == 0x31)
+#define BOOT_FROM_SPI(x)	(x >= 0x32 && x <= 0x39)
 
 #define CFG_SYS_TCLK		((readl(CFG_SAR_REG) & BIT(15)) ? \
 				 200000000 : 250000000)
@@ -184,9 +191,9 @@
 #define BOOT_DEV_SEL_OFFS	11
 #define BOOT_DEV_SEL_MASK	(0x7 << BOOT_DEV_SEL_OFFS)
 
-#define BOOT_FROM_NAND		0x1
-#define BOOT_FROM_UART		0x2
-#define BOOT_FROM_SPI		0x3
+#define BOOT_FROM_NAND(x)	(x == 0x1)
+#define BOOT_FROM_UART(x)	(x == 0x2)
+#define BOOT_FROM_SPI(x)	(x == 0x3)
 
 #define CFG_SYS_TCLK		200000000	/* 200MHz */
 #elif defined(CONFIG_ARMADA_XP)
@@ -206,8 +213,12 @@
 #define BOOT_DEV_SEL_OFFS	5
 #define BOOT_DEV_SEL_MASK	(0xf << BOOT_DEV_SEL_OFFS)
 
-#define BOOT_FROM_UART		0x2
-#define BOOT_FROM_SPI		0x3
+#define BOOT_FROM_NOR(x)	(x == 0x0)
+#define BOOT_FROM_NAND(x)	(x == 0x1)
+#define BOOT_FROM_UART(x)	(x == 0x2)
+#define BOOT_FROM_SPI(x)	(x == 0x3)
+#define BOOT_FROM_PEX(x)	(x == 0x4)
+#define BOOT_FROM_SATA(x)	(x == 0x5)
 
 #define CFG_SYS_TCLK		250000000	/* 250MHz */
 #endif
diff --git a/arch/powerpc/cpu/mpc83xx/cpu_init.c b/arch/powerpc/cpu/mpc83xx/cpu_init.c
index 2af5c89..f5cb000 100644
--- a/arch/powerpc/cpu/mpc83xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc83xx/cpu_init.c
@@ -227,30 +227,6 @@
 	im->sysconf.lblaw[3].bar = CFG_SYS_LBLAWBAR3_PRELIM;
 	im->sysconf.lblaw[3].ar = CFG_SYS_LBLAWAR3_PRELIM;
 #endif
-#if defined(CONFIG_SYS_LBLAWBAR4_PRELIM) && defined(CONFIG_SYS_LBLAWAR4_PRELIM)
-	im->sysconf.lblaw[4].bar = CONFIG_SYS_LBLAWBAR4_PRELIM;
-	im->sysconf.lblaw[4].ar = CONFIG_SYS_LBLAWAR4_PRELIM;
-#endif
-#if defined(CONFIG_SYS_LBLAWBAR5_PRELIM) && defined(CONFIG_SYS_LBLAWAR5_PRELIM)
-	im->sysconf.lblaw[5].bar = CONFIG_SYS_LBLAWBAR5_PRELIM;
-	im->sysconf.lblaw[5].ar = CONFIG_SYS_LBLAWAR5_PRELIM;
-#endif
-#if defined(CONFIG_SYS_LBLAWBAR6_PRELIM) && defined(CONFIG_SYS_LBLAWAR6_PRELIM)
-	im->sysconf.lblaw[6].bar = CONFIG_SYS_LBLAWBAR6_PRELIM;
-	im->sysconf.lblaw[6].ar = CONFIG_SYS_LBLAWAR6_PRELIM;
-#endif
-#if defined(CONFIG_SYS_LBLAWBAR7_PRELIM) && defined(CONFIG_SYS_LBLAWAR7_PRELIM)
-	im->sysconf.lblaw[7].bar = CONFIG_SYS_LBLAWBAR7_PRELIM;
-	im->sysconf.lblaw[7].ar = CONFIG_SYS_LBLAWAR7_PRELIM;
-#endif
-#ifdef CONFIG_SYS_GPIO1_PRELIM
-	im->gpio[0].dat = CONFIG_SYS_GPIO1_DAT;
-	im->gpio[0].dir = CONFIG_SYS_GPIO1_DIR;
-#endif
-#ifdef CONFIG_SYS_GPIO2_PRELIM
-	im->gpio[1].dat = CONFIG_SYS_GPIO2_DAT;
-	im->gpio[1].dir = CONFIG_SYS_GPIO2_DIR;
-#endif
 }
 
 int cpu_init_r (void)
diff --git a/board/siemens/iot2050/Kconfig b/board/siemens/iot2050/Kconfig
index 063142a..e66b242 100644
--- a/board/siemens/iot2050/Kconfig
+++ b/board/siemens/iot2050/Kconfig
@@ -1,20 +1,40 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
-# Copyright (c) Siemens AG, 2018-2021
+# Copyright (c) Siemens AG, 2018-2022
 #
 # Authors:
 #   Le Jin <le.jin@siemens.com>
 #   Jan Kiszka <jan.kiszka@siemens.com>
 
-config TARGET_IOT2050_A53
-	bool "IOT2050 running on A53"
+choice
+        prompt "Siemens SIMATIC IOT2050 boards"
+        optional
+
+config TARGET_IOT2050_A53_PG1
+	bool "IOT2050 PG1 running on A53"
+	select IOT2050_A53_COMMON
+	help
+	  This builds U-Boot for the Product Generation 1 (PG1) of the IOT2050
+	  devices.
+
+config TARGET_IOT2050_A53_PG2
+	bool "IOT2050 PG2 running on A53"
+	select IOT2050_A53_COMMON
+	help
+	  This builds U-Boot for the Product Generation 2 (PG2) of the IOT2050
+	  devices.
+
+endchoice
+
+config IOT2050_A53_COMMON
+	bool
 	select ARM64
 	select SOC_K3_AM654
 	select BOARD_LATE_INIT
 	select SYS_DISABLE_DCACHE_OPS
 	select BINMAN
 
-if TARGET_IOT2050_A53
+if IOT2050_A53_COMMON
 
 config SYS_BOARD
 	default "iot2050"
@@ -29,4 +49,11 @@
 	bool "Disable eMMC boot via USER button (Advanced version only)"
 	default y
 
+config IOT2050_EMBED_OTPCMD
+	bool "Embed OTP programming data"
+	help
+	  Embed signed OTP programming data 'otpcmd.bin' into the firmware
+	  image. This data will be evaluated and executed on first boot of the
+	  device.
+
 endif
diff --git a/board/siemens/iot2050/board.c b/board/siemens/iot2050/board.c
index 8f4b0ea..df705b7 100644
--- a/board/siemens/iot2050/board.c
+++ b/board/siemens/iot2050/board.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Board specific initialization for IOT2050
- * Copyright (c) Siemens AG, 2018-2021
+ * Copyright (c) Siemens AG, 2018-2022
  *
  * Authors:
  *   Le Jin <le.jin@siemens.com>
@@ -11,9 +11,11 @@
 #include <common.h>
 #include <bootstage.h>
 #include <dm.h>
+#include <fdt_support.h>
 #include <i2c.h>
 #include <led.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <net.h>
 #include <phy.h>
 #include <spl.h>
@@ -47,20 +49,120 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static bool board_is_advanced(void)
+struct gpio_config {
+	const char *gpio_name;
+	const char *label;
+};
+
+enum m2_connector_mode {
+	BKEY_PCIEX2 = 0,
+	BKEY_PCIE_EKEY_PCIE,
+	BKEY_USB30_EKEY_PCIE,
+	CONNECTOR_MODE_INVALID
+};
+
+struct m2_config_pins {
+	int config[4];
+};
+
+struct serdes_mux_control {
+	int ctrl_usb30_pcie0_lane0;
+	int ctrl_pcie1_pcie0;
+	int ctrl_usb30_pcie0_lane1;
+};
+
+struct m2_config_table {
+	struct m2_config_pins config_pins;
+	enum m2_connector_mode mode;
+};
+
+static const struct gpio_config serdes_mux_ctl_pin_info[] = {
+	{"gpio@600000_88", "CTRL_USB30_PCIE0_LANE0"},
+	{"gpio@600000_82", "CTRL_PCIE1_PCIE0"},
+	{"gpio@600000_89", "CTRL_USB30_PCIE0_LANE1"},
+};
+
+static const struct gpio_config m2_bkey_cfg_pin_info[] = {
+	{"gpio@601000_18", "KEY_CONFIG_0"},
+	{"gpio@601000_19", "KEY_CONFIG_1"},
+	{"gpio@601000_88", "KEY_CONFIG_2"},
+	{"gpio@601000_89", "KEY_CONFIG_3"},
+};
+
+static const struct m2_config_table m2_config_table[] = {
+	{{{0, 1, 0, 0}}, BKEY_PCIEX2},
+	{{{0, 0, 1, 0}}, BKEY_PCIE_EKEY_PCIE},
+	{{{0, 1, 1, 0}}, BKEY_PCIE_EKEY_PCIE},
+	{{{1, 0, 0, 1}}, BKEY_PCIE_EKEY_PCIE},
+	{{{1, 1, 0, 1}}, BKEY_PCIE_EKEY_PCIE},
+	{{{0, 0, 0, 1}}, BKEY_USB30_EKEY_PCIE},
+	{{{0, 1, 0, 1}}, BKEY_USB30_EKEY_PCIE},
+	{{{0, 0, 1, 1}}, BKEY_USB30_EKEY_PCIE},
+	{{{0, 1, 1, 1}}, BKEY_USB30_EKEY_PCIE},
+	{{{1, 0, 1, 1}}, BKEY_USB30_EKEY_PCIE},
+};
+
+static const struct serdes_mux_control serdes_mux_ctrl[] = {
+	[BKEY_PCIEX2]          = {0, 0, 1},
+	[BKEY_PCIE_EKEY_PCIE]  = {0, 1, 0},
+	[BKEY_USB30_EKEY_PCIE] = {1, 1, 0},
+};
+
+static const char *m2_connector_mode_name[] = {
+	[BKEY_PCIEX2]          = "PCIe x2 (key B)",
+	[BKEY_PCIE_EKEY_PCIE]  = "PCIe (key B) / PCIe (key E)",
+	[BKEY_USB30_EKEY_PCIE] = "USB 3.0 (key B) / PCIe (key E)",
+};
+
+static enum m2_connector_mode connector_mode;
+
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
+static void *connector_overlay;
+static u32 connector_overlay_size;
+#endif
+
+static int get_pinvalue(const char *gpio_name, const char *label)
+{
+	struct gpio_desc gpio;
+
+	if (dm_gpio_lookup_name(gpio_name, &gpio) < 0 ||
+	    dm_gpio_request(&gpio, label) < 0 ||
+	    dm_gpio_set_dir_flags(&gpio, GPIOD_IS_IN) < 0) {
+		pr_err("Cannot get pin %s for M.2 configuration\n", gpio_name);
+		return 0;
+	}
+
+	return dm_gpio_get_value(&gpio);
+}
+
+static void set_pinvalue(const char *gpio_name, const char *label, int value)
+{
+	struct gpio_desc gpio;
+
+	if (dm_gpio_lookup_name(gpio_name, &gpio) < 0 ||
+	    dm_gpio_request(&gpio, label) < 0 ||
+	    dm_gpio_set_dir_flags(&gpio, GPIOD_IS_OUT) < 0) {
+		pr_err("Cannot set pin %s for M.2 configuration\n", gpio_name);
+		return;
+	}
+	dm_gpio_set_value(&gpio, value);
+}
+
+static bool board_is_m2(void)
 {
 	struct iot2050_info *info = IOT2050_INFO_DATA;
 
-	return info->magic == IOT2050_INFO_MAGIC &&
-		strstr((char *)info->name, "IOT2050-ADVANCED") != NULL;
+	return IS_ENABLED(CONFIG_TARGET_IOT2050_A53_PG2) &&
+		info->magic == IOT2050_INFO_MAGIC &&
+		strcmp((char *)info->name, "IOT2050-ADVANCED-M2") == 0;
 }
 
-static bool board_is_sr1(void)
+static bool board_is_advanced(void)
 {
 	struct iot2050_info *info = IOT2050_INFO_DATA;
 
 	return info->magic == IOT2050_INFO_MAGIC &&
-		!strstr((char *)info->name, "-PG2");
+		strstr((char *)info->name, "IOT2050-ADVANCED") != NULL;
 }
 
 static void remove_mmc1_target(void)
@@ -109,12 +211,14 @@
 	}
 
 	if (board_is_advanced()) {
-		if (board_is_sr1())
+		if (IS_ENABLED(CONFIG_TARGET_IOT2050_A53_PG1))
 			fdtfile = "ti/k3-am6548-iot2050-advanced.dtb";
+		else if(board_is_m2())
+			fdtfile = "ti/k3-am6548-iot2050-advanced-m2.dtb";
 		else
 			fdtfile = "ti/k3-am6548-iot2050-advanced-pg2.dtb";
 	} else {
-		if (board_is_sr1())
+		if (IS_ENABLED(CONFIG_TARGET_IOT2050_A53_PG1))
 			fdtfile = "ti/k3-am6528-iot2050-basic.dtb";
 		else
 			fdtfile = "ti/k3-am6528-iot2050-basic-pg2.dtb";
@@ -126,6 +230,101 @@
 	env_save();
 }
 
+static void m2_overlay_prepare(void)
+{
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
+	const char *overlay_path;
+	void *overlay;
+	u64 loadaddr;
+	ofnode node;
+	int ret;
+
+	if (connector_mode == BKEY_PCIEX2)
+		return;
+
+	if (connector_mode == BKEY_PCIE_EKEY_PCIE)
+		overlay_path = "/fit-images/bkey-ekey-pcie-overlay";
+	else
+		overlay_path = "/fit-images/bkey-usb3-overlay";
+
+	node = ofnode_path(overlay_path);
+	if (!ofnode_valid(node))
+		goto fit_error;
+
+	ret = ofnode_read_u64(node, "load", &loadaddr);
+	if (ret)
+		goto fit_error;
+
+	ret = ofnode_read_u32(node, "size", &connector_overlay_size);
+	if (ret)
+		goto fit_error;
+
+	overlay = map_sysmem(loadaddr, connector_overlay_size);
+
+	connector_overlay = malloc(connector_overlay_size);
+	if (!connector_overlay)
+		goto fit_error;
+
+	memcpy(connector_overlay, overlay, connector_overlay_size);
+	return;
+
+fit_error:
+	pr_err("M.2 device tree overlay %s not available,\n", overlay_path);
+#endif
+}
+
+static void m2_connector_setup(void)
+{
+	ulong m2_manual_config = env_get_ulong("m2_manual_config", 10,
+					       CONNECTOR_MODE_INVALID);
+	const char *mode_info = "";
+	struct m2_config_pins config_pins;
+	unsigned int n;
+
+	/* enable M.2 connector power */
+	set_pinvalue("gpio@601000_17", "P3V3_M2_EN", 1);
+	udelay(4 * 100);
+
+	if (m2_manual_config < CONNECTOR_MODE_INVALID) {
+		mode_info = " [manual mode]";
+		connector_mode = m2_manual_config;
+	} else { /* auto detection */
+		for (n = 0; n < ARRAY_SIZE(config_pins.config); n++)
+			config_pins.config[n] =
+				get_pinvalue(m2_bkey_cfg_pin_info[n].gpio_name,
+					     m2_bkey_cfg_pin_info[n].label);
+		connector_mode = CONNECTOR_MODE_INVALID;
+		for (n = 0; n < ARRAY_SIZE(m2_config_table); n++) {
+			if (!memcmp(config_pins.config,
+				    m2_config_table[n].config_pins.config,
+				    sizeof(config_pins.config))) {
+				connector_mode = m2_config_table[n].mode;
+				break;
+			}
+		}
+		if (connector_mode == CONNECTOR_MODE_INVALID) {
+			mode_info = " [fallback, card unknown/unsupported]";
+			connector_mode = BKEY_USB30_EKEY_PCIE;
+		}
+	}
+
+	printf("M.2:   %s%s\n", m2_connector_mode_name[connector_mode],
+	       mode_info);
+
+	/* configure serdes mux */
+	set_pinvalue(serdes_mux_ctl_pin_info[0].gpio_name,
+		     serdes_mux_ctl_pin_info[0].label,
+		     serdes_mux_ctrl[connector_mode].ctrl_usb30_pcie0_lane0);
+	set_pinvalue(serdes_mux_ctl_pin_info[1].gpio_name,
+		     serdes_mux_ctl_pin_info[1].label,
+		     serdes_mux_ctrl[connector_mode].ctrl_pcie1_pcie0);
+	set_pinvalue(serdes_mux_ctl_pin_info[2].gpio_name,
+		     serdes_mux_ctl_pin_info[2].label,
+		     serdes_mux_ctrl[connector_mode].ctrl_usb30_pcie0_lane1);
+
+	m2_overlay_prepare();
+}
+
 int board_init(void)
 {
 	return 0;
@@ -162,6 +361,9 @@
 	struct iot2050_info *info = IOT2050_INFO_DATA;
 	char upper_name[32];
 
+	/* skip the prefix "k3-am65x8-" */
+	name += 10;
+
 	if (info->magic != IOT2050_INFO_MAGIC ||
 	    strlen(name) >= sizeof(upper_name))
 		return -1;
@@ -188,7 +390,7 @@
 
 	memset(&gpio, 0, sizeof(gpio));
 
-	if (dm_gpio_lookup_name("25", &gpio) < 0 ||
+	if (dm_gpio_lookup_name("gpio@42110000_25", &gpio) < 0 ||
 	    dm_gpio_request(&gpio, "USER button") < 0 ||
 	    dm_gpio_set_dir_flags(&gpio, GPIOD_IS_IN) < 0)
 		return false;
@@ -220,6 +422,9 @@
 	/* change CTRL_MMR register to let serdes0 not output USB3.0 signals. */
 	writel(0x3, SERDES0_LANE_SELECT);
 
+	if (board_is_m2())
+		m2_connector_setup();
+
 	set_board_info_env();
 
 	/* remove the eMMC if requested via button */
@@ -231,6 +436,50 @@
 }
 
 #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
+static void m2_fdt_fixup(void *blob)
+{
+	void *overlay_copy = NULL;
+	void *fdt_copy = NULL;
+	u32 fdt_size;
+	int err;
+
+	if (!connector_overlay)
+		return;
+
+	/*
+	 * We need to work with temporary copies here because fdt_overlay_apply
+	 * is destructive to the overlay and also to the target blob, even if
+	 * application fails.
+	 */
+	fdt_size = fdt_totalsize(blob);
+	fdt_copy = malloc(fdt_size);
+	if (!fdt_copy)
+		goto fixup_error;
+
+	memcpy(fdt_copy, blob, fdt_size);
+
+	overlay_copy = malloc(connector_overlay_size);
+	if (!overlay_copy)
+		goto fixup_error;
+
+	memcpy(overlay_copy, connector_overlay, connector_overlay_size);
+
+	err = fdt_overlay_apply_verbose(fdt_copy, overlay_copy);
+	if (err)
+		goto fixup_error;
+
+	memcpy(blob, fdt_copy, fdt_size);
+
+cleanup:
+	free(fdt_copy);
+	free(overlay_copy);
+	return;
+
+fixup_error:
+	pr_err("Could not apply M.2 device tree overlay\n");
+	goto cleanup;
+}
+
 int ft_board_setup(void *blob, struct bd_info *bd)
 {
 	int ret;
@@ -242,6 +491,9 @@
 	if (ret)
 		pr_err("%s: fixing up msmc ram failed %d\n", __func__, ret);
 
+	if (board_is_m2())
+		m2_fdt_fixup(blob);
+
 	return ret;
 }
 #endif
diff --git a/board/siemens/iot2050/iot2050.env b/board/siemens/iot2050/iot2050.env
new file mode 100644
index 0000000..0295879
--- /dev/null
+++ b/board/siemens/iot2050/iot2050.env
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) Siemens AG, 2023
+ *
+ * Authors:
+ *   Jan Kiszka <jan.kiszka@siemens.com>
+ */
+
+usb_pgood_delay=900
+
+watchdog_timeout_ms=CONFIG_WATCHDOG_TIMEOUT_MSECS
+start_watchdog=
+	if test ${watchdog_timeout_ms} -gt 0; then
+		wdt dev watchdog@40610000;
+		wdt start ${watchdog_timeout_ms};
+		echo Watchdog started, timeout ${watchdog_timeout_ms} ms;
+	fi
diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c
index 03adb59..6edb422 100644
--- a/board/solidrun/clearfog/clearfog.c
+++ b/board/solidrun/clearfog/clearfog.c
@@ -10,6 +10,7 @@
 #include <miiphy.h>
 #include <net.h>
 #include <netdev.h>
+#include <mmc.h>
 #include <asm/global_data.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
@@ -261,3 +262,35 @@
 
 	return 0;
 }
+
+static bool has_emmc(void)
+{
+	struct mmc *mmc;
+
+	mmc = find_mmc_device(0);
+	if (!mmc)
+		return 0;
+	return (!mmc_init(mmc) && IS_MMC(mmc)) ? true : false;
+}
+
+/*
+ * The Clearfog devices have only one SDHC device. This is either eMMC
+ * if it is populated on the SOM or SDHC if not. The Linux device tree
+ * assumes the SDHC case. Detect if the device is an eMMC and fixup the
+ * device-tree, so that it will be detected by Linux.
+ */
+int ft_board_setup(void *blob, struct bd_info *bd)
+{
+	int node;
+
+	if (has_emmc()) {
+		node = fdt_node_offset_by_compatible(blob, -1, "marvell,armada-380-sdhci");
+		if (node < 0)
+			return 0; /* Unexpected eMMC device; patching not supported */
+
+		puts("Patching FDT so that eMMC is detected by OS\n");
+		return fdt_setprop_empty(blob, node, "non-removable");
+	}
+
+	return 0;
+}
diff --git a/board/ti/am62ax/Kconfig b/board/ti/am62ax/Kconfig
index 2c18cd4..9b868e4 100644
--- a/board/ti/am62ax/Kconfig
+++ b/board/ti/am62ax/Kconfig
@@ -10,7 +10,6 @@
 config TARGET_AM62A7_A53_EVM
 	bool "TI K3 based AM62A7 EVM running on A53"
 	select ARM64
-	select SOC_K3_AM62A7
 	imply BOARD
 	imply SPL_BOARD
 	imply TI_I2C_BOARD_DETECT
@@ -20,7 +19,6 @@
 	select CPU_V7R
 	select SYS_THUMB_BUILD
 	select K3_LOAD_SYSFW
-	select SOC_K3_AM62A7
 	select RAM
 	select SPL_RAM
 	select K3_DDRSS
diff --git a/board/ti/am62ax/am62ax.env b/board/ti/am62ax/am62ax.env
new file mode 100644
index 0000000..8c1c26e
--- /dev/null
+++ b/board/ti/am62ax/am62ax.env
@@ -0,0 +1,33 @@
+#include <environment/ti/ti_armv7_common.env>
+#include <environment/ti/mmc.env>
+
+default_device_tree=k3-am62a7-sk.dtb
+findfdt=
+	setenv name_fdt ${default_device_tree};
+	setenv fdtfile ${name_fdt}
+name_kern=Image
+console=ttyS2,115200n8
+args_all=setenv optargs ${optargs} earlycon=ns16550a,mmio32,0x02800000
+	${mtdparts}
+run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr}
+
+boot=mmc
+mmcdev=1
+bootpart=1:2
+bootdir=/boot
+rd_spec=-
+init_mmc=run args_all args_mmc
+get_fdt_mmc=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${name_fdt}
+get_overlay_mmc=
+	fdt address ${fdtaddr};
+	fdt resize 0x100000;
+	for overlay in $name_overlays;
+	do;
+	load mmc ${bootpart} ${dtboaddr} ${bootdir}/${overlay} &&
+	fdt apply ${dtboaddr};
+	done;
+get_kern_mmc=load mmc ${bootpart} ${loadaddr}
+	${bootdir}/${name_kern}
+get_fit_mmc=load mmc ${bootpart} ${addr_fit}
+	${bootdir}/${name_fit}
+partitions=name=rootfs,start=0,size=-,uuid=${uuid_gpt_rootfs}
diff --git a/board/ti/am62x/Kconfig b/board/ti/am62x/Kconfig
index 87fed44..5e8dfa3 100644
--- a/board/ti/am62x/Kconfig
+++ b/board/ti/am62x/Kconfig
@@ -10,14 +10,12 @@
 config TARGET_AM625_A53_EVM
 	bool "TI K3 based AM625 EVM running on A53"
 	select ARM64
-	select SOC_K3_AM625
 
 config TARGET_AM625_R5_EVM
 	bool "TI K3 based AM625 EVM running on R5"
 	select CPU_V7R
 	select SYS_THUMB_BUILD
 	select K3_LOAD_SYSFW
-	select SOC_K3_AM625
 	select RAM
 	select SPL_RAM
 	select K3_DDRSS
diff --git a/board/ti/am62x/am62x.env b/board/ti/am62x/am62x.env
index c9a3b3d..e4e64fa 100644
--- a/board/ti/am62x/am62x.env
+++ b/board/ti/am62x/am62x.env
@@ -1,75 +1,5 @@
-loadaddr=0x82000000
-kernel_addr_r=0x82000000
-fdtaddr=0x88000000
-dtboaddr=0x89000000
-fdt_addr_r=0x88000000
-fdtoverlay_addr_r=0x89000000
-rdaddr=0x88080000
-ramdisk_addr_r=0x88080000
-scriptaddr=0x80000000
-pxefile_addr_r=0x80100000
-bootm_size=0x10000000
-boot_fdt=try
-
-mmcrootfstype=ext4 rootwait
-finduuid=part uuid ${boot} ${bootpart} uuid
-args_mmc=run finduuid;setenv bootargs console=${console}
-	${optargs}
-	root=PARTUUID=${uuid} rw
-	rootfstype=${mmcrootfstype}
-loadbootscript=load mmc ${mmcdev} ${loadaddr} boot.scr
-bootscript=echo Running bootscript from mmc${mmcdev} ...;
-	source ${loadaddr}
-bootenvfile=uEnv.txt
-importbootenv=echo Importing environment from mmc${mmcdev} ...;
-	env import -t ${loadaddr} ${filesize}
-loadbootenv=fatload mmc ${mmcdev} ${loadaddr} ${bootenvfile}
-loadimage=load ${devtype} ${bootpart} ${loadaddr} ${bootdir}/${bootfile}
-loadfdt=load ${devtype} ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}
-envboot=mmc dev ${mmcdev};
-	if mmc rescan; then
-		echo SD/MMC found on device ${mmcdev};
-		if run loadbootscript; then
-			run bootscript;
-		else
-			if run loadbootenv; then
-				echo Loaded env from ${bootenvfile};
-				run importbootenv;
-			fi;
-			if test -n $uenvcmd; then
-				echo Running uenvcmd ...;
-				run uenvcmd;
-			fi;
-		fi;
-	fi;
-mmcloados=
-	if test ${boot_fdt} = yes || test ${boot_fdt} = try; then
-		if run loadfdt; then
-			bootz ${loadaddr} - ${fdtaddr};
-		else
-			if test ${boot_fdt} = try; then
-				bootz;
-			else
-				echo WARN: Cannot load the DT;
-			fi;
-		fi;
-	else
-		bootz;
-	fi;
-mmcboot=mmc dev ${mmcdev};
-	devnum=${mmcdev};
-	devtype=mmc;
-	if mmc rescan; then
-		echo SD/MMC found on device ${mmcdev};
-		if run loadimage; then
-			run args_mmc;
-			if test ${boot_fit} -eq 1; then
-				run run_fit;
-			else
-				run mmcloados;
-			fi;
-		fi;
-	fi;
+#include <environment/ti/ti_armv7_common.env>
+#include <environment/ti/mmc.env>
 
 default_device_tree=k3-am625-sk.dtb
 findfdt=
diff --git a/board/ti/am64x/Kconfig b/board/ti/am64x/Kconfig
index 8036947..afb54f8 100644
--- a/board/ti/am64x/Kconfig
+++ b/board/ti/am64x/Kconfig
@@ -9,7 +9,6 @@
 config TARGET_AM642_A53_EVM
 	bool "TI K3 based AM642 EVM running on A53"
 	select ARM64
-	select SOC_K3_AM642
 	imply BOARD
 	imply SPL_BOARD
 	imply TI_I2C_BOARD_DETECT
@@ -19,7 +18,6 @@
 	select CPU_V7R
 	select SYS_THUMB_BUILD
 	select K3_LOAD_SYSFW
-	select SOC_K3_AM642
 	select RAM
 	select SPL_RAM
 	select K3_DDRSS
diff --git a/board/ti/am65x/Kconfig b/board/ti/am65x/Kconfig
index 4765b13..220dd02 100644
--- a/board/ti/am65x/Kconfig
+++ b/board/ti/am65x/Kconfig
@@ -10,7 +10,6 @@
 config TARGET_AM654_A53_EVM
 	bool "TI K3 based AM654 EVM running on A53"
 	select ARM64
-	select SOC_K3_AM654
 	select SYS_DISABLE_DCACHE_OPS
 	select BOARD_LATE_INIT
 	imply TI_I2C_BOARD_DETECT
@@ -19,7 +18,6 @@
 	bool "TI K3 based AM654 EVM running on R5"
 	select CPU_V7R
 	select SYS_THUMB_BUILD
-	select SOC_K3_AM654
 	select K3_LOAD_SYSFW
 	select K3_AM654_DDRSS
 	imply SYS_K3_SPL_ATF
diff --git a/board/ti/am65x/am65x.env b/board/ti/am65x/am65x.env
new file mode 100644
index 0000000..a048b47
--- /dev/null
+++ b/board/ti/am65x/am65x.env
@@ -0,0 +1,47 @@
+#include <environment/ti/ti_armv7_common.env>
+#include <environment/ti/mmc.env>
+#include <environment/ti/k3_dfu.env>
+#if CONFIG_CMD_REMOTEPROC
+#include <environment/ti/k3_rproc.env>
+#endif
+
+findfdt=
+	setenv name_fdt k3-am654-base-board.dtb;
+	setenv fdtfile ${name_fdt}
+name_kern=Image
+console=ttyS2,115200n8
+args_all=setenv optargs ${optargs} earlycon=ns16550a,mmio32,0x02800000
+	${mtdparts}
+run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr}
+
+boot=mmc
+mmcdev=1
+bootpart=1:2
+bootdir=/boot
+rd_spec=-
+init_mmc=run args_all args_mmc
+get_fdt_mmc=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${name_fdt}
+get_overlay_mmc=
+	fdt address ${fdtaddr};
+	fdt resize 0x100000;
+	for overlay in $name_overlays;
+	do;
+	load mmc ${bootpart} ${dtboaddr} ${bootdir}/${overlay} &&
+	fdt apply ${dtboaddr};
+	done;
+get_kern_mmc=load mmc ${bootpart} ${loadaddr}
+	${bootdir}/${name_kern}
+get_fit_mmc=load mmc ${bootpart} ${addr_fit}
+	${bootdir}/${name_fit}
+partitions=name=root,start=0,size=-,uuid=${uuid_gpt_rootfs}
+
+init_ubi=
+    run args_all args_ubi;
+    sf probe;
+    ubi part ospi.rootfs;
+    ubifsmount ubi:rootfs;
+get_kern_ubi=ubifsload ${loadaddr} ${bootdir}/${name_kern}
+get_fdt_ubi=ubifsload ${fdtaddr} ${bootdir}/${name_fdt}
+args_ubi=setenv bootargs console=${console} ${optargs}
+rootfstype=ubifs root=ubi0:rootfs rw ubi.mtd=ospi.rootfs
+
diff --git a/board/ti/common/Kconfig b/board/ti/common/Kconfig
index 49edd98..f03357c 100644
--- a/board/ti/common/Kconfig
+++ b/board/ti/common/Kconfig
@@ -1,5 +1,6 @@
 config TI_I2C_BOARD_DETECT
 	bool "Support for Board detection for TI platforms"
+	select K3_BOARD_DETECT if ARCH_K3
 	help
 	   Support for detection board information on Texas Instrument's
 	   Evaluation Boards which have I2C based EEPROM detection
diff --git a/board/ti/j721e/Kconfig b/board/ti/j721e/Kconfig
index d19d30d..84bca32 100644
--- a/board/ti/j721e/Kconfig
+++ b/board/ti/j721e/Kconfig
@@ -10,7 +10,6 @@
 config TARGET_J721E_A72_EVM
 	bool "TI K3 based J721E EVM running on A72"
 	select ARM64
-	select SOC_K3_J721E
 	select BOARD_LATE_INIT
 	imply TI_I2C_BOARD_DETECT
 	select SYS_DISABLE_DCACHE_OPS
@@ -19,7 +18,6 @@
 	bool "TI K3 based J721E EVM running on R5"
 	select CPU_V7R
 	select SYS_THUMB_BUILD
-	select SOC_K3_J721E
 	select K3_LOAD_SYSFW
 	select RAM
 	select SPL_RAM
@@ -30,7 +28,6 @@
 config TARGET_J7200_A72_EVM
 	bool "TI K3 based J7200 EVM running on A72"
 	select ARM64
-	select SOC_K3_J721E
 	select BOARD_LATE_INIT
 	imply TI_I2C_BOARD_DETECT
 	select SYS_DISABLE_DCACHE_OPS
@@ -39,7 +36,6 @@
 	bool "TI K3 based J7200 EVM running on R5"
 	select CPU_V7R
 	select SYS_THUMB_BUILD
-	select SOC_K3_J721E
 	select K3_LOAD_SYSFW
 	select RAM
 	select SPL_RAM
@@ -60,6 +56,9 @@
 config SYS_CONFIG_NAME
        default "j721e_evm"
 
+config ENV_SOURCE_FILE
+       default "j721e"
+
 source "board/ti/common/Kconfig"
 
 endif
@@ -75,6 +74,9 @@
 config SYS_CONFIG_NAME
        default "j721e_evm"
 
+config ENV_SOURCE_FILE
+       default "j721e"
+
 source "board/ti/common/Kconfig"
 
 endif
@@ -90,6 +92,9 @@
 config SYS_CONFIG_NAME
        default "j721e_evm"
 
+config ENV_SOURCE_FILE
+       default "j721e"
+
 source "board/ti/common/Kconfig"
 
 endif
@@ -105,6 +110,9 @@
 config SYS_CONFIG_NAME
        default "j721e_evm"
 
+config ENV_SOURCE_FILE
+       default "j721e"
+
 source "board/ti/common/Kconfig"
 
 endif
diff --git a/board/ti/j721e/j721e.env b/board/ti/j721e/j721e.env
new file mode 100644
index 0000000..446395a
--- /dev/null
+++ b/board/ti/j721e/j721e.env
@@ -0,0 +1,82 @@
+#include <environment/ti/ti_armv7_common.env>
+#include <environment/ti/mmc.env>
+#include <environment/ti/ufs.env>
+#include <environment/ti/k3_dfu.env>
+
+#if CONFIG_CMD_REMOTEPROC
+#include <environment/ti/k3_rproc.env>
+#endif
+
+default_device_tree=k3-j721e-common-proc-board.dtb
+findfdt=
+	setenv name_fdt ${default_device_tree};
+	if test $board_name = j721e; then
+		setenv name_fdt k3-j721e-common-proc-board.dtb; fi;
+	if test $board_name = j721e-eaik || test $board_name = j721e-sk; then
+		setenv name_fdt k3-j721e-sk.dtb; fi;
+	setenv fdtfile ${name_fdt}
+name_kern=Image
+console=ttyS2,115200n8
+args_all=setenv optargs earlycon=ns16550a,mmio32,0x02800000
+	${mtdparts}
+run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr}
+
+#if CONFIG_SYS_K3_SPL_ATF
+#if CONFIG_TARGET_J721E_R5_EVM
+addr_mcur5f0_0load=0x89000000
+name_mcur5f0_0fw=/lib/firmware/j7-mcu-r5f0_0-fw
+#elif CONFIG_TARGET_J7200_R5_EVM
+addr_mcur5f0_0load=0x89000000
+name_mcur5f0_0fw=/lib/firmware/j7200-mcu-r5f0_0-fw
+#endif
+#endif
+
+boot=mmc
+mmcdev=1
+bootpart=1:2
+bootdir=/boot
+rd_spec=-
+init_mmc=run args_all args_mmc
+get_fdt_mmc=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${name_fdt}
+get_overlay_mmc=
+	fdt address ${fdtaddr};
+	fdt resize 0x100000;
+	for overlay in $name_overlays;
+	do;
+	load mmc ${bootpart} ${dtboaddr} ${bootdir}/${overlay} &&
+	fdt apply ${dtboaddr};
+	done;
+partitions=uuid_disk=${uuid_gpt_disk};
+	name=rootfs,start=0,size=-,uuid=${uuid_gpt_rootfs}
+get_kern_mmc=load mmc ${bootpart} ${loadaddr}
+	${bootdir}/${name_kern}
+get_fit_mmc=load mmc ${bootpart} ${addr_fit}
+	${bootdir}/${name_fit}
+
+#if CONFIG_TARGET_J7200_A72_EVM
+do_main_cpsw0_qsgmii_phyinit=1
+init_main_cpsw0_qsgmii_phy=gpio set gpio@22_17;
+	gpio clear gpio@22_16
+main_cpsw0_qsgmii_phyinit=
+	if test ${do_main_cpsw0_qsgmii_phyinit} -eq 1 && test ${dorprocboot} -eq 1 && test ${boot} = mmc; then
+		run init_main_cpsw0_qsgmii_phy;
+	fi;
+#elif CONFIG_TARGET_J721E_A72_EVM
+init_main_cpsw0_qsgmii_phy=gpio set gpio@22_17;
+	gpio clear gpio@22_16
+main_cpsw0_qsgmii_phyinit=
+	if test $board_name = J721EX-PM1-SOM || test $board_name = J721EX-PM2-SOM || test $board_name = j721e; then
+		do_main_cpsw0_qsgmii_phyinit=1; else
+		do_main_cpsw0_qsgmii_phyinit=0; fi;
+	if test ${do_main_cpsw0_qsgmii_phyinit} -eq 1 && test ${dorprocboot} -eq 1 && test ${boot} = mmc; then
+		run init_main_cpsw0_qsgmii_phy;			\
+	fi;
+#endif
+
+#if CONFIG_TARGET_J721E_A72_EVM
+rproc_fw_binaries=2 /lib/firmware/j7-main-r5f0_0-fw 3 /lib/firmware/j7-main-r5f0_1-fw 4 /lib/firmware/j7-main-r5f1_0-fw 5 /lib/firmware/j7-main-r5f1_1-fw 6 /lib/firmware/j7-c66_0-fw 7 /lib/firmware/j7-c66_1-fw 8 /lib/firmware/j7-c71_0-fw
+#endif
+
+#if CONFIG_TARGET_J7200_A72_EVM
+rproc_fw_binaries=2 /lib/firmware/j7200-main-r5f0_0-fw 3 /lib/firmware/j7200-main-r5f0_1-fw
+#endif
diff --git a/board/ti/j721s2/Kconfig b/board/ti/j721s2/Kconfig
index 6141798..a24641f 100644
--- a/board/ti/j721s2/Kconfig
+++ b/board/ti/j721s2/Kconfig
@@ -10,7 +10,6 @@
 config TARGET_J721S2_A72_EVM
 	bool "TI K3 based J721S2 EVM running on A72"
 	select ARM64
-	select SOC_K3_J721S2
 	select BOARD_LATE_INIT
 	imply TI_I2C_BOARD_DETECT
 	select SYS_DISABLE_DCACHE_OPS
@@ -19,7 +18,6 @@
 	bool "TI K3 based J721S2 EVM running on R5"
 	select CPU_V7R
 	select SYS_THUMB_BUILD
-	select SOC_K3_J721S2
 	select K3_LOAD_SYSFW
 	select RAM
 	select SPL_RAM
@@ -40,6 +38,9 @@
 config SYS_CONFIG_NAME
        default "j721s2_evm"
 
+config ENV_SOURCE_FILE
+       default "j721s2"
+
 source "board/ti/common/Kconfig"
 
 endif
@@ -55,6 +56,9 @@
 config SYS_CONFIG_NAME
        default "j721s2_evm"
 
+config ENV_SOURCE_FILE
+       default "j721s2"
+
 source "board/ti/common/Kconfig"
 
 endif
diff --git a/board/ti/j721s2/j721s2.env b/board/ti/j721s2/j721s2.env
new file mode 100644
index 0000000..2152f88
--- /dev/null
+++ b/board/ti/j721s2/j721s2.env
@@ -0,0 +1,56 @@
+#include <environment/ti/ti_armv7_common.env>
+#include <environment/ti/mmc.env>
+#include <environment/ti/ufs.env>
+#include <environment/ti/k3_dfu.env>
+
+#if CONFIG_CMD_REMOTEPROC
+#include <environment/ti/k3_rproc.env>
+#endif
+
+default_device_tree=k3-j721s2-common-proc-board.dtb
+findfdt=
+	setenv name_fdt ${default_device_tree};
+	if test $board_name = j721s2; then			\
+		setenv name_fdt k3-j721s2-common-proc-board.dtb; fi;
+	if test $board_name = am68-sk; then
+		setenv name_fdt k3-am68-sk-base-board.dtb; fi;
+	setenv fdtfile ${name_fdt}
+name_kern=Image
+console=ttyS2,115200n8
+args_all=setenv optargs earlycon=ns16550a,mmio32,0x02880000
+	${mtdparts}
+run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr}
+
+boot=mmc
+mmcdev=1
+bootpart=1:2
+bootdir=/boot
+#if CONFIG_SYS_K3_SPL_ATF
+#if CONFIG_TARGET_J721S2_R5_EVM
+addr_mcur5f0_0load=0x89000000
+name_mcur5f0_0fw=/lib/firmware/j7-mcu-r5f0_0-fw
+#endif
+#endif
+rd_spec=-
+init_mmc=run args_all args_mmc
+get_fdt_mmc=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${name_fdt}
+get_overlay_mmc=
+	fdt address ${fdtaddr};
+	fdt resize 0x100000;
+	for overlay in $name_overlays;
+	do;
+	load mmc ${bootpart} ${dtboaddr} ${bootdir}/${overlay} &&
+	fdt apply ${dtboaddr};
+	done;
+partitions=uuid_disk=${uuid_gpt_disk};
+	name=rootfs,start=0,size=-,uuid=${uuid_gpt_rootfs}
+get_kern_mmc=load mmc ${bootpart} ${loadaddr}
+	${bootdir}/${name_kern}
+get_fit_mmc=load mmc ${bootpart} ${addr_fit}
+	${bootdir}/${name_fit}
+partitions=uuid_disk=${uuid_gpt_disk};
+	name=rootfs,start=0,size=-,uuid=${uuid_gpt_rootfs}
+
+rproc_fw_binaries= 2 /lib/firmware/j721s2-main-r5f0_0-fw 3 /lib/firmware/j721s2-main-r5f0_1-fw 4 /lib/firmware/j721s2-main-r5f1_0-fw 5 /lib/firmware/j721s2-main-r5f1_1-fw 6 /lib/firmware/j721s2-c71_0-fw 7 /lib/firmware/j721s2-c71_1-fw
+
+
diff --git a/boot/image-board.c b/boot/image-board.c
index 25b60ec..9bf7082 100644
--- a/boot/image-board.c
+++ b/boot/image-board.c
@@ -1004,7 +1004,9 @@
 
 	switch (genimg_get_format(buf)) {
 	case IMAGE_FORMAT_LEGACY:
-		if (IS_ENABLED(CONFIG_LEGACY_IMAGE_FORMAT)) {
+		if (!IS_ENABLED(CONFIG_LEGACY_IMAGE_FORMAT)) {
+			goto exit_image_format;
+		} else {
 			hdr = buf;
 
 			if (!image_check_magic(hdr)) {
@@ -1047,7 +1049,9 @@
 		}
 		break;
 	case IMAGE_FORMAT_FIT:
-		if (IS_ENABLED(CONFIG_FIT)) {
+		if (!IS_ENABLED(CONFIG_FIT)) {
+			goto exit_image_format;
+		} else {
 			fit_hdr = buf;
 			if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
 				puts("Bad FIT image format\n");
@@ -1121,12 +1125,15 @@
 		}
 		break;
 	default:
-		puts("Wrong image format for \"source\" command\n");
-		return -EPERM;
+		goto exit_image_format;
 	}
 
 	*datap = (char *)data;
 	*lenp = len;
 
 	return 0;
+
+exit_image_format:
+	puts("Wrong image format for \"source\" command\n");
+	return -EPERM;
 }
diff --git a/cmd/Kconfig b/cmd/Kconfig
index ba5ec69..8c9b430 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1396,6 +1396,16 @@
 	  peripherals. Sub-commands allow bus enumeration, displaying and
 	  changing configuration space and a few other features.
 
+config CMD_PCI_MPS
+	bool "pci_mps - Configure PCI device MPS"
+	depends on PCI
+	help
+	  Enables PCI Express Maximum Packet Size (MPS) tuning. This
+	  command configures the PCI Express MPS of each endpoint to the
+	  largest value supported by all devices below the root complex.
+	  The Maximum Read Request Size will not be altered. This method is
+	  the same algorithm as used by Linux pci=pcie_bus_safe.
+
 config CMD_PINMUX
 	bool "pinmux - show pins muxing"
 	depends on PINCTRL
@@ -1542,6 +1552,12 @@
 	  export a block device: U-Boot, the USB device, acts as a simple
 	  external hard drive plugged on the host USB port.
 
+config CMD_UMS_ABORT_KEYED
+	bool "UMS abort with any key"
+	depends on CMD_USB_MASS_STORAGE
+	help
+	  Allow interruption of usb mass storage run with any key pressed.
+
 config CMD_PVBLOCK
 	bool "Xen para-virtualized block device"
 	depends on XEN
diff --git a/cmd/Makefile b/cmd/Makefile
index d95833b..e032091 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -131,6 +131,7 @@
 obj-$(CONFIG_CMD_PCAP) += pcap.o
 ifdef CONFIG_PCI
 obj-$(CONFIG_CMD_PCI) += pci.o
+obj-$(CONFIG_CMD_PCI_MPS) += pci_mps.o
 endif
 obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PMC) += pmc.o
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index 7cbc3fd..12eae06 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -1025,6 +1025,7 @@
 	char *from = argv[2];
 	char *default_value = NULL;
 	int ret = 0;
+	char *val;
 
 	if (argc < 3 || argc > 4) {
 		return CMD_RET_USAGE;
@@ -1034,18 +1035,14 @@
 		default_value = argv[3];
 	}
 
-	if (env_get(from) == NULL && default_value == NULL) {
+	val = env_get(from) ?: default_value;
+	if (!val) {
 		printf("## env indirect: Environment variable for <from> (%s) does not exist.\n", from);
 
 		return CMD_RET_FAILURE;
 	}
 
-	if (env_get(from) == NULL) {
-		ret = env_set(to, default_value);
-	}
-	else {
-		ret = env_set(to, env_get(from));
-	}
+	ret = env_set(to, val);
 
 	if (ret == 0) {
 		return CMD_RET_SUCCESS;
diff --git a/cmd/pci_mps.c b/cmd/pci_mps.c
new file mode 100644
index 0000000..555a5fd
--- /dev/null
+++ b/cmd/pci_mps.c
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 Microsoft Corporation <www.microsoft.com>
+ * Stephen Carlson <stcarlso@linux.microsoft.com>
+ *
+ * PCI Express Maximum Packet Size (MPS) configuration
+ */
+
+#include <common.h>
+#include <bootretry.h>
+#include <cli.h>
+#include <command.h>
+#include <console.h>
+#include <dm.h>
+#include <init.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <pci.h>
+
+#define PCI_MPS_SAFE 0
+#define PCI_MPS_PEER2PEER 1
+
+static int pci_mps_find_safe(struct udevice *bus, unsigned int *min_mps,
+			     unsigned int *n)
+{
+	struct udevice *dev;
+	int res = 0, addr;
+	unsigned int mpss;
+	u32 regval;
+
+	if (!min_mps || !n)
+		return -EINVAL;
+
+	for (device_find_first_child(bus, &dev);
+	     dev;
+	     device_find_next_child(&dev)) {
+		addr = dm_pci_find_capability(dev, PCI_CAP_ID_EXP);
+		if (addr <= 0)
+			continue;
+
+		res = dm_pci_read_config32(dev, addr + PCI_EXP_DEVCAP,
+					   &regval);
+		if (res != 0)
+			return res;
+		mpss = (unsigned int)(regval & PCI_EXP_DEVCAP_PAYLOAD);
+		*n += 1;
+		if (mpss < *min_mps)
+			*min_mps = mpss;
+	}
+
+	return res;
+}
+
+static int pci_mps_set_bus(struct udevice *bus, unsigned int target)
+{
+	struct udevice *dev;
+	u32 mpss, target_mps = (u32)(target << 5);
+	u16 mps;
+	int res = 0, addr;
+
+	for (device_find_first_child(bus, &dev);
+	     dev && res == 0;
+	     device_find_next_child(&dev)) {
+		addr = dm_pci_find_capability(dev, PCI_CAP_ID_EXP);
+		if (addr <= 0)
+			continue;
+
+		res = dm_pci_read_config32(dev, addr + PCI_EXP_DEVCAP,
+					   &mpss);
+		if (res != 0)
+			return res;
+
+		/* Do not set device above its maximum MPSS */
+		mpss = (mpss & PCI_EXP_DEVCAP_PAYLOAD) << 5;
+		if (target_mps < mpss)
+			mps = (u16)target_mps;
+		else
+			mps = (u16)mpss;
+		res = dm_pci_clrset_config16(dev, addr + PCI_EXP_DEVCTL,
+					     PCI_EXP_DEVCTL_PAYLOAD, mps);
+	}
+
+	return res;
+}
+
+/*
+ * Sets the MPS of each PCI Express device to the specified policy.
+ */
+static int pci_mps_set(int policy)
+{
+	struct udevice *bus;
+	int i, res = 0;
+	/* 0 = 128B, min value for hotplug */
+	unsigned int mps = 0;
+
+	if (policy == PCI_MPS_SAFE) {
+		unsigned int min_mps = PCI_EXP_DEVCAP_PAYLOAD_4096B, n = 0;
+
+		/* Find maximum MPS supported by all devices */
+		for (i = 0;
+		     uclass_get_device_by_seq(UCLASS_PCI, i, &bus) == 0 &&
+		     res == 0;
+		     i++)
+			res = pci_mps_find_safe(bus, &min_mps, &n);
+
+		/* If no devices were found, do not reconfigure */
+		if (n == 0)
+			return res;
+		mps = min_mps;
+	}
+
+	/* This message is checked by the sandbox test */
+	printf("Setting MPS of all devices to %uB\n", 128U << mps);
+	for (i = 0;
+	     uclass_get_device_by_seq(UCLASS_PCI, i, &bus) == 0 && res == 0;
+	     i++)
+		res = pci_mps_set_bus(bus, mps);
+
+	return res;
+}
+
+/*
+ * PCI MPS tuning commands
+ *
+ * Syntax:
+ *	pci_mps safe
+ *	pci_mps peer2peer
+ */
+static int do_pci_mps(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	char cmd = 'u';
+	int ret = 0;
+
+	if (argc > 1)
+		cmd = argv[1][0];
+
+	switch (cmd) {
+	case 's':		/* safe */
+		ret = pci_mps_set(PCI_MPS_SAFE);
+		break;
+	case 'p':		/* peer2peer/hotplug */
+		ret = pci_mps_set(PCI_MPS_PEER2PEER);
+		break;
+	default:		/* usage, help */
+		goto usage;
+	}
+
+	return ret;
+usage:
+	return CMD_RET_USAGE;
+}
+
+/***************************************************/
+
+#ifdef CONFIG_SYS_LONGHELP
+static char pci_mps_help_text[] =
+	"safe\n"
+	"    - Set PCI Express MPS of all devices to safe values\n"
+	"pci_mps peer2peer\n"
+	"    - Set PCI Express MPS of all devices to support hotplug and peer-to-peer DMA\n";
+#endif
+
+U_BOOT_CMD(pci_mps, 2, 0, do_pci_mps,
+	   "configure PCI Express MPS", pci_mps_help_text);
diff --git a/cmd/usb_mass_storage.c b/cmd/usb_mass_storage.c
index b7daaa6..c3cc197 100644
--- a/cmd/usb_mass_storage.c
+++ b/cmd/usb_mass_storage.c
@@ -231,6 +231,16 @@
 			goto cleanup_register;
 		}
 
+		if (IS_ENABLED(CONFIG_CMD_UMS_ABORT_KEYED)) {
+			/* Abort by pressing any key */
+			if (tstc()) {
+				getchar();
+				printf("\rOperation aborted.\n");
+				rc = CMD_RET_SUCCESS;
+				goto cleanup_register;
+			}
+		}
+
 		schedule();
 	}
 
diff --git a/common/cli.c b/common/cli.c
index 9451e6a..3916a7b 100644
--- a/common/cli.c
+++ b/common/cli.c
@@ -8,6 +8,8 @@
  * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com>
  */
 
+#define pr_fmt(fmt) "cli: %s: " fmt, __func__
+
 #include <common.h>
 #include <bootstage.h>
 #include <cli.h>
@@ -20,6 +22,7 @@
 #include <malloc.h>
 #include <asm/global_data.h>
 #include <dm/ofnode.h>
+#include <linux/errno.h>
 
 #ifdef CONFIG_CMDLINE
 /*
@@ -129,16 +132,26 @@
 int run_commandf(const char *fmt, ...)
 {
 	va_list args;
-	char cmd[128];
-	int i, ret;
+	int nbytes;
 
 	va_start(args, fmt);
-	i = vsnprintf(cmd, sizeof(cmd), fmt, args);
+	/*
+	 * Limit the console_buffer space being used to CONFIG_SYS_CBSIZE,
+	 * because its last byte is used to fit the replacement of \0 by \n\0
+	 * in underlying hush parser
+	 */
+	nbytes = vsnprintf(console_buffer, CONFIG_SYS_CBSIZE, fmt, args);
 	va_end(args);
 
-	ret = run_command(cmd, 0);
-
-	return ret;
+	if (nbytes < 0) {
+		pr_debug("I/O internal error occurred.\n");
+		return -EIO;
+	} else if (nbytes >= CONFIG_SYS_CBSIZE) {
+		pr_debug("'fmt' size:%d exceeds the limit(%d)\n",
+			 nbytes, CONFIG_SYS_CBSIZE);
+		return -ENOSPC;
+	}
+	return run_command(console_buffer, 0);
 }
 
 /****************************************************************************/
diff --git a/configs/am62ax_evm_a53_defconfig b/configs/am62ax_evm_a53_defconfig
index 8b48f5e..46a95a6 100644
--- a/configs/am62ax_evm_a53_defconfig
+++ b/configs/am62ax_evm_a53_defconfig
@@ -1,5 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_K3=y
+CONFIG_TI_SECURE_DEVICE=y
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
diff --git a/configs/am62ax_evm_r5_defconfig b/configs/am62ax_evm_r5_defconfig
index fac48fb..e5bee14 100644
--- a/configs/am62ax_evm_r5_defconfig
+++ b/configs/am62ax_evm_r5_defconfig
@@ -1,5 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_K3=y
+CONFIG_TI_SECURE_DEVICE=y
 CONFIG_SYS_MALLOC_F_LEN=0x9000
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
@@ -52,6 +53,7 @@
 CONFIG_SPL_RAM_DEVICE=y
 CONFIG_SPL_REMOTEPROC=y
 CONFIG_SPL_THERMAL=y
+CONFIG_SPL_YMODEM_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_DFU=y
diff --git a/configs/apple_m1_defconfig b/configs/apple_m1_defconfig
index b4ecf73..7555609 100644
--- a/configs/apple_m1_defconfig
+++ b/configs/apple_m1_defconfig
@@ -21,3 +21,4 @@
 CONFIG_NO_FB_CLEAR=y
 CONFIG_VIDEO_SIMPLE=y
 # CONFIG_GENERATE_SMBIOS_TABLE is not set
+CONFIG_LMB_MAX_REGIONS=64
diff --git a/configs/clearfog_spi_defconfig b/configs/clearfog_spi_defconfig
new file mode 100644
index 0000000..9dcf16f
--- /dev/null
+++ b/configs/clearfog_spi_defconfig
@@ -0,0 +1,83 @@
+CONFIG_ARM=y
+CONFIG_ARCH_CPU_INIT=y
+CONFIG_SYS_THUMB_BUILD=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_TEXT_BASE=0x00800000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xff0000
+CONFIG_TARGET_CLEARFOG=y
+CONFIG_ENV_SECT_SIZE=0x10000
+CONFIG_DEFAULT_DEVICE_TREE="armada-388-clearfog"
+CONFIG_SPL_TEXT_BASE=0x40000030
+CONFIG_SPL_SERIAL=y
+CONFIG_SPL_STACK=0x4002c000
+CONFIG_SPL=y
+CONFIG_DEBUG_UART_BASE=0xf1012000
+CONFIG_DEBUG_UART_CLOCK=250000000
+CONFIG_SYS_LOAD_ADDR=0x800000
+CONFIG_DEBUG_UART=y
+CONFIG_AHCI=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_BOOTDELAY=3
+CONFIG_USE_PREBOOT=y
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_SPL_MAX_SIZE=0x22fd0
+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
+CONFIG_SPL_BSS_START_ADDR=0x40023000
+CONFIG_SPL_BSS_MAX_SIZE=0x4000
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
+CONFIG_SPL_I2C=y
+CONFIG_SYS_MAXARGS=32
+CONFIG_CMD_TLV_EEPROM=y
+CONFIG_SPL_CMD_TLV_EEPROM=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_MVEBU_BUBT=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_MIN_ENTRIES=128
+CONFIG_ARP_TIMEOUT=200
+CONFIG_NET_RETRY_COUNT=50
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_AHCI_MVEBU=y
+CONFIG_DM_PCA953X=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MVTWSI=y
+CONFIG_I2C_EEPROM=y
+CONFIG_SPL_I2C_EEPROM=y
+CONFIG_SUPPORT_EMMC_BOOT=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SDMA=y
+CONFIG_MMC_SDHCI_MV=y
+CONFIG_MTD=y
+CONFIG_SF_DEFAULT_BUS=1
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_PHY_MARVELL=y
+CONFIG_PHY_GIGE=y
+CONFIG_MVNETA=y
+CONFIG_MII=y
+CONFIG_MVMDIO=y
+CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
+CONFIG_SCSI=y
+CONFIG_SPL_DEBUG_UART_BASE=0xd0012000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_KIRKWOOD_SPI=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
diff --git a/configs/iot2050_defconfig b/configs/iot2050_pg1_defconfig
similarity index 92%
rename from configs/iot2050_defconfig
rename to configs/iot2050_pg1_defconfig
index 57387ed..b027696 100644
--- a/configs/iot2050_defconfig
+++ b/configs/iot2050_pg1_defconfig
@@ -8,7 +8,7 @@
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_SOC_K3_AM654=y
-CONFIG_TARGET_IOT2050_A53=y
+CONFIG_TARGET_IOT2050_A53_PG1=y
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80100000
 CONFIG_ENV_SIZE=0x20000
@@ -32,6 +32,7 @@
 CONFIG_BOOTSTAGE=y
 CONFIG_SHOW_BOOT_PROGRESS=y
 CONFIG_SPL_SHOW_BOOT_PROGRESS=y
+CONFIG_BOOTCOMMAND="run start_watchdog; run distro_bootcmd"
 CONFIG_CONSOLE_MUX=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_MAX_SIZE=0x58000
@@ -52,7 +53,7 @@
 # CONFIG_SPL_SPI_FLASH_TINY is not set
 CONFIG_SPL_SPI_FLASH_SFDP_SUPPORT=y
 CONFIG_SPL_SPI_LOAD=y
-CONFIG_SYS_SPI_U_BOOT_OFFS=0x280000
+CONFIG_SYS_SPI_U_BOOT_OFFS=0x380000
 CONFIG_SYS_MAXARGS=64
 CONFIG_SYS_PBSIZE=1050
 CONFIG_CMD_ASKENV=y
@@ -69,6 +70,7 @@
 # CONFIG_ISO_PARTITION is not set
 CONFIG_OF_CONTROL=y
 CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_LIST="k3-am6528-iot2050-basic k3-am6548-iot2050-advanced"
 CONFIG_SPL_MULTI_DTB_FIT=y
 CONFIG_SPL_OF_LIST="k3-am65-iot2050-spl"
 CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y
@@ -139,7 +141,9 @@
 CONFIG_USB_KEYBOARD=y
 # CONFIG_WATCHDOG is not set
 # CONFIG_WATCHDOG_AUTOSTART is not set
+CONFIG_WATCHDOG_TIMEOUT_MSECS=0
 CONFIG_WDT=y
 CONFIG_WDT_K3_RTI=y
 CONFIG_WDT_K3_RTI_LOAD_FW=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_EFI_SCROLL_ON_CLEAR_SCREEN=y
diff --git a/configs/iot2050_defconfig b/configs/iot2050_pg2_defconfig
similarity index 90%
copy from configs/iot2050_defconfig
copy to configs/iot2050_pg2_defconfig
index 57387ed..b206677 100644
--- a/configs/iot2050_defconfig
+++ b/configs/iot2050_pg2_defconfig
@@ -8,7 +8,7 @@
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_SOC_K3_AM654=y
-CONFIG_TARGET_IOT2050_A53=y
+CONFIG_TARGET_IOT2050_A53_PG2=y
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80100000
 CONFIG_ENV_SIZE=0x20000
@@ -16,22 +16,22 @@
 CONFIG_ENV_SECT_SIZE=0x20000
 CONFIG_DM_GPIO=y
 CONFIG_SPL_DM_SPI=y
-CONFIG_DEFAULT_DEVICE_TREE="k3-am6528-iot2050-basic"
+CONFIG_DEFAULT_DEVICE_TREE="k3-am6528-iot2050-basic-pg2"
 CONFIG_SPL_TEXT_BASE=0x80080000
 CONFIG_SYS_PROMPT="IOT2050> "
-CONFIG_DM_RESET=y
 CONFIG_SPL_SERIAL=y
 CONFIG_SPL_STACK_R_ADDR=0x82000000
 CONFIG_ENV_OFFSET_REDUND=0x6a0000
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI=y
+CONFIG_DISTRO_DEFAULTS=y
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_OF_BOARD_SETUP=y
-CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BOOTSTAGE=y
 CONFIG_SHOW_BOOT_PROGRESS=y
 CONFIG_SPL_SHOW_BOOT_PROGRESS=y
+CONFIG_BOOTCOMMAND="run start_watchdog; run distro_bootcmd"
 CONFIG_CONSOLE_MUX=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_MAX_SIZE=0x58000
@@ -52,7 +52,7 @@
 # CONFIG_SPL_SPI_FLASH_TINY is not set
 CONFIG_SPL_SPI_FLASH_SFDP_SUPPORT=y
 CONFIG_SPL_SPI_LOAD=y
-CONFIG_SYS_SPI_U_BOOT_OFFS=0x280000
+CONFIG_SYS_SPI_U_BOOT_OFFS=0x380000
 CONFIG_SYS_MAXARGS=64
 CONFIG_SYS_PBSIZE=1050
 CONFIG_CMD_ASKENV=y
@@ -69,6 +69,7 @@
 # CONFIG_ISO_PARTITION is not set
 CONFIG_OF_CONTROL=y
 CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_LIST="k3-am6528-iot2050-basic-pg2 k3-am6548-iot2050-advanced-pg2 k3-am6548-iot2050-advanced-m2"
 CONFIG_SPL_MULTI_DTB_FIT=y
 CONFIG_SPL_OF_LIST="k3-am65-iot2050-spl"
 CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y
@@ -120,6 +121,7 @@
 CONFIG_POWER_DOMAIN=y
 CONFIG_TI_SCI_POWER_DOMAIN=y
 CONFIG_REMOTEPROC_TI_K3_R5F=y
+CONFIG_DM_RESET=y
 CONFIG_RESET_TI_SCI=y
 CONFIG_DM_SERIAL=y
 CONFIG_SOC_DEVICE=y
@@ -139,7 +141,9 @@
 CONFIG_USB_KEYBOARD=y
 # CONFIG_WATCHDOG is not set
 # CONFIG_WATCHDOG_AUTOSTART is not set
+CONFIG_WATCHDOG_TIMEOUT_MSECS=0
 CONFIG_WDT=y
 CONFIG_WDT_K3_RTI=y
 CONFIG_WDT_K3_RTI_LOAD_FW=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_EFI_SCROLL_ON_CLEAR_SCREEN=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index b0f588d..cbace25 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -78,6 +78,7 @@
 CONFIG_CMD_MUX=y
 CONFIG_CMD_OSD=y
 CONFIG_CMD_PCI=y
+CONFIG_CMD_PCI_MPS=y
 CONFIG_CMD_READ=y
 CONFIG_CMD_REMOTEPROC=y
 CONFIG_CMD_SPI=y
@@ -268,6 +269,7 @@
 CONFIG_RESET_SYSCON=y
 CONFIG_RESET_SCMI=y
 CONFIG_DM_RTC=y
+CONFIG_RTC_MAX313XX=y
 CONFIG_RTC_RV8803=y
 CONFIG_RTC_HT1380=y
 CONFIG_SCSI=y
diff --git a/configs/socrates_defconfig b/configs/socrates_defconfig
index 2465513..df8b31b 100644
--- a/configs/socrates_defconfig
+++ b/configs/socrates_defconfig
@@ -18,7 +18,6 @@
 CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
-CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_BOOTDELAY=1
 CONFIG_AUTOBOOT_KEYED=y
diff --git a/disk/disk-uclass.c b/disk/disk-uclass.c
index d32747e..7f1fd80 100644
--- a/disk/disk-uclass.c
+++ b/disk/disk-uclass.c
@@ -65,26 +65,38 @@
 	return 0;
 }
 
+static int blk_part_setup(struct udevice *dev, lbaint_t *startp,
+			  lbaint_t blkcnt)
+{
+	struct disk_part *part;
+
+	part = dev_get_uclass_plat(dev);
+	if (*startp >= part->gpt_part_info.size)
+		return -E2BIG;
+
+	if (*startp + blkcnt > part->gpt_part_info.size)
+		blkcnt = part->gpt_part_info.size - *startp;
+	*startp += part->gpt_part_info.start;
+
+	return 0;
+}
+
 static ulong part_blk_read(struct udevice *dev, lbaint_t start,
 			   lbaint_t blkcnt, void *buffer)
 {
 	struct udevice *parent;
-	struct disk_part *part;
 	const struct blk_ops *ops;
+	int ret;
 
 	parent = dev_get_parent(dev);
 	ops = blk_get_ops(parent);
 	if (!ops->read)
 		return -ENOSYS;
 
-	part = dev_get_uclass_plat(dev);
-	if (start >= part->gpt_part_info.size)
+	ret = blk_part_setup(dev, &start, blkcnt);
+	if (ret)
 		return 0;
 
-	if ((start + blkcnt) > part->gpt_part_info.size)
-		blkcnt = part->gpt_part_info.size - start;
-	start += part->gpt_part_info.start;
-
 	return ops->read(parent, start, blkcnt, buffer);
 }
 
@@ -92,22 +104,18 @@
 			    lbaint_t blkcnt, const void *buffer)
 {
 	struct udevice *parent;
-	struct disk_part *part;
 	const struct blk_ops *ops;
+	int ret;
 
 	parent = dev_get_parent(dev);
 	ops = blk_get_ops(parent);
 	if (!ops->write)
 		return -ENOSYS;
 
-	part = dev_get_uclass_plat(dev);
-	if (start >= part->gpt_part_info.size)
+	ret = blk_part_setup(dev, &start, blkcnt);
+	if (ret)
 		return 0;
 
-	if ((start + blkcnt) > part->gpt_part_info.size)
-		blkcnt = part->gpt_part_info.size - start;
-	start += part->gpt_part_info.start;
-
 	return ops->write(parent, start, blkcnt, buffer);
 }
 
@@ -115,22 +123,18 @@
 			    lbaint_t blkcnt)
 {
 	struct udevice *parent;
-	struct disk_part *part;
 	const struct blk_ops *ops;
+	int ret;
 
 	parent = dev_get_parent(dev);
 	ops = blk_get_ops(parent);
 	if (!ops->erase)
 		return -ENOSYS;
 
-	part = dev_get_uclass_plat(dev);
-	if (start >= part->gpt_part_info.size)
+	ret = blk_part_setup(dev, &start, blkcnt);
+	if (ret)
 		return 0;
 
-	if ((start + blkcnt) > part->gpt_part_info.size)
-		blkcnt = part->gpt_part_info.size - start;
-	start += part->gpt_part_info.start;
-
 	return ops->erase(parent, start, blkcnt);
 }
 
diff --git a/doc/board/siemens/iot2050.rst b/doc/board/siemens/iot2050.rst
index 7e97f81..074d6aa 100644
--- a/doc/board/siemens/iot2050.rst
+++ b/doc/board/siemens/iot2050.rst
@@ -6,7 +6,9 @@
 
 The SIMATIC IOT2050 is an open industrial IoT gateway that is using the TI
 AM6528 GP (Basic variant) or the AM6548 HS (Advanced variant). The Advanced
-variant is prepared for secure boot.
+variant is prepared for secure boot. M.2 Variant also uses the AM6548 HS.
+Instead of a MiniPCI connector, it comes with two M.2 connectors and can
+support 5G/WIFI/BT applications or connect an SSD.
 
 The IOT2050 starts only from OSPI. It loads a Siemens-provided bootloader
 called SE-Boot for the MCU domain (R5F cores), then hands over to ATF and
@@ -24,11 +26,20 @@
 https://github.com/siemens/meta-iot2050/tree/master/recipes-bsp/u-boot/files/prebuild.
 The following binaries from that source need to be present in the build folder:
 
- - tiboot3.bin
- - sysfw.itb
- - sysfw.itb_HS
- - sysfw_sr2.itb
- - sysfw_sr2.itb_HS
+ - seboot_pg1.bin
+ - seboot_pg2.bin
+
+When using the watchdog, a related firmware for the R5 core(s) is needed, e.g.
+https://github.com/siemens/k3-rti-wdt. The name and location of the image is
+configured via CONFIG_WDT_K3_RTI_FW_FILE.
+
+For building an image containing the OTP key provisioning data, below binary
+needs to be present in the build folder:
+
+ - otpcmd.bin
+
+Regarding how to generating this otpcmd.bin, please refer to:
+https://github.com/siemens/meta-iot2050/tree/master/recipes-bsp/secure-boot-otp-provisioning/files/make-otpcmd.sh
 
 Building
 --------
@@ -57,7 +68,13 @@
 
  $ export ATF=/path/to/bl31.bin
  $ export TEE=/path/to/tee-pager_v2.bin
- $ make iot2050_defconfig
+
+ # configure for PG1
+ $ make iot2050_pg1_defconfig
+
+ # or configure for PG2 or the M.2 variant
+ $ make iot2050_pg2_defconfig
+
  $ make
 
 Flashing
@@ -76,3 +93,73 @@
 .. code-block:: text
 
  $ dpcmd --vcc 2 -v -u flash.bin
+
+Signing (optional)
+------------------
+
+To enable verified boot for the firmware artifacts after the Siemens-managed
+first-stage loader (seboot_pg*.bin), the following steps need to be taken
+before and after the build:
+
+Generate dtsi holding the public key
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: text
+
+ tools/key2dtsi.py -c -s key.pem public-key.dtsi
+
+This will be used to embed the public key into U-Boot SPL and main so that each
+step can validate signatures of the succeeding one.
+
+Adjust U-Boot configuration
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Enabled at least the following options in U-Boot:
+
+.. code-block:: text
+
+ CONFIG_SPL_FIT_SIGNATURE=y
+ CONFIG_DEVICE_TREE_INCLUDES="/path/to/public-key.dtsi"
+ CONFIG_RSA=y
+
+Note that there are more configuration changes needed in order to lock-down
+the command line and the boot process of U-Boot for secure scenarios. These are
+not in scope here.
+
+Build U-Boot
+^^^^^^^^^^^^
+
+See related section above.
+
+Sign flash.bin
+^^^^^^^^^^^^^^
+
+In the build folder still containing artifacts from step 3, invoke:
+
+.. code-block:: text
+
+ tools/iot2050-sign-fw.sh /path/to/key.pem
+
+Flash signed flash.bin
+^^^^^^^^^^^^^^^^^^^^^^
+
+The signing has happen in-place in flash.bin, thus the flashing procedure
+described above.
+
+M.2 slot configuration
+----------------------
+
+The M.2 variant of the IOT2050 comes with one B-keyed and one E-keyed slot.
+These are configured by U-Boot depending on the detected usage (auto
+configuration). The device tree loaded later on for the OS will be fixed up
+by U-Boot according to this configuration.
+
+For the case auto configuration does not work reliably, it is possible to set
+the U-Boot environment variable "m2_manual_config" to select the mode manually:
+
+"0"  -  B-key: PCIe x2, USB 2.0
+        E-key: USB 2.0
+"1"  -  B-key: PCIe, USB 2.0
+        E-key: PCIe, USB 2.0
+"2"  -  B-key: USB 3.0,
+        E-key: PCIe, USB 2.0
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index dbebf3a..c8be5a4 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -1171,6 +1171,13 @@
 {
 	int ret;
 
+	if (!dev) {
+		uclass_foreach_dev_probe(UCLASS_GPIO, dev)
+			if (!gpio_request_by_line_name(dev, line_name, desc, flags))
+				return 0;
+		return -ENOENT;
+	}
+
 	ret = dev_read_stringlist_search(dev, "gpio-line-names", line_name);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 32360d9..c2b365a 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -48,8 +48,8 @@
 
 config BUTTON_KEYBOARD
 	bool "Buttons as keyboard"
-	depends on BUTTON_GPIO
 	depends on DM_KEYBOARD
+	select BUTTON_GPIO
 	help
 	  Enable support for mapping buttons to keycode events. Use linux,code button driver
 	  dt node to define button-event mapping.
diff --git a/drivers/input/button_kbd.c b/drivers/input/button_kbd.c
index 99e65f1..74fadfc 100644
--- a/drivers/input/button_kbd.c
+++ b/drivers/input/button_kbd.c
@@ -111,16 +111,14 @@
 	return 0;
 }
 
-static const struct udevice_id button_kbd_ids[] = {
-	{ .compatible = "button-kbd" },
-	{ }
-};
-
 U_BOOT_DRIVER(button_kbd) = {
 	.name		= "button_kbd",
 	.id		= UCLASS_KEYBOARD,
-	.of_match	= button_kbd_ids,
 	.ops		= &button_kbd_ops,
 	.priv_auto	= sizeof(struct button_kbd_priv),
 	.probe		= button_kbd_probe,
 };
+
+U_BOOT_DRVINFO(button_kbd) = {
+	.name = "button_kbd"
+};
diff --git a/drivers/misc/swap_case.c b/drivers/misc/swap_case.c
index 7093ad1..ee5c12b 100644
--- a/drivers/misc/swap_case.c
+++ b/drivers/misc/swap_case.c
@@ -165,6 +165,9 @@
 	case PCI_CAP_ID_EXP_OFFSET + PCI_CAP_LIST_NEXT:
 		*valuep = PCI_CAP_ID_MSIX_OFFSET;
 		break;
+	case PCI_CAP_ID_EXP_OFFSET + PCI_EXP_DEVCAP:
+		*valuep = PCI_EXP_DEVCAP_PAYLOAD_256B;
+		break;
 	case PCI_CAP_ID_MSIX_OFFSET:
 		if (sandbox_swap_case_use_ea(emul))
 			*valuep = (PCI_CAP_ID_EA_OFFSET << 8) | PCI_CAP_ID_MSIX;
diff --git a/drivers/pci/pcie_apple.c b/drivers/pci/pcie_apple.c
index 9b08e1e..b934fdb 100644
--- a/drivers/pci/pcie_apple.c
+++ b/drivers/pci/pcie_apple.c
@@ -315,6 +315,8 @@
 	for (of_port = ofnode_first_subnode(dev_ofnode(dev));
 	     ofnode_valid(of_port);
 	     of_port = ofnode_next_subnode(of_port)) {
+		if (!ofnode_is_enabled(of_port))
+			continue;
 		ret = apple_pcie_setup_port(pcie, of_port);
 		if (ret) {
 			dev_err(pcie->dev, "Port %d setup fail: %d\n", i, ret);
diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 6646b15..2339717 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -39,6 +39,7 @@
 #define WIZ_DIV_NUM_CLOCKS_10G	1
 
 #define WIZ_SERDES_TYPEC_LN10_SWAP	BIT(30)
+#define WIZ_SERDES_TYPEC_LN23_SWAP	BIT(31)
 
 enum wiz_lane_standard_mode {
 	LANE_MODE_GEN1,
@@ -65,6 +66,14 @@
 	WIZ_EXT_REFCLK1,
 };
 
+/*
+ * List of master lanes used for lane swapping
+ */
+enum wiz_typec_master_lane {
+	LANE0 = 0,
+	LANE2 = 2,
+};
+
 static const struct reg_field por_en = REG_FIELD(WIZ_SERDES_CTRL, 31, 31);
 static const struct reg_field phy_reset_n = REG_FIELD(WIZ_SERDES_RST, 31, 31);
 static const struct reg_field pll1_refclk_mux_sel =
@@ -329,6 +338,7 @@
 	u32			num_lanes;
 	struct gpio_desc	*gpio_typec_dir;
 	u32			lane_phy_type[WIZ_MAX_LANES];
+	u32			master_lane_num[WIZ_MAX_LANES];
 	struct clk		*input_clks[WIZ_MAX_INPUT_CLOCKS];
 	unsigned int		id;
 	const struct wiz_data	*data;
@@ -586,14 +596,42 @@
 		return ret;
 
 	/* if typec-dir gpio was specified, set LN10 SWAP bit based on that */
-	if (id == 0 && wiz->gpio_typec_dir) {
-		if (dm_gpio_get_value(wiz->gpio_typec_dir)) {
-			regmap_update_bits(wiz->regmap, WIZ_SERDES_TYPEC,
-					   WIZ_SERDES_TYPEC_LN10_SWAP,
-					   WIZ_SERDES_TYPEC_LN10_SWAP);
-		} else {
-			regmap_update_bits(wiz->regmap, WIZ_SERDES_TYPEC,
-					   WIZ_SERDES_TYPEC_LN10_SWAP, 0);
+	if (id == 0) {
+		if (wiz->gpio_typec_dir) {
+			if (dm_gpio_get_value(wiz->gpio_typec_dir)) {
+				regmap_update_bits(wiz->regmap, WIZ_SERDES_TYPEC,
+						WIZ_SERDES_TYPEC_LN10_SWAP,
+						WIZ_SERDES_TYPEC_LN10_SWAP);
+			} else {
+				regmap_update_bits(wiz->regmap, WIZ_SERDES_TYPEC,
+						WIZ_SERDES_TYPEC_LN10_SWAP, 0);
+			}
+		}
+	} else {
+		/* if no typec-dir gpio was specified and PHY type is
+		 * USB3 with master lane number is '0', set LN10 SWAP
+		 * bit to '1'
+		 */
+		u32 num_lanes = wiz->num_lanes;
+		int i;
+
+		for (i = 0; i < num_lanes; i++) {
+			if (wiz->lane_phy_type[i] == PHY_TYPE_USB3) {
+				switch (wiz->master_lane_num[i]) {
+				case LANE0:
+					regmap_update_bits(wiz->regmap, WIZ_SERDES_TYPEC,
+							WIZ_SERDES_TYPEC_LN10_SWAP,
+							WIZ_SERDES_TYPEC_LN10_SWAP);
+					break;
+				case LANE2:
+					 regmap_update_bits(wiz->regmap, WIZ_SERDES_TYPEC,
+							WIZ_SERDES_TYPEC_LN23_SWAP,
+							WIZ_SERDES_TYPEC_LN23_SWAP);
+					break;
+				default:
+					break;
+				}
+			}
 		}
 	}
 
@@ -1100,8 +1138,10 @@
 		dev_dbg(dev, "%s: Lanes %u-%u have phy-type %u\n", __func__,
 			reg, reg + num_lanes - 1, phy_type);
 
-		for (i = reg; i < reg + num_lanes; i++)
+		for (i = reg; i < reg + num_lanes; i++) {
 			wiz->lane_phy_type[i] = phy_type;
+			wiz->master_lane_num[i] = reg;
+		}
 	}
 
 	return 0;
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index fcfda28..2317313 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -134,6 +134,19 @@
 	  This driver supports reading and writing the RTC/calendar and detects
 	  total power failures.
 
+config RTC_MAX313XX
+	bool "Analog Devices MAX313XX RTC driver"
+	depends on DM_RTC
+	depends on DM_I2C
+	help
+	  If you say yes here you will get support for the
+	  Analog Devices MAX313XX series RTC family.
+
+	  Chip features not currently supported:
+	  - Timestamp registers as SRAM
+	  - Temperature sensor
+	  - CLKOUT generation
+
 config RTC_PCF8563
 	tristate "Philips PCF8563"
 	help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index b6c9029..308fab8 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -19,6 +19,7 @@
 obj-$(CONFIG_$(SPL_TPL_)RTC_SANDBOX) += i2c_rtc_emul.o
 obj-$(CONFIG_RTC_ISL1208) += isl1208.o
 obj-$(CONFIG_RTC_M41T62) += m41t62.o
+obj-$(CONFIG_RTC_MAX313XX) += max313xx.o
 obj-$(CONFIG_RTC_MC13XXX) += mc13xxx-rtc.o
 obj-$(CONFIG_RTC_MC146818) += mc146818.o
 obj-$(CONFIG_MCFRTC) += mcfrtc.o
diff --git a/drivers/rtc/m41t62.c b/drivers/rtc/m41t62.c
index 66a0faa..891fe09 100644
--- a/drivers/rtc/m41t62.c
+++ b/drivers/rtc/m41t62.c
@@ -283,6 +283,16 @@
 	return m41t62_sqw_enable(dev, true);
 }
 
+static int m41t62_rtc_read8(struct udevice *dev, unsigned int reg)
+{
+	return dm_i2c_reg_read(dev, reg);
+}
+
+static int m41t62_rtc_write8(struct udevice *dev, unsigned int reg, int val)
+{
+	return dm_i2c_reg_write(dev, reg, val);
+}
+
 /*
  * Make sure HT bit is cleared. This bit is set on entering battery backup
  * mode, so do this before the first read access.
@@ -296,6 +306,8 @@
 	.get = m41t62_rtc_get,
 	.set = m41t62_rtc_set,
 	.reset = m41t62_rtc_reset,
+	.read8 = m41t62_rtc_read8,
+	.write8 = m41t62_rtc_write8,
 };
 
 static const struct udevice_id m41t62_rtc_ids[] = {
diff --git a/drivers/rtc/max313xx.c b/drivers/rtc/max313xx.c
new file mode 100644
index 0000000..748f3c4
--- /dev/null
+++ b/drivers/rtc/max313xx.c
@@ -0,0 +1,459 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Analog Devices MAX313XX series I2C RTC driver
+ *
+ * Copyright 2022 Analog Devices Inc.
+ */
+#include <bcd.h>
+#include <dm.h>
+#include <i2c.h>
+#include <rtc.h>
+#include <dm/device_compat.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+
+/* common registers */
+#define MAX313XX_INT_ALARM1		BIT(0)
+#define MAX313XX_INT_ALARM2		BIT(1)
+#define MAX313XX_HRS_F_12_24		BIT(6)
+#define MAX313XX_HRS_F_AM_PM		BIT(5)
+#define MAX313XX_MONTH_CENTURY		BIT(7)
+
+#define MAX313XX_TMR_CFG_ENABLE		BIT(4)
+#define MAX313XX_TMR_CFG_FREQ_MASK	GENMASK(1, 0)
+#define MAX313XX_TMR_CFG_FREQ_16HZ	0x03
+
+#define MAX313XX_REG_MINUTE		0x01
+#define MAX313XX_REG_HOUR		0x02
+
+#define MAX313XX_TIME_SIZE		0x07
+
+/* device specific registers */
+#define MAX3134X_CFG2_REG		0x01
+#define MAX3134X_CFG2_SET_RTC		BIT(1)
+
+#define MAX31341_TRICKLE_RES_MASK	GENMASK(1, 0)
+#define MAX31341_TRICKLE_DIODE_EN	BIT(2)
+#define MAX31341_TRICKLE_ENABLE_BIT	BIT(3)
+#define MAX31341_POWER_MGMT_REG		0x56
+#define MAX31341_POWER_MGMT_TRICKLE_BIT	BIT(0)
+
+#define MAX3133X_TRICKLE_RES_MASK	GENMASK(2, 1)
+#define MAX3133X_TRICKLE_DIODE_EN	BIT(3)
+#define MAX3133X_TRICKLE_ENABLE_BIT	BIT(0)
+
+#define MAX31329_TRICKLE_ENABLE_BIT	BIT(7)
+#define MAX31343_TRICKLE_ENABLE_MASK	GENMASK(7, 4)
+#define MAX31343_TRICKLE_ENABLE_CODE	5
+#define MAX31329_43_TRICKLE_RES_MASK	GENMASK(1, 0)
+#define MAX31329_43_TRICKLE_DIODE_EN	BIT(2)
+
+#define MAX31329_CONFIG2_REG		0x04
+#define MAX31329_CONFIG2_CLKIN_EN	BIT(2)
+#define MAX31329_CONFIG2_CLKIN_FREQ	GENMASK(1, 0)
+
+#define MAX31341_42_CONFIG1_REG		0x00
+#define MAX31341_42_CONFIG1_CLKIN_EN	BIT(7)
+#define MAX31341_42_CONFIG1_CLKIN_FREQ	GENMASK(5, 4)
+#define MAX31341_42_CONFIG1_OSC_DISABLE	BIT(3)
+#define MAX31341_42_CONFIG1_SWRST	BIT(0)
+
+enum max313xx_ids {
+	ID_MAX31328,
+	ID_MAX31329,
+	ID_MAX31331,
+	ID_MAX31334,
+	ID_MAX31341,
+	ID_MAX31342,
+	ID_MAX31343,
+	MAX313XX_ID_NR
+};
+
+/**
+ * struct chip_desc - descriptor for MAX313xx variants
+ * @sec_reg: Offset to seconds register. Used to denote the start of the
+ *           current time registers.
+ * @alarm1_sec_reg: Offset to Alarm1 seconds register. Used to denote the
+ *                  start of the alarm registers.
+ * @int_en_reg: Offset to the interrupt enable register.
+ * @int_status_reg: Offset to the interrupt status register.
+ * @ram_reg: Offset to the timestamp RAM (which can be used as SRAM).
+ * @ram_size: Size of the timestamp RAM.
+ * @temp_reg: Offset to the temperature register (or 0 if temperature
+ *            sensor is not supported).
+ * @trickle_reg: Offset to the trickle charger configuration register (or
+ *                0 if trickle charger is not supported).
+ * @rst_reg: Offset to the reset register.
+ * @rst_bit: Bit within the reset register for the software reset.
+ */
+struct chip_desc {
+	u8 sec_reg;
+	u8 alarm1_sec_reg;
+
+	u8 int_en_reg;
+	u8 int_status_reg;
+
+	u8 ram_reg;
+	u8 ram_size;
+
+	u8 temp_reg;
+
+	u8 trickle_reg;
+
+	u8 rst_reg;
+	u8 rst_bit;
+};
+
+struct max313xx_priv {
+	enum max313xx_ids id;
+	const struct chip_desc *chip;
+};
+
+static const struct chip_desc chip[MAX313XX_ID_NR] = {
+	[ID_MAX31328] = {
+		.int_en_reg = 0x0E,
+		.int_status_reg = 0x0F,
+		.sec_reg = 0x00,
+		.alarm1_sec_reg = 0x07,
+		.temp_reg = 0x11,
+	},
+	[ID_MAX31329] = {
+		.int_en_reg = 0x01,
+		.int_status_reg = 0x00,
+		.sec_reg = 0x06,
+		.alarm1_sec_reg = 0x0D,
+		.ram_reg = 0x22,
+		.ram_size = 64,
+		.trickle_reg = 0x19,
+		.rst_reg = 0x02,
+		.rst_bit = BIT(0),
+	},
+	[ID_MAX31331] = {
+		.int_en_reg = 0x01,
+		.int_status_reg = 0x00,
+		.sec_reg = 0x08,
+		.alarm1_sec_reg = 0x0F,
+		.ram_reg = 0x20,
+		.ram_size = 32,
+		.trickle_reg = 0x1B,
+		.rst_reg = 0x02,
+		.rst_bit = BIT(0),
+	},
+	[ID_MAX31334] = {
+		.int_en_reg = 0x01,
+		.int_status_reg = 0x00,
+		.sec_reg = 0x09,
+		.alarm1_sec_reg = 0x10,
+		.ram_reg = 0x30,
+		.ram_size = 32,
+		.trickle_reg = 0x1E,
+		.rst_reg = 0x02,
+		.rst_bit = BIT(0),
+	},
+	[ID_MAX31341] = {
+		.int_en_reg = 0x04,
+		.int_status_reg = 0x05,
+		.sec_reg = 0x06,
+		.alarm1_sec_reg = 0x0D,
+		.ram_reg = 0x16,
+		.ram_size = 64,
+		.trickle_reg = 0x57,
+		.rst_reg = 0x00,
+		.rst_bit = BIT(0),
+	},
+	[ID_MAX31342] = {
+		.int_en_reg = 0x04,
+		.int_status_reg = 0x05,
+		.sec_reg = 0x06,
+		.alarm1_sec_reg = 0x0D,
+		.rst_reg = 0x00,
+		.rst_bit = BIT(0),
+	},
+	[ID_MAX31343] = {
+		.int_en_reg = 0x01,
+		.int_status_reg = 0x00,
+		.sec_reg = 0x06,
+		.alarm1_sec_reg = 0x0D,
+		.ram_reg = 0x22,
+		.ram_size = 64,
+		.temp_reg = 0x1A,
+		.trickle_reg = 0x19,
+		.rst_reg = 0x02,
+		.rst_bit = BIT(0),
+	},
+};
+
+static const u32 max313xx_trickle_ohms[] = { 3000, 6000, 11000 };
+
+static int max313xx_set_bits(struct udevice *dev, unsigned int reg, unsigned int bits)
+{
+	int ret;
+
+	ret = dm_i2c_reg_read(dev, reg);
+	if (ret < 0)
+		return ret;
+
+	return dm_i2c_reg_write(dev, reg, ret | bits);
+}
+
+static int max313xx_clear_bits(struct udevice *dev, unsigned int reg, unsigned int bits)
+{
+	int ret;
+
+	ret = dm_i2c_reg_read(dev, reg);
+	if (ret < 0)
+		return ret;
+
+	return dm_i2c_reg_write(dev, reg, ret & ~bits);
+}
+
+static int max313xx_get_hour(u8 hour_reg)
+{
+	int hour;
+
+	/* 24Hr mode */
+	if (!FIELD_GET(MAX313XX_HRS_F_12_24, hour_reg))
+		return bcd2bin(hour_reg & 0x3f);
+
+	/* 12Hr mode */
+	hour = bcd2bin(hour_reg & 0x1f);
+	if (hour == 12)
+		hour = 0;
+
+	if (FIELD_GET(MAX313XX_HRS_F_AM_PM, hour_reg))
+		hour += 12;
+
+	return hour;
+}
+
+static int max313xx_read_time(struct udevice *dev, struct rtc_time *t)
+{
+	struct max313xx_priv *rtc = dev_get_priv(dev);
+	u8 regs[7];
+	int ret;
+
+	ret = dm_i2c_read(dev, rtc->chip->sec_reg, regs, 7);
+	if (ret)
+		return ret;
+
+	t->tm_sec = bcd2bin(regs[0] & 0x7f);
+	t->tm_min = bcd2bin(regs[1] & 0x7f);
+	t->tm_hour = max313xx_get_hour(regs[2]);
+	t->tm_wday = bcd2bin(regs[3] & 0x07) - 1;
+	t->tm_mday = bcd2bin(regs[4] & 0x3f);
+	t->tm_mon = bcd2bin(regs[5] & 0x1f);
+	t->tm_year = bcd2bin(regs[6]) + 2000;
+
+	if (FIELD_GET(MAX313XX_MONTH_CENTURY, regs[5]))
+		t->tm_year += 100;
+
+	dev_dbg(dev, "read %4d-%02d-%02d (wday=%d) %2d:%02d:%02d\n",
+		t->tm_year, t->tm_mon, t->tm_mday,
+		t->tm_wday, t->tm_hour, t->tm_min, t->tm_sec);
+
+	return 0;
+}
+
+static int max313xx_set_time(struct udevice *dev, const struct rtc_time *t)
+{
+	struct max313xx_priv *rtc = dev_get_priv(dev);
+	u8 regs[7];
+	int ret;
+
+	dev_dbg(dev, "set %4d-%02d-%02d (wday=%d) %2d:%02d:%02d\n",
+		t->tm_year, t->tm_mon, t->tm_mday,
+		t->tm_wday, t->tm_hour, t->tm_min, t->tm_sec);
+
+	if (t->tm_year < 2000) {
+		dev_err(dev, "year %d (before 2000) not supported\n",
+			t->tm_year);
+		return -EINVAL;
+	}
+
+	if (rtc->chip->rst_bit) {
+		ret = max313xx_clear_bits(dev, rtc->chip->rst_reg, rtc->chip->rst_bit);
+		if (ret)
+			return ret;
+	}
+
+	regs[0] = bin2bcd(t->tm_sec);
+	regs[1] = bin2bcd(t->tm_min);
+	regs[2] = bin2bcd(t->tm_hour);
+	regs[3] = bin2bcd(t->tm_wday + 1);
+	regs[4] = bin2bcd(t->tm_mday);
+	regs[5] = bin2bcd(t->tm_mon);
+	regs[6] = bin2bcd((t->tm_year - 2000) % 100);
+
+	if ((t->tm_year - 2000) >= 200)
+		regs[5] |= FIELD_PREP(MAX313XX_MONTH_CENTURY, 1);
+
+	ret = dm_i2c_write(dev, rtc->chip->sec_reg, regs, 7);
+	if (ret)
+		return ret;
+
+	switch (rtc->id) {
+	case ID_MAX31341:
+	case ID_MAX31342:
+		ret = max313xx_set_bits(dev, MAX3134X_CFG2_REG,
+					MAX3134X_CFG2_SET_RTC);
+		if (ret)
+			return ret;
+
+		udelay(10000);
+
+		ret = max313xx_clear_bits(dev, MAX3134X_CFG2_REG,
+					  MAX3134X_CFG2_SET_RTC);
+		if (ret)
+			return ret;
+
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static int max313xx_reset(struct udevice *dev)
+{
+	struct max313xx_priv *rtc = dev_get_priv(dev);
+	int ret = -EINVAL;
+
+	if (rtc->chip->rst_bit)
+		ret = max313xx_set_bits(dev, rtc->chip->rst_reg, rtc->chip->rst_bit);
+
+	return ret;
+}
+
+static const struct rtc_ops max3133x_rtc_ops = {
+	.get	= max313xx_read_time,
+	.set	= max313xx_set_time,
+	.reset  = max313xx_reset,
+};
+
+static int max313xx_init(struct udevice *dev)
+{
+	struct max313xx_priv *rtc = dev_get_priv(dev);
+	int ret;
+
+	switch (rtc->id) {
+	case ID_MAX31341:
+	case ID_MAX31342:
+		ret = max313xx_clear_bits(dev, MAX31341_42_CONFIG1_REG,
+					  MAX31341_42_CONFIG1_OSC_DISABLE);
+		if (ret)
+			return ret;
+
+		return max313xx_set_bits(dev, MAX31341_42_CONFIG1_REG,
+				       MAX31341_42_CONFIG1_SWRST);
+	default:
+		return 0;
+	}
+}
+
+static int max313xx_trickle_charger_setup(struct udevice *dev)
+{
+	struct max313xx_priv *rtc = dev_get_priv(dev);
+	bool diode;
+	int index, reg;
+	u32 ohms;
+	u32 chargeable;
+	int ret;
+
+	if (dev_read_u32(dev, "trickle-resistor-ohms", &ohms) ||
+	    dev_read_u32(dev, "aux-voltage-chargeable", &chargeable))
+		return 0;
+
+	switch (chargeable) {
+	case 0:
+		diode = false;
+		break;
+	case 1:
+		diode = true;
+		break;
+	default:
+		dev_dbg(dev, "unsupported aux-voltage-chargeable value\n");
+		return -EINVAL;
+	}
+
+	if (!rtc->chip->trickle_reg) {
+		dev_warn(dev, "device does not have trickle charger\n");
+		return -ENOTSUPP;
+	}
+
+	index = find_closest(ohms, max313xx_trickle_ohms,
+			     ARRAY_SIZE(max313xx_trickle_ohms)) + 1;
+
+	switch (rtc->id) {
+	case ID_MAX31329:
+		reg = FIELD_PREP(MAX31329_TRICKLE_ENABLE_BIT, 1) |
+		      FIELD_PREP(MAX31329_43_TRICKLE_RES_MASK, index) |
+		      FIELD_PREP(MAX31329_43_TRICKLE_DIODE_EN, diode);
+		break;
+	case ID_MAX31331:
+	case ID_MAX31334:
+		reg = FIELD_PREP(MAX3133X_TRICKLE_ENABLE_BIT, 1) |
+		      FIELD_PREP(MAX3133X_TRICKLE_DIODE_EN, diode) |
+		      FIELD_PREP(MAX3133X_TRICKLE_RES_MASK, index);
+		break;
+	case ID_MAX31341:
+		if (index == 1)
+			index = 0;
+		reg = FIELD_PREP(MAX31341_TRICKLE_ENABLE_BIT, 1) |
+		      FIELD_PREP(MAX31341_TRICKLE_DIODE_EN, diode) |
+		      FIELD_PREP(MAX31341_TRICKLE_RES_MASK, index);
+
+		ret = max313xx_set_bits(dev, MAX31341_POWER_MGMT_REG,
+					MAX31341_POWER_MGMT_TRICKLE_BIT);
+		if (ret)
+			return ret;
+
+		break;
+	case ID_MAX31343:
+		reg = FIELD_PREP(MAX31329_43_TRICKLE_RES_MASK, index) |
+		      FIELD_PREP(MAX31329_43_TRICKLE_DIODE_EN, diode) |
+		      FIELD_PREP(MAX31343_TRICKLE_ENABLE_MASK,
+				 MAX31343_TRICKLE_ENABLE_CODE);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return dm_i2c_reg_write(dev, rtc->chip->trickle_reg, reg);
+}
+
+static int max313xx_probe(struct udevice *dev)
+{
+	struct max313xx_priv *max313xx = dev_get_priv(dev);
+	int ret;
+
+	max313xx->id = dev_get_driver_data(dev);
+	max313xx->chip = &chip[max313xx->id];
+
+	ret = max313xx_init(dev);
+	if (ret)
+		return ret;
+
+	return max313xx_trickle_charger_setup(dev);
+}
+
+static const struct udevice_id max313xx_of_id[] = {
+	{ .compatible = "adi,max31328", .data = ID_MAX31328 },
+	{ .compatible = "adi,max31329", .data = ID_MAX31329 },
+	{ .compatible = "adi,max31331", .data = ID_MAX31331 },
+	{ .compatible = "adi,max31334", .data = ID_MAX31334 },
+	{ .compatible = "adi,max31341", .data = ID_MAX31341 },
+	{ .compatible = "adi,max31342", .data = ID_MAX31342 },
+	{ .compatible = "adi,max31343", .data = ID_MAX31343 },
+	{ }
+};
+
+U_BOOT_DRIVER(rtc_max313xx) = {
+	.name	= "rtc-max313xx",
+	.id     = UCLASS_RTC,
+	.probe  = max313xx_probe,
+	.of_match = max313xx_of_id,
+	.priv_auto = sizeof(struct max313xx_priv),
+	.ops    = &max3133x_rtc_ops,
+};
diff --git a/drivers/sysinfo/gpio.c b/drivers/sysinfo/gpio.c
index 1d7f050..82f9030 100644
--- a/drivers/sysinfo/gpio.c
+++ b/drivers/sysinfo/gpio.c
@@ -57,7 +57,7 @@
 		int i, ret;
 		u32 revision;
 
-		for (i = 0; i < priv->gpio_num; i++) {
+		for (i = 0; ; i++) {
 			ret = dev_read_u32_index(dev, "revisions", i,
 						 &revision);
 			if (ret) {
@@ -80,7 +80,8 @@
 		strncpy(val, name, size);
 		val[size - 1] = '\0';
 		return 0;
-	} default:
+	}
+	default:
 		return -EINVAL;
 	};
 }
diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c
index f22af45..ea4c5d4 100644
--- a/fs/ext4/ext4_write.c
+++ b/fs/ext4/ext4_write.c
@@ -473,7 +473,7 @@
 	 * special case for symlinks whose target are small enough that
 	 *it fits in struct ext2_inode.b.symlink: no block had been allocated
 	 */
-	if ((le16_to_cpu(inode.mode) & S_IFLNK) &&
+	if (S_ISLNK(le16_to_cpu(inode.mode)) &&
 	    le32_to_cpu(inode.size) <= sizeof(inode.b.symlink)) {
 		no_blocks = 0;
 	}
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 00541eb..413fc43 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -141,6 +141,8 @@
 	if (!strcmp(buf, filename)) {
 		ret = 1;
 		goto out;
+	} else if (!strcasecmp(buf, filename)) {
+		goto out_ret;
 	}
 
 	/* Construct an indexed short name */
@@ -177,12 +179,13 @@
 		if (find_directory_entry(itr, buf))
 			continue;
 
-		debug("chosen short name: %s\n", buf);
-		/* Each long name directory entry takes 13 characters. */
-		ret = (strlen(filename) + 25) / 13;
-		goto out;
+		goto out_ret;
 	}
 	return -EIO;
+out_ret:
+	debug("chosen short name: %s\n", buf);
+	/* Each long name directory entry takes 13 characters. */
+	ret = (strlen(filename) + 25) / 13;
 out:
 	memcpy(shortname, &dirent, SHORT_NAME_SIZE);
 	return ret;
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index dd0bdf2..c4a7fd2 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -580,7 +580,8 @@
  * This allows boards to implement common behaviours using GPIOs while not
  * requiring specific GPIO offsets be used.
  *
- * @dev:	An instance of a GPIO controller udevice
+ * @dev:        An instance of a GPIO controller udevice, or NULL to search
+ *              all GPIO controller devices
  * @line_name:	The name of the GPIO (e.g. "bmc-secure-boot")
  * @desc:	A GPIO descriptor that is populated with the requested GPIO
  *              upon return
diff --git a/include/command.h b/include/command.h
index 1b018cb..c4e3170 100644
--- a/include/command.h
+++ b/include/command.h
@@ -13,6 +13,8 @@
 #include <env.h>
 #include <linker_lists.h>
 
+#include <linux/compiler_attributes.h>
+
 #ifndef NULL
 #define NULL	0
 #endif
@@ -260,12 +262,17 @@
 /**
  * run_commandf() - Run a command created by a format string
  *
- * The command cannot be larger than 127 characters
- *
  * @fmt: printf() format string
  * @...: Arguments to use (flag is always 0)
+ *
+ * The command cannot be larger than (CONFIG_SYS_CBSIZE - 1) characters.
+ *
+ * Return:
+ * Returns 0 on success, -EIO if internal output error occurred, -ENOSPC in
+ *	case of 'fmt' string truncation, or != 0 on error, specific for
+ *	run_command().
  */
-int run_commandf(const char *fmt, ...);
+int run_commandf(const char *fmt, ...) __printf(1, 2);
 
 /**
  * Run a list of commands separated by ; or even \0
diff --git a/include/configs/am62ax_evm.h b/include/configs/am62ax_evm.h
index a18b157..d8ef250 100644
--- a/include/configs/am62ax_evm.h
+++ b/include/configs/am62ax_evm.h
@@ -85,9 +85,6 @@
 
 /* Incorporate settings into the U-Boot environment */
 #define CFG_EXTRA_ENV_SETTINGS					\
-	DEFAULT_LINUX_BOOT_ENV						\
-	DEFAULT_FIT_TI_ARGS						\
-	EXTRA_ENV_AM62A7_BOARD_SETTINGS					\
 	BOOTENV
 
 /* Now for the remaining common defines */
diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h
index 33dd6cf..c549573 100644
--- a/include/configs/am65x_evm.h
+++ b/include/configs/am65x_evm.h
@@ -17,66 +17,6 @@
 /* DDR Configuration */
 #define CFG_SYS_SDRAM_BASE1		0x880000000
 
-#define PARTS_DEFAULT \
-	/* Linux partitions */ \
-	"name=rootfs,start=0,size=-,uuid=${uuid_gpt_rootfs}\0"
-
-/* U-Boot general configuration */
-#define EXTRA_ENV_AM65X_BOARD_SETTINGS					\
-	"findfdt="							\
-		"setenv name_fdt k3-am654-base-board.dtb;"		\
-		"setenv fdtfile ${name_fdt}\0"				\
-	"name_kern=Image\0"						\
-	"console=ttyS2,115200n8\0"					\
-	"stdin=serial,usbkbd\0"						\
-	"args_all=setenv optargs earlycon=ns16550a,mmio32,0x02800000 "  \
-		"${mtdparts}\0"						\
-	"run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr}\0"		\
-
-/* U-Boot MMC-specific configuration */
-#define EXTRA_ENV_AM65X_BOARD_SETTINGS_MMC				\
-	"boot=mmc\0"							\
-	"mmcdev=1\0"							\
-	"bootpart=1:2\0"						\
-	"bootdir=/boot\0"						\
-	"rd_spec=-\0"							\
-	"init_mmc=run args_all args_mmc\0"				\
-	"get_fdt_mmc=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${name_fdt}\0" \
-	"get_overlay_mmc="						\
-		"fdt address ${fdtaddr};"				\
-		"fdt resize 0x100000;"					\
-		"for overlay in $name_overlays;"			\
-		"do;"							\
-		"load mmc ${bootpart} ${dtboaddr} ${bootdir}/${overlay};"	\
-		"fdt apply ${dtboaddr};"				\
-		"done;\0"						\
-	"get_kern_mmc=load mmc ${bootpart} ${loadaddr} "		\
-		"${bootdir}/${name_kern}\0"				\
-	"get_fit_mmc=load mmc ${bootpart} ${addr_fit} "			\
-		"${bootdir}/${name_fit}\0"				\
-	"partitions=" PARTS_DEFAULT
-
-#ifdef DEFAULT_RPROCS
-#undef DEFAULT_RPROCS
-#endif
-#define DEFAULT_RPROCS	""						\
-		"0 /lib/firmware/am65x-mcu-r5f0_0-fw "			\
-		"1 /lib/firmware/am65x-mcu-r5f0_1-fw "
-
-#define EXTRA_ENV_AM65X_BOARD_SETTINGS_UBI				\
-	"init_ubi=run args_all args_ubi; sf probe; "			\
-		"ubi part ospi.rootfs; ubifsmount ubi:rootfs;\0"	\
-	"get_kern_ubi=ubifsload ${loadaddr} ${bootdir}/${name_kern}\0"	\
-	"get_fdt_ubi=ubifsload ${fdtaddr} ${bootdir}/${name_fdt}\0"	\
-	"args_ubi=setenv bootargs console=${console} ${optargs} "	\
-		"rootfstype=ubifs root=ubi0:rootfs rw ubi.mtd=ospi.rootfs\0"
-
-#define EXTRA_ENV_DFUARGS						\
-	DFU_ALT_INFO_MMC						\
-	DFU_ALT_INFO_RAM						\
-	DFU_ALT_INFO_EMMC						\
-	DFU_ALT_INFO_OSPI
-
 #ifdef CONFIG_TARGET_AM654_A53_EVM
 #define BOOT_TARGET_DEVICES(func) \
 	func(MMC, mmc, 1) \
@@ -89,14 +29,6 @@
 
 /* Incorporate settings into the U-Boot environment */
 #define CFG_EXTRA_ENV_SETTINGS					\
-	DEFAULT_LINUX_BOOT_ENV						\
-	DEFAULT_MMC_TI_ARGS						\
-	DEFAULT_FIT_TI_ARGS						\
-	EXTRA_ENV_AM65X_BOARD_SETTINGS					\
-	EXTRA_ENV_AM65X_BOARD_SETTINGS_MMC				\
-	EXTRA_ENV_AM65X_BOARD_SETTINGS_UBI				\
-	EXTRA_ENV_RPROC_SETTINGS					\
-	EXTRA_ENV_DFUARGS						\
 	BOOTENV
 
 /* Now for the remaining common defines */
diff --git a/include/configs/iot2050.h b/include/configs/iot2050.h
index cfff46c..82174b8 100644
--- a/include/configs/iot2050.h
+++ b/include/configs/iot2050.h
@@ -13,12 +13,6 @@
 
 #include <linux/sizes.h>
 
-/* SPL Loader Configuration */
-
-/* U-Boot general configuration */
-#define EXTRA_ENV_IOT2050_BOARD_SETTINGS				\
-	"usb_pgood_delay=900\0"
-
 #if IS_ENABLED(CONFIG_CMD_USB)
 # define BOOT_TARGET_USB(func) \
 	func(USB, usb, 0) \
@@ -40,11 +34,18 @@
 
 #include <config_distro_bootcmd.h>
 
-#define CFG_EXTRA_ENV_SETTINGS					\
+#define CFG_EXTRA_ENV_SETTINGS						\
 	DEFAULT_LINUX_BOOT_ENV						\
-	BOOTENV								\
-	EXTRA_ENV_IOT2050_BOARD_SETTINGS
+	BOOTENV
 
 #include <configs/ti_armv7_common.h>
 
+#ifdef CONFIG_ENV_WRITEABLE_LIST
+#define CFG_ENV_FLAGS_LIST_STATIC					\
+	"board_uuid:sw,board_name:sw,board_serial:sw,board_a5e:sw,"	\
+	"mlfb:sw,fw_version:sw,seboot_version:sw,"			\
+	"m2_manuel_config:sw,"						\
+	"eth1addr:mw,eth2addr:mw,watchdog_timeout_ms:dw,boot_targets:sw"
+#endif
+
 #endif /* __CONFIG_IOT2050_H */
diff --git a/include/configs/j721e_evm.h b/include/configs/j721e_evm.h
index 48b1cea..de92cd4 100644
--- a/include/configs/j721e_evm.h
+++ b/include/configs/j721e_evm.h
@@ -10,10 +10,6 @@
 #define __CONFIG_J721E_EVM_H
 
 #include <linux/sizes.h>
-#include <environment/ti/mmc.h>
-#include <environment/ti/k3_rproc.h>
-#include <environment/ti/ufs.h>
-#include <environment/ti/k3_dfu.h>
 
 /* DDR Configuration */
 #define CFG_SYS_SDRAM_BASE1		0x880000000
@@ -28,127 +24,6 @@
 #define CFG_SYS_UBOOT_BASE		0x50080000
 #endif
 
-/* HyperFlash related configuration */
-
-/* U-Boot general configuration */
-#define EXTRA_ENV_J721E_BOARD_SETTINGS					\
-	"default_device_tree=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0"	\
-	"findfdt="							\
-		"setenv name_fdt ${default_device_tree};"		\
-		"if test $board_name = j721e; then "			\
-			"setenv name_fdt k3-j721e-common-proc-board.dtb; fi;" \
-		"if test $board_name = j721e-eaik || test $board_name = j721e-sk; then "		\
-			"setenv name_fdt k3-j721e-sk.dtb; fi;"	\
-		"setenv fdtfile ${name_fdt}\0"				\
-	"name_kern=Image\0"						\
-	"console=ttyS2,115200n8\0"					\
-	"args_all=setenv optargs earlycon=ns16550a,mmio32,0x02800000 "	\
-		"${mtdparts}\0"						\
-	"run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr}\0"
-
-#define PARTS_DEFAULT \
-	/* Linux partitions */ \
-	"uuid_disk=${uuid_gpt_disk};" \
-	"name=rootfs,start=0,size=-,uuid=${uuid_gpt_rootfs}\0"
-
-#ifdef CONFIG_SYS_K3_SPL_ATF
-#if defined(CONFIG_TARGET_J721E_R5_EVM)
-#define EXTRA_ENV_R5_SPL_RPROC_FW_ARGS_MMC				\
-	"addr_mcur5f0_0load=0x89000000\0"				\
-	"name_mcur5f0_0fw=/lib/firmware/j7-mcu-r5f0_0-fw\0"
-#elif defined(CONFIG_TARGET_J7200_R5_EVM)
-#define EXTRA_ENV_R5_SPL_RPROC_FW_ARGS_MMC				\
-	"addr_mcur5f0_0load=0x89000000\0"				\
-	"name_mcur5f0_0fw=/lib/firmware/j7200-mcu-r5f0_0-fw\0"
-#endif /* CONFIG_TARGET_J721E_R5_EVM */
-#else
-#define EXTRA_ENV_R5_SPL_RPROC_FW_ARGS_MMC ""
-#endif /* CONFIG_SYS_K3_SPL_ATF */
-
-/* U-Boot MMC-specific configuration */
-#define EXTRA_ENV_J721E_BOARD_SETTINGS_MMC				\
-	"boot=mmc\0"							\
-	"mmcdev=1\0"							\
-	"bootpart=1:2\0"						\
-	"bootdir=/boot\0"						\
-	EXTRA_ENV_R5_SPL_RPROC_FW_ARGS_MMC				\
-	"rd_spec=-\0"							\
-	"init_mmc=run args_all args_mmc\0"				\
-	"get_fdt_mmc=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${name_fdt}\0" \
-	"get_overlay_mmc="						\
-		"fdt address ${fdtaddr};"				\
-		"fdt resize 0x100000;"					\
-		"for overlay in $name_overlays;"			\
-		"do;"							\
-		"load mmc ${bootpart} ${dtboaddr} ${bootdir}/${overlay} && "	\
-		"fdt apply ${dtboaddr};"				\
-		"done;\0"						\
-	"partitions=" PARTS_DEFAULT					\
-	"get_kern_mmc=load mmc ${bootpart} ${loadaddr} "		\
-		"${bootdir}/${name_kern}\0"				\
-	"get_fit_mmc=load mmc ${bootpart} ${addr_fit} "			\
-		"${bootdir}/${name_fit}\0"				\
-	"partitions=" PARTS_DEFAULT
-
-/* Set the default list of remote processors to boot */
-#if defined(CONFIG_TARGET_J7200_A72_EVM)
-#define EXTRA_ENV_CONFIG_MAIN_CPSW0_QSGMII_PHY				\
-	"do_main_cpsw0_qsgmii_phyinit=1\0"				\
-	"init_main_cpsw0_qsgmii_phy=gpio set gpio@22_17;"		\
-		 "gpio clear gpio@22_16\0"				\
-	"main_cpsw0_qsgmii_phyinit="					\
-	"if test ${do_main_cpsw0_qsgmii_phyinit} -eq 1 && test ${dorprocboot} -eq 1 && " \
-			"test ${boot} = mmc; then "			\
-		"run init_main_cpsw0_qsgmii_phy;"			\
-	"fi;\0"
-#ifdef DEFAULT_RPROCS
-#undef DEFAULT_RPROCS
-#endif
-#elif defined(CONFIG_TARGET_J721E_A72_EVM)
-#define EXTRA_ENV_CONFIG_MAIN_CPSW0_QSGMII_PHY				\
-	"init_main_cpsw0_qsgmii_phy=gpio set gpio@22_17;"		\
-		 "gpio clear gpio@22_16\0"				\
-	"main_cpsw0_qsgmii_phyinit="					\
-	"if test $board_name = J721EX-PM1-SOM || test $board_name = J721EX-PM2-SOM " \
-	"|| test $board_name = j721e; then " \
-	"do_main_cpsw0_qsgmii_phyinit=1; else "			\
-	"do_main_cpsw0_qsgmii_phyinit=0; fi;"			\
-	"if test ${do_main_cpsw0_qsgmii_phyinit} -eq 1 && test ${dorprocboot} -eq 1 && " \
-			"test ${boot} = mmc; then "			\
-		"run init_main_cpsw0_qsgmii_phy;"			\
-	"fi;\0"
-#ifdef DEFAULT_RPROCS
-#undef DEFAULT_RPROCS
-#endif
-#endif
-
-#ifdef CONFIG_TARGET_J721E_A72_EVM
-#define DEFAULT_RPROCS	""						\
-		"2 /lib/firmware/j7-main-r5f0_0-fw "			\
-		"3 /lib/firmware/j7-main-r5f0_1-fw "			\
-		"4 /lib/firmware/j7-main-r5f1_0-fw "			\
-		"5 /lib/firmware/j7-main-r5f1_1-fw "			\
-		"6 /lib/firmware/j7-c66_0-fw "				\
-		"7 /lib/firmware/j7-c66_1-fw "				\
-		"8 /lib/firmware/j7-c71_0-fw "
-#endif /* CONFIG_TARGET_J721E_A72_EVM */
-
-#ifdef CONFIG_TARGET_J7200_A72_EVM
-#define DEFAULT_RPROCS ""						\
-		"2 /lib/firmware/j7200-main-r5f0_0-fw "			\
-		"3 /lib/firmware/j7200-main-r5f0_1-fw "
-#endif /* CONFIG_TARGET_J7200_A72_EVM */
-
-#ifndef EXTRA_ENV_CONFIG_MAIN_CPSW0_QSGMII_PHY
-#define EXTRA_ENV_CONFIG_MAIN_CPSW0_QSGMII_PHY
-#endif
-
-#define EXTRA_ENV_DFUARGS \
-	DFU_ALT_INFO_MMC \
-	DFU_ALT_INFO_EMMC \
-	DFU_ALT_INFO_RAM \
-	DFU_ALT_INFO_OSPI
-
 #if CONFIG_IS_ENABLED(CMD_PXE)
 # define BOOT_TARGET_PXE(func) func(PXE, pxe, na)
 #else
@@ -178,15 +53,6 @@
 
 /* Incorporate settings into the U-Boot environment */
 #define CFG_EXTRA_ENV_SETTINGS					\
-	DEFAULT_LINUX_BOOT_ENV						\
-	DEFAULT_MMC_TI_ARGS						\
-	DEFAULT_FIT_TI_ARGS						\
-	EXTRA_ENV_J721E_BOARD_SETTINGS					\
-	EXTRA_ENV_J721E_BOARD_SETTINGS_MMC				\
-	EXTRA_ENV_RPROC_SETTINGS					\
-	EXTRA_ENV_DFUARGS						\
-	DEFAULT_UFS_TI_ARGS						\
-	EXTRA_ENV_CONFIG_MAIN_CPSW0_QSGMII_PHY				\
 	BOOTENV
 
 /* Now for the remaining common defines */
diff --git a/include/configs/j721s2_evm.h b/include/configs/j721s2_evm.h
index bfada9e..2fa93b7 100644
--- a/include/configs/j721s2_evm.h
+++ b/include/configs/j721s2_evm.h
@@ -11,10 +11,6 @@
 
 #include <linux/sizes.h>
 #include <config_distro_bootcmd.h>
-#include <environment/ti/mmc.h>
-#include <environment/ti/k3_rproc.h>
-#include <environment/ti/ufs.h>
-#include <environment/ti/k3_dfu.h>
 
 /* DDR Configuration */
 #define CFG_SYS_SDRAM_BASE1		0x880000000
@@ -27,120 +23,8 @@
 #define CFG_SYS_UBOOT_BASE		0x50080000
 #endif
 
-/* U-Boot general configuration */
-#define EXTRA_ENV_J721S2_BOARD_SETTINGS					\
-	"default_device_tree=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0"	\
-	"findfdt="							\
-		"setenv name_fdt ${default_device_tree};"		\
-		"if test $board_name = j721s2; then "			\
-			"setenv name_fdt k3-j721s2-common-proc-board.dtb; fi;" \
-		"if test $board_name = am68-sk; then "			\
-			"setenv name_fdt k3-am68-sk-base-board.dtb; fi;"\
-		"setenv fdtfile ${name_fdt}\0"				\
-	"name_kern=Image\0"						\
-	"console=ttyS2,115200n8\0"					\
-	"args_all=setenv optargs earlycon=ns16550a,mmio32,0x02880000 "	\
-		"${mtdparts}\0"						\
-	"run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr}\0"
-
-#define PARTS_DEFAULT \
-	/* Linux partitions */ \
-	"uuid_disk=${uuid_gpt_disk};" \
-	"name=rootfs,start=0,size=-,uuid=${uuid_gpt_rootfs}\0"
-
-#ifdef CONFIG_SYS_K3_SPL_ATF
-#if defined(CONFIG_TARGET_J721S2_R5_EVM)
-#define EXTRA_ENV_R5_SPL_RPROC_FW_ARGS_MMC				\
-	"addr_mcur5f0_0load=0x89000000\0"				\
-	"name_mcur5f0_0fw=/lib/firmware/j7-mcu-r5f0_0-fw\0"
-#elif defined(CONFIG_TARGET_J7200_R5_EVM)
-#define EXTRA_ENV_R5_SPL_RPROC_FW_ARGS_MMC				\
-	"addr_mcur5f0_0load=0x89000000\0"				\
-	"name_mcur5f0_0fw=/lib/firmware/j7200-mcu-r5f0_0-fw\0"
-#endif /* CONFIG_TARGET_J721S2_R5_EVM */
-#else
-#define EXTRA_ENV_R5_SPL_RPROC_FW_ARGS_MMC ""
-#endif /* CONFIG_SYS_K3_SPL_ATF */
-
-/* U-Boot MMC-specific configuration */
-#define EXTRA_ENV_J721S2_BOARD_SETTINGS_MMC				\
-	"boot=mmc\0"							\
-	"mmcdev=1\0"							\
-	"bootpart=1:2\0"						\
-	"bootdir=/boot\0"						\
-	EXTRA_ENV_R5_SPL_RPROC_FW_ARGS_MMC				\
-	"rd_spec=-\0"							\
-	"init_mmc=run args_all args_mmc\0"				\
-	"get_fdt_mmc=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${name_fdt}\0" \
-	"get_overlay_mmc="						\
-		"fdt address ${fdtaddr};"				\
-		"fdt resize 0x100000;"					\
-		"for overlay in $name_overlays;"			\
-		"do;"							\
-		"load mmc ${bootpart} ${dtboaddr} ${bootdir}/${overlay} && "	\
-		"fdt apply ${dtboaddr};"				\
-		"done;\0"						\
-	"partitions=" PARTS_DEFAULT					\
-	"get_kern_mmc=load mmc ${bootpart} ${loadaddr} "		\
-		"${bootdir}/${name_kern}\0"				\
-	"get_fit_mmc=load mmc ${bootpart} ${addr_fit} "			\
-		"${bootdir}/${name_fit}\0"				\
-	"partitions=" PARTS_DEFAULT
-
-/* Set the default list of remote processors to boot */
-#if defined(CONFIG_TARGET_J721S2_A72_EVM) || defined(CONFIG_TARGET_J7200_A72_EVM)
-#ifdef DEFAULT_RPROCS
-#undef DEFAULT_RPROCS
-#endif
-#endif
-
-#ifdef CONFIG_TARGET_J721S2_A72_EVM
-#define DEFAULT_RPROCS	""						\
-		"2 /lib/firmware/j721s2-main-r5f0_0-fw "			\
-		"3 /lib/firmware/j721s2-main-r5f0_1-fw "			\
-		"4 /lib/firmware/j721s2-main-r5f1_0-fw "			\
-		"5 /lib/firmware/j721s2-main-r5f1_1-fw "			\
-		"6 /lib/firmware/j721s2-c71_0-fw "				\
-		"7 /lib/firmware/j721s2-c71_1-fw "
-#endif /* CONFIG_TARGET_J721S2_A72_EVM */
-
-#ifdef CONFIG_TARGET_J7200_A72_EVM
-#define EXTRA_ENV_CONFIG_MAIN_CPSW0_QSGMII_PHY				\
-	"do_main_cpsw0_qsgmii_phyinit=1\0"				\
-	"init_main_cpsw0_qsgmii_phy=gpio set gpio@22_17;"		\
-		 "gpio clear gpio@22_16\0"				\
-	"main_cpsw0_qsgmii_phyinit="					\
-	"if test ${do_main_cpsw0_qsgmii_phyinit} -eq 1 && test ${dorprocboot} -eq 1 && " \
-			"test ${boot} = mmc; then "			\
-		"run init_main_cpsw0_qsgmii_phy;"			\
-	"fi;\0"
-#define DEFAULT_RPROCS ""						\
-		"2 /lib/firmware/j7200-main-r5f0_0-fw "			\
-		"3 /lib/firmware/j7200-main-r5f0_1-fw "
-#endif /* CONFIG_TARGET_J7200_A72_EVM */
-
-#ifndef EXTRA_ENV_CONFIG_MAIN_CPSW0_QSGMII_PHY
-#define EXTRA_ENV_CONFIG_MAIN_CPSW0_QSGMII_PHY
-#endif
-
-/* set default dfu_bufsiz to 128KB (sector size of OSPI) */
-#define EXTRA_ENV_DFUARGS \
-	DFU_ALT_INFO_MMC \
-	DFU_ALT_INFO_EMMC \
-	DFU_ALT_INFO_RAM \
-	DFU_ALT_INFO_OSPI
-
 /* Incorporate settings into the U-Boot environment */
-#define CFG_EXTRA_ENV_SETTINGS					\
-	DEFAULT_LINUX_BOOT_ENV						\
-	DEFAULT_MMC_TI_ARGS						\
-	DEFAULT_FIT_TI_ARGS						\
-	EXTRA_ENV_J721S2_BOARD_SETTINGS					\
-	EXTRA_ENV_J721S2_BOARD_SETTINGS_MMC				\
-	EXTRA_ENV_RPROC_SETTINGS					\
-	EXTRA_ENV_DFUARGS						\
-	DEFAULT_UFS_TI_ARGS						\
-	EXTRA_ENV_CONFIG_MAIN_CPSW0_QSGMII_PHY
+#define CFG_EXTRA_ENV_SETTINGS
 
 /* Now for the remaining common defines */
 #include <configs/ti_armv7_common.h>
diff --git a/include/environment/ti/k3_dfu.env b/include/environment/ti/k3_dfu.env
new file mode 100644
index 0000000..2015296
--- /dev/null
+++ b/include/environment/ti/k3_dfu.env
@@ -0,0 +1,30 @@
+dfu_alt_info_mmc=
+	boot part 1 1;
+	rootfs part 1 2;
+	tiboot3.bin fat 1 1;
+	tispl.bin fat 1 1;
+	u-boot.img fat 1 1;
+	uEnv.txt fat 1 1;
+	sysfw.itb fat 1 1
+
+dfu_alt_info_emmc=
+	rawemmc raw 0 0x800000 mmcpart 1;
+	rootfs part 0 1 mmcpart 0;
+	tiboot3.bin.raw raw 0x0 0x400 mmcpart 1;
+	tispl.bin.raw raw 0x400 0x1000 mmcpart 1;
+	u-boot.img.raw raw 0x1400 0x2000 mmcpart 1;
+	u-env.raw raw 0x3400 0x100 mmcpart 1;
+	sysfw.itb.raw raw 0x3600 0x800 mmcpart 1
+
+dfu_alt_info_ospi=
+	tiboot3.bin raw 0x0 0x080000;
+	tispl.bin raw 0x080000 0x200000;
+	u-boot.img raw 0x280000 0x400000;
+	u-boot-env raw 0x680000 0x020000;
+	sysfw.itb raw 0x6c0000 0x100000;
+	rootfs raw 0x800000 0x3800000
+
+dfu_alt_info_ram=
+	tispl.bin ram 0x80080000 0x200000;
+	u-boot.img ram 0x81000000 0x400000
+
diff --git a/include/environment/ti/k3_rproc.env b/include/environment/ti/k3_rproc.env
new file mode 100644
index 0000000..21dad7b
--- /dev/null
+++ b/include/environment/ti/k3_rproc.env
@@ -0,0 +1,26 @@
+dorprocboot=0
+boot_rprocs=
+	if test ${dorprocboot} -eq 1 && test ${boot} = mmc; then
+			rproc init;
+			run boot_rprocs_mmc;
+		fi;
+rproc_load_and_boot_one=
+	if load mmc ${bootpart} $loadaddr ${rproc_fw}; then
+		if rproc load ${rproc_id} ${loadaddr} ${filesize}; then
+			rproc start ${rproc_id}
+		fi;
+	fi
+boot_rprocs_mmc=
+	env set rproc_id;
+	env set rproc_fw;
+	for i in ${rproc_fw_binaries} ; do
+		if test -z ${rproc_id} ; then
+			env set rproc_id $i;
+		else
+			env set rproc_fw $i;
+			run rproc_load_and_boot_one;
+			env set rproc_id;
+			env set rproc_fw;
+		fi;
+	done
+
diff --git a/include/environment/ti/mmc.env b/include/environment/ti/mmc.env
new file mode 100644
index 0000000..5677d05
--- /dev/null
+++ b/include/environment/ti/mmc.env
@@ -0,0 +1,61 @@
+mmcdev=0
+mmcrootfstype=ext4 rootwait
+finduuid=part uuid ${boot} ${bootpart} uuid
+args_mmc=run finduuid;setenv bootargs console=${console}
+	${optargs}
+	root=PARTUUID=${uuid} rw
+	rootfstype=${mmcrootfstype}
+loadbootscript=load mmc ${mmcdev} ${loadaddr} boot.scr
+bootscript=echo Running bootscript from mmc${mmcdev} ...;
+	source ${loadaddr}
+bootenvfile=uEnv.txt
+importbootenv=echo Importing environment from mmc${mmcdev} ...;
+	env import -t ${loadaddr} ${filesize}
+loadbootenv=fatload mmc ${mmcdev} ${loadaddr} ${bootenvfile}
+loadimage=load ${devtype} ${bootpart} ${loadaddr} ${bootdir}/${bootfile}
+loadfdt=load ${devtype} ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}
+envboot=mmc dev ${mmcdev};
+	if mmc rescan; then
+		echo SD/MMC found on device ${mmcdev};
+		if run loadbootscript; then
+			run bootscript;
+		else
+			if run loadbootenv; then
+				echo Loaded env from ${bootenvfile};
+				run importbootenv;
+			fi;
+			if test -n $uenvcmd; then
+				echo Running uenvcmd ...;
+				run uenvcmd;
+			fi;
+		fi;
+	fi;
+mmcloados=
+	if test ${boot_fdt} = yes || test ${boot_fdt} = try; then
+		if run loadfdt; then
+			bootz ${loadaddr} - ${fdtaddr};
+		else
+			if test ${boot_fdt} = try; then
+				bootz;
+			else
+				echo WARN: Cannot load the DT;
+				fi;
+		fi;
+	else
+		bootz;
+	fi;
+mmcboot=mmc dev ${mmcdev};
+	devnum=${mmcdev};
+	devtype=mmc;
+	if mmc rescan; then
+		echo SD/MMC found on device ${mmcdev};
+		if run loadimage; then
+			run args_mmc;
+			if test ${boot_fit} -eq 1; then
+				run run_fit;
+			else
+				run mmcloados;
+			fi;
+		fi;
+fi;
+
diff --git a/include/environment/ti/nand.env b/include/environment/ti/nand.env
new file mode 100644
index 0000000..4e185c1
--- /dev/null
+++ b/include/environment/ti/nand.env
@@ -0,0 +1,14 @@
+mtdids=nor0=47040000.spi.0,nor0=47034000.hyperbus
+mtdparts=mtdparts=47040000.spi.0:512k(ospi.tiboot3),2m(ospi.tispl),4m(ospi.u-boot),256k(ospi.env),256k(ospi.env.backup),57088k@8m(ospi.rootfs),256k(ospi.phypattern);47034000.hyperbus:512k(hbmc.tiboot3),2m(hbmc.tispl),4m(hbmc.u-boot),256k(hbmc.env),-@8m(hbmc.rootfs)
+nandargs=setenv bootargs console=${console}
+	${optargs}
+	root=${nandroot}
+	rootfstype=${nandrootfstype}
+nandroot=ubi0:rootfs rw ubi.mtd=NAND.file-system,2048
+nandrootfstype=ubifs rootwait
+nandboot=echo Booting from nand ...;
+	run nandargs;
+	nand read ${fdtaddr} NAND.u-boot-spl-os;
+	nand read ${loadaddr} NAND.kernel;
+	bootz ${loadaddr} - ${fdtaddr}
+
diff --git a/include/environment/ti/ti_armv7_common.env b/include/environment/ti/ti_armv7_common.env
new file mode 100644
index 0000000..4d33464
--- /dev/null
+++ b/include/environment/ti/ti_armv7_common.env
@@ -0,0 +1,24 @@
+loadaddr=0x82000000
+kernel_addr_r=0x82000000
+fdtaddr=0x88000000
+dtboaddr=0x89000000
+fdt_addr_r=0x88000000
+fdtoverlay_addr_r=0x89000000
+rdaddr=0x88080000
+ramdisk_addr_r=0x88080000
+scriptaddr=0x80000000
+pxefile_addr_r=0x80100000
+bootm_size=0x10000000
+boot_fdt=try
+
+boot_fit=0
+addr_fit=0x90000000
+name_fit=fitImage
+update_to_fit=setenv loadaddr ${addr_fit}; setenv bootfile ${name_fit}
+get_overlaystring=
+	for overlay in $name_overlays;
+	do;
+	setenv overlaystring ${overlaystring}'#'${overlay};
+	done;
+run_fit=bootm ${addr_fit}#conf-${fdtfile}${overlaystring}
+
diff --git a/include/environment/ti/ufs.env b/include/environment/ti/ufs.env
new file mode 100644
index 0000000..509a87b
--- /dev/null
+++ b/include/environment/ti/ufs.env
@@ -0,0 +1,22 @@
+scsirootfstype=ext4 rootwait
+ufs_finduuid=part uuid scsi ${bootpart} uuid
+args_ufs=setenv devtype scsi;setenv bootpart 1:1;
+	run ufs_finduuid;
+	setenv bootargs console = ${console}
+	${optargs}
+	root=PARTUUID=${uuid} rw
+	rootfstype=${scsirootfstype};
+	setenv devtype scsi;
+	setenv bootpart 1:1
+init_ufs=ufs init; scsi scan; run args_ufs
+get_kern_ufs=load ${devtype} ${bootpart} ${loadaddr} ${bootdir}/${name_kern}
+get_fdt_ufs=load ${devtype} ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}
+get_overlay_ufs=
+	fdt address ${fdtaddr};
+	fdt resize 0x100000;
+	for overlay in $name_overlays;
+	do;
+	load scsi ${bootpart} ${dtboaddr} ${bootdir}/${overlay} &&
+	fdt apply ${dtboaddr};
+	done;
+
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 3e71d61..5cd6c9d 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -284,4 +284,28 @@
 	offsetof(struct structure, member) == (offset), \
 	"`struct " #structure "` offset for `" #member "` is not " #offset)
 
+#define __find_closest(x, a, as, op)					\
+({									\
+	typeof(as) __fc_i, __fc_as = (as) - 1;				\
+	typeof(x) __fc_x = (x);						\
+	typeof(*a) const *__fc_a = (a);					\
+	for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) {			\
+		if (__fc_x op DIV_ROUND_CLOSEST(__fc_a[__fc_i] +	\
+						__fc_a[__fc_i + 1], 2))	\
+			break;						\
+	}								\
+	(__fc_i);							\
+})
+
+/**
+ * find_closest - locate the closest element in a sorted array
+ * @x: The reference value.
+ * @a: The array in which to look for the closest element. Must be sorted
+ *  in ascending order.
+ * @as: Size of 'a'.
+ *
+ * Returns the index of the element closest to 'x'.
+ */
+#define find_closest(x, a, as) __find_closest(x, a, as, <=)
+
 #endif
diff --git a/include/pci.h b/include/pci.h
index c55d610..2f5eb30 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -360,6 +360,13 @@
 #define   PCI_EXP_TYPE_PCIE_BRIDGE 0x8	/* PCI/PCI-X to PCIe Bridge */
 #define PCI_EXP_DEVCAP		4	/* Device capabilities */
 #define  PCI_EXP_DEVCAP_FLR	0x10000000 /* Function Level Reset */
+#define  PCI_EXP_DEVCAP_PAYLOAD 0x0007	/* Max payload size supported */
+#define  PCI_EXP_DEVCAP_PAYLOAD_128B 0x0000 /* 128 Bytes */
+#define  PCI_EXP_DEVCAP_PAYLOAD_256B 0x0001 /* 256 Bytes */
+#define  PCI_EXP_DEVCAP_PAYLOAD_512B 0x0002 /* 512 Bytes */
+#define  PCI_EXP_DEVCAP_PAYLOAD_1024B 0x0003 /* 1024 Bytes */
+#define  PCI_EXP_DEVCAP_PAYLOAD_2048B 0x0004 /* 2048 Bytes */
+#define  PCI_EXP_DEVCAP_PAYLOAD_4096B 0x0005 /* 4096 Bytes */
 #define PCI_EXP_DEVCTL		8	/* Device Control */
 #define  PCI_EXP_DEVCTL_PAYLOAD	0x00e0	/* Max_Payload_Size */
 #define  PCI_EXP_DEVCTL_PAYLOAD_128B 0x0000 /* 128 Bytes */
diff --git a/include/test/suites.h b/include/test/suites.h
index 7c4960c..7349ce5 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -48,6 +48,8 @@
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
 		  char *const argv[]);
+int do_ut_pci_mps(struct cmd_tbl *cmdtp, int flag, int argc,
+		  char *const argv[]);
 int do_ut_print(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_seama(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_setexpr(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/lib/Kconfig b/lib/Kconfig
index 4278b24..202a34a 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -16,7 +16,7 @@
 	  Sets the number of entries in the virtual-physical mapping table.
 
 config SYS_TIMER_COUNTS_DOWN
-	bool "System timer counts down rathe than up"
+	bool "System timer counts down rather than up"
 
 config PHYSMEM
 	bool "Access to physical memory region (> 4G)"
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 7848f34..055adc6 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -14,6 +14,9 @@
 obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o
 obj-$(CONFIG_CMD_LOADM) += loadm.o
 obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
+ifdef CONFIG_CMD_PCI
+obj-$(CONFIG_CMD_PCI_MPS) += pci_mps.o
+endif
 obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PWM) += pwm.o
 obj-$(CONFIG_CMD_SEAMA) += seama.o
diff --git a/test/cmd/exit.c b/test/cmd/exit.c
index ca34abe..7e160f7 100644
--- a/test/cmd/exit.c
+++ b/test/cmd/exit.c
@@ -60,20 +60,20 @@
 
 	/* Validate that 'exit' behaves the same way as 'exit 0' */
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("setenv foo 'echo bar ; exit ; echo baz' ; run foo ; echo $?", i));
+	ut_assertok(run_commandf("setenv foo 'echo bar ; exit ; echo baz' ; run foo ; echo $?"));
 	ut_assert_nextline("bar");
 	ut_assert_nextline("0");
 	ut_assertok(ut_check_console_end(uts));
 
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("setenv foo 'echo bar ; exit ; echo baz' ; run foo && echo quux ; echo $?", i));
+	ut_assertok(run_commandf("setenv foo 'echo bar ; exit ; echo baz' ; run foo && echo quux ; echo $?"));
 	ut_assert_nextline("bar");
 	ut_assert_nextline("quux");
 	ut_assert_nextline("0");
 	ut_assertok(ut_check_console_end(uts));
 
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("setenv foo 'echo bar ; exit ; echo baz' ; run foo || echo quux ; echo $?", i));
+	ut_assertok(run_commandf("setenv foo 'echo bar ; exit ; echo baz' ; run foo || echo quux ; echo $?"));
 	ut_assert_nextline("bar");
 	/* Either 'exit' returns 0, or 'echo quux' returns 0 */
 	ut_assert_nextline("0");
@@ -81,39 +81,39 @@
 
 	/* Validate that return value still propagates from 'run' command */
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("setenv foo 'echo bar ; true' ; run foo ; echo $?", i));
+	ut_assertok(run_commandf("setenv foo 'echo bar ; true' ; run foo ; echo $?"));
 	ut_assert_nextline("bar");
 	ut_assert_nextline("0");
 	ut_assertok(ut_check_console_end(uts));
 
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("setenv foo 'echo bar ; true' ; run foo && echo quux ; echo $?", i));
+	ut_assertok(run_commandf("setenv foo 'echo bar ; true' ; run foo && echo quux ; echo $?"));
 	ut_assert_nextline("bar");
 	ut_assert_nextline("quux");
 	ut_assert_nextline("0");
 	ut_assertok(ut_check_console_end(uts));
 
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("setenv foo 'echo bar ; true' ; run foo || echo quux ; echo $?", i));
+	ut_assertok(run_commandf("setenv foo 'echo bar ; true' ; run foo || echo quux ; echo $?"));
 	ut_assert_nextline("bar");
 	/* The 'true' returns 0 */
 	ut_assert_nextline("0");
 	ut_assertok(ut_check_console_end(uts));
 
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("setenv foo 'echo bar ; false' ; run foo ; echo $?", i));
+	ut_assertok(run_commandf("setenv foo 'echo bar ; false' ; run foo ; echo $?"));
 	ut_assert_nextline("bar");
 	ut_assert_nextline("1");
 	ut_assertok(ut_check_console_end(uts));
 
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("setenv foo 'echo bar ; false' ; run foo && echo quux ; echo $?", i));
+	ut_assertok(run_commandf("setenv foo 'echo bar ; false' ; run foo && echo quux ; echo $?"));
 	ut_assert_nextline("bar");
 	ut_assert_nextline("1");
 	ut_assertok(ut_check_console_end(uts));
 
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("setenv foo 'echo bar ; false' ; run foo || echo quux ; echo $?", i));
+	ut_assertok(run_commandf("setenv foo 'echo bar ; false' ; run foo || echo quux ; echo $?"));
 	ut_assert_nextline("bar");
 	ut_assert_nextline("quux");
 	/* The 'echo quux' returns 0 */
diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c
index 22e8c7e..597fecb 100644
--- a/test/cmd/fdt.c
+++ b/test/cmd/fdt.c
@@ -175,7 +175,7 @@
 	/* Set the working FDT */
 	set_working_fdt_addr(0);
 	ut_assert_nextline("Working FDT set to 0");
-	ut_assertok(run_commandf("fdt addr %08x", addr));
+	ut_assertok(run_commandf("fdt addr %08lx", addr));
 	ut_assert_nextline("Working FDT set to %lx", addr);
 	ut_asserteq(addr, map_to_sysmem(working_fdt));
 	ut_assertok(ut_check_console_end(uts));
@@ -185,7 +185,7 @@
 	/* Set the control FDT */
 	fdt_blob = gd->fdt_blob;
 	gd->fdt_blob = NULL;
-	ret = run_commandf("fdt addr -c %08x", addr);
+	ret = run_commandf("fdt addr -c %08lx", addr);
 	new_fdt = gd->fdt_blob;
 	gd->fdt_blob = fdt_blob;
 	ut_assertok(ret);
@@ -194,7 +194,7 @@
 
 	/* Test setting an invalid FDT */
 	fdt[0] = 123;
-	ut_asserteq(1, run_commandf("fdt addr %08x", addr));
+	ut_asserteq(1, run_commandf("fdt addr %08lx", addr));
 	ut_assert_nextline("libfdt fdt_check_header(): FDT_ERR_BADMAGIC");
 	ut_assertok(ut_check_console_end(uts));
 
@@ -223,19 +223,19 @@
 
 	/* Test setting and resizing the working FDT to a larger size */
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("fdt addr %08x %x", addr, newsize));
+	ut_assertok(run_commandf("fdt addr %08lx %x", addr, newsize));
 	ut_assert_nextline("Working FDT set to %lx", addr);
 	ut_assertok(ut_check_console_end(uts));
 
 	/* Try shrinking it */
-	ut_assertok(run_commandf("fdt addr %08x %x", addr, sizeof(fdt) / 4));
+	ut_assertok(run_commandf("fdt addr %08lx %zx", addr, sizeof(fdt) / 4));
 	ut_assert_nextline("Working FDT set to %lx", addr);
 	ut_assert_nextline("New length %d < existing length %d, ignoring",
 			   (int)sizeof(fdt) / 4, newsize);
 	ut_assertok(ut_check_console_end(uts));
 
 	/* ...quietly */
-	ut_assertok(run_commandf("fdt addr -q %08x %x", addr, sizeof(fdt) / 4));
+	ut_assertok(run_commandf("fdt addr -q %08lx %zx", addr, sizeof(fdt) / 4));
 	ut_assert_nextline("Working FDT set to %lx", addr);
 	ut_assertok(ut_check_console_end(uts));
 
@@ -265,13 +265,13 @@
 
 	/* Test moving the working FDT to a new location */
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("fdt move %08x %08x %x", addr, newaddr, ts));
+	ut_assertok(run_commandf("fdt move %08lx %08lx %x", addr, newaddr, ts));
 	ut_assert_nextline("Working FDT set to %lx", newaddr);
 	ut_assertok(ut_check_console_end(uts));
 
 	/* Compare the source and destination DTs */
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("cmp.b %08x %08x %x", addr, newaddr, ts));
+	ut_assertok(run_commandf("cmp.b %08lx %08lx %x", addr, newaddr, ts));
 	ut_assert_nextline("Total of %d byte(s) were the same", ts);
 	ut_assertok(ut_check_console_end(uts));
 
@@ -1406,7 +1406,7 @@
 
 	/* Test simple DTO application */
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("fdt apply 0x%08x", addro));
+	ut_assertok(run_commandf("fdt apply 0x%08lx", addro));
 	ut_assertok(run_commandf("fdt print /"));
 	ut_assert_nextline("/ {");
 	ut_assert_nextline("\tnewstring = \"newvalue\";");
@@ -1451,7 +1451,7 @@
 
 	/* Test complex DTO application */
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("fdt apply 0x%08x", addro));
+	ut_assertok(run_commandf("fdt apply 0x%08lx", addro));
 	ut_assertok(run_commandf("fdt print /"));
 	ut_assert_nextline("/ {");
 	ut_assert_nextline("\tempty-property;");
@@ -1495,7 +1495,7 @@
 
 	/* Test complex DTO application */
 	ut_assertok(console_record_reset_enable());
-	ut_assertok(run_commandf("fdt apply 0x%08x", addro));
+	ut_assertok(run_commandf("fdt apply 0x%08lx", addro));
 	ut_assertok(run_commandf("fdt print /"));
 	ut_assert_nextline("/ {");
 	ut_assert_nextline("\tempty-property;");
diff --git a/test/cmd/pci_mps.c b/test/cmd/pci_mps.c
new file mode 100644
index 0000000..fd96f4f
--- /dev/null
+++ b/test/cmd/pci_mps.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Tests that the PCI Maximum Payload Size (MPS) command can set the sandbox
+ * PCI Express device to safe mode and determine the correct payload size.
+ *
+ * Copyright 2023 Microsoft
+ * Written by Stephen Carlson <stcarlso@linux.microsoft.com>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <test/suites.h>
+#include <test/ut.h>
+
+#define PCI_MPS_TEST(_name, _flags) UNIT_TEST(_name, _flags, pci_mps_test)
+
+/* Test "pci_mps" command in safe "s" mode */
+static int test_pci_mps_safe(struct unit_test_state *uts)
+{
+	/* Enumerate PCI Express first */
+	ut_assertok(run_command("pci e", 0));
+	ut_assert_console_end();
+
+	/* Test pci_mps s */
+	ut_assertok(run_command("pci_mps s", 0));
+	ut_assert_nextline("Setting MPS of all devices to 256B");
+	ut_assert_console_end();
+
+	return 0;
+}
+
+PCI_MPS_TEST(test_pci_mps_safe, UT_TESTF_CONSOLE_REC);
+
+int do_ut_pci_mps(struct cmd_tbl *cmdtp, int flag, int argc,
+		  char * const argv[])
+{
+	struct unit_test *tests = UNIT_TEST_SUITE_START(pci_mps_test);
+	const int n = UNIT_TEST_SUITE_COUNT(pci_mps_test);
+
+	return cmd_ut_category("cmd_pci_mps", "pci_mps_test_", tests, n,
+			       argc, argv);
+}
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 409c22b..d440da8 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -110,6 +110,9 @@
 #ifdef CONFIG_CMD_LOADM
 	U_BOOT_CMD_MKENT(loadm, CONFIG_SYS_MAXARGS, 1, do_ut_loadm, "", ""),
 #endif
+#ifdef CONFIG_CMD_PCI_MPS
+	U_BOOT_CMD_MKENT(pci_mps, CONFIG_SYS_MAXARGS, 1, do_ut_pci_mps, "", ""),
+#endif
 #ifdef CONFIG_CMD_SEAMA
 	U_BOOT_CMD_MKENT(seama, CONFIG_SYS_MAXARGS, 1, do_ut_seama, "", ""),
 #endif
@@ -210,6 +213,9 @@
 #ifdef CONFIG_UT_OVERLAY
 	"\noverlay - device tree overlays"
 #endif
+#ifdef CONFIG_CMD_PCI_MPS
+	"\npci_mps - PCI Express Maximum Payload Size"
+#endif
 	"\nprint  - printing things to the console"
 	"\nsetexpr - setexpr command"
 #ifdef CONFIG_SANDBOX
diff --git a/test/command_ut.c b/test/command_ut.c
index 9837d10..a74bd10 100644
--- a/test/command_ut.c
+++ b/test/command_ut.c
@@ -9,6 +9,8 @@
 #include <command.h>
 #include <env.h>
 #include <log.h>
+#include <string.h>
+#include <linux/errno.h>
 
 static const char test_cmd[] = "setenv list 1\n setenv list ${list}2; "
 		"setenv list ${list}3\0"
@@ -17,6 +19,8 @@
 static int do_ut_cmd(struct cmd_tbl *cmdtp, int flag, int argc,
 		     char *const argv[])
 {
+	char long_str[CONFIG_SYS_CBSIZE + 42];
+
 	printf("%s: Testing commands\n", __func__);
 	run_command("env default -f -a", 0);
 
@@ -60,6 +64,36 @@
 
 	assert(run_command("'", 0) == 1);
 
+	/* Variadic function test-cases */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-zero-length"
+	assert(run_commandf("") == 0);
+#pragma GCC diagnostic pop
+	assert(run_commandf(" ") == 0);
+	assert(run_commandf("'") == 1);
+
+	assert(run_commandf("env %s %s", "delete -f", "list") == 0);
+	/* Expected: "Error: "list" not defined" */
+	assert(run_commandf("printenv list") == 1);
+
+	memset(long_str, 'x', sizeof(long_str));
+	assert(run_commandf("Truncation case: %s", long_str) == -ENOSPC);
+
+	if (IS_ENABLED(CONFIG_HUSH_PARSER)) {
+		assert(run_commandf("env %s %s %s %s", "delete -f", "adder",
+				    "black", "foo") == 0);
+		assert(run_commandf("setenv foo 'setenv %s 1\nsetenv %s 2'",
+				    "black", "adder") == 0);
+		run_command("run foo", 0);
+		assert(env_get("black"));
+		assert(!strcmp("1", env_get("black")));
+		assert(env_get("adder"));
+		assert(!strcmp("2", env_get("adder")));
+	}
+
+	/* Clean up before exit */
+	run_command("env default -f -a", 0);
+
 	printf("%s: Everything went swimmingly\n", __func__);
 	return 0;
 }
diff --git a/test/py/tests/test_fs/test_ext.py b/test/py/tests/test_fs/test_ext.py
index dba874f..05fefa5 100644
--- a/test/py/tests/test_fs/test_ext.py
+++ b/test/py/tests/test_fs/test_ext.py
@@ -8,11 +8,24 @@
 This test verifies extended write operation on file system.
 """
 
+import os.path
 import pytest
 import re
+from subprocess import check_output
 from fstest_defs import *
 from fstest_helpers import assert_fs_integrity
 
+PLAIN_FILE='abcdefgh.txt'
+MANGLE_FILE='abcdefghi.txt'
+
+def str2fat(long_filename):
+    splitext = os.path.splitext(long_filename.upper())
+    name = splitext[0]
+    ext = splitext[1][1:]
+    if len(name) > 8:
+        name = '%s~1' % name[:6]
+    return '%-8s %s' % (name, ext)
+
 @pytest.mark.boardspec('sandbox')
 @pytest.mark.slow
 class TestFsExt(object):
@@ -317,3 +330,26 @@
             assert('FILE0123456789_79' in output)
 
             assert_fs_integrity(fs_type, fs_img)
+
+    def test_fs_ext12(self, u_boot_console, fs_obj_ext):
+        """
+        Test Case 12 - write plain and mangle file
+        """
+        fs_type,fs_img,md5val = fs_obj_ext
+        with u_boot_console.log.section('Test Case 12 - write plain and mangle file'):
+            # Test Case 12a - Check if command successfully returned
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % fs_img,
+                '%swrite host 0:0 %x /%s 0'
+                    % (fs_type, ADDR, PLAIN_FILE),
+                '%swrite host 0:0 %x /%s 0'
+                    % (fs_type, ADDR, MANGLE_FILE)])
+            assert('0 bytes written' in ''.join(output))
+            # Test Case 12b - Read file system content
+            output = check_output('mdir -i %s' % fs_img, shell=True).decode()
+            # Test Case 12c - Check if short filename is not mangled
+            assert(str2fat(PLAIN_FILE) in ''.join(output))
+            # Test Case 12d - Check if long filename is mangled
+            assert(str2fat(MANGLE_FILE) in ''.join(output))
+
+            assert_fs_integrity(fs_type, fs_img)
diff --git a/tools/binman/missing-blob-help b/tools/binman/missing-blob-help
index f3a44d0..f013367 100644
--- a/tools/binman/missing-blob-help
+++ b/tools/binman/missing-blob-help
@@ -21,13 +21,15 @@
 iot2050-seboot:
 See the documentation for IOT2050 board. Your image is missing SEBoot
 which is mandatory for board startup. Prebuilt SEBoot located at
-meta-iot2050/tree/master/recipes-bsp/u-boot/files/prebuild/tiboot3.bin.
+meta-iot2050/tree/master/recipes-bsp/u-boot/files/prebuild/seboot_pg*.bin.
 
-iot2050-sysfw:
-See the documentation for IOT2050 board. Your image is missing system
-firmware which is mandatory for board startup. Prebuilt system firmware
-located at meta-iot2050/tree/master/recipes-bsp/u-boot/files/prebuild/
-with sysfw prefix.
+iot2050-otpcmd:
+See the documentation for IOT2050 board. Your image is missing OTP command data
+block which is used for provisioning the customer keys to the board.
+Please refer to
+meta-iot2050/tree/master/recipes-bsp/secure-boot-otp-provisioning/files/make-otpcmd.sh
+for how to generate this binary. If you are not using secure boot or do not
+intend to provision the keys, disable CONFIG_IOT2050_EMBED_OTPCMD.
 
 k3-rti-wdt-firmware:
 If CONFIG_WDT_K3_RTI_LOAD_FW is enabled, a firmware image is needed for
diff --git a/tools/iot2050-sign-fw.sh b/tools/iot2050-sign-fw.sh
new file mode 100755
index 0000000..4d1d794
--- /dev/null
+++ b/tools/iot2050-sign-fw.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+if [ -z "$1" ]; then
+	echo "Usage: $0 KEY"
+	exit 1
+fi
+
+TEMP_X509=$(mktemp XXXXXXXX.temp)
+
+REVISION=${2:-0}
+SHA_VAL=$(openssl dgst -sha512 -hex tispl.bin | sed -e "s/^.*= //g")
+BIN_SIZE=$(stat -c %s tispl.bin)
+
+cat <<EOF >$TEMP_X509
+[ req ]
+distinguished_name     = req_distinguished_name
+x509_extensions        = v3_ca
+prompt                 = no
+dirstring_type         = nobmp
+
+[ req_distinguished_name ]
+CN                     = IOT2050 Firmware Signature
+
+[ v3_ca ]
+basicConstraints       = CA:true
+1.3.6.1.4.1.294.1.3    = ASN1:SEQUENCE:swrv
+1.3.6.1.4.1.294.1.34   = ASN1:SEQUENCE:sysfw_image_integrity
+
+[ swrv ]
+swrv = INTEGER:$REVISION
+
+[ sysfw_image_integrity ]
+shaType                = OID:2.16.840.1.101.3.4.2.3
+shaValue               = FORMAT:HEX,OCT:$SHA_VAL
+imageSize              = INTEGER:$BIN_SIZE
+EOF
+
+CERT_X509=$(mktemp XXXXXXXX.crt)
+
+openssl req -new -x509 -key $1 -nodes -outform DER -out $CERT_X509 -config $TEMP_X509 -sha512
+cat $CERT_X509 tispl.bin > tispl.bin_signed
+# currently broken in upstream
+#source/tools/binman/binman replace -i flash.bin -f tispl.bin_signed blob@0x180000
+dd if=tispl.bin_signed of=flash.bin bs=$((0x1000)) seek=$((0x180000/0x1000)) conv=notrunc
+
+rm $TEMP_X509 $CERT_X509
+
+tools/mkimage -G $1 -r -o sha256,rsa4096 -F fit@0x380000.fit
+# currently broken in upstream
+#source/tools/binman/binman replace -i flash.bin -f fit@0x380000.fit fit@0x380000
+dd if=fit@0x380000.fit of=flash.bin bs=$((0x1000)) seek=$((0x380000/0x1000)) conv=notrunc
diff --git a/tools/key2dtsi.py b/tools/key2dtsi.py
new file mode 100755
index 0000000..1dbb2cc
--- /dev/null
+++ b/tools/key2dtsi.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Public key to dtsi converter.
+#
+# Copyright (c) Siemens AG, 2022
+#
+
+from argparse import ArgumentParser, FileType
+from os.path import basename, splitext
+from Cryptodome.PublicKey import RSA
+from Cryptodome.Util.number import inverse
+
+def int_to_bytestr(n, length=None):
+    if not length:
+        length = (n.bit_length() + 7) // 8
+    byte_array = n.to_bytes(length, 'big')
+    return ' '.join(['{:02x}'.format(byte) for byte in byte_array])
+
+ap = ArgumentParser(description='Public key to dtsi converter')
+
+ap.add_argument('--hash', '-H', default='sha256',
+                help='hash to be used with key (default: sha256)')
+ap.add_argument('--required-conf', '-c', action='store_true',
+                help='mark key required for configuration')
+ap.add_argument('--required-image', '-i', action='store_true',
+                help='mark key required for image')
+ap.add_argument('--spl', '-s', action='store_true',
+                help='mark key for usage in SPL')
+ap.add_argument('key_file', metavar='KEY_FILE', type=FileType('r'),
+                help='key file (formats: X.509, PKCS#1, OpenSSH)')
+ap.add_argument('dtsi_file', metavar='DTSI_FILE', type=FileType('w'),
+                help='dtsi output file')
+
+args = ap.parse_args()
+
+key_name, _ = splitext(basename(args.key_file.name))
+
+key_data = args.key_file.read()
+key = RSA.importKey(key_data)
+
+r_squared = (2**key.size_in_bits())**2 % key.n
+n0_inverse = 2**32 - inverse(key.n, 2**32)
+
+out = args.dtsi_file
+out.write('/ {\n')
+out.write('\tsignature {\n')
+out.write('\t\tkey-{} {{\n'.format(key_name))
+out.write('\t\t\tkey-name-hint = "{}";\n'.format(key_name))
+out.write('\t\t\talgo = "{},rsa{}";\n'.format(args.hash, key.size_in_bits()))
+out.write('\t\t\trsa,num-bits = <{}>;\n'.format(key.size_in_bits()))
+out.write('\t\t\trsa,modulus = [{}];\n'.format(int_to_bytestr(key.n)))
+out.write('\t\t\trsa,exponent = [{}];\n'.format(int_to_bytestr(key.e, 8)))
+out.write('\t\t\trsa,r-squared = [{}];\n'.format(int_to_bytestr(r_squared)))
+out.write('\t\t\trsa,n0-inverse = <0x{:x}>;\n'.format(n0_inverse))
+if args.required_conf:
+    out.write('\t\t\trequired = "conf";\n')
+elif args.required_image:
+    out.write('\t\t\trequired = "image";\n')
+if args.spl:
+    out.write('\t\t\tu-boot,dm-spl;\n')
+out.write('\t\t};\n')
+out.write('\t};\n')
+out.write('};\n')