Merge branch '2022-06-22-platform-updates-and-additions' into next

- Add hpe gxp architecture and platform, Arm corstone1000 platform.
- ast2600, devkit8000, NPCM7xx improvements
diff --git a/MAINTAINERS b/MAINTAINERS
index 2ebec1f..ba9fdb5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -279,6 +279,19 @@
 F:	arch/arm/include/asm/arch-hi6220/
 F:	arch/arm/include/asm/arch-hi3660/
 
+ARM HPE GXP ARCHITECTURE
+M:	Jean-Marie Verdun <verdun@hpe.com>
+M:	Nick Hawkins <nick.hawkins@hpe.com>
+S:	Maintained
+F:	arch/arm/dts/hpe-bmc*
+F:	arch/arm/dts/hpe-gxp*
+F:	arch/arm/mach-hpe/
+F:	board/hpe/
+F:	configs/gxp_defconfig
+F:	doc/device-tree-bindings/spi/hpe,gxp-spi.yaml
+F:	drivers/timer/gxp-timer.c
+F:	drivers/spi/gxp_spi.c
+
 ARM IPQ40XX
 M:	Robert Marko <robert.marko@sartura.hr>
 M:	Luka Kovacic <luka.kovacic@sartura.hr>
diff --git a/README b/README
index 9800359..f330422 100644
--- a/README
+++ b/README
@@ -2415,6 +2415,7 @@
 diskboot- boot from IDE devicebootd   - boot default, i.e., run 'bootcmd'
 loads	- load S-Record file over serial line
 loadb	- load binary file over serial line (kermit mode)
+loadm   - load binary blob from source address to destination address
 md	- memory display
 mm	- memory modify (auto-incrementing)
 nm	- memory modify (constant address)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c618aad..dab785e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1352,6 +1352,12 @@
 	select ENV_IS_IN_FLASH if MTD
 	imply DISTRO_DEFAULTS
 
+config TARGET_CORSTONE1000
+	bool "Support Corstone1000 Platform"
+	select ARM64
+	select PL01X_SERIAL
+	select DM
+
 config TARGET_TOTAL_COMPUTE
 	bool "Support Total Compute Platform"
 	select ARM64
@@ -2089,6 +2095,12 @@
 	select SSCANF
 	imply OF_HAS_PRIOR_STAGE
 
+config ARCH_GXP
+	bool "Support HPE GXP SoCs"
+	select DM
+	select OF_CONTROL
+	imply CMD_DM
+
 endchoice
 
 config SUPPORT_PASSING_ATAGS
@@ -2199,6 +2211,8 @@
 
 source "arch/arm/mach-exynos/Kconfig"
 
+source "arch/arm/mach-hpe/gxp/Kconfig"
+
 source "arch/arm/mach-highbank/Kconfig"
 
 source "arch/arm/mach-integrator/Kconfig"
@@ -2300,7 +2314,7 @@
 source "arch/arm/mach-npcm/Kconfig"
 
 source "board/armltd/total_compute/Kconfig"
-
+source "board/armltd/corstone1000/Kconfig"
 source "board/bosch/shc/Kconfig"
 source "board/bosch/guardian/Kconfig"
 source "board/Marvell/octeontx/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index a342d72..64c58f4 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -63,6 +63,7 @@
 machine-$(CONFIG_ARCH_BCMSTB)		+= bcmstb
 machine-$(CONFIG_ARCH_DAVINCI)		+= davinci
 machine-$(CONFIG_ARCH_EXYNOS)		+= exynos
+machine-$(CONFIG_ARCH_GXP)		+= hpe
 machine-$(CONFIG_ARCH_HIGHBANK)		+= highbank
 machine-$(CONFIG_ARCH_IPQ40XX)		+= ipq40xx
 machine-$(CONFIG_ARCH_K3)		+= k3
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 85346c5..4b940f8 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -1069,6 +1069,8 @@
 	omap3-beagle-xm.dtb \
 	omap3-beagle.dtb
 
+dtb-$(CONFIG_TARGET_DEVKIT8000) += omap3-devkit8000.dtb
+
 dtb-$(CONFIG_TARGET_OMAP3_IGEP00X0) += \
 	omap3-igep0020.dtb
 
@@ -1245,6 +1247,8 @@
 
 dtb-$(CONFIG_TARGET_PRESIDIO_ASIC) += ca-presidio-engboard.dtb
 
+dtb-$(CONFIG_TARGET_GXP) += hpe-bmc-dl360gen10.dts
+
 dtb-$(CONFIG_TARGET_IMX8MM_CL_IOT_GATE) += imx8mm-cl-iot-gate.dtb \
 					imx8mm-cl-iot-gate-ied.dtbo \
 					imx8mm-cl-iot-gate-ied-adc0.dtbo \
@@ -1271,6 +1275,9 @@
 
 dtb-$(CONFIG_ARCH_QEMU) += qemu-arm.dtb qemu-arm64.dtb
 
+dtb-$(CONFIG_TARGET_CORSTONE1000) += corstone1000-mps3.dtb \
+				corstone1000-fvp.dtb
+
 include $(srctree)/scripts/Makefile.dts
 
 targets += $(dtb-y)
diff --git a/arch/arm/dts/corstone1000-fvp.dts b/arch/arm/dts/corstone1000-fvp.dts
new file mode 100644
index 0000000..26b0f1b
--- /dev/null
+++ b/arch/arm/dts/corstone1000-fvp.dts
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0 or MIT
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022, Linaro Limited. All rights reserved.
+ *
+ */
+
+/dts-v1/;
+
+#include "corstone1000.dtsi"
+
+/ {
+	model = "ARM Corstone1000 FVP (Fixed Virtual Platform)";
+	compatible = "arm,corstone1000-fvp";
+
+	smsc: ethernet@4010000 {
+		compatible = "smsc,lan91c111";
+		reg = <0x40100000 0x10000>;
+		phy-mode = "mii";
+		interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+		reg-io-width = <2>;
+	};
+
+	vmmc_v3_3d: fixed_v3_3d {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmc_supply";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	sdmmc0: mmc@40300000 {
+		compatible = "arm,pl18x", "arm,primecell";
+		reg = <0x40300000 0x1000>;
+		interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+		max-frequency = <12000000>;
+		vmmc-supply = <&vmmc_v3_3d>;
+		clocks = <&smbclk>, <&refclk100mhz>;
+		clock-names = "smclk", "apb_pclk";
+	};
+
+	sdmmc1: mmc@50000000 {
+		compatible = "arm,pl18x", "arm,primecell";
+		reg = <0x50000000 0x10000>;
+		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+		max-frequency = <12000000>;
+		vmmc-supply = <&vmmc_v3_3d>;
+		clocks = <&smbclk>, <&refclk100mhz>;
+		clock-names = "smclk", "apb_pclk";
+	};
+};
diff --git a/arch/arm/dts/corstone1000-mps3.dts b/arch/arm/dts/corstone1000-mps3.dts
new file mode 100644
index 0000000..e314674
--- /dev/null
+++ b/arch/arm/dts/corstone1000-mps3.dts
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0 or MIT
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022, Linaro Limited. All rights reserved.
+ *
+ */
+
+/dts-v1/;
+
+#include "corstone1000.dtsi"
+
+/ {
+	model = "ARM Corstone1000 FPGA MPS3 board";
+	compatible = "arm,corstone1000-mps3";
+
+	smsc: ethernet@4010000 {
+		compatible = "smsc,lan9220", "smsc,lan9115";
+		reg = <0x40100000 0x10000>;
+		phy-mode = "mii";
+		interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+		reg-io-width = <2>;
+		smsc,irq-push-pull;
+	};
+
+	usb_host: usb@40200000 {
+		compatible = "nxp,usb-isp1763";
+		reg = <0x40200000 0x100000>;
+		interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+		bus-width = <16>;
+		dr_mode = "host";
+	};
+};
diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi
new file mode 100644
index 0000000..4e46826
--- /dev/null
+++ b/arch/arm/dts/corstone1000.dtsi
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: GPL-2.0 or MIT
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022, Linaro Limited. All rights reserved.
+ *
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a35";
+			reg = <0>;
+			next-level-cache = <&L2_0>;
+		};
+	};
+
+	memory@88200000 {
+		device_type = "memory";
+		reg = <0x88200000 0x77e00000>;
+	};
+
+	gic: interrupt-controller@1c000000 {
+		compatible = "arm,gic-400";
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+		reg =	<0x1c010000 0x1000>,
+			<0x1c02f000 0x2000>,
+			<0x1c04f000 0x1000>,
+			<0x1c06f000 0x2000>;
+		interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(1) |
+			      IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	L2_0: l2-cache0 {
+		compatible = "cache";
+		cache-level = <2>;
+		cache-size = <0x80000>;
+		cache-line-size = <64>;
+		cache-sets = <1024>;
+	};
+
+	refclk100mhz: refclk100mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+		clock-output-names = "apb_pclk";
+	};
+
+	smbclk: refclk24mhzx2 {
+		/* Reference 24MHz clock x 2 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <48000000>;
+		clock-output-names = "smclk";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts =	<GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) |
+				 IRQ_TYPE_LEVEL_LOW)>,
+				<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) |
+				 IRQ_TYPE_LEVEL_LOW)>,
+				<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) |
+				 IRQ_TYPE_LEVEL_LOW)>,
+				<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) |
+				 IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	uartclk: uartclk {
+		/* UART clock - 50MHz */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <50000000>;
+		clock-output-names = "uartclk";
+	};
+
+	psci {
+		compatible = "arm,psci-1.0", "arm,psci-0.2";
+		method = "smc";
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupt-parent = <&gic>;
+		ranges;
+
+		timer@1a220000 {
+			compatible = "arm,armv7-timer-mem";
+			reg = <0x1a220000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clock-frequency = <50000000>;
+			ranges;
+
+			frame@1a230000 {
+				frame-number = <0>;
+				interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0x1a230000 0x1000>;
+			};
+		};
+
+		uart0: serial@1a510000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x1a510000 0x1000>;
+			interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&uartclk>, <&refclk100mhz>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+
+		uart1: serial@1a520000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x1a520000 0x1000>;
+			interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&uartclk>, <&refclk100mhz>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+
+		mhu_hse1: mailbox@1b820000 {
+			compatible = "arm,mhuv2-tx", "arm,primecell";
+			reg = <0x1b820000 0x1000>;
+			clocks = <&refclk100mhz>;
+			clock-names = "apb_pclk";
+			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+			#mbox-cells = <2>;
+			arm,mhuv2-protocols = <0 0>;
+			secure-status = "okay";     /* secure-world-only */
+			status = "disabled";
+		};
+
+		mhu_seh1: mailbox@1b830000 {
+			compatible = "arm,mhuv2-rx", "arm,primecell";
+			reg = <0x1b830000 0x1000>;
+			clocks = <&refclk100mhz>;
+			clock-names = "apb_pclk";
+			interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+			#mbox-cells = <2>;
+			arm,mhuv2-protocols = <0 0>;
+			secure-status = "okay";     /* secure-world-only */
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/dts/hpe-bmc-dl360gen10.dts b/arch/arm/dts/hpe-bmc-dl360gen10.dts
new file mode 100644
index 0000000..b8030d9
--- /dev/null
+++ b/arch/arm/dts/hpe-bmc-dl360gen10.dts
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for HPE DL360Gen10
+ */
+
+/include/ "hpe-gxp-u-boot.dtsi"
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "hpe,gxp-dl360gen10", "hpe,gxp";
+	model = "Hewlett Packard Enterprise ProLiant dl360 Gen10";
+
+	aliases {
+		serial0 = &uartc;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@40000000 {
+		device_type = "memory";
+		reg = <0x40000000 0x20000000>;
+	};
+};
diff --git a/arch/arm/dts/hpe-gxp-u-boot.dtsi b/arch/arm/dts/hpe-gxp-u-boot.dtsi
new file mode 100644
index 0000000..7a2b488
--- /dev/null
+++ b/arch/arm/dts/hpe-gxp-u-boot.dtsi
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for HPE GXP
+ */
+
+/include/ "hpe-gxp.dtsi"
+
+/ {
+
+	axi {
+		u-boot,dm-pre-reloc;
+
+		ahb@c0000000 {
+			u-boot,dm-pre-reloc;
+
+			spi0: spi@200 {
+				compatible = "hpe,gxp-spi";
+				reg = <0x200 0x80>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/hpe-gxp.dtsi b/arch/arm/dts/hpe-gxp.dtsi
new file mode 100644
index 0000000..cf735b3
--- /dev/null
+++ b/arch/arm/dts/hpe-gxp.dtsi
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for HPE GXP
+ */
+
+/dts-v1/;
+/ {
+	model = "Hewlett Packard Enterprise GXP BMC";
+	compatible = "hpe,gxp";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+			device_type = "cpu";
+			next-level-cache = <&L2>;
+		};
+	};
+
+	clocks {
+		pll: clock-0 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <1600000000>;
+		};
+
+		iopclk: clock-1 {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <4>;
+			clock-mult = <1>;
+			clocks = <&pll>;
+		};
+	};
+
+	axi {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		dma-ranges;
+
+		L2: cache-controller@b0040000 {
+			compatible = "arm,pl310-cache";
+			reg = <0xb0040000 0x1000>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		ahb@c0000000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0xc0000000 0x30000000>;
+			dma-ranges;
+
+			vic0: interrupt-controller@eff0000 {
+				compatible = "arm,pl192-vic";
+				reg = <0xeff0000 0x1000>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			vic1: interrupt-controller@80f00000 {
+				compatible = "arm,pl192-vic";
+				reg = <0x80f00000 0x1000>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			uarta: serial@e0 {
+				compatible = "ns16550a";
+				reg = <0xe0 0x8>;
+				interrupts = <17>;
+				interrupt-parent = <&vic0>;
+				clock-frequency = <1846153>;
+				reg-shift = <0>;
+			};
+
+			uartb: serial@e8 {
+				compatible = "ns16550a";
+				reg = <0xe8 0x8>;
+				interrupts = <18>;
+				interrupt-parent = <&vic0>;
+				clock-frequency = <1846153>;
+				reg-shift = <0>;
+			};
+
+			uartc: serial@f0 {
+				compatible = "ns16550a";
+				reg = <0xf0 0x8>;
+				interrupts = <19>;
+				interrupt-parent = <&vic0>;
+				clock-frequency = <1846153>;
+				reg-shift = <0>;
+			};
+
+			usb0: usb@efe0000 {
+				compatible = "hpe,gxp-ehci", "generic-ehci";
+				reg = <0xefe0000 0x100>;
+				interrupts = <7>;
+				interrupt-parent = <&vic0>;
+			};
+
+			st: timer@80 {
+				compatible = "hpe,gxp-timer";
+				reg = <0x80 0x16>;
+				interrupts = <0>;
+				interrupt-parent = <&vic0>;
+				clocks = <&iopclk>;
+				clock-names = "iop";
+			};
+
+			usb1: usb@efe0100 {
+				compatible = "hpe,gxp-ohci", "generic-ohci";
+				reg = <0xefe0100 0x110>;
+				interrupts = <6>;
+				interrupt-parent = <&vic0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/omap3-devkit8000-u-boot.dtsi b/arch/arm/dts/omap3-devkit8000-u-boot.dtsi
new file mode 100644
index 0000000..a5768b7
--- /dev/null
+++ b/arch/arm/dts/omap3-devkit8000-u-boot.dtsi
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * U-Boot additions
+ *
+ * (C) Copyright 2017 Derald D. Woods <woods.technical@gmail.com>
+ */
+
+#include "omap3-u-boot.dtsi"
+
+/ {
+	chosen {
+		stdout-path = &uart3;
+	};
+
+	ethernet@2c000000 {
+	        compatible = "davicom,dm9000";
+	        reg = <0x2c000000 2 0x2c000400 2>;
+	        bank-width = <2>;
+	};
+};
diff --git a/arch/arm/dts/omap3-devkit8000.dts b/arch/arm/dts/omap3-devkit8000.dts
new file mode 100644
index 0000000..eee3ba0
--- /dev/null
+++ b/arch/arm/dts/omap3-devkit8000.dts
@@ -0,0 +1,349 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Author: Anthoine Bourgeois <anthoine.bourgeois@gmail.com>
+ */
+/dts-v1/;
+
+#include "omap34xx.dtsi"
+/ {
+	model = "TimLL OMAP3 Devkit8000";
+	compatible = "timll,omap3-devkit8000", "ti,omap3430", "ti,omap3";
+
+	aliases {
+		display1 = &dvi0;
+		display2 = &tv0;
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>;	/* 256 MB */
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		heartbeat {
+			label = "devkit8000::led1";
+			gpios = <&gpio6 26 GPIO_ACTIVE_HIGH>;	/* 186 -> LED1 */
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+
+		mmc {
+			label = "devkit8000::led2";
+			gpios = <&gpio6 3 GPIO_ACTIVE_HIGH>;	/* 163 -> LED2 */
+			default-state = "on";
+			linux,default-trigger = "none";
+		};
+
+		usr {
+			label = "devkit8000::led3";
+			gpios = <&gpio6 4 GPIO_ACTIVE_HIGH>;	/* 164 -> LED3 */
+			default-state = "on";
+			linux,default-trigger = "usr";
+		};
+
+		pmu_stat {
+			label = "devkit8000::pmu_stat";
+			gpios = <&twl_gpio 19 GPIO_ACTIVE_HIGH>; /* LEDB */
+		};
+	};
+
+	sound {
+		compatible = "ti,omap-twl4030";
+		ti,model = "devkit8000";
+
+		ti,mcbsp = <&mcbsp2>;
+		ti,audio-routing =
+			"Ext Spk", "PREDRIVEL",
+			"Ext Spk", "PREDRIVER",
+			"MAINMIC", "Main Mic",
+			"Main Mic", "Mic Bias 1";
+	};
+
+	tfp410: encoder0 {
+		compatible = "ti,tfp410";
+		powerdown-gpios = <&twl_gpio 7 GPIO_ACTIVE_LOW>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				tfp410_in: endpoint {
+					remote-endpoint = <&dpi_dvi_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				tfp410_out: endpoint {
+					remote-endpoint = <&dvi_connector_in>;
+				};
+			};
+		};
+	};
+
+	dvi0: connector0 {
+		compatible = "dvi-connector";
+		label = "dvi";
+
+		digital;
+
+		ddc-i2c-bus = <&i2c2>;
+
+		port {
+			dvi_connector_in: endpoint {
+				remote-endpoint = <&tfp410_out>;
+			};
+		};
+	};
+
+	tv0: connector1 {
+		compatible = "svideo-connector";
+		label = "tv";
+
+		port {
+			tv_connector_in: endpoint {
+				remote-endpoint = <&venc_out>;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	clock-frequency = <2600000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		interrupts = <7>;	/* SYS_NIRQ cascaded to intc */
+
+		twl_audio: audio {
+			compatible = "ti,twl4030-audio";
+			codec {
+			};
+		};
+	};
+};
+
+&i2c2 {
+	clock-frequency = <400000>;
+};
+
+&i2c3 {
+	status = "disabled";
+};
+
+#include "twl4030.dtsi"
+#include "twl4030_omap3.dtsi"
+
+&mmc1 {
+	vmmc-supply = <&vmmc1>;
+	vqmmc-supply = <&vsim>;
+	bus-width = <8>;
+};
+
+&mmc2 {
+	status = "disabled";
+};
+
+&mmc3 {
+	status = "disabled";
+};
+
+&twl_gpio {
+	ti,use-leds;
+	/*
+	 * pulldowns:
+	 * BIT(1), BIT(2), BIT(6), BIT(7), BIT(8), BIT(13)
+	 * BIT(15), BIT(16), BIT(17)
+	 */
+	ti,pulldowns = <0x03a1c6>;
+};
+
+&wdt2 {
+	status = "disabled";
+};
+
+&mcbsp2 {
+	status = "okay";
+};
+
+&gpmc {
+	ranges = <0 0 0x30000000 0x1000000	/* CS0: 16MB for NAND */
+		  6 0 0x2c000000 0x1000000>;	/* CS6: 16MB for DM9000 */
+
+	nand@0,0 {
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		interrupt-parent = <&gpmc>;
+		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		nand-bus-width = <16>;
+		gpmc,device-width = <2>;
+		ti,nand-ecc-opt = "sw";
+
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		x-loader@0 {
+			label = "X-Loader";
+			reg = <0 0x80000>;
+		};
+
+		bootloaders@80000 {
+			label = "U-Boot";
+			reg = <0x80000 0x1e0000>;
+		};
+
+		bootloaders_env@260000 {
+			label = "U-Boot Env";
+			reg = <0x260000 0x20000>;
+		};
+
+		kernel@280000 {
+			label = "Kernel";
+			reg = <0x280000 0x400000>;
+		};
+
+		filesystem@680000 {
+			label = "File System";
+			reg = <0x680000 0xf980000>;
+		};
+	};
+
+	ethernet@6,0 {
+		compatible = "davicom,dm9000";
+		reg =  <6 0x000 2
+			6 0x400 2>; /* CS6, offset 0 and 0x400, IO size 2 */
+		bank-width = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
+		davicom,no-eeprom;
+
+		gpmc,mux-add-data = <0>;
+		gpmc,device-width = <1>;
+		gpmc,wait-pin = <0>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-diffcsen;
+
+		gpmc,cs-on-ns = <6>;
+		gpmc,cs-rd-off-ns = <180>;
+		gpmc,cs-wr-off-ns = <180>;
+		gpmc,adv-on-ns = <0>;
+		gpmc,adv-rd-off-ns = <18>;
+		gpmc,adv-wr-off-ns = <48>;
+		gpmc,oe-on-ns = <54>;
+		gpmc,oe-off-ns = <168>;
+		gpmc,we-on-ns = <54>;
+		gpmc,we-off-ns = <168>;
+		gpmc,rd-cycle-ns = <186>;
+		gpmc,wr-cycle-ns = <186>;
+		gpmc,access-ns = <144>;
+		gpmc,page-burst-access-ns = <24>;
+		gpmc,bus-turnaround-ns = <90>;
+		gpmc,cycle2cycle-delay-ns = <90>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+		gpmc,wr-access-ns = <0>;
+	};
+};
+
+&omap3_pmx_core {
+	dss_dpi_pins: pinmux_dss_dpi_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0)	/* dss_pclk.dss_pclk */
+			OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0)	/* dss_hsync.dss_hsync */
+			OMAP3_CORE1_IOPAD(0x20d8, PIN_OUTPUT | MUX_MODE0)	/* dss_vsync.dss_vsync */
+			OMAP3_CORE1_IOPAD(0x20da, PIN_OUTPUT | MUX_MODE0)	/* dss_acbias.dss_acbias */
+			OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE0)	/* dss_data0.dss_data0 */
+			OMAP3_CORE1_IOPAD(0x20de, PIN_OUTPUT | MUX_MODE0)	/* dss_data1.dss_data1 */
+			OMAP3_CORE1_IOPAD(0x20e0, PIN_OUTPUT | MUX_MODE0)	/* dss_data2.dss_data2 */
+			OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE0)	/* dss_data3.dss_data3 */
+			OMAP3_CORE1_IOPAD(0x20e4, PIN_OUTPUT | MUX_MODE0)	/* dss_data4.dss_data4 */
+			OMAP3_CORE1_IOPAD(0x20e6, PIN_OUTPUT | MUX_MODE0)	/* dss_data5.dss_data5 */
+			OMAP3_CORE1_IOPAD(0x20e8, PIN_OUTPUT | MUX_MODE0)	/* dss_data6.dss_data6 */
+			OMAP3_CORE1_IOPAD(0x20ea, PIN_OUTPUT | MUX_MODE0)	/* dss_data7.dss_data7 */
+			OMAP3_CORE1_IOPAD(0x20ec, PIN_OUTPUT | MUX_MODE0)	/* dss_data8.dss_data8 */
+			OMAP3_CORE1_IOPAD(0x20ee, PIN_OUTPUT | MUX_MODE0)	/* dss_data9.dss_data9 */
+			OMAP3_CORE1_IOPAD(0x20f0, PIN_OUTPUT | MUX_MODE0)	/* dss_data10.dss_data10 */
+			OMAP3_CORE1_IOPAD(0x20f2, PIN_OUTPUT | MUX_MODE0)	/* dss_data11.dss_data11 */
+			OMAP3_CORE1_IOPAD(0x20f4, PIN_OUTPUT | MUX_MODE0)	/* dss_data12.dss_data12 */
+			OMAP3_CORE1_IOPAD(0x20f6, PIN_OUTPUT | MUX_MODE0)	/* dss_data13.dss_data13 */
+			OMAP3_CORE1_IOPAD(0x20f8, PIN_OUTPUT | MUX_MODE0)	/* dss_data14.dss_data14 */
+			OMAP3_CORE1_IOPAD(0x20fa, PIN_OUTPUT | MUX_MODE0)	/* dss_data15.dss_data15 */
+			OMAP3_CORE1_IOPAD(0x20fc, PIN_OUTPUT | MUX_MODE0)	/* dss_data16.dss_data16 */
+			OMAP3_CORE1_IOPAD(0x20fe, PIN_OUTPUT | MUX_MODE0)	/* dss_data17.dss_data17 */
+			OMAP3_CORE1_IOPAD(0x2100, PIN_OUTPUT | MUX_MODE0)	/* dss_data18.dss_data18 */
+			OMAP3_CORE1_IOPAD(0x2102, PIN_OUTPUT | MUX_MODE0)	/* dss_data19.dss_data19 */
+			OMAP3_CORE1_IOPAD(0x2104, PIN_OUTPUT | MUX_MODE0)	/* dss_data20.dss_data20 */
+			OMAP3_CORE1_IOPAD(0x2106, PIN_OUTPUT | MUX_MODE0)	/* dss_data21.dss_data21 */
+			OMAP3_CORE1_IOPAD(0x2108, PIN_OUTPUT | MUX_MODE0)	/* dss_data22.dss_data22 */
+			OMAP3_CORE1_IOPAD(0x210a, PIN_OUTPUT | MUX_MODE0)	/* dss_data23.dss_data23 */
+		>;
+	};
+};
+
+&vpll1 {
+	/* Needed for DSS */
+	regulator-name = "vdds_dsi";
+
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+};
+
+&dss {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&dss_dpi_pins>;
+
+	vdds_dsi-supply = <&vpll1>;
+	vdda_dac-supply = <&vdac>;
+
+	port {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		dpi_dvi_out: endpoint@0 {
+			reg = <0>;
+			remote-endpoint = <&tfp410_in>;
+			data-lines = <24>;
+		};
+
+		endpoint@1 {
+			reg = <1>;
+		};
+	};
+};
+
+&venc {
+	status = "okay";
+
+	vdda-supply = <&vdac>;
+
+	port {
+		venc_out: endpoint {
+			remote-endpoint = <&tv_connector_in>;
+			ti,channels = <2>;
+		};
+	};
+};
diff --git a/arch/arm/dts/omap3-u-boot.dtsi b/arch/arm/dts/omap3-u-boot.dtsi
index 32bea6b..96d8ac5 100644
--- a/arch/arm/dts/omap3-u-boot.dtsi
+++ b/arch/arm/dts/omap3-u-boot.dtsi
@@ -78,4 +78,5 @@
 
 &i2c1 {
 	u-boot,dm-spl;
+	clock-frequency = <100000>;
 };
diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2600.h b/arch/arm/include/asm/arch-aspeed/scu_ast2600.h
index 7c5aab9..251bfa2 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2600.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2600.h
@@ -87,6 +87,9 @@
 #define SCU_HWSTRAP1_CPU_FREQ_SHIFT		8
 #define SCU_HWSTRAP1_MAC2_INTF			BIT(7)
 #define SCU_HWSTRAP1_MAC1_INTF			BIT(6)
+#define SCU_HWSTRAP1_BOOT_EMMC			BIT(2)
+
+#define SCU_HWSTRAP2_BOOT_UART			BIT(8)
 
 #define SCU_EFUSE_DIS_DP			BIT(17)
 #define SCU_EFUSE_DIS_VGA			BIT(14)
diff --git a/arch/arm/include/asm/arch-npcm7xx/aes.h b/arch/arm/include/asm/arch-npcm7xx/aes.h
new file mode 100644
index 0000000..255efcb
--- /dev/null
+++ b/arch/arm/include/asm/arch-npcm7xx/aes.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _NPCM_AES_H_
+#define _NPCM_AES_H_
+
+#define AES_OP_ENCRYPT          0
+#define AES_OP_DECRYPT          1
+#define SIZE_AES_BLOCK          (AES128_KEY_LENGTH)
+
+struct npcm_aes_regs {
+	unsigned char reserved_0[0x400];    // 0x000
+	unsigned int aes_key_0;             // 0x400
+	unsigned int aes_key_1;             // 0x404
+	unsigned int aes_key_2;             // 0x408
+	unsigned int aes_key_3;             // 0x40c
+	unsigned char reserved_1[0x30];     // 0x410
+	unsigned int aes_iv_0;              // 0x440
+	unsigned char reserved_2[0x1c];     // 0x444
+	unsigned int aes_ctr_0;             // 0x460
+	unsigned char reserved_3[0x0c];     // 0x464
+	unsigned int aes_busy;              // 0x470
+	unsigned char reserved_4[0x04];     // 0x474
+	unsigned int aes_sk;                // 0x478
+	unsigned char reserved_5[0x14];     // 0x47c
+	unsigned int aes_prev_iv_0;         // 0x490
+	unsigned char reserved_6[0x0c];     // 0x494
+	unsigned int aes_din_dout;          // 0x4a0
+	unsigned char reserved_7[0x1c];     // 0x4a4
+	unsigned int aes_control;           // 0x4c0
+	unsigned int aes_version;           // 0x4c4
+	unsigned int aes_hw_flags;          // 0x4c8
+	unsigned char reserved_8[0x28];     // 0x4cc
+	unsigned int aes_sw_reset;          // 0x4f4
+	unsigned char reserved_9[0x08];     // 0x4f8
+	unsigned int aes_fifo_data;         // 0x500
+	unsigned char reserved_10[0xfc];    // 0x504
+	unsigned int aes_fifo_status;       // 0x600
+};
+
+#define AES_BUSY_BIT            BIT(0)
+#define SW_RESET_BIT            BIT(0)
+#define AES_SK_BIT              BIT(0)
+
+#define DIN_FIFO_FULL           BIT(0)
+#define DIN_FIFO_EMPTY          BIT(1)
+#define DOUT_FIFO_FULL          BIT(2)
+#define DOUT_FIFO_EMPTY         BIT(3)
+#define DIN_FIFO_OVERFLOW       BIT(4)
+#define DOUT_FIFO_UNDERFLOW     BIT(5)
+
+int npcm_aes_select_key(u8 fkeyind);
+
+#endif
diff --git a/arch/arm/include/asm/arch-npcm7xx/otp.h b/arch/arm/include/asm/arch-npcm7xx/otp.h
new file mode 100644
index 0000000..11d1e85
--- /dev/null
+++ b/arch/arm/include/asm/arch-npcm7xx/otp.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _NPCM_OTP_H_
+#define _NPCM_OTP_H_
+
+#ifdef CONFIG_ARCH_NPCM8XX
+enum {
+	NPCM_KEY_SA    = 0,
+	NPCM_FUSE_SA   = 0,
+	NPCM_NUM_OF_SA   = 1
+};
+#else
+enum {
+	NPCM_KEY_SA    = 0,
+	NPCM_FUSE_SA   = 1,
+	NPCM_NUM_OF_SA = 2
+};
+#endif
+
+struct npcm_otp_regs {
+	unsigned int fst;
+	unsigned int faddr;
+	unsigned int fdata;
+	unsigned int fcfg;
+	unsigned int fustrap_fkeyind;
+	unsigned int fctl;
+};
+
+#define FST_RDY                 BIT(0)
+#define FST_RDST                BIT(1)
+#define FST_RIEN                BIT(2)
+
+#ifdef CONFIG_ARCH_NPCM8XX
+#define FADDR_BYTEADDR(addr)        ((addr) << 3)
+#define FADDR_BITPOS(pos)           ((pos) << 0)
+#define FADDR_VAL(addr, pos)        (FADDR_BITPOS(pos) | FADDR_BYTEADDR(addr))
+#define FADDR_IN_PROG               BIT(16)
+#else
+#define FADDR_BYTEADDR(addr)    ((addr) << 0)
+#define FADDR_BITPOS(pos)       ((pos) << 10)
+#define FADDR_VAL(addr, pos)    (FADDR_BYTEADDR(addr) | FADDR_BITPOS(pos))
+#define FADDR_IN_PROG               BIT(16)
+#endif
+
+#define FDATA_MASK              (0xff)
+
+#define FUSTRAP_O_SECBOOT       BIT(23)
+
+#define FCFG_FDIS               BIT(31)
+
+#define FKEYIND_KVAL            BIT(0)
+#define FKEYIND_KSIZE_MASK      (0x00000070)
+#define FKEYIND_KSIZE_128       (0x40)
+#define FKEYIND_KSIZE_192       (0x50)
+#define FKEYIND_KSIZE_256       (0x60)
+#define FKEYIND_KIND_MASK       (0x000c0000)
+#define FKEYIND_KIND_KEY(indx)  ((indx) << 18)
+
+// Program cycle initiation values (sequence of two adjacent writes)
+#define PROGRAM_ARM             0x1
+#define PROGRAM_INIT            0xBF79E5D0
+
+#define OTP2_BASE               0xF018A000
+#define FUSTRAP                 (OTP2_BASE + 0x10)
+
+// Read cycle initiation value
+#define READ_INIT               0x02
+
+// Value to clean FDATA contents
+#define FDATA_CLEAN_VALUE       0x01
+
+#ifdef CONFIG_ARCH_NPCM8XX
+#define NPCM_OTP_ARR_BYTE_SIZE        8192
+#else
+#define NPCM_OTP_ARR_BYTE_SIZE        1024
+#endif
+
+#define MIN_PROGRAM_PULSES               4
+#define MAX_PROGRAM_PULSES               20
+#define NPCM_OTP_ARR_BYTE_SIZE        1024
+
+int fuse_prog_image(u32 bank, uintptr_t address);
+int  fuse_program_data(u32 bank, u32 word, u8 *data, u32 size);
+int  npcm_otp_select_key(u8 key_index);
+bool npcm_otp_is_fuse_array_disabled(u32 arr);
+void npcm_otp_nibble_parity_ecc_encode(u8 *datain, u8 *dataout, u32 size);
+void npcm_otp_majority_rule_ecc_encode(u8 *datain, u8 *dataout, u32 size);
+void npcm_arch_preboot_os(void);
+
+#endif
diff --git a/arch/arm/mach-aspeed/ast2600/spl.c b/arch/arm/mach-aspeed/ast2600/spl.c
index 6c49d6a..53c8a15 100644
--- a/arch/arm/mach-aspeed/ast2600/spl.c
+++ b/arch/arm/mach-aspeed/ast2600/spl.c
@@ -7,6 +7,7 @@
 #include <dm.h>
 #include <spl.h>
 #include <init.h>
+#include <linux/err.h>
 #include <asm/io.h>
 #include <asm/arch/scu_ast2600.h>
 #include <asm/global_data.h>
@@ -21,8 +22,37 @@
 	dram_init();
 }
 
+/*
+ * Try to detect the boot mode. Fallback to the default,
+ * memory mapped SPI XIP booting if detection failed.
+ */
 u32 spl_boot_device(void)
 {
+	int rc;
+	struct udevice *scu_dev;
+	struct ast2600_scu *scu;
+
+	rc = uclass_get_device_by_driver(UCLASS_CLK,
+					 DM_DRIVER_GET(aspeed_ast2600_scu), &scu_dev);
+	if (rc) {
+		debug("%s: failed to get SCU driver\n", __func__);
+		goto out;
+	}
+
+	scu = devfdt_get_addr_ptr(scu_dev);
+	if (IS_ERR_OR_NULL(scu)) {
+		debug("%s: failed to get SCU base\n", __func__);
+		goto out;
+	}
+
+	/* boot from UART has higher priority */
+	if (scu->hwstrap2 & SCU_HWSTRAP2_BOOT_UART)
+		return BOOT_DEVICE_UART;
+
+	if (scu->hwstrap1 & SCU_HWSTRAP1_BOOT_EMMC)
+		return BOOT_DEVICE_MMC1;
+
+out:
 	return BOOT_DEVICE_RAM;
 }
 
diff --git a/arch/arm/mach-aspeed/ast2600/u-boot-spl.lds b/arch/arm/mach-aspeed/ast2600/u-boot-spl.lds
new file mode 100644
index 0000000..22b4e16
--- /dev/null
+++ b/arch/arm/mach-aspeed/ast2600/u-boot-spl.lds
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2004-2008 Texas Instruments
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * (C) Copyright 2022
+ * Chia-Wei Wang <chiawei_wang@aspeedtech.com>
+ */
+
+MEMORY { .nor : ORIGIN = CONFIG_SPL_TEXT_BASE,
+		LENGTH = CONFIG_SPL_SIZE_LIMIT }
+MEMORY { .bss : ORIGIN = CONFIG_SPL_BSS_START_ADDR,
+		LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text :
+	{
+		__image_copy_start = .;
+		*(.vectors)
+		CPUDIR/start.o (.text*)
+		*(.text*)
+		*(.glue*)
+	} > .nor
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } > .nor
+
+	. = ALIGN(4);
+	.data : {
+		*(.data*)
+	} > .nor
+
+	. = ALIGN(4);
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*)));
+	} > .nor
+
+	. = ALIGN(4);
+	.binman_sym_table : {
+		__binman_sym_start = .;
+		KEEP(*(SORT(.binman_sym*)));
+		__binman_sym_end = .;
+	} > .nor
+
+	. = ALIGN(4);
+
+	__image_copy_end = .;
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	} > .nor
+
+	.end :
+	{
+		*(.__end)
+	} > .nor
+
+	_image_binary_end = .;
+
+	.bss : {
+		__bss_start = .;
+		*(.bss*)
+		 . = ALIGN(4);
+		__bss_end = .;
+	} > .bss
+
+	__bss_size = __bss_end - __bss_start;
+}
+
+#if defined(IMAGE_MAX_SIZE)
+ASSERT(__image_copy_end - __image_copy_start <= (IMAGE_MAX_SIZE), \
+	"SPL image too big");
+#endif
+
+#if defined(CONFIG_SPL_BSS_MAX_SIZE)
+ASSERT(__bss_end - __bss_start <= (CONFIG_SPL_BSS_MAX_SIZE), \
+	"SPL image BSS too big");
+#endif
+
+#if defined(CONFIG_SPL_MAX_FOOTPRINT)
+ASSERT(__bss_end - _start <= (CONFIG_SPL_MAX_FOOTPRINT), \
+	"SPL image plus BSS too big");
+#endif
diff --git a/arch/arm/mach-hpe/Makefile b/arch/arm/mach-hpe/Makefile
new file mode 100644
index 0000000..afe5f7a
--- /dev/null
+++ b/arch/arm/mach-hpe/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SOC_GXP) += gxp/
diff --git a/arch/arm/mach-hpe/gxp/Kconfig b/arch/arm/mach-hpe/gxp/Kconfig
new file mode 100644
index 0000000..2d43133
--- /dev/null
+++ b/arch/arm/mach-hpe/gxp/Kconfig
@@ -0,0 +1,9 @@
+if ARCH_GXP
+
+config SOC_GXP
+	bool
+	select CPU_V7A
+
+source "board/hpe/gxp/Kconfig"
+
+endif
diff --git a/arch/arm/mach-hpe/gxp/Makefile b/arch/arm/mach-hpe/gxp/Makefile
new file mode 100644
index 0000000..f3cc668
--- /dev/null
+++ b/arch/arm/mach-hpe/gxp/Makefile
@@ -0,0 +1 @@
+obj-y += reset.o
diff --git a/arch/arm/mach-hpe/gxp/reset.c b/arch/arm/mach-hpe/gxp/reset.c
new file mode 100644
index 0000000..ce018a3
--- /dev/null
+++ b/arch/arm/mach-hpe/gxp/reset.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * GXP driver
+ *
+ * (C) Copyright 2022 Hewlett Packard Enterprise Development LP.
+ * Author: Nick Hawkins <nick.hawkins@hpe.com>
+ * Author: Jean-Marie Verdun <verdun@hpe.com>
+ */
+
+#include <asm/io.h>
+
+#define GXP_CCR	0xc0000000
+
+/* empty to satisfy current lowlevel_init, can be removed any time */
+void lowlevel_init(void)
+{
+}
+
+void reset_cpu(ulong ignored)
+{
+	writel(1, GXP_CCR);
+
+	while (1)
+		;	/* loop forever till reset */
+}
diff --git a/board/armltd/corstone1000/Kconfig b/board/armltd/corstone1000/Kconfig
new file mode 100644
index 0000000..709674d
--- /dev/null
+++ b/board/armltd/corstone1000/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_CORSTONE1000
+
+config SYS_BOARD
+	default "corstone1000"
+
+config SYS_VENDOR
+	default "armltd"
+
+config SYS_CONFIG_NAME
+	default "corstone1000"
+
+endif
diff --git a/board/armltd/corstone1000/MAINTAINERS b/board/armltd/corstone1000/MAINTAINERS
new file mode 100644
index 0000000..8c90568
--- /dev/null
+++ b/board/armltd/corstone1000/MAINTAINERS
@@ -0,0 +1,7 @@
+CORSTONE1000 BOARD
+M:	Rui Miguel Silva <rui.silva@linaro.org>
+M:	Vishnu Banavath <vishnu.banavath@arm.com>
+S:	Maintained
+F:	board/armltd/corstone1000/
+F:	include/configs/corstone1000.h
+F:	configs/corstone1000_defconfig
diff --git a/board/armltd/corstone1000/Makefile b/board/armltd/corstone1000/Makefile
new file mode 100644
index 0000000..77a82c28
--- /dev/null
+++ b/board/armltd/corstone1000/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2022 Arm Limited
+# (C) Copyright 2022 Linaro
+# Rui Miguel Silva <rui.silva@linaro.org>
+
+obj-y	:= corstone1000.o
diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c
new file mode 100644
index 0000000..4f4b96a
--- /dev/null
+++ b/board/armltd/corstone1000/corstone1000.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * (C) Copyright 2022 Linaro
+ * Rui Miguel Silva <rui.silva@linaro.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <netdev.h>
+#include <dm/platform_data/serial_pl01x.h>
+#include <asm/armv8/mmu.h>
+#include <asm/global_data.h>
+
+static struct mm_region corstone1000_mem_map[] = {
+	{
+		/* CVM */
+		.virt = 0x02000000UL,
+		.phys = 0x02000000UL,
+		.size = 0x02000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			PTE_BLOCK_INNER_SHARE
+	}, {
+		/* QSPI */
+		.virt = 0x08000000UL,
+		.phys = 0x08000000UL,
+		.size = 0x08000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			PTE_BLOCK_INNER_SHARE
+	}, {
+		/* Host Peripherals */
+		.virt = 0x1A000000UL,
+		.phys = 0x1A000000UL,
+		.size = 0x26000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			PTE_BLOCK_NON_SHARE |
+			PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* USB */
+		.virt = 0x40200000UL,
+		.phys = 0x40200000UL,
+		.size = 0x00100000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			PTE_BLOCK_NON_SHARE |
+			PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* ethernet */
+		.virt = 0x40100000UL,
+		.phys = 0x40100000UL,
+		.size = 0x00100000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			PTE_BLOCK_NON_SHARE |
+			PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* OCVM */
+		.virt = 0x80000000UL,
+		.phys = 0x80000000UL,
+		.size = 0x80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			PTE_BLOCK_INNER_SHARE
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = corstone1000_mem_map;
+
+int board_init(void)
+{
+	return 0;
+}
+
+int dram_init(void)
+{
+	gd->ram_size = PHYS_SDRAM_1_SIZE;
+
+	return 0;
+}
+
+int dram_init_banksize(void)
+{
+	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+	gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
+
+	return 0;
+}
+
+void reset_cpu(ulong addr)
+{
+}
diff --git a/board/armltd/corstone1000/corstone1000.env b/board/armltd/corstone1000/corstone1000.env
new file mode 100644
index 0000000..b24ff07
--- /dev/null
+++ b/board/armltd/corstone1000/corstone1000.env
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+usb_pgood_delay=250
+boot_bank_flag=0x08002000
+kernel_addr_bank_0=0x083EE000
+kernel_addr_bank_1=0x0936E000
+retrieve_kernel_load_addr=
+	if itest.l *${boot_bank_flag} == 0; then
+		setenv kernel_addr $kernel_addr_bank_0;
+	else
+		setenv kernel_addr $kernel_addr_bank_1;
+	fi;
+kernel_addr_r=0x88200000
diff --git a/board/hpe/gxp/Kconfig b/board/hpe/gxp/Kconfig
new file mode 100644
index 0000000..5b154a3
--- /dev/null
+++ b/board/hpe/gxp/Kconfig
@@ -0,0 +1,46 @@
+choice
+	prompt "SoC select"
+
+config TARGET_GXP
+	bool "GXP"
+	select DM
+	select SOC_GXP
+	imply CMD_DM
+
+config TARGET_GXP2
+	bool "GXP2"
+	select DM
+	select SOC_GXP
+	select GXP_ECC
+	imply CMD_DM
+
+endchoice
+
+choice
+	prompt "GXP VROM size"
+	default GXP_VROM_64MB
+	optional
+
+config GXP_VROM_64MB
+	bool "64MB"
+
+config GXP_VROM_32MB
+	bool "32MB"
+endchoice
+
+config GXP_ECC
+	bool "Enable memory ECC protected"
+	help
+	  Use half of memory to enable ECC protected
+
+config SYS_BOARD
+	default "gxp"
+
+config SYS_VENDOR
+	default "hpe"
+
+config SYS_CONFIG_NAME
+	default "gxp"
+
+config SYS_TEXT_BASE
+	default 0x50000000
diff --git a/board/hpe/gxp/Makefile b/board/hpe/gxp/Makefile
new file mode 100644
index 0000000..775d6bf
--- /dev/null
+++ b/board/hpe/gxp/Makefile
@@ -0,0 +1 @@
+obj-y += gxp_board.o
diff --git a/board/hpe/gxp/gxp.env b/board/hpe/gxp/gxp.env
new file mode 100644
index 0000000..4760bf1
--- /dev/null
+++ b/board/hpe/gxp/gxp.env
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+recover_file=openbmc-hpe-recovery-image.mtd
+recover_cmd=usb start; mw.b 0xD100000D 0x40;
+	if fatload usb 0 0x50000000 $recover_file 0x4C0000 0x80000; then
+		setenv bootargs console=ttyS0,115200 recovery;
+		setenv force_recovery;
+		saveenv;
+		bootm  0x50000000;
+	else
+		while itest 0 < 1; do
+			mw.b 0xd1000005 0xc0;
+			sleep .1;
+		mw.b 0xd1000005 0x00;
+		sleep .1;
+		done;
+	fi;
+	reset;
+spiboot=if itest.b *0xD10000B2 == 6; then
+		run recover_cmd;
+	fi;
+	if printenv force_recovery; then
+		run recover_cmd;
+	else
+		bootm 0xfc080000;
+		run recover_cmd;
+	fi;
diff --git a/board/hpe/gxp/gxp_board.c b/board/hpe/gxp/gxp_board.c
new file mode 100644
index 0000000..d94d9b8
--- /dev/null
+++ b/board/hpe/gxp/gxp_board.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * GXP timer driver
+ *
+ * (C) Copyright 2022 Hewlett Packard Enterprise Development LP.
+ * Author: Nick Hawkins <nick.hawkins@hpe.com>
+ * Author: Jean-Marie Verdun <verdun@hpe.com>
+ */
+
+#include <linux/sizes.h>
+#include <asm/io.h>
+#include <dm.h>
+#include <dm/uclass.h>
+#include <ram.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ECHI_CMD 0xcefe0010
+
+int board_init(void)
+{
+	writel(0x00080002, ECHI_CMD);
+
+	return 0;
+}
+
+int dram_init(void)
+{
+	if (IS_ENABLED(CONFIG_TARGET_GXP)) {
+		if (IS_ENABLED(CONFIG_GXP_ECC)) {
+			/* 0x0f800000 */
+			gd->ram_size = SZ_128M + SZ_64M + SZ_32M + SZ_16M + SZ_8M;
+		} else {
+			/* 0x1f000000 */
+			gd->ram_size = SZ_256M + SZ_128M + SZ_64M + SZ_32M + SZ_16M;
+		}
+
+		if (IS_ENABLED(CONFIG_GXP_VROM_64MB)) {
+			if (IS_ENABLED(CONFIG_GXP_ECC)) {
+				/* 0x0c000000 */
+				gd->ram_size = SZ_128M + SZ_64M;
+			} else {
+				/* 0x18000000 */
+				gd->ram_size = SZ_256M + SZ_128M;
+			}
+		}
+
+		if (IS_ENABLED(CONFIG_GXP_VROM_32MB)) {
+			if (IS_ENABLED(CONFIG_GXP_ECC)) {
+				/* 0x0e000000 */
+				gd->ram_size = SZ_128M + SZ_64M + SZ_32M;
+			} else {
+				/* 0x1c000000 */
+				gd->ram_size = SZ_256M + SZ_128M + SZ_64M;
+			}
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_TARGET_GXP2)) {
+		/* 0x1b200000 */
+		gd->ram_size = SZ_256M + SZ_128M + SZ_32M + SZ_16M + SZ_2M;
+		if (IS_ENABLED(CONFIG_GXP_VROM_64MB)) {
+			/* 0x14000000 */
+			gd->ram_size = SZ_256M + SZ_64M;
+		}
+
+		if (IS_ENABLED(CONFIG_GXP_VROM_32MB)) {
+			/* 0x18000000 */
+			gd->ram_size = SZ_256M + SZ_128M;
+		}
+	}
+
+	return 0;
+}
+
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 9a0b720..dea3729 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1160,6 +1160,11 @@
 	help
 	  Load a binary file over serial line.
 
+config CMD_LOADM
+	bool "loadm"
+	help
+	  Load a binary over memory mapped.
+
 config CMD_LOADS
 	bool "loads"
 	default y
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 827fcd9..37ce659 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -35,6 +35,18 @@
 static size_t image_size;
 
 /**
+ * efi_get_image_parameters() - return image parameters
+ *
+ * @img_addr:		address of loaded image in memory
+ * @img_size:		size of loaded image
+ */
+void efi_get_image_parameters(void **img_addr, size_t *img_size)
+{
+	*img_addr = image_addr;
+	*img_size = image_size;
+}
+
+/**
  * efi_clear_bootdev() - clear boot device
  */
 static void efi_clear_bootdev(void)
diff --git a/cmd/load.c b/cmd/load.c
index 7e4a552..1224a7f 100644
--- a/cmd/load.c
+++ b/cmd/load.c
@@ -1063,6 +1063,44 @@
 
 #endif
 
+#if defined(CONFIG_CMD_LOADM)
+static int do_load_memory_bin(struct cmd_tbl *cmdtp, int flag, int argc,
+			      char *const argv[])
+{
+	ulong	addr, dest, size;
+	void	*src, *dst;
+
+	if (argc != 4)
+		return CMD_RET_USAGE;
+
+	addr = simple_strtoul(argv[1], NULL, 16);
+
+	dest = simple_strtoul(argv[2], NULL, 16);
+
+	size = simple_strtoul(argv[3], NULL, 16);
+
+	if (!size) {
+		printf("loadm: can not load zero bytes\n");
+		return 1;
+	}
+
+	src = map_sysmem(addr, size);
+	dst = map_sysmem(dest, size);
+
+	memcpy(dst, src, size);
+
+	unmap_sysmem(src);
+	unmap_sysmem(dst);
+
+	if (IS_ENABLED(CONFIG_CMD_BOOTEFI))
+		efi_set_bootdev("Mem", "", "", map_sysmem(dest, 0), size);
+
+	printf("loaded bin to memory: size: %lu\n", size);
+
+	return 0;
+}
+#endif
+
 /* -------------------------------------------------------------------- */
 
 #if defined(CONFIG_CMD_LOADS)
@@ -1137,3 +1175,13 @@
 );
 
 #endif	/* CONFIG_CMD_LOADB */
+
+#if defined(CONFIG_CMD_LOADM)
+U_BOOT_CMD(
+	loadm, 4, 0,	do_load_memory_bin,
+	"load binary blob from source address to destination address",
+	"[src_addr] [dst_addr] [size]\n"
+	"     - load a binary blob from one memory location to other"
+	" from src_addr to dst_addr by size bytes"
+);
+#endif /* CONFIG_CMD_LOADM */
diff --git a/cmd/misc.c b/cmd/misc.c
index bcd8d96..ec32b41 100644
--- a/cmd/misc.c
+++ b/cmd/misc.c
@@ -44,7 +44,6 @@
 static int do_misc_op(struct cmd_tbl *cmdtp, int flag,
 		      int argc, char *const argv[], enum misc_op op)
 {
-	int (*misc_op)(struct udevice *, int, void *, int);
 	struct udevice *dev;
 	int offset;
 	void *buf;
@@ -62,11 +61,10 @@
 	size = hextoul(argv[3], NULL);
 
 	if (op == MISC_OP_READ)
-		misc_op = misc_read;
+		ret = misc_read(dev, offset, buf, size);
 	else
-		misc_op = misc_write;
+		ret = misc_write(dev, offset, buf, size);
 
-	ret = misc_op(dev, offset, buf, size);
 	if (ret < 0) {
 		if (ret == -ENOSYS) {
 			printf("The device does not support %s\n",
diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
new file mode 100644
index 0000000..49a651a
--- /dev/null
+++ b/configs/corstone1000_defconfig
@@ -0,0 +1,52 @@
+CONFIG_ARM=y
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_TARGET_CORSTONE1000=y
+CONFIG_SYS_TEXT_BASE=0x80000000
+CONFIG_SYS_MALLOC_LEN=0x2000000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEFAULT_DEVICE_TREE="corstone1000-mps3"
+CONFIG_IDENT_STRING=" corstone1000 aarch64 "
+CONFIG_SYS_LOAD_ADDR=0x82100000
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x83f00000
+CONFIG_FIT=y
+CONFIG_BOOTDELAY=3
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyAMA0 loglevel=9 ip=dhcp earlyprintk"
+CONFIG_BOOTCOMMAND="run retrieve_kernel_load_addr; echo Loading kernel from $kernel_addr to memory ... ; loadm $kernel_addr $kernel_addr_r 0xc00000; usb start; usb reset; run distro_bootcmd; bootefi $kernel_addr_r $fdtcontroladdr;"
+CONFIG_CONSOLE_RECORD=y
+CONFIG_LOGLEVEL=7
+# CONFIG_DISPLAY_CPUINFO is not set
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_SYS_PROMPT="corstone1000# "
+CONFIG_SYS_MAXARGS=64
+CONFIG_SYS_CBSIZE=512
+# CONFIG_CMD_CONSOLE is not set
+CONFIG_CMD_BOOTZ=y
+# CONFIG_CMD_XIMG is not set
+CONFIG_CMD_LOADM=y
+# CONFIG_CMD_LOADS is not set
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_RTC=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_GETTIME=y
+CONFIG_OF_CONTROL=y
+CONFIG_VERSION_VARIABLE=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_REGMAP=y
+CONFIG_MISC=y
+# CONFIG_MMC is not set
+CONFIG_PHYLIB=y
+CONFIG_PHY_SMSC=y
+CONFIG_DM_ETH=y
+CONFIG_SMC911X=y
+CONFIG_PHY=y
+CONFIG_RAM=y
+CONFIG_DM_RTC=y
+CONFIG_RTC_EMULATION=y
+CONFIG_DM_SERIAL=y
+CONFIG_USB=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/devkit8000_defconfig b/configs/devkit8000_defconfig
index 4e144a9..a5e9f61 100644
--- a/configs/devkit8000_defconfig
+++ b/configs/devkit8000_defconfig
@@ -2,21 +2,26 @@
 CONFIG_ARCH_OMAP2PLUS=y
 CONFIG_SYS_TEXT_BASE=0x80100000
 CONFIG_SYS_MALLOC_LEN=0x40000
-CONFIG_SYS_MALLOC_F_LEN=0x400
+CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_NR_DRAM_BANKS=2
+CONFIG_DEFAULT_DEVICE_TREE="omap3-devkit8000"
 CONFIG_SPL_TEXT_BASE=0x40200000
 CONFIG_TARGET_DEVKIT8000=y
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x400
 CONFIG_SPL=y
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x4020ff00
 CONFIG_BOOTCOMMAND="run autoboot"
+CONFIG_USE_PREBOOT=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_SPL_MAX_SIZE=0xec00
 CONFIG_SPL_BSS_START_ADDR=0x80000500
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SYS_SPL_MALLOC=y
 CONFIG_HAS_CUSTOM_SPL_MALLOC_START=y
 CONFIG_CUSTOM_SYS_SPL_MALLOC_ADDR=0x80208000
+# CONFIG_SPL_FS_EXT4 is not set
 CONFIG_SPL_NAND_DRIVERS=y
 CONFIG_SPL_NAND_ECC=y
 CONFIG_SPL_NAND_SIMPLE=y
@@ -31,8 +36,8 @@
 CONFIG_SYS_MAXARGS=64
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_SPL=y
-CONFIG_CMD_SPL_NAND_OFS=0x680000
-CONFIG_CMD_SPL_WRITE_SIZE=0x400
+CONFIG_CMD_SPL_NAND_OFS=0x280000
+CONFIG_CMD_SPL_WRITE_SIZE=0x20000
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
@@ -50,16 +55,25 @@
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nand0=nand"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=nand:512k(x-loader),1920k(u-boot),128k(u-boot-env),4m(kernel),-(fs)"
+# CONFIG_ISO_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="clocks clock-names interrupt-parent"
 CONFIG_ENV_OVERWRITE=y
 CONFIG_ENV_IS_IN_NAND=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_NET_RETRY_COUNT=20
 CONFIG_BOOTP_SEND_HOSTNAME=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_SPL_OF_TRANSLATE=y
 CONFIG_SYS_I2C_LEGACY=y
 CONFIG_SPL_SYS_I2C_LEGACY=y
 CONFIG_TWL4030_LED=y
 CONFIG_MMC_OMAP_HS=y
+CONFIG_DM_I2C=y
 CONFIG_MTD=y
 CONFIG_MTD_RAW_NAND=y
 CONFIG_NAND_OMAP_ECCSCHEME_HAM1_CODE_HW=y
@@ -70,7 +84,6 @@
 CONFIG_SYS_NAND_BUSWIDTH_16BIT=y
 CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y
 CONFIG_SYS_NAND_U_BOOT_OFFS=0x80000
+CONFIG_DM_ETH=y
 CONFIG_DRIVER_DM9000=y
-CONFIG_CONS_INDEX=3
 CONFIG_JFFS2_NAND=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/evb-ast2600_defconfig b/configs/evb-ast2600_defconfig
index bfd0a5f..a91a53d 100644
--- a/configs/evb-ast2600_defconfig
+++ b/configs/evb-ast2600_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_SYS_DCACHE_OFF=y
 CONFIG_SPL_SYS_THUMB_BUILD=y
+CONFIG_SPL_LDSCRIPT="arch/arm/mach-aspeed/ast2600/u-boot-spl.lds"
 CONFIG_ARCH_ASPEED=y
 CONFIG_SYS_TEXT_BASE=0x80000000
 CONFIG_SYS_MALLOC_LEN=0x2000000
@@ -32,10 +33,13 @@
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_SIZE_LIMIT_SUBTRACT_GD=y
 CONFIG_SPL_SIZE_LIMIT_SUBTRACT_MALLOC=y
-CONFIG_SPL_NO_BSS_LIMIT=y
+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
+CONFIG_SPL_BSS_START_ADDR=0x83000000
+CONFIG_SPL_BSS_MAX_SIZE=0x1000000
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000000
+CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_FIT_IMAGE_TINY=y
 CONFIG_SPL_DM_RESET=y
 CONFIG_SPL_RAM_SUPPORT=y
diff --git a/configs/gxp_defconfig b/configs/gxp_defconfig
new file mode 100644
index 0000000..4408c6c
--- /dev/null
+++ b/configs/gxp_defconfig
@@ -0,0 +1,60 @@
+CONFIG_ARM=y
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_SYS_THUMB_BUILD=y
+CONFIG_ARCH_GXP=y
+CONFIG_SYS_MALLOC_LEN=0x4000000
+CONFIG_GXP_VROM_64MB=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x60000
+CONFIG_ENV_SECT_SIZE=0x10000
+CONFIG_DEFAULT_DEVICE_TREE="hpe-bmc-dl360gen10"
+CONFIG_ENV_OFFSET_REDUND=0x70000
+CONFIG_SYS_LOAD_ADDR=0x40100000
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x2000000
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_BOOTDELAY=5
+CONFIG_AUTOBOOT_KEYED=y
+CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
+CONFIG_AUTOBOOT_STOP_STR=" "
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="earlyprintk console=ttyS2,115200 user_debug=31"
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="run spiboot"
+# CONFIG_DISPLAY_CPUINFO is not set
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="gxp# "
+# CONFIG_BOOTM_NETBSD is not set
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
+CONFIG_CMD_GPT=y
+# CONFIG_RANDOM_UUID is not set
+CONFIG_CMD_MISC=y
+CONFIG_CMD_FAT=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
+CONFIG_NETCONSOLE=y
+CONFIG_MISC=y
+# CONFIG_MMC is not set
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SF_DEFAULT_MODE=3
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_SST=y
+CONFIG_SPI_FLASH_WINBOND=y
+# CONFIG_POWER is not set
+CONFIG_RAM=y
+CONFIG_DM_SERIAL=y
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_GXP_SPI=y
+CONFIG_TIMER=y
+CONFIG_GXP_TIMER=y
+CONFIG_SHA512=y
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 9d72e39..46a9b16 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -47,6 +47,7 @@
 CONFIG_CMD_GPT_RENAME=y
 CONFIG_CMD_IDE=y
 CONFIG_CMD_I2C=y
+CONFIG_CMD_LOADM=y
 CONFIG_CMD_OSD=y
 CONFIG_CMD_PCI=y
 CONFIG_CMD_READ=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index be40562..86204c7 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -67,6 +67,7 @@
 CONFIG_CMD_GPT_RENAME=y
 CONFIG_CMD_IDE=y
 CONFIG_CMD_I2C=y
+CONFIG_CMD_LOADM=y
 CONFIG_CMD_LSBLK=y
 CONFIG_CMD_MUX=y
 CONFIG_CMD_OSD=y
diff --git a/doc/device-tree-bindings/spi/hpe,gxp-spi.yaml b/doc/device-tree-bindings/spi/hpe,gxp-spi.yaml
new file mode 100644
index 0000000..5e23de1
--- /dev/null
+++ b/doc/device-tree-bindings/spi/hpe,gxp-spi.yaml
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/spi/hpe,gxp-spi.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: HPE GXP SPI Controller
+
+maintainers:
+  - Nick Hawkins <nick.hawkins@hpe.com>
+  - Jean-Marie Verdun <verdun@hpe.com>
+
+allOf:
+  - $ref: "spi-controller.yaml#"
+
+properties:
+  compatible:
+    const: mikrotik,rb4xx-spi
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    spi@c00000200{
+          compatible = "hpe,gxp-spi";
+          reg = <0xc0000200 0x80>;
+          #address-cells = <1>;
+          #size-cells = <0>;
+    };
+
diff --git a/doc/usage/cmd/loadm.rst b/doc/usage/cmd/loadm.rst
new file mode 100644
index 0000000..b657114
--- /dev/null
+++ b/doc/usage/cmd/loadm.rst
@@ -0,0 +1,49 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+loadm command
+=============
+
+Synopsis
+--------
+
+::
+
+    loadm <src_addr> <dst_addr> <len>
+
+Description
+-----------
+
+The loadm command is used to copy memory content from source address
+to destination address and, if efi is enabled, will setup a "Mem" efi
+boot device.
+
+The number of transferred bytes must be set by bytes parameter
+
+src_addr
+    start address of the memory location to be loaded
+
+dst_addr
+    destination address of the byte stream to be loaded
+
+len
+    number of bytes to be copied in hexadecimal. Can not be 0 (zero).
+
+Example
+-------
+
+::
+
+    => loadm ${kernel_addr} ${kernel_addr_r} ${kernel_size}
+    loaded bin to memory: size: 12582912
+
+Configuration
+-------------
+
+The command is only available if CONFIG_CMD_LOADM=y.
+
+Return value
+------------
+
+The return value $? is set 0 (true) if the loading is succefull, and
+is set to 1 (false) in case of error.
+
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 7704184..8d08ea1 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -44,6 +44,7 @@
    cmd/fatload
    cmd/for
    cmd/load
+   cmd/loadm
    cmd/loady
    cmd/mbr
    cmd/md
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 675081e..12ef84c 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -6,4 +6,6 @@
 
 source drivers/crypto/aspeed/Kconfig
 
+source drivers/crypto/nuvoton/Kconfig
+
 endmenu
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 6b76256..b910518 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -8,3 +8,4 @@
 obj-y += fsl/
 obj-y += hash/
 obj-y += aspeed/
+obj-y += nuvoton/
diff --git a/drivers/crypto/nuvoton/Kconfig b/drivers/crypto/nuvoton/Kconfig
new file mode 100644
index 0000000..034fcad
--- /dev/null
+++ b/drivers/crypto/nuvoton/Kconfig
@@ -0,0 +1,14 @@
+config NPCM_AES
+	bool "Support the NPCM AES algorithm"
+	select NPCM_OTP
+	help
+	  This provides a means to encrypt and decrypt data using the NPCM
+	  AES (Advanced Encryption Standard). This algorithm uses a symmetric
+	  key and is widely used as a streaming cipher. This command only
+	  supports AES256-CBC.
+
+config NPCM_SHA
+	bool "Enable NPCM cryptographic HW SHA accelerator"
+	help
+	  This option enables support of NPCM cryptographic HW SHA accelerator.
+	  It supports SHA1 and SHA256 hashing algorithms.
diff --git a/drivers/crypto/nuvoton/Makefile b/drivers/crypto/nuvoton/Makefile
new file mode 100644
index 0000000..5a1173d
--- /dev/null
+++ b/drivers/crypto/nuvoton/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_NPCM_AES) += npcm_aes.o
+obj-$(CONFIG_NPCM_SHA) += npcm_sha.o
diff --git a/drivers/crypto/nuvoton/npcm_aes.c b/drivers/crypto/nuvoton/npcm_aes.c
new file mode 100644
index 0000000..6493ea1
--- /dev/null
+++ b/drivers/crypto/nuvoton/npcm_aes.c
@@ -0,0 +1,301 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021 Nuvoton Technology Corp.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <uboot_aes.h>
+#include <asm/io.h>
+#include <asm/arch/aes.h>
+#include <asm/arch/otp.h>
+#include <malloc.h>
+
+#define ONE_SECOND 0xC00000
+
+struct npcm_aes_priv {
+	struct npcm_aes_regs *regs;
+};
+
+static struct npcm_aes_priv *aes_priv;
+static u8 fkeyind_to_set = 0xff;
+
+static int second_timeout(u32 *addr, u32 bitmask, u32 bitpol)
+{
+	ulong time, i = 0;
+
+	time = get_timer(0);
+
+	/* default 1 second timeout */
+	while (((readl(addr) & bitmask) == bitpol) && i < ONE_SECOND)
+		i++;
+
+	if (i == ONE_SECOND) {
+		printf("%xms timeout: addr = %x, mask = %x\n", (u32)get_timer(time),
+		       *addr, bitmask);
+		return -1;
+	}
+
+	return 0;
+}
+
+int npcm_aes_select_key(u8 fkeyind)
+{
+	if (npcm_otp_is_fuse_array_disabled(NPCM_KEY_SA)) {
+		printf("AES key access denied\n");
+		return -EACCES;
+	}
+
+	if (fkeyind < 4)
+		fkeyind_to_set = fkeyind;
+
+	return 0;
+}
+
+static int npcm_aes_init(u8 dec_enc)
+{
+	struct npcm_aes_regs *regs = aes_priv->regs;
+	u32 ctrl, orgctrlval, wrtimeout;
+
+	/* reset hw */
+	writel(readl(&regs->aes_sw_reset) | SW_RESET_BIT, &regs->aes_sw_reset);
+	writel(readl(&regs->aes_fifo_status) | DIN_FIFO_OVERFLOW, &regs->aes_fifo_status);
+	writel(readl(&regs->aes_fifo_status) | DOUT_FIFO_UNDERFLOW, &regs->aes_fifo_status);
+
+	/* Workaround to over come Errata #648 */
+	orgctrlval = readl(&regs->aes_control);
+	ctrl = (0x00002004 | dec_enc);    /* AES256(CBC) */
+
+	if (ctrl != orgctrlval) {
+		writel(ctrl, &regs->aes_control);
+
+		if (ctrl != readl(&regs->aes_control)) {
+			u32 read_ctrl;
+			int intwr;
+
+			for (wrtimeout = 0; wrtimeout < 1000; wrtimeout++) {
+				for (intwr = 0 ; intwr < 10; intwr++) {
+					writel(ctrl, &regs->aes_control);
+					writew(ctrl, (u16 *)&regs->aes_control + 1);
+					/* Write configurable info in a single write operation */
+					mb();
+				}
+
+				read_ctrl = readl(&regs->aes_control);
+				if (ctrl == read_ctrl)
+					break;
+			}
+
+			if (wrtimeout == 1000) {
+				printf("\nTIMEOUT expected data=0x%x Actual AES_CONTROL data 0x%x\n\n",
+				       ctrl, read_ctrl);
+				return -EAGAIN;
+			}
+
+			printf("Workaround success, wrtimeout = %d\n", wrtimeout);
+		}
+	}
+
+	if (second_timeout(&regs->aes_busy, AES_BUSY_BIT, AES_BUSY_BIT))
+		return -EAGAIN;
+
+	return 0;
+}
+
+static inline void npcm_aes_load_iv(u8 *iv)
+{
+	struct npcm_aes_regs *regs = aes_priv->regs;
+	u32 *p = (u32 *)iv;
+	u32 i;
+
+	/* Initialization Vector is loaded in 32-bit chunks */
+	for (i = 0; i < (SIZE_AES_BLOCK / sizeof(u32)); i++)
+		writel(p[i], &regs->aes_iv_0 + i);
+}
+
+static inline void npcm_aes_load_key(u8 *key)
+{
+	struct npcm_aes_regs *regs = aes_priv->regs;
+	u32 *p = (u32 *)key;
+	u32 i;
+
+	/* The key can be loaded either via the configuration or by using sideband
+	 *  key port (aes_select_key).
+	 *  If aes_select_key has been called ('fkeyind_to_set' was set to desired
+	 *  key index) and no key is specified (key is NULL), we should use the
+	 *  key index. Otherwise, we write the given key to the registers.
+	 */
+	if (!key && fkeyind_to_set < 4) {
+		npcm_otp_select_key(fkeyind_to_set);
+
+		/* Sample the new key */
+		writel(readl(&regs->aes_sk) | AES_SK_BIT, &regs->aes_sk);
+
+	} else {
+		/* Initialization Vector is loaded in 32-bit chunks */
+		for (i = 0; i < (2 * SIZE_AES_BLOCK / sizeof(u32)); i++)
+			writel(p[i], &regs->aes_key_0 + i);
+
+		fkeyind_to_set = 0xff;
+	}
+}
+
+static inline void npcm_aes_write(u32 *in)
+{
+	struct npcm_aes_regs *regs = aes_priv->regs;
+	u32 i;
+
+	/* 16 Byte AES Block is written in 32-bit chunks */
+	for (i = 0; i < (SIZE_AES_BLOCK / sizeof(u32)); i++)
+		writel(in[i], &regs->aes_fifo_data);
+}
+
+static inline void npcm_aes_read(u32 *out)
+{
+	struct npcm_aes_regs *regs = aes_priv->regs;
+	u32 i;
+
+	/* Data is read in 32-bit chunks */
+	for (i = 0; i < (SIZE_AES_BLOCK / sizeof(u32)); i++)
+		out[i] = readl(&regs->aes_fifo_data);
+}
+
+static void npcm_aes_feed(u32 num_aes_blocks, u32 *datain, u32 *dataout)
+{
+	struct npcm_aes_regs *regs = aes_priv->regs;
+	u32 aes_datablk;
+	u32 total_blocks = num_aes_blocks;
+	u32 blocks_left = num_aes_blocks;
+
+	/* data mode */
+	writel(readl(&regs->aes_busy) | AES_BUSY_BIT, &regs->aes_busy);
+
+	/* Clear overflow and underflow */
+	writel(readl(&regs->aes_fifo_status) | DIN_FIFO_OVERFLOW, &regs->aes_fifo_status);
+	writel(readl(&regs->aes_fifo_status) | DOUT_FIFO_UNDERFLOW, &regs->aes_fifo_status);
+
+	/* datain/dataout is advanced in 32-bit chunks */
+	aes_datablk = (SIZE_AES_BLOCK / sizeof(u32));
+
+	/* Quit if there is no complete blocks */
+	if (total_blocks == 0)
+		return;
+
+	/* Write the first block */
+	if (total_blocks > 1) {
+		npcm_aes_write(datain);
+		datain += aes_datablk;
+		blocks_left--;
+	}
+
+	/* Write the second block */
+	if (total_blocks > 2) {
+		second_timeout(&regs->aes_fifo_status, DIN_FIFO_EMPTY, 0);
+		npcm_aes_write(datain);
+		datain += aes_datablk;
+		blocks_left--;
+	}
+
+	/* Write & read available blocks */
+	while (blocks_left > 0) {
+		second_timeout(&regs->aes_fifo_status, DIN_FIFO_FULL, DIN_FIFO_FULL);
+
+		/* Write next block */
+		npcm_aes_write(datain);
+		datain  += aes_datablk;
+
+		/* Wait till DOUT FIFO is empty */
+		second_timeout(&regs->aes_fifo_status, DOUT_FIFO_EMPTY, DOUT_FIFO_EMPTY);
+
+		/* Read next block */
+		npcm_aes_read(dataout);
+		dataout += aes_datablk;
+
+		blocks_left--;
+	}
+
+	if (total_blocks > 2) {
+		second_timeout(&regs->aes_fifo_status, DOUT_FIFO_FULL, 0);
+
+		/* Read next block */
+		npcm_aes_read(dataout);
+		dataout += aes_datablk;
+
+		second_timeout(&regs->aes_fifo_status, DOUT_FIFO_FULL, 0);
+
+		/* Read next block */
+		npcm_aes_read(dataout);
+		dataout += aes_datablk;
+	} else if (total_blocks > 1) {
+		second_timeout(&regs->aes_fifo_status, DOUT_FIFO_FULL, 0);
+
+		/* Read next block */
+		npcm_aes_read(dataout);
+		dataout += aes_datablk;
+	}
+}
+
+void aes_expand_key(u8 *key, u32 key_size, u8 *expkey)
+{
+	/* npcm hw expands the key automatically, just copy it */
+	memcpy(expkey, key, SIZE_AES_BLOCK * 2);
+}
+
+void aes_cbc_encrypt_blocks(u32 key_size, u8 *key_exp, u8 *iv, u8 *src, u8 *dst,
+			    u32 num_aes_blocks)
+{
+	if (npcm_aes_init(AES_OP_ENCRYPT))
+		return;
+
+	npcm_aes_load_iv(iv);
+
+	npcm_aes_load_key(key_exp);
+
+	npcm_aes_feed(num_aes_blocks, (u32 *)src, (u32 *)dst);
+}
+
+void aes_cbc_decrypt_blocks(u32 key_size, u8 *key_exp, u8 *iv, u8 *src, u8 *dst,
+			    u32 num_aes_blocks)
+{
+	if (npcm_aes_init(AES_OP_DECRYPT))
+		return;
+
+	npcm_aes_load_iv(iv);
+
+	npcm_aes_load_key(key_exp);
+
+	npcm_aes_feed(num_aes_blocks, (u32 *)src, (u32 *)dst);
+}
+
+static int npcm_aes_bind(struct udevice *dev)
+{
+	aes_priv = calloc(1, sizeof(struct npcm_aes_priv));
+	if (!aes_priv) {
+		printf("%s: %d\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	aes_priv->regs = dev_read_addr_ptr(dev);
+	if (!aes_priv->regs) {
+		printf("Cannot find aes reg address, binding failed\n");
+		return -EINVAL;
+	}
+
+	printf("AES: NPCM AES module bind OK\n");
+
+	return 0;
+}
+
+static const struct udevice_id npcm_aes_ids[] = {
+	{ .compatible = "nuvoton,npcm845-aes" },
+	{ .compatible = "nuvoton,npcm750-aes" },
+	{ }
+};
+
+U_BOOT_DRIVER(npcm_aes) = {
+	.name = "npcm_aes",
+	.id = UCLASS_MISC,
+	.of_match = npcm_aes_ids,
+	.priv_auto = sizeof(struct npcm_aes_priv),
+	.bind = npcm_aes_bind,
+};
diff --git a/drivers/crypto/nuvoton/npcm_sha.c b/drivers/crypto/nuvoton/npcm_sha.c
new file mode 100644
index 0000000..7ebdfa1
--- /dev/null
+++ b/drivers/crypto/nuvoton/npcm_sha.c
@@ -0,0 +1,897 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Nuvoton Technology Corp.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <hash.h>
+#include <malloc.h>
+#include <uboot_aes.h>
+#include <asm/io.h>
+
+#define HASH_DIG_H_NUM			8
+
+#define HASH_CTR_STS_SHA_EN             BIT(0)
+#define HASH_CTR_STS_SHA_BUSY           BIT(1)
+#define HASH_CTR_STS_SHA_RST            BIT(2)
+#define HASH_CFG_SHA1_SHA2              BIT(0)
+
+/* SHA type */
+enum npcm_sha_type {
+	npcm_sha_type_sha2 = 0,
+	npcm_sha_type_sha1,
+	npcm_sha_type_num
+};
+
+struct npcm_sha_regs {
+	unsigned int hash_data_in;
+	unsigned char hash_ctr_sts;
+	unsigned char reserved_0[0x03];
+	unsigned char hash_cfg;
+	unsigned char reserved_1[0x03];
+	unsigned char hash_ver;
+	unsigned char reserved_2[0x13];
+	unsigned int hash_dig[HASH_DIG_H_NUM];
+};
+
+struct npcm_sha_priv {
+	struct npcm_sha_regs *regs;
+};
+
+static struct npcm_sha_priv *sha_priv;
+
+#ifdef SHA_DEBUG_MODULE
+#define sha_print(fmt, args...)  printf(fmt, ##args)
+#else
+#define sha_print(fmt, args...)  (void)0
+#endif
+
+#define SHA_BLOCK_LENGTH        (512 / 8)
+#define SHA_2_HASH_LENGTH       (256 / 8)
+#define SHA_1_HASH_LENGTH       (160 / 8)
+#define SHA_HASH_LENGTH(type)   ((type == npcm_sha_type_sha2) ? \
+							(SHA_2_HASH_LENGTH) : (SHA_1_HASH_LENGTH))
+
+#define SHA_SECRUN_BUFF_SIZE    64
+#define SHA_TIMEOUT             100
+#define SHA_DATA_LAST_BYTE      0x80
+
+#define SHA2_NUM_OF_SELF_TESTS  3
+#define SHA1_NUM_OF_SELF_TESTS  4
+
+#define NUVOTON_ALIGNMENT       4
+
+/*-----------------------------------------------------------------------------*/
+/* SHA instance struct handler                                                 */
+/*-----------------------------------------------------------------------------*/
+struct SHA_HANDLE_T {
+	u32                 hv[SHA_2_HASH_LENGTH / sizeof(u32)];
+	u32                 length0;
+	u32                 length1;
+	u32					block[SHA_BLOCK_LENGTH / sizeof(u32)];
+	u8					type;
+	bool                active;
+};
+
+// The # of bytes currently in the sha  block buffer
+#define SHA_BUFF_POS(length)        ((length) & (SHA_BLOCK_LENGTH - 1))
+
+// The # of free bytes in the sha block buffer
+#define SHA_BUFF_FREE(length)       (SHA_BLOCK_LENGTH - SHA_BUFF_POS(length))
+
+static void SHA_FlushLocalBuffer_l(const u32 *buff);
+static int  SHA_BusyWait_l(void);
+static void SHA_GetShaDigest_l(u8 *hashdigest, u8 type);
+static void SHA_SetShaDigest_l(const u32 *hashdigest, u8 type);
+static void SHA_SetBlock_l(const u8 *data, u32 len, u16 position, u32 *block);
+static void SHA_ClearBlock_l(u16 len, u16 position, u32 *block);
+static void SHA_SetLength32_l(struct SHA_HANDLE_T *handleptr, u32 *block);
+
+static int SHA_Init(struct SHA_HANDLE_T *handleptr);
+static int SHA_Start(struct SHA_HANDLE_T *handleptr, u8 type);
+static int SHA_Update(struct SHA_HANDLE_T *handleptr, const u8 *buffer, u32 len);
+static int SHA_Finish(struct SHA_HANDLE_T *handleptr, u8 *hashdigest);
+static int SHA_Reset(void);
+static int SHA_Power(bool on);
+#ifdef SHA_PRINT
+static void SHA_PrintRegs(void);
+static void SHA_PrintVersion(void);
+#endif
+
+static struct SHA_HANDLE_T sha_handle;
+
+/*----------------------------------------------------------------------------*/
+/* Checks if give function returns int error, and returns the error           */
+/* immediately after SHA disabling                                            */
+/*----------------------------------------------------------------------------*/
+int npcm_sha_check(int status)
+{
+	if (status != 0) {
+		SHA_Power(false);
+		return status;
+	}
+	return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        npcm_sha_calc                                          */
+/*                                                                            */
+/* Parameters:      type - SHA module type                                    */
+/*                  inBuff  - Pointer to a buffer containing the data to      */
+/*                            be hashed                                       */
+/*                  len     - Length of the data to hash                      */
+/*                  hashDigest - Pointer to a buffer where the reseulting     */
+/*                               digest will be copied to                     */
+/*                                                                            */
+/* Returns:         0 on success or other int error code on error             */
+/* Side effects:                                                              */
+/* Description:                                                               */
+/*                  This routine performs complete SHA calculation in one     */
+/*                  step                                                      */
+/*----------------------------------------------------------------------------*/
+int npcm_sha_calc(u8 type, const u8 *inbuff, u32 len, u8 *hashdigest)
+{
+	int status;
+	struct SHA_HANDLE_T handle;
+
+	SHA_Init(&handle);
+	SHA_Power(true);
+	SHA_Reset();
+	SHA_Start(&handle, type);
+	status = SHA_Update(&handle, inbuff, len);
+	npcm_sha_check(status);
+	status = SHA_Finish(&handle, hashdigest);
+	npcm_sha_check(status);
+	SHA_Power(false);
+
+	return 0;
+}
+
+/*
+ * Computes hash value of input pbuf using h/w acceleration
+ *
+ * @param in_addr    A pointer to the input buffer
+ * @param bufleni    Byte length of input buffer
+ * @param out_addr   A pointer to the output buffer. When complete
+ *           32 bytes are copied to pout[0]...pout[31]. Thus, a user
+ *           should allocate at least 32 bytes at pOut in advance.
+ * @param chunk_size chunk size for sha256
+ */
+void hw_sha256(const uchar *in_addr, uint buflen, uchar *out_addr, uint chunk_size)
+{
+	puts("\nhw_sha256 using BMC HW accelerator\t");
+	npcm_sha_calc(npcm_sha_type_sha2, (u8 *)in_addr, buflen, (u8 *)out_addr);
+}
+
+/*
+ * Computes hash value of input pbuf using h/w acceleration
+ *
+ * @param in_addr    A pointer to the input buffer
+ * @param bufleni    Byte length of input buffer
+ * @param out_addr   A pointer to the output buffer. When complete
+ *           32 bytes are copied to pout[0]...pout[31]. Thus, a user
+ *           should allocate at least 32 bytes at pOut in advance.
+ * @param chunk_size chunk_size for sha1
+ */
+void hw_sha1(const uchar *in_addr, uint buflen, uchar *out_addr, uint chunk_size)
+{
+	puts("\nhw_sha1 using BMC HW accelerator\t");
+	npcm_sha_calc(npcm_sha_type_sha1, (u8 *)in_addr, buflen, (u8 *)out_addr);
+}
+
+/*
+ * Create the context for sha progressive hashing using h/w acceleration
+ *
+ * @algo: Pointer to the hash_algo struct
+ * @ctxp: Pointer to the pointer of the context for hashing
+ * @return 0 if ok, -ve on error
+ */
+int hw_sha_init(struct hash_algo *algo, void **ctxp)
+{
+	const char *algo_name1 = "sha1";
+	const char *algo_name2 = "sha256";
+
+	SHA_Init(&sha_handle);
+	SHA_Power(true);
+	SHA_Reset();
+	if (!strcmp(algo_name1, algo->name))
+		return SHA_Start(&sha_handle, npcm_sha_type_sha1);
+	else if (!strcmp(algo_name2, algo->name))
+		return SHA_Start(&sha_handle, npcm_sha_type_sha2);
+	else
+		return -EPROTO;
+}
+
+/*
+ * Update buffer for sha progressive hashing using h/w acceleration
+ *
+ * The context is freed by this function if an error occurs.
+ *
+ * @algo: Pointer to the hash_algo struct
+ * @ctx: Pointer to the context for hashing
+ * @buf: Pointer to the buffer being hashed
+ * @size: Size of the buffer being hashed
+ * @is_last: 1 if this is the last update; 0 otherwise
+ * @return 0 if ok, -ve on error
+ */
+int hw_sha_update(struct hash_algo *algo, void *ctx, const void *buf,
+		  unsigned int size, int is_last)
+{
+	return SHA_Update(&sha_handle, buf, size);
+}
+
+/*
+ * Copy sha hash result at destination location
+ *
+ * The context is freed after completion of hash operation or after an error.
+ *
+ * @algo: Pointer to the hash_algo struct
+ * @ctx: Pointer to the context for hashing
+ * @dest_buf: Pointer to the destination buffer where hash is to be copied
+ * @size: Size of the buffer being hashed
+ * @return 0 if ok, -ve on error
+ */
+int hw_sha_finish(struct hash_algo *algo, void *ctx, void *dest_buf, int size)
+{
+	int status;
+
+	status = SHA_Finish(&sha_handle, dest_buf);
+	npcm_sha_check(status);
+	return SHA_Power(false);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_Init                                                  */
+/*                                                                            */
+/* Parameters:      handlePtr - SHA processing handle pointer                 */
+/* Returns:         0 on success or other int error code on error.            */
+/* Side effects:                                                              */
+/* Description:                                                               */
+/*                  This routine initialize the SHA module                    */
+/*----------------------------------------------------------------------------*/
+static int SHA_Init(struct SHA_HANDLE_T *handleptr)
+{
+	handleptr->active = false;
+
+	return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_Start                                                 */
+/*                                                                            */
+/* Parameters:      handlePtr   - SHA processing handle pointer               */
+/*                  type        - SHA module type                             */
+/*                                                                            */
+/* Returns:         0 on success or other int error code on error.            */
+/* Side effects:                                                              */
+/* Description:                                                               */
+/*                  This routine start a single SHA process                   */
+/*----------------------------------------------------------------------------*/
+static int SHA_Start(struct SHA_HANDLE_T *handleptr, u8 type)
+{
+	struct npcm_sha_regs *regs = sha_priv->regs;
+
+	// Initialize handle
+	handleptr->length0 = 0;
+	handleptr->length1 = 0;
+	handleptr->type = type;
+	handleptr->active = true;
+
+	// Set SHA type
+	writeb(handleptr->type & HASH_CFG_SHA1_SHA2, &regs->hash_cfg);
+
+	// Reset SHA hardware
+	SHA_Reset();
+
+	/* The handlePtr->hv is initialized with the correct IV as the SHA engine
+	 * automatically fill the HASH_DIG_Hn registers according to SHA spec
+	 * (following SHA_RST assertion)
+	 */
+	SHA_GetShaDigest_l((u8 *)handleptr->hv, type);
+
+	// Init block with zeros
+	memset(handleptr->block, 0, sizeof(handleptr->block));
+
+	return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_Update                                                */
+/*                                                                            */
+/* Parameters:      handlePtr - SHA processing handle pointer                 */
+/*                  buffer    - Pointer to the data that will be added to     */
+/*                              the hash calculation                          */
+/*                  len -      Length of data to add to SHA calculation       */
+/*                                                                            */
+/*                                                                            */
+/* Returns:         0 on success or other int error code on error             */
+/* Side effects:                                                              */
+/* Description:                                                               */
+/*                  This routine adds data to previously started SHA          */
+/*                  calculation                                               */
+/*----------------------------------------------------------------------------*/
+static int SHA_Update(struct SHA_HANDLE_T *handleptr, const u8 *buffer, u32 len)
+{
+	struct npcm_sha_regs *regs = sha_priv->regs;
+	u32 localbuffer[SHA_SECRUN_BUFF_SIZE / sizeof(u32)];
+	u32 bufferlen = len;
+	u16 pos = 0;
+	u8 *blockptr;
+	int status;
+
+	// Error check
+	if (!handleptr->active)
+		return -EPROTO;
+
+	// Wait till SHA is not busy
+	status = SHA_BusyWait_l();
+	npcm_sha_check(status);
+
+	// Set SHA type
+	writeb(handleptr->type & HASH_CFG_SHA1_SHA2, &regs->hash_cfg);
+
+	// Write SHA latest digest into SHA module
+	SHA_SetShaDigest_l(handleptr->hv, handleptr->type);
+
+	// Set number of unhashed bytes which remained from last update
+	pos = SHA_BUFF_POS(handleptr->length0);
+
+	// Copy unhashed bytes which remained from last update to secrun buffer
+	SHA_SetBlock_l((u8 *)handleptr->block, pos, 0, localbuffer);
+
+	while (len) {
+		// Wait for the hardware to be available (in case we are hashing)
+		status = SHA_BusyWait_l();
+		npcm_sha_check(status);
+
+		// Move as much bytes  as we can into the secrun buffer
+		bufferlen = min(len, SHA_BUFF_FREE(handleptr->length0));
+
+		// Copy current given buffer to the secrun buffer
+		SHA_SetBlock_l((u8 *)buffer, bufferlen, pos, localbuffer);
+
+		// Update size of hashed bytes
+		handleptr->length0 += bufferlen;
+
+		if (handleptr->length0 < bufferlen)
+			handleptr->length1++;
+
+		// Update length of data left to digest
+		len -= bufferlen;
+
+		// Update given buffer pointer
+		buffer += bufferlen;
+
+		// If secrun buffer is full
+		if (SHA_BUFF_POS(handleptr->length0) == 0) {
+			/* We just filled up the buffer perfectly, so let it hash (we'll
+			 * unload the hash only when we are done with all hashing)
+			 */
+			SHA_FlushLocalBuffer_l(localbuffer);
+
+			pos = 0;
+			bufferlen = 0;
+		}
+	}
+
+	// Wait till SHA is not busy
+	status = SHA_BusyWait_l();
+	npcm_sha_check(status);
+
+	/* Copy unhashed bytes from given buffer to handle block for next update/finish */
+	blockptr = (u8 *)handleptr->block;
+	while (bufferlen)
+		blockptr[--bufferlen + pos] = *(--buffer);
+
+	// Save SHA current digest
+	SHA_GetShaDigest_l((u8 *)handleptr->hv, handleptr->type);
+
+	return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_Finish                                                */
+/*                                                                            */
+/* Parameters:      handlePtr  - SHA processing handle pointer                */
+/*                  hashDigest - Pointer to a buffer where the final digest   */
+/*                               will be copied to                            */
+/*                                                                            */
+/* Returns:         0 on success or other int error code on error             */
+/* Side effects:                                                              */
+/* Description:                                                               */
+/*                  This routine finish SHA calculation and get               */
+/*                  the resulting SHA digest                                  */
+/*----------------------------------------------------------------------------*/
+static int SHA_Finish(struct SHA_HANDLE_T *handleptr, u8 *hashdigest)
+{
+	struct npcm_sha_regs *regs = sha_priv->regs;
+	u32 localbuffer[SHA_SECRUN_BUFF_SIZE / sizeof(u32)];
+	const u8 lastbyte = SHA_DATA_LAST_BYTE;
+	u16 pos;
+	int status;
+
+	// Error check
+	if (!handleptr->active)
+		return -EPROTO;
+
+	// Set SHA type
+	writeb(handleptr->type & HASH_CFG_SHA1_SHA2, &regs->hash_cfg);
+
+	// Wait till SHA is not busy
+	status = SHA_BusyWait_l();
+	npcm_sha_check(status);
+
+	// Finish off the current buffer with the SHA spec'ed padding
+	pos = SHA_BUFF_POS(handleptr->length0);
+
+	// Init SHA digest
+	SHA_SetShaDigest_l(handleptr->hv, handleptr->type);
+
+	// Load data into secrun buffer
+	SHA_SetBlock_l((u8 *)handleptr->block, pos, 0, localbuffer);
+
+	// Set data last byte as in SHA algorithm spec
+	SHA_SetBlock_l(&lastbyte, 1, pos++, localbuffer);
+
+	// If the remainder of data is longer then one block
+	if (pos > (SHA_BLOCK_LENGTH - 8)) {
+		/* The length will be in the next block Pad the rest of the last block with 0's */
+		SHA_ClearBlock_l((SHA_BLOCK_LENGTH - pos), pos, localbuffer);
+
+		// Hash the current block
+		SHA_FlushLocalBuffer_l(localbuffer);
+
+		pos = 0;
+
+		// Wait till SHA is not busy
+		status = SHA_BusyWait_l();
+		npcm_sha_check(status);
+	}
+
+	// Pad the rest of the last block with 0's except for the last 8-3 bytes
+	SHA_ClearBlock_l((SHA_BLOCK_LENGTH - (8 - 3)) - pos, pos, localbuffer);
+
+	/* The last 8-3 bytes are set to the bit-length of the message in big-endian form */
+	SHA_SetLength32_l(handleptr, localbuffer);
+
+	// Hash all that, and save the hash for the caller
+	SHA_FlushLocalBuffer_l(localbuffer);
+
+	// Wait till SHA is not busy
+	status = SHA_BusyWait_l();
+	npcm_sha_check(status);
+
+	// Save SHA final digest into given buffer
+	SHA_GetShaDigest_l(hashdigest, handleptr->type);
+
+	// Free handle
+	handleptr->active = false;
+
+	return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_Reset                                                 */
+/*                                                                            */
+/* Parameters:      none                                                      */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:                                                               */
+/*                  This routine reset SHA module                             */
+/*----------------------------------------------------------------------------*/
+static int SHA_Reset(void)
+{
+	struct npcm_sha_regs *regs = sha_priv->regs;
+
+	writel(readl(&regs->hash_ctr_sts) | HASH_CTR_STS_SHA_RST, &regs->hash_ctr_sts);
+
+	return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_Power                                                 */
+/*                                                                            */
+/* Parameters:      on - true enable the module, false disable the module     */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:                                                               */
+/*                  This routine set SHA module power on/off                  */
+/*----------------------------------------------------------------------------*/
+static int SHA_Power(bool on)
+{
+	struct npcm_sha_regs *regs = sha_priv->regs;
+	u8 hash_sts;
+
+	hash_sts = readb(&regs->hash_ctr_sts) & ~HASH_CTR_STS_SHA_EN;
+	writeb(hash_sts | (on & HASH_CTR_STS_SHA_EN), &regs->hash_ctr_sts);
+
+	return 0;
+}
+
+#ifdef SHA_PRINT
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_PrintRegs                                             */
+/*                                                                            */
+/* Parameters:      none                                                      */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:                                                               */
+/*                  This routine prints the module registers                  */
+/*----------------------------------------------------------------------------*/
+static void SHA_PrintRegs(void)
+{
+#ifdef SHA_DEBUG_MODULE
+	struct npcm_sha_regs *regs = sha_priv->regs;
+#endif
+	unsigned int i;
+
+	sha_print("/*--------------*/\n");
+	sha_print("/*     SHA      */\n");
+	sha_print("/*--------------*/\n\n");
+
+	sha_print("HASH_CTR_STS    = 0x%02X\n", readb(&regs->hash_ctr_sts));
+	sha_print("HASH_CFG        = 0x%02X\n", readb(&regs->hash_cfg));
+
+	for (i = 0; i < HASH_DIG_H_NUM; i++)
+		sha_print("HASH_DIG_H%d     = 0x%08X\n", i, readl(&regs->hash_dig[i]));
+
+	sha_print("HASH_VER         = 0x%08X\n", readb(&regs->hash_ver));
+
+	sha_print("\n");
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_PrintVersion                                          */
+/*                                                                            */
+/* Parameters:      none                                                      */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:                                                               */
+/*                  This routine prints the module version                    */
+/*----------------------------------------------------------------------------*/
+static void SHA_PrintVersion(void)
+{
+	struct npcm_sha_regs *regs = sha_priv->regs;
+
+	printf("SHA MODULE VER  = %d\n", readb(&regs->hash_ver));
+}
+#endif
+
+/*----------------------------------------------------------------------------*/
+/* Function:        npcm_sha_selftest                                      */
+/*                                                                            */
+/* Parameters:      type - SHA module type                                    */
+/* Returns:         0 on success or other int error code on error             */
+/* Side effects:                                                              */
+/* Description:                                                               */
+/*                  This routine performs various tests on the SHA HW and SW  */
+/*----------------------------------------------------------------------------*/
+int npcm_sha_selftest(u8 type)
+{
+	int status;
+	struct SHA_HANDLE_T handle;
+	u8 hashdigest[max(SHA_1_HASH_LENGTH, SHA_2_HASH_LENGTH)];
+	u16 i, j;
+
+	/*------------------------------------------------------------------------*/
+	/* SHA1 tests info                                                        */
+	/*------------------------------------------------------------------------*/
+
+	static const u8 sha1selftestbuff[SHA1_NUM_OF_SELF_TESTS][94] = {
+		{"abc"},
+		{"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
+		{"0123456789012345678901234567890123456789012345678901234567890123"},
+		{0x30, 0x5c, 0x30, 0x2c, 0x02, 0x01, 0x00, 0x30, 0x09, 0x06, 0x05, 0x2b,
+		 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x30, 0x06, 0x06, 0x04, 0x67, 0x2a,
+		 0x01, 0x0c, 0x04, 0x14, 0xe1, 0xb6, 0x93, 0xfe, 0x33, 0x43, 0xc1, 0x20,
+		 0x5d, 0x4b, 0xaa, 0xb8, 0x63, 0xfb, 0xcf, 0x6c, 0x46, 0x1e, 0x88, 0x04,
+		 0x30, 0x2c, 0x02, 0x01, 0x00, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
+		 0x02, 0x1a, 0x05, 0x00, 0x30, 0x06, 0x06, 0x04, 0x67, 0x2a, 0x01, 0x0c,
+		 0x04, 0x14, 0x13, 0xc1, 0x0c, 0xfc, 0xc8, 0x92, 0xd7, 0xde, 0x07, 0x1c,
+		 0x40, 0xde, 0x4f, 0xcd, 0x07, 0x5b, 0x68, 0x20, 0x5a, 0x6c}
+	};
+
+	static const u8 sha1selftestbufflen[SHA1_NUM_OF_SELF_TESTS] = {
+		3, 56, 64, 94
+	};
+
+	static const u8 sha1selftestexpres[SHA1_NUM_OF_SELF_TESTS][SHA_1_HASH_LENGTH] = {
+		{0xA9, 0x99, 0x3E, 0x36,
+		 0x47, 0x06, 0x81, 0x6A,
+		 0xBA, 0x3E, 0x25, 0x71,
+		 0x78, 0x50, 0xC2, 0x6C,
+		 0x9C, 0xD0, 0xD8, 0x9D},
+		{0x84, 0x98, 0x3E, 0x44,
+		 0x1C, 0x3B, 0xD2, 0x6E,
+		 0xBA, 0xAE, 0x4A, 0xA1,
+		 0xF9, 0x51, 0x29, 0xE5,
+		 0xE5, 0x46, 0x70, 0xF1},
+		{0xCF, 0x08, 0x00, 0xF7,
+		 0x64, 0x4A, 0xCE, 0x3C,
+		 0xB4, 0xC3, 0xFA, 0x33,
+		 0x38, 0x8D, 0x3B, 0xA0,
+		 0xEA, 0x3C, 0x8B, 0x6E},
+		{0xc9, 0x84, 0x45, 0xc8,
+		 0x64, 0x04, 0xb1, 0xe3,
+		 0x3c, 0x6b, 0x0a, 0x8c,
+		 0x8b, 0x80, 0x94, 0xfc,
+		 0xf3, 0xc9, 0x98, 0xab}
+	};
+
+	/*------------------------------------------------------------------------*/
+	/* SHA2 tests info                                                        */
+	/*------------------------------------------------------------------------*/
+
+	static const u8 sha2selftestbuff[SHA2_NUM_OF_SELF_TESTS][100] = {
+		{ "abc" },
+		{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+		{'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
+		 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
+		 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
+		 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
+		 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
+		 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
+		 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
+		 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
+		 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
+		 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'}
+	};
+
+	static const u8 sha2selftestbufflen[SHA2_NUM_OF_SELF_TESTS] = {
+		3, 56, 100
+	};
+
+	static const u8 sha2selftestexpres[SHA2_NUM_OF_SELF_TESTS][SHA_2_HASH_LENGTH] = {
+		/*
+		 * SHA-256 test vectors
+		 */
+		{ 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
+		  0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
+		  0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
+		  0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
+		{ 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
+		  0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
+		  0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
+		  0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
+		{ 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
+		  0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
+		  0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
+		  0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 },
+	};
+
+	if (type == npcm_sha_type_sha1) {
+		/*--------------------------------------------------------------------*/
+		/* SHA 1 TESTS                                                        */
+		/*--------------------------------------------------------------------*/
+		for (i = 0; i < SHA1_NUM_OF_SELF_TESTS; i++) {
+			if (i != 3) {
+				status = npcm_sha_calc(npcm_sha_type_sha1, sha1selftestbuff[i], sha1selftestbufflen[i], hashdigest);
+				npcm_sha_check(status);
+			} else {
+				SHA_Power(true);
+				SHA_Reset();
+				status = SHA_Start(&handle, npcm_sha_type_sha1);
+				npcm_sha_check(status);
+				status = SHA_Update(&handle, sha1selftestbuff[i], 73);
+				npcm_sha_check(status);
+				status = SHA_Update(&handle, &sha1selftestbuff[i][73], sha1selftestbufflen[i] - 73);
+				npcm_sha_check(status);
+				status = SHA_Finish(&handle, hashdigest);
+				npcm_sha_check(status);
+				SHA_Power(false);
+			}
+
+			if (memcmp(hashdigest, sha1selftestexpres[i], SHA_1_HASH_LENGTH))
+				return -1;
+		}
+
+	} else {
+		/*--------------------------------------------------------------------*/
+		/* SHA 2 TESTS                                                        */
+		/*--------------------------------------------------------------------*/
+		for (i = 0; i < SHA2_NUM_OF_SELF_TESTS; i++) {
+			SHA_Power(true);
+			SHA_Reset();
+			status = SHA_Start(&handle, npcm_sha_type_sha2);
+			npcm_sha_check(status);
+			if (i == 2) {
+				for (j = 0; j < 10000; j++) { //not working
+					status = SHA_Update(&handle, sha2selftestbuff[i], sha2selftestbufflen[i]);
+					npcm_sha_check(status);
+				}
+			} else {
+				status = SHA_Update(&handle, sha2selftestbuff[i], sha2selftestbufflen[i]);
+				npcm_sha_check(status);
+			}
+
+			status = SHA_Finish(&handle, hashdigest);
+			npcm_sha_check(status);
+			SHA_Power(false);
+			if (memcmp(hashdigest, sha2selftestexpres[i], SHA_2_HASH_LENGTH))
+				return -1;
+
+			npcm_sha_calc(npcm_sha_type_sha2, sha2selftestbuff[i], sha2selftestbufflen[i], hashdigest);
+			if (memcmp(hashdigest, sha2selftestexpres[i], SHA_2_HASH_LENGTH))
+				return -1;
+		}
+	}
+
+	return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_FlushLocalBuffer_l                                    */
+/*                                                                            */
+/* Parameters:                                                                */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:     This routine flush secrun buffer to SHA module            */
+/*----------------------------------------------------------------------------*/
+static void SHA_FlushLocalBuffer_l(const u32 *buff)
+{
+	struct npcm_sha_regs *regs = sha_priv->regs;
+	u32 i;
+
+	for (i = 0; i < (SHA_BLOCK_LENGTH / sizeof(u32)); i++)
+		writel(buff[i], &regs->hash_data_in);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_BusyWait_l                                            */
+/*                                                                            */
+/* Parameters:                                                                */
+/* Returns:         0 if no error was found or DEFS_STATUS_ERROR otherwise    */
+/* Side effects:                                                              */
+/* Description:     This routine wait for SHA unit to no longer be busy       */
+/*----------------------------------------------------------------------------*/
+static int SHA_BusyWait_l(void)
+{
+	struct npcm_sha_regs *regs = sha_priv->regs;
+	u32 timeout = SHA_TIMEOUT;
+
+	do {
+		if (timeout-- == 0)
+			return -ETIMEDOUT;
+	} while ((readb(&regs->hash_ctr_sts) & HASH_CTR_STS_SHA_BUSY)
+						== HASH_CTR_STS_SHA_BUSY);
+
+	return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_GetShaDigest_l                                        */
+/*                                                                            */
+/* Parameters:      hashDigest - buffer for the hash output.                  */
+/*                  type - SHA module type                                    */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:     This routine copy the hash digest from the hardware       */
+/*                  and into given buffer (in ram)                            */
+/*----------------------------------------------------------------------------*/
+static void SHA_GetShaDigest_l(u8 *hashdigest, u8 type)
+{
+	struct npcm_sha_regs *regs = sha_priv->regs;
+	u16 j;
+	u8 len = SHA_HASH_LENGTH(type) / sizeof(u32);
+
+	// Copy Bytes from SHA module to given buffer
+	for (j = 0; j < len; j++)
+		((u32 *)hashdigest)[j] = readl(&regs->hash_dig[j]);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_SetShaDigest_l                                        */
+/*                                                                            */
+/* Parameters:      hashDigest - input buffer to set as hash digest           */
+/*                  type - SHA module type                                    */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:     This routine set the hash digest in the hardware from     */
+/*                  a given buffer (in ram)                                   */
+/*----------------------------------------------------------------------------*/
+static void SHA_SetShaDigest_l(const u32 *hashdigest, u8 type)
+{
+	struct npcm_sha_regs *regs = sha_priv->regs;
+	u16 j;
+	u8 len = SHA_HASH_LENGTH(type) / sizeof(u32);
+
+	// Copy Bytes from given buffer to SHA module
+	for (j = 0; j < len; j++)
+		writel(hashdigest[j], &regs->hash_dig[j]);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_SetBlock_l                                            */
+/*                                                                            */
+/* Parameters:      data        - data to copy                                */
+/*                  len         - size of data                                */
+/*                  position    - byte offset into the block at which data    */
+/*                                should be placed                            */
+/*                  block       - block buffer                                */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:     This routine load bytes into block buffer                 */
+/*----------------------------------------------------------------------------*/
+static void SHA_SetBlock_l(const u8 *data, u32 len, u16 position, u32 *block)
+{
+	u8 *dest = (u8 *)block;
+
+	memcpy(dest + position, data, len);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_SetBlock_l                                            */
+/*                                                                            */
+/* Parameters:                                                                */
+/*                  len - size of data                                        */
+/*                  position - byte offset into the block at which data       */
+/*                             should be placed                               */
+/*                  block - block buffer                                      */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:     This routine load zero's into the block buffer            */
+/*----------------------------------------------------------------------------*/
+static void SHA_ClearBlock_l(u16 len, u16 position, u32 *block)
+{
+	u8 *dest = (u8 *)block;
+
+	memset(dest + position, 0, len);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        SHA_SetLength32_l                                         */
+/*                                                                            */
+/* Parameters:                                                                */
+/*                  handlePtr  -   SHA processing handle pointer              */
+/*                  block - block buffer                                      */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:     This routine set the length of the hash's data            */
+/*                  len is the 32-bit byte length of the message              */
+/*lint -efunc(734,SHA_SetLength32_l) Supperess loss of percision lint warning */
+/*----------------------------------------------------------------------------*/
+static void SHA_SetLength32_l(struct SHA_HANDLE_T *handleptr, u32 *block)
+{
+	u16 *secrunbufferswappedptr = (u16 *)(void *)(block);
+
+	secrunbufferswappedptr[(SHA_BLOCK_LENGTH / sizeof(u16)) - 1] = (u16)
+	((handleptr->length0 << 3) << 8) | ((u16)(handleptr->length0 << 3) >> 8);
+	secrunbufferswappedptr[(SHA_BLOCK_LENGTH / sizeof(u16)) - 2] = (u16)
+	((handleptr->length0 >> (16 - 3)) >> 8) | ((u16)(handleptr->length0 >> (16 - 3)) << 8);
+	secrunbufferswappedptr[(SHA_BLOCK_LENGTH / sizeof(u16)) - 3] = (u16)
+	((handleptr->length1 << 3) << 8) | ((u16)(handleptr->length1 << 3) >> 8);
+	secrunbufferswappedptr[(SHA_BLOCK_LENGTH / sizeof(u16)) - 4] = (u16)
+	((handleptr->length1 >> (16 - 3)) >> 8) | ((u16)(handleptr->length1 >> (16 - 3)) << 8);
+}
+
+static int npcm_sha_bind(struct udevice *dev)
+{
+	sha_priv = calloc(1, sizeof(struct npcm_sha_priv));
+	if (!sha_priv)
+		return -ENOMEM;
+
+	sha_priv->regs = dev_remap_addr_index(dev, 0);
+	if (!sha_priv->regs) {
+		printf("Cannot find sha reg address, binding failed\n");
+		return -EINVAL;
+	}
+
+	printf("SHA: NPCM SHA module bind OK\n");
+
+	return 0;
+}
+
+static const struct udevice_id npcm_sha_ids[] = {
+	{ .compatible = "nuvoton,npcm845-sha" },
+	{ .compatible = "nuvoton,npcm750-sha" },
+	{ }
+};
+
+U_BOOT_DRIVER(npcm_sha) = {
+	.name = "npcm_sha",
+	.id = UCLASS_MISC,
+	.of_match = npcm_sha_ids,
+	.priv_auto = sizeof(struct npcm_sha_priv),
+	.bind = npcm_sha_bind,
+};
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 7b6c371..28d5da4 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -321,6 +321,15 @@
 	  Programmable memory pages, that are stored on some
 	  Freescale i.MX processors, in SPL.
 
+config NPCM_OTP
+	bool "Nnvoton NPCM BMC On-Chip OTP Memory Support"
+	depends on (ARM && ARCH_NPCM)
+	default n
+	help
+	  Support NPCM BMC OTP memory (fuse).
+	  To compile this driver as a module, choose M here: the module
+	  will be called npcm_otp.
+
 config NUVOTON_NCT6102D
 	bool "Enable Nuvoton NCT6102D Super I/O driver"
 	help
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 0a33364..0bf05ca 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -56,6 +56,7 @@
 obj-$(CONFIG_$(SPL_TPL_)LS2_SFP) += ls2_sfp.o
 obj-$(CONFIG_$(SPL_)MXC_OCOTP) += mxc_ocotp.o
 obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o
+obj-$(CONFIG_NPCM_OTP) += npcm_otp.o
 obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o
 obj-$(CONFIG_P2SB) += p2sb-uclass.o
 obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
diff --git a/drivers/misc/npcm_otp.c b/drivers/misc/npcm_otp.c
new file mode 100644
index 0000000..3049108
--- /dev/null
+++ b/drivers/misc/npcm_otp.c
@@ -0,0 +1,512 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021 Nuvoton Technology Corp.
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fuse.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <asm/arch/otp.h>
+
+struct npcm_otp_priv {
+	struct npcm_otp_regs *regs[2];
+};
+
+static struct npcm_otp_priv *otp_priv;
+
+/*----------------------------------------------------------------------------*/
+/* Function:        npcm_otp_check_inputs                                     */
+/*                                                                            */
+/* Parameters:      arr - fuse array number to check                          */
+/*                  word - fuse word (offset) to check                        */
+/* Returns:         int                                                       */
+/* Side effects:                                                              */
+/* Description:     Checks is arr and word are illegal and do not exceed      */
+/*                  their range. Return 0 if they are legal, -1 if not        */
+/*----------------------------------------------------------------------------*/
+static int npcm_otp_check_inputs(u32 arr, u32 word)
+{
+	if (arr >= NPCM_NUM_OF_SA) {
+		if (IS_ENABLED(CONFIG_ARCH_NPCM8XX))
+			printf("\nError: npcm8XX otp includs only one bank: 0\n");
+		if (IS_ENABLED(CONFIG_ARCH_NPCM7XX))
+			printf("\nError: npcm7XX otp includs only two banks: 0 and 1\n");
+		return -1;
+	}
+
+	if (word >= NPCM_OTP_ARR_BYTE_SIZE) {
+		printf("\nError: npcm otp array comprises only %d bytes, numbered from 0 to %d\n",
+		       NPCM_OTP_ARR_BYTE_SIZE, NPCM_OTP_ARR_BYTE_SIZE - 1);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        npcm_otp_wait_for_otp_ready                               */
+/*                                                                            */
+/* Parameters:      array - fuse array to wait for                            */
+/* Returns:         int                                                       */
+/* Side effects:                                                              */
+/* Description:     Initialize the Fuse HW module.                            */
+/*----------------------------------------------------------------------------*/
+static int npcm_otp_wait_for_otp_ready(u32 arr, u32 timeout)
+{
+	struct npcm_otp_regs *regs = otp_priv->regs[arr];
+	u32 time = timeout;
+
+	/*------------------------------------------------------------------------*/
+	/* check parameters validity                                              */
+	/*------------------------------------------------------------------------*/
+	if (arr > NPCM_FUSE_SA)
+		return -EINVAL;
+
+	while (--time > 1) {
+		if (readl(&regs->fst) & FST_RDY) {
+			/* fuse is ready, clear the status. */
+			writel(readl(&regs->fst) | FST_RDST, &regs->fst);
+			return 0;
+		}
+	}
+
+	/* try to clear the status in case it was set */
+	writel(readl(&regs->fst) | FST_RDST, &regs->fst);
+
+	return -EINVAL;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        npcm_otp_read_byte                                        */
+/*                                                                            */
+/* Parameters:      arr  - Storage Array type [input].                        */
+/*                  addr - Byte-address to read from [input].                 */
+/*                  data - Pointer to result [output].                        */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:     Read 8-bit data from an OTP storage array.                */
+/*----------------------------------------------------------------------------*/
+static void npcm_otp_read_byte(u32 arr, u32 addr, u8 *data)
+{
+	struct npcm_otp_regs *regs = otp_priv->regs[arr];
+
+	/* Wait for the Fuse Box Idle */
+	npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF);
+
+	/* Configure the byte address in the fuse array for read operation */
+	writel(FADDR_VAL(addr, 0), &regs->faddr);
+
+	/* Initiate a read cycle */
+	writel(READ_INIT, &regs->fctl);
+
+	/* Wait for read operation completion */
+	npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF);
+
+	/* Read the result */
+	*data = readl(&regs->fdata) & FDATA_MASK;
+
+	/* Clean FDATA contents to prevent unauthorized software from reading
+	 * sensitive information
+	 */
+	writel(FDATA_CLEAN_VALUE, &regs->fdata);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        npcm_otp_bit_is_programmed                                */
+/*                                                                            */
+/* Parameters:      arr     - Storage Array type [input].                     */
+/*                  byte_offset - Byte offset in array [input].               */
+/*                  bit_offset  - Bit offset in byte [input].                 */
+/* Returns:         Nonzero if bit is programmed, zero otherwise.             */
+/* Side effects:                                                              */
+/* Description:     Check if a bit is programmed in an OTP storage array.     */
+/*----------------------------------------------------------------------------*/
+static bool npcm_otp_bit_is_programmed(u32  arr,
+				       u32 byte_offset, u8 bit_offset)
+{
+	u32 data = 0;
+
+	/* Read the entire byte you wish to program */
+	npcm_otp_read_byte(arr, byte_offset, (u8 *)&data);
+
+	/* Check whether the bit is already programmed */
+	if (data & (1 << bit_offset))
+		return true;
+
+	return false;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        npcm_otp_program_bit                                      */
+/*                                                                            */
+/* Parameters:      arr     - Storage Array type [input].                     */
+/*                  byte)offset - Byte offset in array [input].               */
+/*                  bit_offset  - Bit offset in byte [input].                 */
+/* Returns:         int                                                       */
+/* Side effects:                                                              */
+/* Description:     Program (set to 1) a bit in an OTP storage array.         */
+/*----------------------------------------------------------------------------*/
+static int npcm_otp_program_bit(u32 arr, u32 byte_offset,
+				u8 bit_offset)
+{
+	struct npcm_otp_regs *regs = otp_priv->regs[arr];
+	int count;
+	u8 read_data;
+
+	/* Wait for the Fuse Box Idle */
+	npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF);
+
+	/* Make sure the bit is not already programmed */
+	if (npcm_otp_bit_is_programmed(arr, byte_offset, bit_offset))
+		return 0;
+
+	/* Configure the bit address in the fuse array for program operation */
+	writel(FADDR_VAL(byte_offset, bit_offset), &regs->faddr);
+	writel(readl(&regs->faddr) | FADDR_IN_PROG, &regs->faddr);
+
+	// program up to MAX_PROGRAM_PULSES
+	for (count = 1; count <= MAX_PROGRAM_PULSES; count++) {
+		/* Initiate a program cycle */
+		writel(PROGRAM_ARM, &regs->fctl);
+		writel(PROGRAM_INIT, &regs->fctl);
+
+		/* Wait for program operation completion */
+		npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF);
+
+		// after MIN_PROGRAM_PULSES start verifying the result
+		if (count >= MIN_PROGRAM_PULSES) {
+			/* Initiate a read cycle */
+			writel(READ_INIT, &regs->fctl);
+
+			/* Wait for read operation completion */
+			npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF);
+
+			/* Read the result */
+			read_data = readl(&regs->fdata) & FDATA_MASK;
+
+			/* If the bit is set the sequence ended correctly */
+			if (read_data & (1 << bit_offset))
+				break;
+		}
+	}
+
+	// check if programmking failed
+	if (count > MAX_PROGRAM_PULSES) {
+		printf("program fail\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Clean FDATA contents to prevent unauthorized software from reading
+	 * sensitive information
+	 */
+	writel(FDATA_CLEAN_VALUE, &regs->fdata);
+
+	return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        npcm_otp_program_byte                                     */
+/*                                                                            */
+/* Parameters:      arr     - Storage Array type [input].                     */
+/*                  byte_offset - Byte offset in array [input].               */
+/*                  value   - Byte to program [input].                        */
+/* Returns:         int                                                       */
+/* Side effects:                                                              */
+/* Description:     Program (set to 1) a given byte's relevant bits in an     */
+/*                  OTP storage array.                                        */
+/*----------------------------------------------------------------------------*/
+static int npcm_otp_program_byte(u32 arr, u32 byte_offset,
+				 u8 value)
+{
+	int status = 0;
+	unsigned int i;
+	u8 data = 0;
+	int rc;
+
+	rc = npcm_otp_check_inputs(arr, byte_offset);
+	if (rc != 0)
+		return rc;
+
+	/* Wait for the Fuse Box Idle */
+	npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF);
+
+	/* Read the entire byte you wish to program */
+	npcm_otp_read_byte(arr, byte_offset, &data);
+
+	/* In case all relevant bits are already programmed - nothing to do */
+	if ((~data & value) == 0)
+		return status;
+
+	/* Program unprogrammed bits. */
+	for (i = 0; i < 8; i++) {
+		if (value & (1 << i)) {
+			/* Program (set to 1) the relevant bit */
+			int last_status = npcm_otp_program_bit(arr, byte_offset, (u8)i);
+
+			if (last_status != 0)
+				status = last_status;
+		}
+	}
+	return status;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        npcm_otp_is_fuse_array_disabled                           */
+/*                                                                            */
+/* Parameters:      arr - Storage Array type [input].                         */
+/* Returns:         bool                                                      */
+/* Side effects:                                                              */
+/* Description:     Return true if access to the first 2048 bits of the       */
+/*                  specified fuse array is disabled, false if not            */
+/*----------------------------------------------------------------------------*/
+bool npcm_otp_is_fuse_array_disabled(u32 arr)
+{
+	struct npcm_otp_regs *regs = otp_priv->regs[arr];
+
+	return (readl(&regs->fcfg) & FCFG_FDIS) != 0;
+}
+
+int npcm_otp_select_key(u8 key_index)
+{
+	struct npcm_otp_regs *regs = otp_priv->regs[NPCM_KEY_SA];
+	u32 idx = 0;
+	u32 time = 0xDAEDBEEF;
+
+	if (key_index >= 4)
+		return -1;
+
+	/* Do not destroy ECCDIS bit */
+	idx = readl(&regs->fustrap_fkeyind);
+
+	/* Configure the key size */
+	idx &= ~FKEYIND_KSIZE_MASK;
+	idx |= FKEYIND_KSIZE_256;
+
+	/* Configure the key index (0 to 3) */
+	idx &= ~FKEYIND_KIND_MASK;
+	idx |= FKEYIND_KIND_KEY(key_index);
+
+	writel(idx, &regs->fustrap_fkeyind);
+
+	/* Wait for selection completetion */
+	while (--time > 1) {
+		if (readl(&regs->fustrap_fkeyind) & FKEYIND_KVAL)
+			return 0;
+		udelay(1);
+	}
+
+	return -1;
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        npcm_otp_nibble_parity_ecc_encode                         */
+/*                                                                            */
+/* Parameters:      datain - pointer to decoded data buffer                   */
+/*                  dataout - pointer to encoded data buffer (buffer size     */
+/*                            should be 2 x dataout)                          */
+/*                  size - size of encoded data (decoded data x 2)            */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:     Decodes the data according to nibble parity ECC scheme.   */
+/*                  Size specifies the encoded data size.                     */
+/*                  Decodes whole bytes only                                  */
+/*----------------------------------------------------------------------------*/
+void npcm_otp_nibble_parity_ecc_encode(u8 *datain, u8 *dataout, u32 size)
+{
+	u32 i, idx;
+	u8 E0, E1, E2, E3;
+
+	for (i = 0; i < (size / 2); i++) {
+		E0 = (datain[i] >> 0) & 0x01;
+		E1 = (datain[i] >> 1) & 0x01;
+		E2 = (datain[i] >> 2) & 0x01;
+		E3 = (datain[i] >> 3) & 0x01;
+
+		idx = i * 2;
+		dataout[idx] = datain[i] & 0x0f;
+		dataout[idx] |= (E0 ^ E1) << 4;
+		dataout[idx] |= (E2 ^ E3) << 5;
+		dataout[idx] |= (E0 ^ E2) << 6;
+		dataout[idx] |= (E1 ^ E3) << 7;
+
+		E0 = (datain[i] >> 4) & 0x01;
+		E1 = (datain[i] >> 5) & 0x01;
+		E2 = (datain[i] >> 6) & 0x01;
+		E3 = (datain[i] >> 7) & 0x01;
+
+		idx = i * 2 + 1;
+		dataout[idx] = (datain[i] & 0xf0) >> 4;
+		dataout[idx] |= (E0 ^ E1) << 4;
+		dataout[idx] |= (E2 ^ E3) << 5;
+		dataout[idx] |= (E0 ^ E2) << 6;
+		dataout[idx] |= (E1 ^ E3) << 7;
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        npcm_otp_majority_rule_ecc_encode                         */
+/*                                                                            */
+/* Parameters:      datain - pointer to decoded data buffer                   */
+/*                  dataout - pointer to encoded data buffer (buffer size     */
+/*                            should be 3 x dataout)                          */
+/*                  size - size of encoded data (decoded data x 3)            */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:     Decodes the data according to Major Rule ECC scheme.      */
+/*                  Size specifies the encoded data size.                     */
+/*                  Decodes whole bytes only                                  */
+/*----------------------------------------------------------------------------*/
+void npcm_otp_majority_rule_ecc_encode(u8 *datain, u8 *dataout, u32 size)
+{
+	u32 byte;
+	u32 bit;
+	u8 bit_val;
+	u32 decoded_size = size / 3;
+
+	for (byte = 0; byte < decoded_size; byte++) {
+		for (bit = 0; bit < 8; bit++) {
+			bit_val = (datain[byte] >> bit) & 0x01;
+
+			if (bit_val) {
+				dataout[byte] |= (1 << bit);
+				dataout[decoded_size + byte] |= (1 << bit);
+				dataout[decoded_size * 2 + byte] |= (1 << bit);
+			} else {
+				dataout[byte] &= ~(1 << bit);
+				dataout[decoded_size + byte] &= ~(1 << bit);
+				dataout[decoded_size * 2 + byte] &= ~(1 << bit);
+			}
+		}
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+/* Function:        fuse_program_data                                         */
+/*                                                                            */
+/* Parameters:      bank - Storage Array type [input].                        */
+/*                  word - Byte offset in array [input].                      */
+/*                  data - Pointer to data buffer to program.                 */
+/*                  size - Number of bytes to program.                        */
+/* Returns:         none                                                      */
+/* Side effects:                                                              */
+/* Description:     Programs the given byte array (size bytes) to the given   */
+/*                  OTP storage array, starting from offset word.             */
+/*----------------------------------------------------------------------------*/
+int fuse_program_data(u32 bank, u32 word, u8 *data, u32 size)
+{
+	u32 arr = (u32)bank;
+	u32 byte;
+	int rc;
+
+	rc = npcm_otp_check_inputs(bank, word + size - 1);
+	if (rc != 0)
+		return rc;
+
+	for (byte = 0; byte < size; byte++) {
+		u8 val;
+
+		val = data[byte];
+		if (val == 0) // optimization
+			continue;
+
+		rc = npcm_otp_program_byte(arr, word + byte, data[byte]);
+		if (rc != 0)
+			return rc;
+
+		// verify programming of every '1' bit
+		val = 0;
+		npcm_otp_read_byte((u32)bank, byte, &val);
+		if ((data[byte] & ~val) != 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+int fuse_prog_image(u32 bank, uintptr_t address)
+{
+	return fuse_program_data(bank, 0, (u8 *)address, NPCM_OTP_ARR_BYTE_SIZE);
+}
+
+int fuse_read(u32 bank, u32 word, u32 *val)
+{
+	int rc = npcm_otp_check_inputs(bank, word);
+
+	if (rc != 0)
+		return rc;
+
+	*val = 0;
+	npcm_otp_read_byte((u32)bank, word, (u8 *)val);
+
+	return 0;
+}
+
+int fuse_sense(u32 bank, u32 word, u32 *val)
+{
+	/* We do not support overriding */
+	return -EINVAL;
+}
+
+int fuse_prog(u32 bank, u32 word, u32 val)
+{
+	int rc;
+
+	rc = npcm_otp_check_inputs(bank, word);
+	if (rc != 0)
+		return rc;
+
+	return npcm_otp_program_byte(bank, word, (u8)val);
+}
+
+int fuse_override(u32 bank, u32 word, u32 val)
+{
+	/* We do not support overriding */
+	return -EINVAL;
+}
+
+static int npcm_otp_bind(struct udevice *dev)
+{
+	struct npcm_otp_regs *regs;
+
+	otp_priv = calloc(1, sizeof(struct npcm_otp_priv));
+	if (!otp_priv)
+		return -ENOMEM;
+
+	regs = dev_remap_addr_index(dev, 0);
+	if (!regs) {
+		printf("Cannot find reg address (arr #0), binding failed\n");
+		return -EINVAL;
+	}
+	otp_priv->regs[0] = regs;
+
+	if (IS_ENABLED(CONFIG_ARCH_NPCM7xx)) {
+		regs = dev_remap_addr_index(dev, 1);
+		if (!regs) {
+			printf("Cannot find reg address (arr #1), binding failed\n");
+			return -EINVAL;
+		}
+		otp_priv->regs[1] = regs;
+	}
+	printf("OTP: NPCM OTP module bind OK\n");
+
+	return 0;
+}
+
+static const struct udevice_id npcm_otp_ids[] = {
+	{ .compatible = "nuvoton,npcm845-otp" },
+	{ .compatible = "nuvoton,npcm750-otp" },
+	{ }
+};
+
+U_BOOT_DRIVER(npcm_otp) = {
+	.name = "npcm_otp",
+	.id = UCLASS_MISC,
+	.of_match = npcm_otp_ids,
+	.priv_auto = sizeof(struct npcm_otp_priv),
+	.bind = npcm_otp_bind,
+};
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index a1e515c..e48d72d 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -186,6 +186,12 @@
 	  Enable the Freescale QSPI driver to use full AHB memory map space for
 	  flash access.
 
+config GXP_SPI
+	bool "SPI driver for GXP"
+	imply SPI_FLASH_BAR
+	help
+	  Enable support for SPI on GXP.
+
 config ICH_SPI
 	bool "Intel ICH SPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 06e81b4..8755408 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -33,6 +33,7 @@
 obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o
 obj-$(CONFIG_FSL_ESPI) += fsl_espi.o
 obj-$(CONFIG_SYNQUACER_SPI) += spi-synquacer.o
+obj-$(CONFIG_GXP_SPI) += gxp_spi.o
 obj-$(CONFIG_ICH_SPI) +=  ich.o
 obj-$(CONFIG_IPROC_QSPI) += iproc_qspi.o
 obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
diff --git a/drivers/spi/gxp_spi.c b/drivers/spi/gxp_spi.c
new file mode 100644
index 0000000..70d76ac
--- /dev/null
+++ b/drivers/spi/gxp_spi.c
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * GXP SPI driver
+ *
+ * (C) Copyright 2022 Hewlett Packard Enterprise Development LP.
+ * Author: Nick Hawkins <nick.hawkins@hpe.com>
+ * Author: Jean-Marie Verdun <verdun@hpe.com>
+ */
+
+#include <spi.h>
+#include <asm/io.h>
+#include <dm.h>
+
+#define GXP_SPI0_MAX_CHIPSELECT		2
+
+#define MANUAL_MODE	0
+#define AUTO_MODE		1
+#define OFFSET_SPIMCFG	0x00
+#define OFFSET_SPIMCTRL	0x04
+#define OFFSET_SPICMD		0x05
+#define OFFSET_SPIDCNT	0x06
+#define OFFSET_SPIADDR	0x08
+#define OFFSET_SPILDAT	0x40
+#define GXP_SPILDAT_SIZE 64
+
+#define SPIMCTRL_START	0x01
+#define SPIMCTRL_BUSY		0x02
+
+#define CMD_READ_ARRAY_FAST		0x0b
+
+struct gxp_spi_priv {
+	struct spi_slave	slave;
+	void __iomem *base;
+	unsigned int mode;
+
+};
+
+static void spi_set_mode(struct gxp_spi_priv *priv, int mode)
+{
+	unsigned char value;
+
+	value = readb(priv->base + OFFSET_SPIMCTRL);
+	if (mode == MANUAL_MODE) {
+		writeb(0x55, priv->base + OFFSET_SPICMD);
+		writeb(0xaa, priv->base + OFFSET_SPICMD);
+		/* clear bit5 and bit4, auto_start and start_mask */
+		value &= ~(0x03 << 4);
+	} else {
+		value |= (0x03 << 4);
+	}
+	writeb(value, priv->base + OFFSET_SPIMCTRL);
+}
+
+static int gxp_spi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, void *din,
+			unsigned long flags)
+{
+	struct gxp_spi_priv *priv = dev_get_priv(dev->parent);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+	struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev);
+
+	unsigned int len = bitlen / 8;
+	unsigned int value;
+	unsigned int addr = 0;
+	unsigned char uchar_out[len];
+	unsigned char *uchar_in = (unsigned char *)din;
+	int read_len;
+	int read_ptr;
+
+	if (dout && din) {
+		/*
+		 * error: gxp spi engin cannot send data to dout and read data from din at the same
+		 * time
+		 */
+		return -1;
+	}
+
+	memset(uchar_out, 0, sizeof(uchar_out));
+	if (dout)
+		memcpy(uchar_out, dout, len);
+
+	if (flags & SPI_XFER_BEGIN) {
+		/* the dout is cmd + addr, cmd=dout[0], add1~3=dout[1~3]. */
+		/* cmd reg */
+		writeb(uchar_out[0], priv->base + OFFSET_SPICMD);
+
+		/* config reg */
+		value = readl(priv->base + OFFSET_SPIMCFG);
+		value &= ~(1 << 24);
+		/* set chipselect */
+		value |= (slave_plat->cs << 24);
+
+		/* addr reg and addr size */
+		if (len >= 4) {
+			addr = uchar_out[1] << 16 | uchar_out[2] << 8 | uchar_out[3];
+			writel(addr, priv->base + OFFSET_SPIADDR);
+			value &= ~(0x07 << 16);
+			/* set the address size to 3 byte */
+			value |= (3 << 16);
+		} else {
+			writel(0, priv->base + OFFSET_SPIADDR);
+			/* set the address size to 0 byte */
+			value &= ~(0x07 << 16);
+		}
+
+		/* dummy */
+		/* clear dummy_cnt to */
+		value &= ~(0x1f << 19);
+		if (uchar_out[0] == CMD_READ_ARRAY_FAST) {
+			/* fast read needs 8 dummy clocks */
+			value |= (8 << 19);
+		}
+
+		writel(value, priv->base + OFFSET_SPIMCFG);
+
+		if (flags & SPI_XFER_END) {
+			/* no data cmd just start it */
+			/* set the data direction bit to 1 */
+			value = readb(priv->base + OFFSET_SPIMCTRL);
+			value |= (1 << 3);
+			writeb(value, priv->base + OFFSET_SPIMCTRL);
+
+			/* set the data byte count */
+			writeb(0, priv->base + OFFSET_SPIDCNT);
+
+			/* set the start bit */
+			value = readb(priv->base + OFFSET_SPIMCTRL);
+			value |= SPIMCTRL_START;
+			writeb(value, priv->base + OFFSET_SPIMCTRL);
+
+			/* wait busy bit is cleared */
+			do {
+				value = readb(priv->base + OFFSET_SPIMCTRL);
+			} while (value & SPIMCTRL_BUSY);
+			return 0;
+		}
+	}
+
+	if (!(flags & SPI_XFER_END) && (flags & SPI_XFER_BEGIN)) {
+		/* first of spi_xfer calls */
+		return 0;
+	}
+
+	/* if dout != null, write data to buf and start transaction */
+	if (dout) {
+		if (len > slave->max_write_size) {
+			printf("SF: write length is too big(>%d)\n", slave->max_write_size);
+			return -1;
+		}
+
+		/* load the data bytes */
+		memcpy((u8 *)priv->base + OFFSET_SPILDAT, dout, len);
+
+		/* write: set the data direction bit to 1 */
+		value = readb(priv->base + OFFSET_SPIMCTRL);
+		value |= (1 << 3);
+		writeb(value, priv->base + OFFSET_SPIMCTRL);
+
+		/* set the data byte count */
+		writeb(len, priv->base + OFFSET_SPIDCNT);
+
+		/* set the start bit */
+		value = readb(priv->base + OFFSET_SPIMCTRL);
+		value |= SPIMCTRL_START;
+		writeb(value, priv->base + OFFSET_SPIMCTRL);
+
+		/* wait busy bit is cleared */
+		do {
+			value = readb(priv->base + OFFSET_SPIMCTRL);
+		} while (value & SPIMCTRL_BUSY);
+
+		return 0;
+	}
+
+	/* if din !=null, start and read data */
+	if (uchar_in) {
+		read_ptr = 0;
+
+		while (read_ptr < len) {
+			read_len = len - read_ptr;
+			if (read_len > GXP_SPILDAT_SIZE)
+				read_len = GXP_SPILDAT_SIZE;
+
+			/* read: set the data direction bit to 0 */
+			value = readb(priv->base + OFFSET_SPIMCTRL);
+			value &= ~(1 << 3);
+			writeb(value, priv->base + OFFSET_SPIMCTRL);
+
+			/* set the data byte count */
+			writeb(read_len, priv->base + OFFSET_SPIDCNT);
+
+			/* set the start bit */
+			value = readb(priv->base + OFFSET_SPIMCTRL);
+			value |= SPIMCTRL_START;
+			writeb(value, priv->base + OFFSET_SPIMCTRL);
+
+			/* wait busy bit is cleared */
+			do {
+				value = readb(priv->base + OFFSET_SPIMCTRL);
+			} while (value & SPIMCTRL_BUSY);
+
+			/* store the data bytes */
+			memcpy(uchar_in + read_ptr, (u8 *)priv->base + OFFSET_SPILDAT, read_len);
+			/* update read_ptr and addr reg */
+			read_ptr += read_len;
+
+			addr = readl(priv->base + OFFSET_SPIADDR);
+			addr += read_len;
+			writel(addr, priv->base + OFFSET_SPIADDR);
+		}
+
+		return 0;
+	}
+	return -2;
+}
+
+static int gxp_spi_set_speed(struct udevice *dev, unsigned int speed)
+{
+	/* Accept any speed */
+	return 0;
+}
+
+static int gxp_spi_set_mode(struct udevice *dev, unsigned int mode)
+{
+	struct gxp_spi_priv *priv = dev_get_priv(dev->parent);
+
+	priv->mode = mode;
+
+	return 0;
+}
+
+static int gxp_spi_claim_bus(struct udevice *dev)
+{
+	struct gxp_spi_priv *priv = dev_get_priv(dev->parent);
+	unsigned char cmd;
+
+	spi_set_mode(priv, MANUAL_MODE);
+
+	/* exit 4 bytes addr mode, uboot spi_flash only supports 3 byets address mode */
+	cmd = 0xe9;
+	gxp_spi_xfer(dev, 1 * 8, &cmd, NULL, SPI_XFER_BEGIN | SPI_XFER_END);
+	return 0;
+}
+
+static int gxp_spi_release_bus(struct udevice *dev)
+{
+	struct gxp_spi_priv *priv = dev_get_priv(dev->parent);
+
+	spi_set_mode(priv, AUTO_MODE);
+
+	return 0;
+}
+
+int gxp_spi_cs_info(struct udevice *bus, unsigned int cs, struct spi_cs_info *info)
+{
+	if (cs < GXP_SPI0_MAX_CHIPSELECT)
+		return 0;
+	else
+		return -ENODEV;
+}
+
+static int gxp_spi_probe(struct udevice *bus)
+{
+	struct gxp_spi_priv *priv = dev_get_priv(bus);
+
+	priv->base = dev_read_addr_ptr(bus);
+	if (!priv->base)
+		return -ENOENT;
+
+	return 0;
+}
+
+static int gxp_spi_child_pre_probe(struct udevice *dev)
+{
+	struct spi_slave *slave = dev_get_parent_priv(dev);
+
+	slave->max_write_size = GXP_SPILDAT_SIZE;
+
+	return 0;
+}
+
+static const struct dm_spi_ops gxp_spi_ops = {
+	.claim_bus = gxp_spi_claim_bus,
+	.release_bus = gxp_spi_release_bus,
+	.xfer = gxp_spi_xfer,
+	.set_speed = gxp_spi_set_speed,
+	.set_mode = gxp_spi_set_mode,
+	.cs_info = gxp_spi_cs_info,
+};
+
+static const struct udevice_id gxp_spi_ids[] = {
+	{ .compatible = "hpe,gxp-spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(gxp_spi) = {
+	.name	= "gxp_spi",
+	.id	= UCLASS_SPI,
+	.of_match = gxp_spi_ids,
+	.ops	= &gxp_spi_ops,
+	.priv_auto = sizeof(struct gxp_spi_priv),
+	.probe	= gxp_spi_probe,
+	.child_pre_probe = gxp_spi_child_pre_probe,
+};
+
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 7b8ab56..d592dba 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -139,6 +139,13 @@
 	  Enables support for the Designware APB Timer driver. This timer is
 	  present on Altera SoCFPGA SoCs.
 
+config GXP_TIMER
+	bool "HPE GXP Timer"
+	depends on TIMER
+	help
+	  Enables support for the GXP Timer driver. This timer is
+	  present on HPE GXP SoCs.
+
 config MPC83XX_TIMER
 	bool "MPC83xx timer support"
 	depends on TIMER
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index b2f002d..cc2b851 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -12,6 +12,7 @@
 obj-$(CONFIG_$(SPL_)ATMEL_TCB_TIMER) += atmel_tcb_timer.o
 obj-$(CONFIG_CADENCE_TTC_TIMER)	+= cadence-ttc.o
 obj-$(CONFIG_DESIGNWARE_APB_TIMER)	+= dw-apb-timer.o
+obj-$(CONFIG_GXP_TIMER)		+= gxp-timer.o
 obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o
 obj-$(CONFIG_NOMADIK_MTU_TIMER)	+= nomadik-mtu-timer.o
 obj-$(CONFIG_NPCM_TIMER)        += npcm-timer.o
diff --git a/drivers/timer/gxp-timer.c b/drivers/timer/gxp-timer.c
new file mode 100644
index 0000000..6f316bc
--- /dev/null
+++ b/drivers/timer/gxp-timer.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * GXP timer driver
+ *
+ * (C) Copyright 2022 Hewlett Packard Enterprise Development LP.
+ * Author: Nick Hawkins <nick.hawkins@hpe.com>
+ * Author: Jean-Marie Verdun <verdun@hpe.com>
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <timer.h>
+#include <asm/io.h>
+
+#define USTIMELO	0x18
+#define USTIMEHI	0x1C
+
+struct gxp_timer_priv {
+	void __iomem *base;
+};
+
+static u64 gxp_timer_get_count(struct udevice *dev)
+{
+	struct gxp_timer_priv *priv = dev_get_priv(dev);
+	u64 val;
+
+	val = readl(priv->base + USTIMEHI);
+	val = (val << 32) | readl(priv->base + USTIMELO);
+
+	return val;
+}
+
+static int gxp_timer_probe(struct udevice *dev)
+{
+	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct gxp_timer_priv *priv = dev_get_priv(dev);
+
+	priv->base = dev_read_addr_ptr(dev);
+	if (!priv->base)
+		return -ENOENT;
+
+	uc_priv->clock_rate = 1000000;
+
+	return 0;
+}
+
+static const struct timer_ops gxp_timer_ops = {
+	.get_count = gxp_timer_get_count,
+};
+
+static const struct udevice_id gxp_timer_ids[] = {
+	{ .compatible = "hpe,gxp-timer" },
+	{}
+};
+
+U_BOOT_DRIVER(gxp_timer) = {
+	.name = "gxp-timer",
+	.id = UCLASS_TIMER,
+	.of_match = gxp_timer_ids,
+	.priv_auto = sizeof(struct gxp_timer_priv),
+	.probe = gxp_timer_probe,
+	.ops = &gxp_timer_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
new file mode 100644
index 0000000..38d7fe8
--- /dev/null
+++ b/include/configs/corstone1000.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * (C) Copyright 2022 Linaro
+ * Rui Miguel Silva <rui.silva@linaro.org>
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ *
+ * Configuration for Corstone1000. Parts were derived from other ARM
+ * configurations.
+ */
+
+#ifndef __CORSTONE1000_H
+#define __CORSTONE1000_H
+
+#include <linux/sizes.h>
+
+#define V2M_BASE		0x80000000
+
+#define CONFIG_PL011_CLOCK	50000000
+
+/* Physical Memory Map */
+#define PHYS_SDRAM_1		(V2M_BASE)
+#define PHYS_SDRAM_1_SIZE	0x80000000
+
+#define CONFIG_SYS_SDRAM_BASE	PHYS_SDRAM_1
+
+#endif
diff --git a/include/configs/devkit8000.h b/include/configs/devkit8000.h
index 4e91f8c..d45115b 100644
--- a/include/configs/devkit8000.h
+++ b/include/configs/devkit8000.h
@@ -14,17 +14,6 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
-/* High Level Configuration Options */
-
-/*
- * 1MB into the SDRAM to allow for SPL's bss at the beginning of SDRAM
- * 64 bytes before this address should be set aside for u-boot.img's
- * header. That is 0x800FFFC0--0x80100000 should not be used for any
- * other needs.
- */
-
-/*  Physical Memory Map  */
-
 #include <configs/ti_omap3_common.h>
 
 /* Hardware drivers */
@@ -40,9 +29,12 @@
 
 /* BOOTP/DHCP options */
 
+#define MEM_LAYOUT_ENV_SETTINGS \
+	DEFAULT_LINUX_BOOT_ENV
+
 /* Environment information */
 #define CONFIG_EXTRA_ENV_SETTINGS \
-	"loadaddr=0x82000000\0" \
+	MEM_LAYOUT_ENV_SETTINGS \
 	"console=ttyO2,115200n8\0" \
 	"mmcdev=0\0" \
 	"vram=12M\0" \
diff --git a/include/configs/gxp.h b/include/configs/gxp.h
new file mode 100644
index 0000000..e3c97b2
--- /dev/null
+++ b/include/configs/gxp.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * GXP board
+ *
+ * (C) Copyright 2022 Hewlett Packard Enterprise Development LP.
+ * Author: Nick Hawkins <nick.hawkins@hpe.com>
+ * Author: Jean-Marie Verdun <verdun@hpe.com>
+ */
+
+#ifndef _GXP_H_
+#define _GXP_H_
+
+#define CONFIG_SYS_SDRAM_BASE   0x40000000
+
+#endif
diff --git a/include/efi_loader.h b/include/efi_loader.h
index c1e00eb..31de191 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -591,6 +591,8 @@
 void efi_save_gd(void);
 /* Call this to relocate the runtime section to an address space */
 void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map);
+/* Call this to get image parameters */
+void efi_get_image_parameters(void **img_addr, size_t *img_size);
 /* Add a new object to the object list. */
 void efi_add_handle(efi_handle_t obj);
 /* Create handle */
diff --git a/include/test/suites.h b/include/test/suites.h
index ee6858a..ddb8827 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -39,6 +39,7 @@
 int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_env(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index 171661b..2493d74 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -1158,6 +1158,8 @@
 {
 	struct blk_desc *desc = NULL;
 	struct disk_partition fs_partition;
+	size_t image_size;
+	void *image_addr;
 	int part = 0;
 	char *filename;
 	char *s;
@@ -1173,6 +1175,13 @@
 	} else if (!strcmp(dev, "Uart")) {
 		if (device)
 			*device = efi_dp_from_uart();
+	} else if (!strcmp(dev, "Mem")) {
+		efi_get_image_parameters(&image_addr, &image_size);
+
+		if (device)
+			*device = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
+						  (uintptr_t)image_addr,
+						  image_size);
 	} else {
 		part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
 					       1);
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index a59adb1..4b2d7df 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -7,6 +7,7 @@
 endif
 obj-y += mem.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
+obj-$(CONFIG_CMD_LOADM) += loadm.o
 obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
 obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PWM) += pwm.o
diff --git a/test/cmd/loadm.c b/test/cmd/loadm.c
new file mode 100644
index 0000000..41e005a
--- /dev/null
+++ b/test/cmd/loadm.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for loadm command
+ *
+ * Copyright 2022 ARM Limited
+ * Copyright 2022 Linaro
+ *
+ * Authors:
+ *   Rui Miguel Silva <rui.silva@linaro.org>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <mapmem.h>
+#include <asm/global_data.h>
+#include <dm/test.h>
+#include <test/suites.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define BUF_SIZE 0x100
+
+#define LOADM_TEST(_name, _flags)	UNIT_TEST(_name, _flags, loadm_test)
+
+static int loadm_test_params(struct unit_test_state *uts)
+{
+	ut_assertok(console_record_reset_enable());
+	run_command("loadm", 0);
+	ut_assert_nextline("loadm - load binary blob from source address to destination address");
+
+	ut_assertok(console_record_reset_enable());
+	run_command("loadm 0x12345678", 0);
+	ut_assert_nextline("loadm - load binary blob from source address to destination address");
+
+	ut_assertok(console_record_reset_enable());
+	run_command("loadm 0x12345678 0x12345678", 0);
+	ut_assert_nextline("loadm - load binary blob from source address to destination address");
+
+	ut_assertok(console_record_reset_enable());
+	run_command("loadm 0x12345678 0x12345678 0", 0);
+	ut_assert_nextline("loadm: can not load zero bytes");
+
+	return 0;
+}
+LOADM_TEST(loadm_test_params, UT_TESTF_CONSOLE_REC);
+
+static int loadm_test_load (struct unit_test_state *uts)
+{
+	char *buf;
+
+	buf = map_sysmem(0, BUF_SIZE);
+	memset(buf, '\0', BUF_SIZE);
+	memset(buf, 0xaa, BUF_SIZE / 2);
+
+	ut_assertok(console_record_reset_enable());
+	run_command("loadm 0x0 0x80 0x80", 0);
+	ut_assert_nextline("loaded bin to memory: size: 128");
+
+	unmap_sysmem(buf);
+
+	return 0;
+}
+LOADM_TEST(loadm_test_load, UT_TESTF_CONSOLE_REC);
+
+int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct unit_test *tests = UNIT_TEST_SUITE_START(loadm_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(loadm_test);
+
+	return cmd_ut_category("loadm", "loadm_test_", tests, n_ents, argc,
+			       argv);
+}
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 67a13ee..d70b726 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -74,6 +74,9 @@
 #ifdef CONFIG_CMD_ADDRMAP
 	U_BOOT_CMD_MKENT(addrmap, CONFIG_SYS_MAXARGS, 1, do_ut_addrmap, "", ""),
 #endif
+#ifdef CONFIG_CMD_LOADM
+	U_BOOT_CMD_MKENT(loadm, CONFIG_SYS_MAXARGS, 1, do_ut_loadm, "", ""),
+#endif
 };
 
 static int do_ut_all(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -156,6 +159,9 @@
 #ifdef CONFIG_CMD_ADDRMAP
 	"ut addrmap - Very basic test of addrmap command\n"
 #endif
+#ifdef CONFIG_CMD_LOADM
+	"ut loadm [test-name]- test of parameters and load memory blob\n"
+#endif
 	;
 #endif /* CONFIG_SYS_LONGHELP */