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

u-boot-imx-20231016
-------------------

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

- Imrovement MX93
- Toradex: fixes
- Convert to DM (serial, watchdog) for some boards
- HAB improvements for Secure Boot
- DTO overlay for DHCOM
- USB fixes, Mass storage for MX28
- Cleanup some code
- Phytec MX8M : EEProm detection, fixes
- Gateworks Boards improvements
diff --git a/MAINTAINERS b/MAINTAINERS
index 7d5d053..16b17fd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -161,6 +161,7 @@
 F:	drivers/adc/meson-saradc.c
 F:	drivers/phy/meson*
 F:	drivers/mmc/meson_gx_mmc.c
+F:	drivers/sm/meson-sm.c
 F:	drivers/spi/meson_spifc.c
 F:	drivers/pinctrl/meson/
 F:	drivers/power/domain/meson-gx-pwrc-vpu.c
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 99d8e89..2a42fd8 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -66,6 +66,7 @@
 	kirkwood-ns2max.dtb \
 	kirkwood-ns2mini.dtb \
 	kirkwood-nsa310s.dtb \
+	kirkwood-nsa325.dtb \
 	kirkwood-openrd-base.dtb \
 	kirkwood-openrd-client.dtb \
 	kirkwood-openrd-ultimate.dtb \
diff --git a/arch/arm/dts/ac5-98dx35xx-atl-x240.dts b/arch/arm/dts/ac5-98dx35xx-atl-x240.dts
index c19b259..820ec18 100644
--- a/arch/arm/dts/ac5-98dx35xx-atl-x240.dts
+++ b/arch/arm/dts/ac5-98dx35xx-atl-x240.dts
@@ -16,7 +16,7 @@
 		gpio0 = &gpio0;
 		gpio1 = &gpio1;
 		spi0 = &spi0;
-		i2c0 = &i2cgpio;
+		i2c0 = &i2c0;
 		usb0 = &usb0;
 		pinctrl0 = &pinctrl0;
 	};
@@ -40,19 +40,6 @@
 			default-state = "on";
 		};
 	};
-
-	i2cgpio: i2c-gpio-0 {
-			compatible = "i2c-gpio";
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			pinctrl-names = "default";
-			pinctrl-0 =  <&i2c0_gpio>;
-			scl-gpios = <&gpio0 26 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
-			sda-gpios = <&gpio0 27 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
-			i2c-gpio,delay-us = <2>;
-			status = "okay";
-		 };
 };
 
 &nand {
@@ -83,7 +70,9 @@
 	status = "okay";
 };
 
-&i2cgpio {
+&i2c0 {
+	status = "okay";
+
 	mux@71 {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -188,8 +177,8 @@
 	 * LED_OE_N              [23]
 	 * USB_PWR_FLT_N         [24]
 	 * SFP_INT_N             [25]
-	 * I2C0_SCL              [26] (GPIO)
-	 * I2C0_SDA              [27] (GPIO)
+	 * I2C0_SCL              [26]
+	 * I2C0_SDA              [27]
 	 * USB_EN                [28]
 	 * MONITOR_INT_N         [29]
 	 * XM1_MDC               [30]
@@ -212,7 +201,7 @@
 	/*	     0    1    2    3    4    5    6    7    8    9 */
 	pin-func = < 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
 		     0xff 0xff 1    1    1    1    0xff 0xff 0    0
-		     0    0    0    0    0    0    0xff 0xff 0    0
+		     0    0    0    0    0    0    1    1    0    0
 		     1    1    1    1    0    0    0    0    0    0
 		     0    0    0    1    1    1    >;
 
@@ -220,9 +209,4 @@
 		marvell,pins = <0 1 2 3 4 5 6 7 8 9 10 11 16 17>;
 		marvell,function = <2>;
 	};
-
-	i2c0_gpio: i2c0-gpio-pins {
-		marvell,pins = <26 27>;
-		marvell,function = <0>;
-	};
 };
diff --git a/arch/arm/dts/cn9130-crb.dtsi b/arch/arm/dts/cn9130-crb.dtsi
index b229725..7dd36ca 100644
--- a/arch/arm/dts/cn9130-crb.dtsi
+++ b/arch/arm/dts/cn9130-crb.dtsi
@@ -125,11 +125,6 @@
 		marvell,function = <0>;
 	};
 
-	cp0_spi1_pins_crb: cp0-spi-pins-crb {
-		marvell,pins = < 13 14 15 16 >;
-		marvell,function = <3>;
-	};
-
 	cp0_smi_pins_crb: cp0-smi-pins-crb {
 		marvell,pins = < 40 41 >;
 		marvell,function = <8>;
@@ -170,7 +165,7 @@
 
 &cp0_spi1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&cp0_spi1_pins_crb>;
+	pinctrl-0 = <&cp0_spi1_pins>;
 	reg = <0x700680 0x50>,		/* control */
 	      <0x2000000 0x1000000>,	/* CS0 */
 	      <0 0xffffffff>,		/* CS1 */
diff --git a/arch/arm/dts/cn9130-db.dtsi b/arch/arm/dts/cn9130-db.dtsi
index 1b28732..4b21ff4 100644
--- a/arch/arm/dts/cn9130-db.dtsi
+++ b/arch/arm/dts/cn9130-db.dtsi
@@ -183,7 +183,7 @@
 /* U55 */
 &cp0_spi1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&cp0_spi0_pins>;
+	pinctrl-0 = <&cp0_spi1_pins>;
 	reg = <0x700680 0x50>,		/* control */
 	      <0x2000000 0x1000000>,	/* CS0 */
 	      <0 0xffffffff>,		/* CS1 */
diff --git a/arch/arm/dts/cn9130.dtsi b/arch/arm/dts/cn9130.dtsi
index 68b767a..efcb2e9 100644
--- a/arch/arm/dts/cn9130.dtsi
+++ b/arch/arm/dts/cn9130.dtsi
@@ -66,7 +66,7 @@
 		marvell,pins = < 56 57 58 59 60 61 >;
 		marvell,function = <14>;
 	};
-	cp0_spi0_pins: cp0-spi-pins-0 {
+	cp0_spi1_pins: cp0-spi-pins-1 {
 		marvell,pins = < 13 14 15 16 >;
 		marvell,function = <3>;
 	};
diff --git a/arch/arm/dts/kirkwood-6282.dtsi b/arch/arm/dts/kirkwood-6282.dtsi
new file mode 100644
index 0000000..e732c50
--- /dev/null
+++ b/arch/arm/dts/kirkwood-6282.dtsi
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0
+/ {
+	mbus@f1000000 {
+		pciec: pcie@82000000 {
+			compatible = "marvell,kirkwood-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000
+				0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000
+				0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000
+				0x82000000 0x1 0     MBUS_ID(0x04, 0xe8) 0       1 0 /* Port 0.0 MEM */
+				0x81000000 0x1 0     MBUS_ID(0x04, 0xe0) 0       1 0 /* Port 0.0 IO  */
+				0x82000000 0x2 0     MBUS_ID(0x04, 0xd8) 0       1 0 /* Port 1.0 MEM */
+				0x81000000 0x2 0     MBUS_ID(0x04, 0xd0) 0       1 0 /* Port 1.0 IO  */>;
+
+			pcie0: pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x00040000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				bus-range = <0x00 0xff>;
+				interrupt-names = "intx", "error";
+				interrupts = <9>, <44>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie0_intc 0>,
+						<0 0 0 2 &pcie0_intc 1>,
+						<0 0 0 3 &pcie0_intc 2>,
+						<0 0 0 4 &pcie0_intc 3>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gate_clk 2>;
+				status = "disabled";
+
+				pcie0_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
+			};
+
+			pcie1: pcie@2,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82001000 0 0x00044000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+					  0x81000000 0 0 0x81000000 0x2 0 1 0>;
+				bus-range = <0x00 0xff>;
+				interrupt-names = "intx", "error";
+				interrupts = <10>, <45>;
+				interrupt-map-mask = <0 0 0 7>;
+				interrupt-map = <0 0 0 1 &pcie1_intc 0>,
+						<0 0 0 2 &pcie1_intc 1>,
+						<0 0 0 3 &pcie1_intc 2>,
+						<0 0 0 4 &pcie1_intc 3>;
+				marvell,pcie-port = <1>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gate_clk 18>;
+				status = "disabled";
+
+				pcie1_intc: interrupt-controller {
+					interrupt-controller;
+					#interrupt-cells = <1>;
+				};
+			};
+		};
+	};
+	ocp@f1000000 {
+
+		pinctrl: pin-controller@10000 {
+			compatible = "marvell,88f6282-pinctrl";
+
+			pmx_sata0: pmx-sata0 {
+				marvell,pins = "mpp5", "mpp21", "mpp23";
+				marvell,function = "sata0";
+			};
+			pmx_sata1: pmx-sata1 {
+				marvell,pins = "mpp4", "mpp20", "mpp22";
+				marvell,function = "sata1";
+			};
+
+			/*
+			 * Default I2C1 pinctrl setting on mpp36/mpp37,
+			 * overwrite marvell,pins on board level if required.
+			 */
+			pmx_twsi1: pmx-twsi1 {
+				marvell,pins = "mpp36", "mpp37";
+				marvell,function = "twsi1";
+			};
+
+			pmx_sdio: pmx-sdio {
+				marvell,pins = "mpp12", "mpp13", "mpp14",
+					       "mpp15", "mpp16", "mpp17";
+				marvell,function = "sdio";
+			};
+		};
+
+		thermal: thermal@10078 {
+			compatible = "marvell,kirkwood-thermal";
+			reg = <0x10078 0x4>;
+			status = "okay";
+		};
+
+		rtc: rtc@10300 {
+			compatible = "marvell,kirkwood-rtc", "marvell,orion-rtc";
+			reg = <0x10300 0x20>;
+			interrupts = <53>;
+			clocks = <&gate_clk 7>;
+		};
+
+		i2c1: i2c@11100 {
+			compatible = "marvell,mv64xxx-i2c";
+			reg = <0x11100 0x20>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <32>;
+			clock-frequency = <100000>;
+			clocks = <&gate_clk 7>;
+			pinctrl-0 = <&pmx_twsi1>;
+			pinctrl-names = "default";
+			status = "disabled";
+		};
+
+		sata: sata@80000 {
+			compatible = "marvell,orion-sata";
+			reg = <0x80000 0x5000>;
+			interrupts = <21>;
+			clocks = <&gate_clk 14>, <&gate_clk 15>;
+			clock-names = "0", "1";
+			phys = <&sata_phy0>, <&sata_phy1>;
+			phy-names = "port0", "port1";
+			status = "disabled";
+		};
+
+		sdio: mvsdio@90000 {
+			compatible = "marvell,orion-sdio";
+			reg = <0x90000 0x200>;
+			interrupts = <28>;
+			clocks = <&gate_clk 4>;
+			pinctrl-0 = <&pmx_sdio>;
+			pinctrl-names = "default";
+			bus-width = <4>;
+			cap-sdio-irq;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/dts/kirkwood-nsa325.dts b/arch/arm/dts/kirkwood-nsa325.dts
new file mode 100644
index 0000000..efc57cf
--- /dev/null
+++ b/arch/arm/dts/kirkwood-nsa325.dts
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Device tree file for the Zyxel NSA 325 NAS box.
+ *
+ * Copyright (c) 2015, Hans Ulli Kroll <ulli.kroll@googlemail.com>
+ *
+ *
+ * Based upon the board setup file created by Peter Schildmann
+ */
+
+/dts-v1/;
+
+#include "kirkwood-nsa3x0-common.dtsi"
+
+/ {
+	model = "ZyXEL NSA325";
+	compatible = "zyxel,nsa325", "marvell,kirkwood-88f6282", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200";
+		stdout-path = &uart0;
+	};
+
+	ocp@f1000000 {
+		pinctrl: pin-controller@10000 {
+			pinctrl-names = "default";
+
+			pmx_led_hdd2_green: pmx-led-hdd2-green {
+				marvell,pins = "mpp12";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_hdd2_red: pmx-led-hdd2-red {
+				marvell,pins = "mpp13";
+				marvell,function = "gpio";
+			};
+
+			pmx_mcu_data: pmx-mcu-data {
+				marvell,pins = "mpp14";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_usb_green: pmx-led-usb-green {
+				marvell,pins = "mpp15";
+				marvell,function = "gpio";
+			};
+
+			pmx_mcu_clk: pmx-mcu-clk {
+				marvell,pins = "mpp16";
+				marvell,function = "gpio";
+			};
+
+			pmx_mcu_act: pmx-mcu-act {
+				marvell,pins = "mpp17";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_sys_green: pmx-led-sys-green {
+				marvell,pins = "mpp28";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_sys_orange: pmx-led-sys-orange {
+				marvell,pins = "mpp29";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_hdd1_green: pmx-led-hdd1-green {
+				marvell,pins = "mpp41";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_hdd1_red: pmx-led-hdd1-red {
+				marvell,pins = "mpp42";
+				marvell,function = "gpio";
+			};
+
+			pmx_htp: pmx-htp {
+				marvell,pins = "mpp43";
+				marvell,function = "gpio";
+			};
+
+			/*
+			 * Buzzer needs to be switched at around 1kHz so is
+			 * not compatible with the gpio-beeper driver.
+			 */
+			pmx_buzzer: pmx-buzzer {
+				marvell,pins = "mpp44";
+				marvell,function = "gpio";
+			};
+
+			pmx_vid_b1: pmx-vid-b1 {
+				marvell,pins = "mpp45";
+				marvell,function = "gpio";
+			};
+
+			pmx_power_resume_data: pmx-power-resume-data {
+				marvell,pins = "mpp47";
+				marvell,function = "gpio";
+			};
+
+			pmx_power_resume_clk: pmx-power-resume-clk {
+				marvell,pins = "mpp49";
+				marvell,function = "gpio";
+			};
+
+			pmx_pwr_sata1: pmx-pwr-sata1 {
+				marvell,pins = "mpp47";
+				marvell,function = "gpio";
+			};
+		};
+
+		/* This board uses the pcf8563 RTC instead of the SoC RTC */
+		rtc@10300 {
+			status = "disabled";
+		};
+
+		i2c@11000 {
+			status = "okay";
+
+			pcf8563: pcf8563@51 {
+				compatible = "nxp,pcf8563";
+				reg = <0x51>;
+			};
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_pwr_sata1>;
+		pinctrl-names = "default";
+
+		usb0_power: regulator@1 {
+			enable-active-high;
+		};
+
+		sata1_power: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "SATA1 Power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio1 15 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pmx_led_hdd2_green &pmx_led_hdd2_red
+			     &pmx_led_usb_green
+			     &pmx_led_sys_green &pmx_led_sys_orange
+			     &pmx_led_copy_green &pmx_led_copy_red
+			     &pmx_led_hdd1_green &pmx_led_hdd1_red>;
+		pinctrl-names = "default";
+
+		green-sys {
+			label = "nsa325:green:sys";
+			gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
+		};
+		orange-sys {
+			label = "nsa325:orange:sys";
+			gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
+		};
+		green-hdd1 {
+			label = "nsa325:green:hdd1";
+			gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+		};
+		red-hdd1 {
+			label = "nsa325:red:hdd1";
+			gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+		};
+		green-hdd2 {
+			label = "nsa325:green:hdd2";
+			gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
+		};
+		red-hdd2 {
+			label = "nsa325:red:hdd2";
+			gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
+		};
+		green-usb {
+			label = "nsa325:green:usb";
+			gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
+		};
+		green-copy {
+			label = "nsa325:green:copy";
+			gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+		};
+		red-copy {
+			label = "nsa325:red:copy";
+			gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+		};
+
+	/* The following pins are currently not assigned to a driver,
+	   some of them should be configured as inputs.
+	pinctrl-0 = <&pmx_mcu_data &pmx_mcu_clk &pmx_mcu_act
+		     &pmx_htp &pmx_vid_b1
+		     &pmx_power_resume_data &pmx_power_resume_clk>; */
+	};
+
+};
+
+&mdio {
+	status = "okay";
+	ethphy0: ethernet-phy@1 {
+		reg = <1>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
+
+&pciec {
+	status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/kirkwood-nsa3x0-common.dtsi b/arch/arm/dts/kirkwood-nsa3x0-common.dtsi
new file mode 100644
index 0000000..a21c50d
--- /dev/null
+++ b/arch/arm/dts/kirkwood-nsa3x0-common.dtsi
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+
+/ {
+	model = "ZyXEL NSA310";
+
+	ocp@f1000000 {
+		pinctrl: pin-controller@10000 {
+
+			pmx_usb_power: pmx-usb-power {
+				marvell,pins = "mpp21";
+				marvell,function = "gpio";
+			};
+
+			pmx_pwr_off: pmx-pwr-off {
+				marvell,pins = "mpp48";
+				marvell,function = "gpio";
+			};
+
+			pmx_btn_reset: pmx-btn-reset {
+				marvell,pins = "mpp36";
+				marvell,function = "gpio";
+			};
+
+			pmx_btn_copy: pmx-btn-copy {
+				marvell,pins = "mpp37";
+				marvell,function = "gpio";
+			};
+
+			pmx_btn_power: pmx-btn-power {
+				marvell,pins = "mpp46";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_copy_green: pmx-led-copy-green {
+				marvell,pins = "mpp39";
+				marvell,function = "gpio";
+			};
+
+			pmx_led_copy_red: pmx-led-copy-red {
+				marvell,pins = "mpp40";
+				marvell,function = "gpio";
+			};
+		};
+
+		serial@12000 {
+			status = "okay";
+		};
+
+		sata@80000 {
+			status = "okay";
+			nr-ports = <2>;
+		};
+	};
+
+	gpio_poweroff {
+		compatible = "gpio-poweroff";
+		pinctrl-0 = <&pmx_pwr_off>;
+		pinctrl-names = "default";
+		gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_btn_reset &pmx_btn_copy &pmx_btn_power>;
+		pinctrl-names = "default";
+
+		power {
+			label = "Power Button";
+			linux,code = <KEY_POWER>;
+			gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>;
+		};
+		copy {
+			label = "Copy Button";
+			linux,code = <KEY_COPY>;
+			gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
+		};
+		reset {
+			label = "Reset Button";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&pmx_usb_power>;
+		pinctrl-names = "default";
+
+		usb0_power: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "USB Power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
+
+&nand {
+	status = "okay";
+	chip-delay = <35>;
+
+	partition@0 {
+		label = "uboot";
+		reg = <0x0000000 0x0100000>;
+	};
+	partition@100000 {
+		label = "uboot_env";
+		reg = <0x0100000 0x0080000>;
+	};
+	partition@180000 {
+		label = "key_store";
+		reg = <0x0180000 0x0080000>;
+	};
+	partition@200000 {
+		label = "info";
+		reg = <0x0200000 0x0080000>;
+	};
+	partition@280000 {
+		label = "etc";
+		reg = <0x0280000 0x0a00000>;
+	};
+	partition@c80000 {
+		label = "kernel_1";
+		reg = <0x0c80000 0x0a00000>;
+	};
+	partition@1680000 {
+		label = "rootfs1";
+		reg = <0x1680000 0x2fc0000>;
+	};
+	partition@4640000 {
+		label = "kernel_2";
+		reg = <0x4640000 0x0a00000>;
+	};
+	partition@5040000 {
+		label = "rootfs2";
+		reg = <0x5040000 0x2fc0000>;
+	};
+};
+
+&pciec {
+	status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/meson-a1.dtsi b/arch/arm/dts/meson-a1.dtsi
index 6509329..e3a42c5 100644
--- a/arch/arm/dts/meson-a1.dtsi
+++ b/arch/arm/dts/meson-a1.dtsi
@@ -124,6 +124,17 @@
 				clock-names = "xtal", "pclk", "baud";
 				status = "disabled";
 			};
+
+			hwrng: rng@5118 {
+				compatible = "amlogic,meson-rng";
+				reg = <0x0 0x5118 0x0 0x4>;
+			};
+
+			sec_AO: ao-secure@5a20 {
+				compatible = "amlogic,meson-gx-ao-secure", "syscon";
+				reg = <0x0 0x5a20 0x0 0x140>;
+				amlogic,has-chip-id;
+			};
 		};
 
 		gic: interrupt-controller@ff901000 {
diff --git a/arch/arm/include/asm/arch-meson/clock-a1.h b/arch/arm/include/asm/arch-meson/clock-a1.h
new file mode 100644
index 0000000..f6795f5
--- /dev/null
+++ b/arch/arm/include/asm/arch-meson/clock-a1.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 - AmLogic, Inc.
+ * Copyright 2023 (C) SberDevices, Inc.
+ */
+
+#ifndef _ARCH_MESON_CLOCK_A1_H_
+#define _ARCH_MESON_CLOCK_A1_H_
+
+/*
+ * Clock controller register offsets
+ */
+#define A1_SYS_OSCIN_CTRL		0x0
+#define A1_SYS_CLK_CTRL0		0x10
+#define A1_SYS_CLK_EN0			0x1c
+#define A1_SAR_ADC_CLK_CTR		0xc0
+#define A1_SPIFC_CLK_CTRL		0xd8
+#define A1_USB_BUSCLK_CTRL		0xdc
+#define A1_SD_EMMC_CLK_CTRL		0xe0
+
+#define A1_ANACTRL_FIXPLL_CTRL0		0x0
+
+#endif /* _ARCH_MESON_CLOCK_A1_H_ */
diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
index c54f52b..70a213a 100644
--- a/arch/arm/mach-imx/cmd_nandbcb.c
+++ b/arch/arm/mach-imx/cmd_nandbcb.c
@@ -1561,8 +1561,7 @@
 	return CMD_RET_USAGE;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char nandbcb_help_text[] =
+U_BOOT_LONGHELP(nandbcb,
 	"init addr off|partition len - update 'len' bytes starting at\n"
 	"       'off|part' to memory address 'addr', skipping  bad blocks\n"
 	"nandbcb bcbonly off|partition fw1-off fw1-size [fw2-off fw2-size]\n"
@@ -1572,8 +1571,7 @@
 	"       FIY, BCB isn't erased automatically, so mtd erase should\n"
 	"       be called in advance before writing new BCB:\n"
 	"           > mtd erase mx7-bcb\n"
-	"nandbcb dump off|partition - dump/verify boot structures\n";
-#endif
+	"nandbcb dump off|partition - dump/verify boot structures\n");
 
 U_BOOT_CMD(nandbcb, 7, 1, do_nandbcb,
 	   "i.MX NAND Boot Control Blocks write",
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index 54027cc..c2fff84 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -133,6 +133,12 @@
 	select KW88F6192
 	select KIRKWOOD_COMMON
 
+config TARGET_NSA325
+	bool "ZyXEL NSA325"
+	select FEROCEON_88FR131
+	select KW88F6281
+	select KIRKWOOD_COMMON
+
 config TARGET_SBx81LIFKW
 	bool "Allied Telesis SBx81GS24/SBx81GT40/SBx81XS6/SBx81XS16"
 	select FEROCEON_88FR131
@@ -177,6 +183,7 @@
 source "board/Seagate/goflexhome/Kconfig"
 source "board/Seagate/nas220/Kconfig"
 source "board/zyxel/nsa310s/Kconfig"
+source "board/zyxel/nsa325/Kconfig"
 source "board/alliedtelesis/SBx81LIFKW/Kconfig"
 source "board/alliedtelesis/SBx81LIFXCAT/Kconfig"
 
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig
index 669ca09..d6c8905 100644
--- a/arch/arm/mach-meson/Kconfig
+++ b/arch/arm/mach-meson/Kconfig
@@ -11,6 +11,7 @@
 	select PWRSEQ
 	select MMC_PWRSEQ
 	select BOARD_LATE_INIT
+	select MESON_SM
 	imply CMD_DM
 
 config MESON_GX
diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c
index d600c64d..914fd11 100644
--- a/arch/arm/mach-meson/sm.c
+++ b/arch/arm/mach-meson/sm.c
@@ -6,7 +6,11 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <log.h>
+#include <regmap.h>
+#include <sm.h>
+#include <syscon.h>
 #include <asm/arch/sm.h>
 #include <asm/cache.h>
 #include <asm/global_data.h>
@@ -14,74 +18,63 @@
 #include <linux/bitops.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
-#include <dm.h>
 #include <linux/bitfield.h>
-#include <regmap.h>
-#include <syscon.h>
+#include <meson/sm.h>
 
-#define FN_GET_SHARE_MEM_INPUT_BASE	0x82000020
-#define FN_GET_SHARE_MEM_OUTPUT_BASE	0x82000021
-#define FN_EFUSE_READ			0x82000030
-#define FN_EFUSE_WRITE			0x82000031
-#define FN_CHIP_ID			0x82000044
-#define FN_PWRDM_SET			0x82000093
-
-static void *shmem_input;
-static void *shmem_output;
-
-static void meson_init_shmem(void)
+static inline struct udevice *meson_get_sm_device(void)
 {
-	struct pt_regs regs;
+	struct udevice *dev;
+	int err;
 
-	if (shmem_input && shmem_output)
-		return;
+	err = uclass_first_device_err(UCLASS_SM, &dev);
+	if (err) {
+		pr_err("Mesom SM device not found\n");
+		return ERR_PTR(err);
+	}
 
-	regs.regs[0] = FN_GET_SHARE_MEM_INPUT_BASE;
-	smc_call(&regs);
-	shmem_input = (void *)regs.regs[0];
-
-	regs.regs[0] = FN_GET_SHARE_MEM_OUTPUT_BASE;
-	smc_call(&regs);
-	shmem_output = (void *)regs.regs[0];
-
-	debug("Secure Monitor shmem: 0x%p 0x%p\n", shmem_input, shmem_output);
+	return dev;
 }
 
 ssize_t meson_sm_read_efuse(uintptr_t offset, void *buffer, size_t size)
 {
-	struct pt_regs regs;
+	struct udevice *dev;
+	struct pt_regs regs = { 0 };
+	int err;
 
-	meson_init_shmem();
+	dev = meson_get_sm_device();
+	if (IS_ERR(dev))
+		return PTR_ERR(dev);
 
-	regs.regs[0] = FN_EFUSE_READ;
 	regs.regs[1] = offset;
 	regs.regs[2] = size;
 
-	smc_call(&regs);
+	err = sm_call_read(dev, buffer, size,
+			   MESON_SMC_CMD_EFUSE_READ, &regs);
+	if (err < 0)
+		pr_err("Failed to read efuse memory (%d)\n", err);
 
-	if (regs.regs[0] == 0)
-		return -1;
-
-	memcpy(buffer, shmem_output, min(size, regs.regs[0]));
-
-	return regs.regs[0];
+	return err;
 }
 
 ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size)
 {
-	struct pt_regs regs;
+	struct udevice *dev;
+	struct pt_regs regs = { 0 };
+	int err;
 
-	meson_init_shmem();
+	dev = meson_get_sm_device();
+	if (IS_ERR(dev))
+		return PTR_ERR(dev);
 
-        memcpy(shmem_input, buffer, size);
-
-	regs.regs[0] = FN_EFUSE_WRITE;
 	regs.regs[1] = offset;
 	regs.regs[2] = size;
 
-	smc_call(&regs);
+	err = sm_call_write(dev, buffer, size,
+			    MESON_SMC_CMD_EFUSE_WRITE, &regs);
+	if (err < 0)
+		pr_err("Failed to write efuse memory (%d)\n", err);
 
-	return regs.regs[0];
+	return err;
 }
 
 #define SM_CHIP_ID_LENGTH	119
@@ -90,18 +83,21 @@
 
 int meson_sm_get_serial(void *buffer, size_t size)
 {
-	struct pt_regs regs;
+	struct udevice *dev;
+	struct pt_regs regs = { 0 };
+	u8 id_buffer[SM_CHIP_ID_LENGTH];
+	int err;
 
-	meson_init_shmem();
+	dev = meson_get_sm_device();
+	if (IS_ERR(dev))
+		return PTR_ERR(dev);
 
-	regs.regs[0] = FN_CHIP_ID;
-	regs.regs[1] = 0;
-	regs.regs[2] = 0;
+	err = sm_call_read(dev, id_buffer, SM_CHIP_ID_LENGTH,
+			   MESON_SMC_CMD_CHIP_ID_GET, &regs);
+	if (err < 0)
+		pr_err("Failed to read serial number (%d)\n", err);
 
-	smc_call(&regs);
-
-	memcpy(buffer, shmem_output + SM_CHIP_ID_OFFSET,
-	       min_t(size_t, size, SM_CHIP_ID_SIZE));
+	memcpy(buffer, id_buffer + SM_CHIP_ID_OFFSET, size);
 
 	return 0;
 }
@@ -141,13 +137,21 @@
 
 int meson_sm_pwrdm_set(size_t index, int cmd)
 {
-	struct pt_regs regs;
+	struct udevice *dev;
+	struct pt_regs regs = { 0 };
+	int err;
 
-	regs.regs[0] = FN_PWRDM_SET;
+	dev = meson_get_sm_device();
+	if (IS_ERR(dev))
+		return PTR_ERR(dev);
+
 	regs.regs[1] = index;
 	regs.regs[2] = cmd;
 
-	smc_call(&regs);
+	err = sm_call(dev, MESON_SMC_CMD_PWRDM_SET, NULL, &regs);
+	if (err)
+		pr_err("Failed to %s power domain ind=%zu (%d)\n", cmd == PWRDM_ON ?
+				"enable" : "disable", index, err);
 
-	return regs.regs[0];
+	return err;
 }
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index c0ed2d8..e88c267 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -764,6 +764,10 @@
 				};
 			};
 		};
+
+		sm: secure-monitor {
+			compatible = "sandbox,sm";
+		};
 	};
 
 	fpga {
diff --git a/board/d-link/dns325/dns325.c b/board/d-link/dns325/dns325.c
index 055783f..8ebfe4c 100644
--- a/board/d-link/dns325/dns325.c
+++ b/board/d-link/dns325/dns325.c
@@ -89,6 +89,7 @@
 	kw_gpio_set_blink(DNS325_GPIO_LED_POWER , 1);
 
 	kw_gpio_set_value(DNS325_GPIO_SATA0_EN , 1);
+	kw_gpio_set_value(DNS325_GPIO_SATA1_EN , 1);
 	return 0;
 }
 
diff --git a/board/freescale/common/ngpixis.c b/board/freescale/common/ngpixis.c
index 37a6f77..7be1cce 100644
--- a/board/freescale/common/ngpixis.c
+++ b/board/freescale/common/ngpixis.c
@@ -234,15 +234,13 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char pixis_help_text[] =
+U_BOOT_LONGHELP(pixis,
 	"- hard reset to default bank\n"
 	"pixis_reset altbank - reset to alternate bank\n"
 #ifdef DEBUG
 	"pixis_reset dump - display the PIXIS registers\n"
 #endif
-	"pixis_reset sysclk <SYSCLK_freq> - reset with SYSCLK frequency(KHz)\n";
-#endif
+	"pixis_reset sysclk <SYSCLK_freq> - reset with SYSCLK frequency(KHz)\n");
 
 U_BOOT_CMD(
 	pixis_reset, CONFIG_SYS_MAXARGS, 1, pixis_reset_cmd,
diff --git a/board/freescale/common/sys_eeprom.c b/board/freescale/common/sys_eeprom.c
index 431f8ca..64139d4 100644
--- a/board/freescale/common/sys_eeprom.c
+++ b/board/freescale/common/sys_eeprom.c
@@ -424,7 +424,7 @@
 			prog_eeprom();
 			break;
 		default:
-			return cmd_usage(cmdtp);
+			return CMD_RET_USAGE;
 		}
 
 		return 0;
@@ -623,3 +623,27 @@
 	return MPC85XX_CPU_BOARD_REV(be.major, be.minor);
 }
 #endif
+
+U_BOOT_LONGHELP(mac,
+	"[read|save|id|num|errata|date|ports|port_number]\n"
+	"mac read\n"
+	"    - read EEPROM content into memory data structure\n"
+	"mac save\n"
+	"    - save memory data structure to the EEPROM\n"
+	"mac id\n"
+	"    - program system id per hard coded value\n"
+	"mac num string\n"
+	"    - program system serial number to value string\n"
+	"mac errata string\n"
+	"    - program errata data to value string\n"
+	"mac date YYMMDDhhmmss\n"
+	"    - program date to string value YYMMDDhhmmss\n"
+	"mac ports N\n"
+	"    - program the number of network ports to integer N\n"
+	"mac X string\n"
+	"    - program MAC addr for port X [X=0,1..] to colon separated string");
+
+U_BOOT_CMD(
+	mac, 3, 1,  do_mac,
+	"display and program the system ID and MAC addresses in EEPROM",
+	mac_help_text);
diff --git a/board/sifive/unmatched/hifive-platform-i2c-eeprom.c b/board/sifive/unmatched/hifive-platform-i2c-eeprom.c
index 2b985b9..c82fb57 100644
--- a/board/sifive/unmatched/hifive-platform-i2c-eeprom.c
+++ b/board/sifive/unmatched/hifive-platform-i2c-eeprom.c
@@ -426,7 +426,7 @@
 	}
 
 	if (argc > 3)
-		return cmd_usage(cmdtp);
+		return CMD_RET_USAGE;
 
 	cmd = argv[1];
 
@@ -443,7 +443,7 @@
 	}
 
 	if (argc != 3)
-		return cmd_usage(cmdtp);
+		return CMD_RET_USAGE;
 
 	if (!is_match_magic()) {
 		printf("Please read the EEPROM ('read_eeprom') and/or initialize the EEPROM ('initialize') first.\n");
@@ -470,7 +470,7 @@
 		return 0;
 	}
 
-	return cmd_usage(cmdtp);
+	return CMD_RET_USAGE;
 }
 
 /**
@@ -551,3 +551,19 @@
 
 	return be.pcb_revision;
 }
+
+U_BOOT_LONGHELP(mac,
+	"- displays memory copy of EEPROM\n"
+	"mac read_eeprom - reads EEPROM into memory\n"
+	"mac initialize - initializes memory copy with magic number\n"
+	"mac write_eeprom -  writes the EEPROM from memory\n"
+	"mac manuf_test_status [unknown|pass|fail] - sets test status in memory\n"
+	"mac_address <addr> - sets MAC address in memory\n"
+	"mac pcb_revision <rev> - sets PCB revision in memory\n"
+	"mac bom_variant <var> - sets BOM variant in memory\n"
+	"mac bom_revision <rev> - sets BOM revision in memory\n");
+
+U_BOOT_CMD(
+	mac, 3, 1,  do_mac,
+	"display and program the board revision and MAC address in EEPROM",
+	mac_help_text);
diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c
index 6edb422..6fa2fe5 100644
--- a/board/solidrun/clearfog/clearfog.c
+++ b/board/solidrun/clearfog/clearfog.c
@@ -36,7 +36,7 @@
 #define BOARD_GPP_POL_LOW	0x0
 #define BOARD_GPP_POL_MID	0x0
 
-static struct tlv_data cf_tlv_data;
+static struct tlv_data cf_tlv_data = { 0 };
 
 static void cf_read_tlv_data(void)
 {
@@ -159,6 +159,9 @@
 	cf_read_tlv_data();
 
 	switch (cf_tlv_data.ram_size) {
+	case 2:
+		ifp->memory_size = MV_DDR_DIE_CAP_2GBIT;
+		break;
 	case 4:
 	default:
 		ifp->memory_size = MV_DDR_DIE_CAP_4GBIT;
@@ -168,6 +171,18 @@
 		break;
 	}
 
+	switch (cf_tlv_data.ram_channels) {
+	default:
+	case 1:
+		for (uint8_t i = 0; i < 5; i++)
+			ifp->as_bus_params[i].cs_bitmask = 0x1;
+		break;
+	case 2:
+		for (uint8_t i = 0; i < 5; i++)
+			ifp->as_bus_params[i].cs_bitmask = 0x3;
+		break;
+	}
+
 	/* Return the board topology as defined in the board code */
 	return &board_topology_map;
 }
diff --git a/board/solidrun/common/tlv_data.c b/board/solidrun/common/tlv_data.c
index 11d6e4a..cf58248 100644
--- a/board/solidrun/common/tlv_data.c
+++ b/board/solidrun/common/tlv_data.c
@@ -45,9 +45,14 @@
 
 	if (val[4] != SR_TLV_CODE_RAM_SIZE)
 		return;
-	if (tlv_entry->length != 6)
+	if (tlv_entry->length < 6)
 		return;
 	td->ram_size = val[5];
+
+	/* extension with additional data field for number of ddr channels */
+	if (tlv_entry->length >= 7) {
+		td->ram_channels = val[6];
+	}
 }
 
 static void parse_tlv_data(u8 *eeprom, struct tlvinfo_header *hdr,
diff --git a/board/solidrun/common/tlv_data.h b/board/solidrun/common/tlv_data.h
index a1432e4..be3f782 100644
--- a/board/solidrun/common/tlv_data.h
+++ b/board/solidrun/common/tlv_data.h
@@ -10,6 +10,7 @@
 	/* Store product name of both SOM and carrier */
 	char tlv_product_name[2][32];
 	unsigned int ram_size;
+	uint8_t ram_channels;
 };
 
 void read_tlv_data(struct tlv_data *td);
diff --git a/board/starfive/visionfive2/visionfive2-i2c-eeprom.c b/board/starfive/visionfive2/visionfive2-i2c-eeprom.c
index c334d98..c36de1a 100644
--- a/board/starfive/visionfive2/visionfive2-i2c-eeprom.c
+++ b/board/starfive/visionfive2/visionfive2-i2c-eeprom.c
@@ -190,6 +190,7 @@
 		       pbuf.eeprom.atom4.data.mac1_addr[4], pbuf.eeprom.atom4.data.mac1_addr[5]);
 	} else {
 		printf("Custom data v%d is not Supported\n", pbuf.eeprom.atom4.data.version);
+		dump_raw_eeprom();
 	}
 	printf("--------EEPROM INFO--------\n\n");
 }
@@ -404,29 +405,6 @@
 	update_crc();
 }
 
-static int print_usage(void)
-{
-	printf("display and program the system ID and MAC addresses in EEPROM\n"
-	"[read_eeprom|initialize|write_eeprom|mac_address|pcb_revision|bom_revision|product_id]\n"
-	"mac read_eeprom\n"
-	"    - read EEPROM content into memory data structure\n"
-	"mac write_eeprom\n"
-	"    - save memory data structure to the EEPROM\n"
-	"mac initialize\n"
-	"    - initialize the in-memory EEPROM copy with default data\n"
-	"mac mac0_address <xx:xx:xx:xx:xx:xx>\n"
-	"    - stores a MAC0 address into the local EEPROM copy\n"
-	"mac mac1_address <xx:xx:xx:xx:xx:xx>\n"
-	"    - stores a MAC1 address into the local EEPROM copy\n"
-	"mac pcb_revision <?>\n"
-	"    - stores a StarFive PCB revision into the local EEPROM copy\n"
-	"mac bom_revision <A>\n"
-	"    - stores a StarFive BOM revision into the local EEPROM copy\n"
-	"mac product_id <VF7110A1-2228-D008E000-xxxxxxxx>\n"
-	"    - stores a StarFive product ID into the local EEPROM copy\n");
-	return 0;
-}
-
 int do_mac(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
 	char *cmd;
@@ -437,7 +415,7 @@
 	}
 
 	if (argc > 3)
-		return print_usage();
+		return CMD_RET_USAGE;
 
 	cmd = argv[1];
 
@@ -450,10 +428,13 @@
 		return 0;
 	} else if (!strcmp(cmd, "write_eeprom")) {
 		return prog_eeprom(STARFIVE_EEPROM_HATS_SIZE_MAX);
+	} else if (!strcmp(cmd, "raw")) {
+		dump_raw_eeprom();
+		return 0;
 	}
 
 	if (argc != 3)
-		return print_usage();
+		return CMD_RET_USAGE;
 
 	if (is_match_magic()) {
 		printf("Please read the EEPROM ('read_eeprom') and/or initialize the EEPROM ('initialize') first.\n");
@@ -477,7 +458,7 @@
 		return 0;
 	}
 
-	return print_usage();
+	return CMD_RET_USAGE;
 }
 
 /**
@@ -559,3 +540,30 @@
 
 	return hextoul(&pbuf.eeprom.atom1.data.pstr[14], NULL);
 }
+
+U_BOOT_LONGHELP(mac,
+	"\n"
+	"    - display EEPROM content\n"
+	"mac read_eeprom\n"
+	"    - read EEPROM content into memory data structure\n"
+	"mac write_eeprom\n"
+	"    - save memory data structure to the EEPROM\n"
+	"mac initialize\n"
+	"    - initialize the in-memory EEPROM copy with default data\n"
+	"mac raw\n"
+	"    - hexdump memory data structure\n"
+	"mac mac0_address <xx:xx:xx:xx:xx:xx>\n"
+	"    - stores a MAC0 address into the local EEPROM copy\n"
+	"mac mac1_address <xx:xx:xx:xx:xx:xx>\n"
+	"    - stores a MAC1 address into the local EEPROM copy\n"
+	"mac pcb_revision <?>\n"
+	"    - stores a StarFive PCB revision into the local EEPROM copy\n"
+	"mac bom_revision <A>\n"
+	"    - stores a StarFive BOM revision into the local EEPROM copy\n"
+	"mac product_id <VF7110A1-2228-D008E000-xxxxxxxx>\n"
+	"    - stores a StarFive product ID into the local EEPROM copy\n");
+
+U_BOOT_CMD(
+	mac, 3, 1,  do_mac,
+	"display and program the board revision and MAC address in EEPROM",
+	mac_help_text);
diff --git a/board/work-microwave/work_92105/work_92105_display.c b/board/work-microwave/work_92105/work_92105_display.c
index 5f625e6..64dd5d4 100644
--- a/board/work-microwave/work_92105/work_92105_display.c
+++ b/board/work-microwave/work_92105/work_92105_display.c
@@ -293,12 +293,10 @@
 	return 1;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char max6957aax_help_text[] =
+U_BOOT_LONGHELP(max6957aax,
 	"max6957aax - write or read display register:\n"
 		"\tmax6957aax R|r reg - read display register;\n"
-		"\tmax6957aax reg val - write display register.";
-#endif
+		"\tmax6957aax reg val - write display register.");
 
 U_BOOT_CMD(
 	max6957aax, 6, 1, do_max6957aax,
@@ -337,13 +335,11 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char hd44780_help_text[] =
+U_BOOT_LONGHELP(hd44780,
 	"hd44780 - control LCD driver:\n"
 		"\thd44780 cmd <val> - send command <val> to driver;\n"
 		"\thd44780 data <val> - send data <val> to driver;\n"
-		"\thd44780 str \"<text>\" - send \"<text>\" to driver.";
-#endif
+		"\thd44780 str \"<text>\" - send \"<text>\" to driver.");
 
 U_BOOT_CMD(
 	hd44780, 6, 1, do_hd44780,
diff --git a/board/xilinx/common/fru.c b/board/xilinx/common/fru.c
index f6ca46c..c916c3d 100644
--- a/board/xilinx/common/fru.c
+++ b/board/xilinx/common/fru.c
@@ -72,17 +72,14 @@
 }
 
 /***************************************************/
-#ifdef CONFIG_SYS_LONGHELP
-static char fru_help_text[] =
+U_BOOT_LONGHELP(fru,
 	"capture <addr> - Parse and capture FRU table present at address.\n"
 	"fru display - Displays content of FRU table that was captured using\n"
 	"              fru capture command\n"
 	"fru board_gen <addr> <manufacturer> <board name> <serial number>\n"
 	"              <part number> <revision> - Generate FRU format with\n"
 	"              board info area filled based on parameters. <addr> is\n"
-	"              pointing to place where FRU is generated.\n"
-	;
-#endif
+	"              pointing to place where FRU is generated.\n");
 
 U_BOOT_CMD(
 	fru, 8, 1, do_fru,
diff --git a/board/xilinx/versal/cmds.c b/board/xilinx/versal/cmds.c
index 148fa51..9cc2cdc 100644
--- a/board/xilinx/versal/cmds.c
+++ b/board/xilinx/versal/cmds.c
@@ -91,12 +91,9 @@
 	return cmd_process_error(c, ret);
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char versal_help_text[] =
+U_BOOT_LONGHELP(versal,
 	"loadpdi addr len - Load pdi image\n"
-	"load pdi image at ddr address 'addr' with pdi image size 'len'\n"
-;
-#endif
+	"load pdi image at ddr address 'addr' with pdi image size 'len'\n");
 
 U_BOOT_CMD(versal, 4, 1, do_versal,
 	   "versal sub-system",
diff --git a/board/xilinx/zynq/cmds.c b/board/xilinx/zynq/cmds.c
index 024fac6..d7c7b2f 100644
--- a/board/xilinx/zynq/cmds.c
+++ b/board/xilinx/zynq/cmds.c
@@ -527,8 +527,7 @@
 	return cmd_process_error(zynq_cmd, ret);
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char zynq_help_text[] =
+U_BOOT_LONGHELP(zynq,
 	""
 #ifdef CONFIG_CMD_ZYNQ_RSA
 	"rsa <baseaddr>  - Verifies the authenticated and encrypted\n"
@@ -545,8 +544,7 @@
 	"       if operation type is load or loadp, it loads the encrypted\n"
 	"       full or partial bitstream on to PL respectively.\n"
 #endif
-	;
-#endif
+	);
 
 U_BOOT_CMD(zynq,	6,	0,	do_zynq,
 	   "Zynq specific commands", zynq_help_text
diff --git a/board/xilinx/zynqmp/cmds.c b/board/xilinx/zynqmp/cmds.c
index fadb0ed..f1f3eff 100644
--- a/board/xilinx/zynqmp/cmds.c
+++ b/board/xilinx/zynqmp/cmds.c
@@ -381,8 +381,7 @@
 }
 
 /***************************************************/
-#ifdef CONFIG_SYS_LONGHELP
-static char zynqmp_help_text[] =
+U_BOOT_LONGHELP(zynqmp,
 	"secure src len [key_addr] - verifies secure images of $len bytes\n"
 	"                            long at address $src. Optional key_addr\n"
 	"                            can be specified if user key needs to\n"
@@ -422,8 +421,7 @@
 	"	48 bytes hash value into srcaddr\n"
 	"	Optional key_addr can be specified for saving sha3 hash value\n"
 	"	Note: srcaddr/srclen should not be 0\n"
-	;
-#endif
+	);
 
 U_BOOT_CMD(
 	zynqmp, 9, 1, do_zynqmp,
diff --git a/board/zyxel/nsa325/Kconfig b/board/zyxel/nsa325/Kconfig
new file mode 100644
index 0000000..1fe5ead
--- /dev/null
+++ b/board/zyxel/nsa325/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_NSA325
+
+config SYS_BOARD
+	default "nsa325"
+
+config SYS_VENDOR
+	default "zyxel"
+
+config SYS_CONFIG_NAME
+	default "nsa325"
+
+endif
diff --git a/board/zyxel/nsa325/MAINTAINERS b/board/zyxel/nsa325/MAINTAINERS
new file mode 100644
index 0000000..013cb84
--- /dev/null
+++ b/board/zyxel/nsa325/MAINTAINERS
@@ -0,0 +1,9 @@
+NSA325 BOARD
+M:	Tony Dinh <mibodhi@gmail.com>
+S:	Maintained
+F:	arch/arm/dts/kirkwood-6282.dtsi
+F:	arch/arm/dts/kirkwood-nsa325.dts
+F:	arch/arm/dts/kirkwood-nsa3x0-common.dtsi
+F:	board/zyxel/nsa325/
+F:	include/configs/nsa325.h
+F:	configs/nsa325_defconfig
diff --git a/board/zyxel/nsa325/Makefile b/board/zyxel/nsa325/Makefile
new file mode 100644
index 0000000..2887ba2
--- /dev/null
+++ b/board/zyxel/nsa325/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2015-2023 Tony Dinh <mibodhi@gmail.com>
+#
+# Based on
+# (C) Copyright 2009
+# Marvell Semiconductor <www.marvell.com>
+# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+#
+
+obj-y	:= nsa325.o
diff --git a/board/zyxel/nsa325/kwbimage.cfg b/board/zyxel/nsa325/kwbimage.cfg
new file mode 100644
index 0000000..a497300
--- /dev/null
+++ b/board/zyxel/nsa325/kwbimage.cfg
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2015-2023 Tony Dinh <mibodhi@gmail.com>
+#
+# Extracted from Zyxel GPL source for u-boot-1.1.4_NSA325v2
+#
+# Boot Media configurations
+BOOT_FROM       nand
+NAND_ECC_MODE   default
+NAND_PAGE_SIZE  0x0800
+
+# SOC registers configuration using bootrom header extension
+# Maximum KWBIMAGE_MAX_CONFIG configurations allowed
+
+# Configure RGMII-0 interface pad voltage to 1.8V
+DATA 0xFFD100e0 0x1b1b1b9b
+
+#Dram initalization
+DATA 0xFFD01400 0x4301503E      # DDR Configuration register
+DATA 0xFFD01404 0xB9843000      # DDR Controller Control Low
+DATA 0xFFD01408 0x33137777      # DDR Timing (Low)
+DATA 0xFFD0140C 0x16000C55      # DDR Timing (High)
+DATA 0xFFD01410 0x04000000      # DDR Address Control
+DATA 0xFFD01414 0x00000000	#  DDR Open Pages Control
+DATA 0xFFD01418 0x00000000	#  DDR Operation
+DATA 0xFFD0141C 0x00000672	#  DDR Mode
+DATA 0xFFD01420 0x00000004	#  DDR Extended Mode
+DATA 0xFFD01424 0x0000F14F	#  DDR Controller Control High
+DATA 0xFFD01428 0x000D6720	# DDR3 ODT Read Timing
+DATA 0xFFD0147C 0x0000B571	# DDR2 ODT Write Timing
+DATA 0xFFD01504 0x1FFFFFF1      # CS[0]n Size
+DATA 0xFFD01508 0x20000000      # CS[1]n Base address to 512Mb
+DATA 0xFFD0150C 0x1FFFFFF4      # CS[1]n Size 512Mb Window enabled for CS1
+DATA 0xFFD01514 0x00000000      # CS[2]n Size, window disabled
+DATA 0xFFD0151C 0x00000000      # CS[3]n Size, window disabled
+DATA 0xFFD01494 0x00120000      #  DDR ODT Control (Low)
+DATA 0xFFD01498 0x00000000      #  DDR ODT Control (High)
+DATA 0xFFD0149C 0x0000E803      # CPU ODT Control
+
+DATA 0xFFD015D0 0x00000630
+DATA 0xFFD015D4 0x00000046
+DATA 0xFFD015D8 0x00000008
+DATA 0xFFD015DC 0x00000000
+DATA 0xFFD015E0 0x00000023
+DATA 0xFFD015E4 0x00203C18
+DATA 0xFFD01620 0x00384800
+DATA 0xFFD01480 0x00000001
+DATA 0xFFD20134 0x66666666
+DATA 0xFFD20138 0x00066666
+
+DATA 0xFFD10100 0x00004000	# stop the watchdog
+DATA 0xFFD10104 0xFFFFBFFF
+
+# End of Header extension
+DATA 0x0 0x0
diff --git a/board/zyxel/nsa325/nsa325.c b/board/zyxel/nsa325/nsa325.c
new file mode 100644
index 0000000..f5f63ee
--- /dev/null
+++ b/board/zyxel/nsa325/nsa325.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014-2023 Tony Dinh <mibodhi@gmail.com>
+ *
+ * Based on
+ * Copyright (C) 2014  Jason Plum <jplum@archlinuxarm.org>
+ *
+ * Based on nsa320.c originall written by
+ * Copyright (C) 2012  Peter Schildmann <linux@schildmann.info>
+ *
+ * Based on guruplug.c originally written by
+ * Siddarth Gore <gores@marvell.com>
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ */
+
+#include <common.h>
+#include <asm/arch/soc.h>
+#include <asm/arch/mpp.h>
+#include <netdev.h>
+#include <asm/arch/cpu.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+#include <asm/mach-types.h>
+#include <bootstage.h>
+#include <command.h>
+#include <init.h>
+#include <linux/bitops.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* low GPIO's */
+#define HDD2_GREEN_LED		BIT(12)
+#define HDD2_RED_LED		BIT(13)
+#define USB_GREEN_LED		BIT(15)
+#define USB_POWER		BIT(21)
+#define SYS_GREEN_LED		BIT(28)
+#define SYS_ORANGE_LED		BIT(29)
+
+#define PIN_USB_GREEN_LED	15
+#define PIN_USB_POWER		21
+
+#define NSA325_OE_LOW		(~(HDD2_GREEN_LED | HDD2_RED_LED |	\
+				   USB_GREEN_LED | USB_POWER |		\
+				   SYS_GREEN_LED | SYS_ORANGE_LED))
+#define NSA325_VAL_LOW		(SYS_GREEN_LED | USB_POWER)
+
+/* high GPIO's */
+#define COPY_GREEN_LED		BIT(7)
+#define COPY_RED_LED		BIT(8)
+#define HDD1_GREEN_LED		BIT(9)
+#define HDD1_RED_LED		BIT(10)
+#define HDD2_POWER		BIT(15)
+#define WATCHDOG_SIGNAL		BIT(14)
+
+#define NSA325_OE_HIGH		(~(COPY_GREEN_LED | COPY_RED_LED | \
+				   HDD1_GREEN_LED | HDD1_RED_LED | HDD2_POWER | WATCHDOG_SIGNAL))
+#define NSA325_VAL_HIGH		(WATCHDOG_SIGNAL | HDD2_POWER)
+
+#define BTN_POWER				46
+#define BTN_RESET				36
+#define BTN_COPY				37
+
+int board_early_init_f(void)
+{
+	/*
+	 * default gpio configuration
+	 * There are maximum 64 gpios controlled through 2 sets of registers
+	 * the below configuration configures mainly initial LED status
+	 */
+	mvebu_config_gpio(NSA325_VAL_LOW, NSA325_VAL_HIGH,
+			  NSA325_OE_LOW, NSA325_OE_HIGH);
+
+	/* Multi-Purpose Pins Functionality configuration */
+	/* (all LEDs & power off active high) */
+	u32 kwmpp_config[] = {
+		MPP0_NF_IO2,
+		MPP1_NF_IO3,
+		MPP2_NF_IO4,
+		MPP3_NF_IO5,
+		MPP4_NF_IO6,
+		MPP5_NF_IO7,
+		MPP6_SYSRST_OUTn,
+		MPP7_GPO,
+		MPP8_TW_SDA,		/* PCF8563 RTC chip   */
+		MPP9_TW_SCK,		/* connected to TWSI  */
+		MPP10_UART0_TXD,
+		MPP11_UART0_RXD,
+		MPP12_GPO,		/* HDD2 LED (green)   */
+		MPP13_GPIO,		/* HDD2 LED (red)     */
+		MPP14_GPIO,		/* MCU DATA pin (in)  */
+		MPP15_GPIO,		/* USB LED (green)    */
+		MPP16_GPIO,		/* MCU CLK pin (out)  */
+		MPP17_GPIO,		/* MCU ACT pin (out)  */
+		MPP18_NF_IO0,
+		MPP19_NF_IO1,
+		MPP20_GPIO,
+		MPP21_GPIO,		/* USB power          */
+		MPP22_GPIO,
+		MPP23_GPIO,
+		MPP24_GPIO,
+		MPP25_GPIO,
+		MPP26_GPIO,
+		MPP27_GPIO,
+		MPP28_GPIO,		/* SYS LED (green)    */
+		MPP29_GPIO,		/* SYS LED (orange)   */
+		MPP30_GPIO,
+		MPP31_GPIO,
+		MPP32_GPIO,
+		MPP33_GPIO,
+		MPP34_GPIO,
+		MPP35_GPIO,
+		MPP36_GPIO,		/* reset button       */
+		MPP37_GPIO,		/* copy button        */
+		MPP38_GPIO,		/* VID B0             */
+		MPP39_GPIO,		/* COPY LED (green)   */
+		MPP40_GPIO,		/* COPY LED (red)     */
+		MPP41_GPIO,		/* HDD1 LED (green)   */
+		MPP42_GPIO,		/* HDD1 LED (red)     */
+		MPP43_GPIO,		/* HTP pin            */
+		MPP44_GPIO,		/* buzzer             */
+		MPP45_GPIO,		/* VID B1             */
+		MPP46_GPIO,		/* power button       */
+		MPP47_GPIO,		/* HDD2 power         */
+		MPP48_GPIO,		/* power off          */
+		0
+	};
+	kirkwood_mpp_conf(kwmpp_config, NULL);
+	return 0;
+}
+
+int board_eth_init(struct bd_info *bis)
+{
+	return cpu_eth_init(bis);
+}
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+
+	return 0;
+}
+
+int board_late_init(void)
+{
+	/* Do late init to ensure successful enumeration of XHCI devices */
+	pci_init();
+	return 0;
+}
+
+#if defined(CONFIG_SHOW_BOOT_PROGRESS)
+void show_boot_progress(int val)
+{
+	struct kwgpio_registers *gpio0 = (struct kwgpio_registers *)MVEBU_GPIO0_BASE;
+	u32 dout0 = readl(&gpio0->dout);
+	u32 blen0 = readl(&gpio0->blink_en);
+
+	struct kwgpio_registers *gpio1 = (struct kwgpio_registers *)MVEBU_GPIO1_BASE;
+	u32 dout1 = readl(&gpio1->dout);
+	u32 blen1 = readl(&gpio1->blink_en);
+
+	switch (val) {
+	case BOOTSTAGE_ID_DECOMP_IMAGE:
+		writel(blen0 & ~(SYS_GREEN_LED | SYS_ORANGE_LED), &gpio0->blink_en);
+		writel((dout0 & ~SYS_GREEN_LED) | SYS_ORANGE_LED, &gpio0->dout);
+		break;
+	case BOOTSTAGE_ID_RUN_OS:
+		writel(dout0 & ~SYS_ORANGE_LED, &gpio0->dout);
+		writel(blen0 | SYS_GREEN_LED, &gpio0->blink_en);
+		break;
+	case BOOTSTAGE_ID_NET_START:
+		writel(dout1 & ~COPY_RED_LED, &gpio1->dout);
+		writel((blen1 & ~COPY_RED_LED) | COPY_GREEN_LED, &gpio1->blink_en);
+		break;
+	case BOOTSTAGE_ID_NET_LOADED:
+		writel(blen1 & ~(COPY_RED_LED | COPY_GREEN_LED), &gpio1->blink_en);
+		writel((dout1 & ~COPY_RED_LED) | COPY_GREEN_LED, &gpio1->dout);
+		break;
+	case -BOOTSTAGE_ID_NET_NETLOOP_OK:
+	case -BOOTSTAGE_ID_NET_LOADED:
+		writel(dout1 & ~COPY_GREEN_LED, &gpio1->dout);
+		writel((blen1 & ~COPY_GREEN_LED) | COPY_RED_LED, &gpio1->blink_en);
+		break;
+	default:
+		if (val < 0) {
+			/* error */
+			printf("Error occurred, error code = %d\n", -val);
+			writel(dout0 & ~SYS_GREEN_LED, &gpio0->dout);
+			writel(blen0 | SYS_ORANGE_LED, &gpio0->blink_en);
+		}
+		break;
+	}
+}
+#endif /* CONFIG_SHOW_BOOT_PROGRESS */
diff --git a/cmd/Makefile b/cmd/Makefile
index 971f78a..44db5f2 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -108,7 +108,6 @@
 obj-y += load.o
 obj-$(CONFIG_CMD_LOG) += log.o
 obj-$(CONFIG_CMD_LSBLK) += lsblk.o
-obj-$(CONFIG_ID_EEPROM) += mac.o
 obj-$(CONFIG_CMD_MD5SUM) += md5sum.o
 obj-$(CONFIG_CMD_MEMORY) += mem.o
 obj-$(CONFIG_CMD_IO) += io.o
@@ -236,6 +235,11 @@
 obj-$(CONFIG_CMD_MESON) += meson/
 
 obj-$(CONFIG_ARCH_MVEBU) += mvebu/
+
+# TI
+obj-$(CONFIG_ARCH_KEYSTONE) += ti/
+obj-$(CONFIG_ARCH_K3) += ti/
+obj-$(CONFIG_ARCH_OMAP2PLUS) += ti/
 endif # !CONFIG_SPL_BUILD
 
 obj-$(CONFIG_$(SPL_)CMD_TLV_EEPROM) += tlv_eeprom.o
@@ -245,8 +249,6 @@
 
 obj-$(CONFIG_CMD_BCM_EXT_UTILS) += broadcom/
 
-obj-$(CONFIG_TI_COMMON_CMD_OPTIONS) += ti/
-
 filechk_data_gz = (echo "static const char data_gz[] ="; cat $< | scripts/bin2c; echo ";")
 
 filechk_data_size = \
diff --git a/cmd/acpi.c b/cmd/acpi.c
index ede9c8c..7e397d1 100644
--- a/cmd/acpi.c
+++ b/cmd/acpi.c
@@ -171,13 +171,11 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char acpi_help_text[] =
+U_BOOT_LONGHELP(acpi,
 	"list  - list ACPI tables\n"
 	"acpi items [-d]   - List/dump each piece of ACPI data from devices\n"
 	"acpi set [<addr>] - Set or show address of ACPI tables\n"
-	"acpi dump <name>  - Dump ACPI table";
-#endif
+	"acpi dump <name>  - Dump ACPI table");
 
 U_BOOT_CMD_WITH_SUBCMDS(acpi, "ACPI tables", acpi_help_text,
 	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_acpi_list),
diff --git a/cmd/aes.c b/cmd/aes.c
index 1936518..1264675 100644
--- a/cmd/aes.c
+++ b/cmd/aes.c
@@ -88,8 +88,7 @@
 }
 
 /***************************************************/
-#ifdef CONFIG_SYS_LONGHELP
-static char aes_help_text[] =
+U_BOOT_LONGHELP(aes,
 	"[.128,.192,.256] enc key iv src dst len - Encrypt block of data $len bytes long\n"
 	"                             at address $src using a key at address\n"
 	"                             $key with initialization vector at address\n"
@@ -101,8 +100,7 @@
 	"                             $key with initialization vector at address\n"
 	"                             $iv. Store the result at address $dst.\n"
 	"                             The $len size must be multiple of 16 bytes.\n"
-	"                             The $key and $iv must be 16 bytes long.";
-#endif
+	"                             The $key and $iv must be 16 bytes long.");
 
 U_BOOT_CMD(
 	aes, 7, 1, do_aes,
diff --git a/cmd/armffa.c b/cmd/armffa.c
index 7e6eafc..9585150 100644
--- a/cmd/armffa.c
+++ b/cmd/armffa.c
@@ -188,13 +188,13 @@
 	return CMD_RET_SUCCESS;
 }
 
-static char armffa_help_text[] =
+U_BOOT_LONGHELP(armffa,
 	"getpart <partition UUID>\n"
 	"       - lists the partition(s) info\n"
 	"ping <partition ID>\n"
 	"       - sends a data pattern to the specified partition\n"
 	"devlist\n"
-	"       - displays information about the FF-A device/driver\n";
+	"       - displays information about the FF-A device/driver\n");
 
 U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
 			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
diff --git a/cmd/axi.c b/cmd/axi.c
index b97b43e..5620891 100644
--- a/cmd/axi.c
+++ b/cmd/axi.c
@@ -344,11 +344,11 @@
 		return CMD_RET_USAGE;
 }
 
-static char axi_help_text[] =
+U_BOOT_LONGHELP(axi,
 	"bus  - show AXI bus info\n"
 	"axi dev [bus] - show or set current AXI bus to bus number [bus]\n"
 	"axi md size addr [# of objects] - read from AXI device at address [addr] and data width [size] (one of 8, 16, 32)\n"
-	"axi mw size addr value [count] - write data [value] to AXI device at address [addr] and data width [size] (one of 8, 16, 32)\n";
+	"axi mw size addr value [count] - write data [value] to AXI device at address [addr] and data width [size] (one of 8, 16, 32)\n");
 
 U_BOOT_CMD(axi, 7, 1, do_ihs_axi,
 	   "AXI sub-system",
diff --git a/cmd/bloblist.c b/cmd/bloblist.c
index 21e7ff6..26548ec 100644
--- a/cmd/bloblist.c
+++ b/cmd/bloblist.c
@@ -29,11 +29,9 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char bloblist_help_text[] =
+U_BOOT_LONGHELP(bloblist,
 	"info   - show information about the bloblist\n"
-	"bloblist list   - list blobs in the bloblist";
-#endif
+	"bloblist list   - list blobs in the bloblist");
 
 U_BOOT_CMD_WITH_SUBCMDS(bloblist, "Bloblists", bloblist_help_text,
 	U_BOOT_SUBCMD_MKENT(info, 1, 1, do_bloblist_info),
diff --git a/cmd/bootcount.c b/cmd/bootcount.c
index 3898d25..30ce5db 100644
--- a/cmd/bootcount.c
+++ b/cmd/bootcount.c
@@ -46,16 +46,11 @@
 	return CMD_RET_USAGE;
 }
 
-#if IS_ENABLED(CONFIG_SYS_LONGHELP)
-static char bootcount_help_text[] =
+U_BOOT_LONGHELP(bootcount,
 	"print - print current bootcounter\n"
-	"reset - reset the bootcounter"
-	;
-#endif
+	"reset - reset the bootcounter");
 
 U_BOOT_CMD(bootcount, 2, 1, do_bootcount,
 	   "bootcount",
-#if IS_ENABLED(CONFIG_SYS_LONGHELP)
 	   bootcount_help_text
-#endif
 );
diff --git a/cmd/bootdev.c b/cmd/bootdev.c
index a657de6..471189c 100644
--- a/cmd/bootdev.c
+++ b/cmd/bootdev.c
@@ -139,13 +139,11 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char bootdev_help_text[] =
+U_BOOT_LONGHELP(bootdev,
 	"list [-p]         - list all available bootdevs (-p to probe)\n"
 	"bootdev hunt [-l|<spec>]  - use hunt drivers to find bootdevs\n"
 	"bootdev select <bd>       - select a bootdev by name | label | seq\n"
-	"bootdev info [-p]         - show information about a bootdev (-p to probe)";
-#endif
+	"bootdev info [-p]         - show information about a bootdev (-p to probe)");
 
 U_BOOT_CMD_WITH_SUBCMDS(bootdev, "Boot devices", bootdev_help_text,
 	U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootdev_list),
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index f73d6eb..20e5c94 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -698,8 +698,7 @@
 	return ret;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char bootefi_help_text[] =
+U_BOOT_LONGHELP(bootefi,
 	"<image address>[:<image size>] [<fdt address>]\n"
 	"  - boot EFI payload\n"
 #ifdef CONFIG_CMD_BOOTEFI_HELLO
@@ -719,8 +718,7 @@
 	"    If specified, the device tree located at <fdt address> gets\n"
 	"    exposed as EFI configuration table.\n"
 #endif
-	;
-#endif
+	);
 
 U_BOOT_CMD(
 	bootefi, 4, 0, do_bootefi,
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index 300ad3a..ad39ebe 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -541,8 +541,7 @@
 }
 #endif /* CONFIG_CMD_BOOTFLOW_FULL */
 
-#ifdef CONFIG_SYS_LONGHELP
-static char bootflow_help_text[] =
+U_BOOT_LONGHELP(bootflow,
 #ifdef CONFIG_CMD_BOOTFLOW_FULL
 	"scan [-abeGl] [bdev]  - scan for valid bootflows (-l list, -a all, -e errors, -b boot, -G no global)\n"
 	"bootflow list [-e]             - list scanned bootflows (-e errors)\n"
@@ -551,11 +550,11 @@
 	"bootflow read                  - read all current-bootflow files\n"
 	"bootflow boot                  - boot current bootflow\n"
 	"bootflow menu [-t]             - show a menu of available bootflows\n"
-	"bootflow cmdline [set|get|clear|delete|auto] <param> [<value>] - update cmdline";
+	"bootflow cmdline [set|get|clear|delete|auto] <param> [<value>] - update cmdline"
 #else
-	"scan - boot first available bootflow\n";
+	"scan - boot first available bootflow\n"
 #endif
-#endif /* CONFIG_SYS_LONGHELP */
+	);
 
 U_BOOT_CMD_WITH_SUBCMDS(bootflow, "Boot flows", bootflow_help_text,
 	U_BOOT_SUBCMD_MKENT(scan, 3, 1, do_bootflow_scan),
diff --git a/cmd/booti.c b/cmd/booti.c
index 6ac3919..1d531bd 100644
--- a/cmd/booti.c
+++ b/cmd/booti.c
@@ -134,8 +134,7 @@
 	return ret;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char booti_help_text[] =
+U_BOOT_LONGHELP(booti,
 	"[addr [initrd[:size]] [fdt]]\n"
 	"    - boot Linux flat or compressed 'Image' stored at 'addr'\n"
 	"\tThe argument 'initrd' is optional and specifies the address\n"
@@ -151,8 +150,7 @@
 	"\tis required. To boot a kernel with a device-tree blob but\n"
 	"\twithout an initrd image, use a '-' for the initrd argument.\n"
 #endif
-	"";
-#endif
+	);
 
 U_BOOT_CMD(
 	booti,	CONFIG_SYS_MAXARGS,	1,	do_booti,
diff --git a/cmd/bootm.c b/cmd/bootm.c
index 7968415..3e504cc 100644
--- a/cmd/bootm.c
+++ b/cmd/bootm.c
@@ -168,8 +168,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char bootm_help_text[] =
+U_BOOT_LONGHELP(bootm,
 	"[addr [arg ...]]\n    - boot application image stored in memory\n"
 	"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
 	"\t'arg' can be the address of an initrd image\n"
@@ -208,8 +207,7 @@
 #if defined(CONFIG_TRACE)
 	"\tfake    - OS specific fake start without go\n"
 #endif
-	"\tgo      - start OS";
-#endif
+	"\tgo      - start OS");
 
 U_BOOT_CMD(
 	bootm,	CONFIG_SYS_MAXARGS,	1,	do_bootm,
diff --git a/cmd/bootmeth.c b/cmd/bootmeth.c
index 9fbcccd..f5b0134 100644
--- a/cmd/bootmeth.c
+++ b/cmd/bootmeth.c
@@ -104,11 +104,9 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char bootmeth_help_text[] =
+U_BOOT_LONGHELP(bootmeth,
 	"list [-a]     - list available bootmeths (-a all)\n"
-	"bootmeth order [<bd> ...]  - select bootmeth order / subset to use";
-#endif
+	"bootmeth order [<bd> ...]  - select bootmeth order / subset to use");
 
 U_BOOT_CMD_WITH_SUBCMDS(bootmeth, "Boot methods", bootmeth_help_text,
 	U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootmeth_list),
diff --git a/cmd/bootz.c b/cmd/bootz.c
index f142357..742889f 100644
--- a/cmd/bootz.c
+++ b/cmd/bootz.c
@@ -88,8 +88,7 @@
 	return ret;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char bootz_help_text[] =
+U_BOOT_LONGHELP(bootz,
 	"[addr [initrd[:size]] [fdt]]\n"
 	"    - boot Linux zImage stored in memory\n"
 	"\tThe argument 'initrd' is optional and specifies the address\n"
@@ -102,8 +101,7 @@
 	"\tuse a '-' for the second argument. If you do not pass a third\n"
 	"\ta bd_info struct will be passed instead\n"
 #endif
-	"";
-#endif
+	);
 
 U_BOOT_CMD(
 	bootz,	CONFIG_SYS_MAXARGS,	1,	do_bootz,
diff --git a/cmd/cat.c b/cmd/cat.c
index b059080..18aa6ca 100644
--- a/cmd/cat.c
+++ b/cmd/cat.c
@@ -60,11 +60,9 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char cat_help_text[] =
+U_BOOT_LONGHELP(cat,
 	"<interface> <dev[:part]> <file>\n"
-	"  - Print file from 'dev' on 'interface' to standard output\n";
-#endif
+	"  - Print file from 'dev' on 'interface' to standard output\n");
 
 U_BOOT_CMD(cat, 4, 1, do_cat,
 	   "Print file to standard output",
diff --git a/cmd/cedit.c b/cmd/cedit.c
index 2ff284f..6352e63 100644
--- a/cmd/cedit.c
+++ b/cmd/cedit.c
@@ -270,8 +270,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char cedit_help_text[] =
+U_BOOT_LONGHELP(cedit,
 	"load <interface> <dev[:part]> <filename>   - load config editor\n"
 	"cedit read_fdt <i/f> <dev[:part]> <filename>     - read settings\n"
 	"cedit write_fdt <i/f> <dev[:part]> <filename>    - write settings\n"
@@ -279,8 +278,7 @@
 	"cedit write_env [-v]                             - write settings to env vars\n"
 	"cedit read_cmos [-v] [dev]                       - read settings from CMOS RAM\n"
 	"cedit write_cmos [-v] [dev]                      - write settings to CMOS RAM\n"
-	"cedit run                                        - run config editor";
-#endif /* CONFIG_SYS_LONGHELP */
+	"cedit run                                        - run config editor");
 
 U_BOOT_CMD_WITH_SUBCMDS(cedit, "Configuration editor", cedit_help_text,
 	U_BOOT_SUBCMD_MKENT(load, 5, 1, do_cedit_load),
diff --git a/cmd/clk.c b/cmd/clk.c
index ff7c764..c7c379d 100644
--- a/cmd/clk.c
+++ b/cmd/clk.c
@@ -152,10 +152,8 @@
 		return CMD_RET_USAGE;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char clk_help_text[] =
+U_BOOT_LONGHELP(clk,
 	"dump - Print clock frequencies\n"
-	"clk setfreq [clk] [freq] - Set clock frequency";
-#endif
+	"clk setfreq [clk] [freq] - Set clock frequency");
 
 U_BOOT_CMD(clk, 4, 1, do_clk, "CLK sub-system", clk_help_text);
diff --git a/cmd/conitrace.c b/cmd/conitrace.c
index d50f3bf..9a1bc35 100644
--- a/cmd/conitrace.c
+++ b/cmd/conitrace.c
@@ -41,9 +41,7 @@
 	return CMD_RET_SUCCESS;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char conitrace_help_text[] = "";
-#endif
+U_BOOT_LONGHELP(conitrace, "");
 
 U_BOOT_CMD_COMPLETE(
 	conitrace, 2, 0, do_conitrace,
diff --git a/cmd/cpu.c b/cmd/cpu.c
index 3148524..245a82f 100644
--- a/cmd/cpu.c
+++ b/cmd/cpu.c
@@ -83,12 +83,9 @@
 	return 0;
 }
 
-#if IS_ENABLED(CONFIG_SYS_LONGHELP)
-static char cpu_help_text[] =
+U_BOOT_LONGHELP(cpu,
 	"list	- list available CPUs\n"
-	"cpu detail	- show CPU detail"
-	;
-#endif
+	"cpu detail	- show CPU detail");
 
 U_BOOT_CMD_WITH_SUBCMDS(cpu, "display information about CPUs", cpu_help_text,
 	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_cpu_list),
diff --git a/cmd/cyclic.c b/cmd/cyclic.c
index 946f1d7..ad7fc3b 100644
--- a/cmd/cyclic.c
+++ b/cmd/cyclic.c
@@ -76,9 +76,9 @@
 	return 0;
 }
 
-static char cyclic_help_text[] =
+U_BOOT_LONGHELP(cyclic,
 	"demo <cycletime_ms> <delay_us> - register cyclic demo function\n"
-	"cyclic list - list cyclic functions\n";
+	"cyclic list - list cyclic functions\n");
 
 U_BOOT_CMD_WITH_SUBCMDS(cyclic, "Cyclic", cyclic_help_text,
 	U_BOOT_SUBCMD_MKENT(demo, 3, 1, do_cyclic_demo),
diff --git a/cmd/dm.c b/cmd/dm.c
index 1aa86aa..fb605c2 100644
--- a/cmd/dm.c
+++ b/cmd/dm.c
@@ -112,17 +112,14 @@
 #define DM_MEM
 #endif
 
-#if IS_ENABLED(CONFIG_SYS_LONGHELP)
-static char dm_help_text[] =
+U_BOOT_LONGHELP(dm,
 	"compat        Dump list of drivers with compatibility strings\n"
 	"dm devres        Dump list of device resources for each device\n"
 	"dm drivers       Dump list of drivers with uclass and instances\n"
 	DM_MEM_HELP
 	"dm static        Dump list of drivers with static platform data\n"
 	"dm tree [-s][-e][name]   Dump tree of driver model devices (-s=sort)\n"
-	"dm uclass [-e][name]     Dump list of instances for each uclass"
-	;
-#endif
+	"dm uclass [-e][name]     Dump list of instances for each uclass");
 
 U_BOOT_CMD_WITH_SUBCMDS(dm, "Driver model low level access", dm_help_text,
 	U_BOOT_SUBCMD_MKENT(compat, 1, 1, do_dm_dump_driver_compat),
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index 0be3af3..201531a 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -1484,8 +1484,7 @@
 	return cp->cmd(cmdtp, flag, argc, argv);
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char efidebug_help_text[] =
+U_BOOT_LONGHELP(efidebug,
 	"  - UEFI Shell-like interface to configure UEFI environment\n"
 	"\n"
 	"efidebug boot add - set UEFI BootXXXX variable\n"
@@ -1532,8 +1531,7 @@
 	"  - run simple bootmgr for test\n"
 #endif
 	"efidebug query [-nv][-bs][-rt][-at]\n"
-	"  - show size of UEFI variables store\n";
-#endif
+	"  - show size of UEFI variables store\n");
 
 U_BOOT_CMD(
 	efidebug, CONFIG_SYS_MAXARGS, 0, do_efidebug,
diff --git a/cmd/event.c b/cmd/event.c
index b4b779f..f6cdb55 100644
--- a/cmd/event.c
+++ b/cmd/event.c
@@ -18,10 +18,8 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char event_help_text[] =
-	"list - list event spies";
-#endif
+U_BOOT_LONGHELP(event,
+	"list - list event spies");
 
 U_BOOT_CMD_WITH_SUBCMDS(event, "Events", event_help_text,
 	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_event_list));
diff --git a/cmd/fdt.c b/cmd/fdt.c
index 2401ea8..331564c 100644
--- a/cmd/fdt.c
+++ b/cmd/fdt.c
@@ -1113,8 +1113,7 @@
 }
 
 /********************************************************************/
-#ifdef CONFIG_SYS_LONGHELP
-static char fdt_help_text[] =
+U_BOOT_LONGHELP(fdt,
 	"addr [-c] [-q] <addr> [<size>]  - Set the [control] fdt location to <addr>\n"
 #ifdef CONFIG_OF_LIBFDT_OVERLAY
 	"fdt apply <addr>                    - Apply overlay to the DT\n"
@@ -1153,8 +1152,7 @@
 	"                                               default gd->fdt_blob\n"
 #endif
 	"NOTE: Dereference aliases by omitting the leading '/', "
-		"e.g. fdt print ethernet0.";
-#endif
+		"e.g. fdt print ethernet0.");
 
 U_BOOT_CMD(
 	fdt,	255,	0,	do_fdt,
diff --git a/cmd/font.c b/cmd/font.c
index fe2d65c..cb39c88 100644
--- a/cmd/font.c
+++ b/cmd/font.c
@@ -79,12 +79,10 @@
 }
 
 
-#ifdef CONFIG_SYS_LONGHELP
-static char font_help_text[] =
+U_BOOT_LONGHELP(font,
 	"list       - list available fonts\n"
 	"font select <name> [<size>] - select font to use\n"
-	"font size <size> - select font size to";
-#endif
+	"font size <size> - select font size to");
 
 U_BOOT_CMD_WITH_SUBCMDS(font, "Fonts", font_help_text,
 	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_font_list),
diff --git a/cmd/help.c b/cmd/help.c
index 8d67d97..9f8393e 100644
--- a/cmd/help.c
+++ b/cmd/help.c
@@ -29,7 +29,10 @@
 );
 
 #ifdef CONFIG_CMDLINE
-/* This does not use the U_BOOT_CMD macro as ? can't be used in symbol names */
+/*
+ * This does not use the U_BOOT_CMD macro as ? can't be used in symbol names
+ * nor can we rely on the CONFIG_SYS_LONGHELP helper macro
+ */
 ll_entry_declare(struct cmd_tbl, question_mark, cmd) = {
 	"?",	CONFIG_SYS_MAXARGS, cmd_always_repeatable,	do_help,
 	"alias for 'help'",
diff --git a/cmd/i2c.c b/cmd/i2c.c
index f0a5fa2..8083156 100644
--- a/cmd/i2c.c
+++ b/cmd/i2c.c
@@ -1969,8 +1969,7 @@
 }
 
 /***************************************************/
-#ifdef CONFIG_SYS_LONGHELP
-static char i2c_help_text[] =
+U_BOOT_LONGHELP(i2c,
 #if CONFIG_IS_ENABLED(SYS_I2C_LEGACY) || CONFIG_IS_ENABLED(DM_I2C)
 	"bus [muxtype:muxaddr:muxchannel] - show I2C bus info\n"
 	"i2c " /* That's the prefix for the crc32 command below. */
@@ -1999,8 +1998,7 @@
 #if defined(CONFIG_CMD_SDRAM)
 	"i2c sdram chip - print SDRAM configuration information\n"
 #endif
-	"i2c speed [speed] - show or set I2C bus speed";
-#endif
+	"i2c speed [speed] - show or set I2C bus speed");
 
 U_BOOT_CMD(
 	i2c, 7, 1, do_i2c,
diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
index 8a1d812..9acb8e1 100644
--- a/cmd/kaslrseed.c
+++ b/cmd/kaslrseed.c
@@ -68,11 +68,9 @@
 	return ret;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char kaslrseed_help_text[] =
+U_BOOT_LONGHELP(kaslrseed,
 	"[n]\n"
-	"  - append random bytes to chosen kaslr-seed node\n";
-#endif
+	"  - append random bytes to chosen kaslr-seed node\n");
 
 U_BOOT_CMD(
 	kaslrseed, 1, 0, do_kaslr_seed,
diff --git a/cmd/log.c b/cmd/log.c
index c377aee..c9a23e4 100644
--- a/cmd/log.c
+++ b/cmd/log.c
@@ -375,8 +375,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char log_help_text[] =
+U_BOOT_LONGHELP(log,
 	"level [<level>] - get/set log level\n"
 	"categories - list log categories\n"
 	"drivers - list log drivers\n"
@@ -405,9 +404,7 @@
 	"\tc=category, l=level, F=file, L=line number, f=function, m=msg\n"
 	"\tor 'default', or 'all' for all\n"
 	"log rec <category> <level> <file> <line> <func> <message> - "
-		"output a log record"
-	;
-#endif
+		"output a log record");
 
 U_BOOT_CMD_WITH_SUBCMDS(log, "log system", log_help_text,
 	U_BOOT_SUBCMD_MKENT(level, 2, 1, do_log_level),
diff --git a/cmd/mac.c b/cmd/mac.c
deleted file mode 100644
index a39e116..0000000
--- a/cmd/mac.c
+++ /dev/null
@@ -1,33 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright 2006 Freescale Semiconductor
- * York Sun (yorksun@freescale.com)
- */
-
-#include <common.h>
-#include <command.h>
-
-extern int do_mac(struct cmd_tbl *cmdtp, int flag, int argc,
-		  char *const argv[]);
-
-U_BOOT_CMD(
-	mac, 3, 1,  do_mac,
-	"display and program the system ID and MAC addresses in EEPROM",
-	"[read|save|id|num|errata|date|ports|port_number]\n"
-	"mac read\n"
-	"    - read EEPROM content into memory data structure\n"
-	"mac save\n"
-	"    - save memory data structure to the EEPROM\n"
-	"mac id\n"
-	"    - program system id per hard coded value\n"
-	"mac num string\n"
-	"    - program system serial number to value string\n"
-	"mac errata string\n"
-	"    - program errata data to value string\n"
-	"mac date YYMMDDhhmmss\n"
-	"    - program date to string value YYMMDDhhmmss\n"
-	"mac ports N\n"
-	"    - program the number of network ports to integer N\n"
-	"mac X string\n"
-	"    - program MAC addr for port X [X=0,1..] to colon separated string"
-);
diff --git a/cmd/mp.c b/cmd/mp.c
index 8d14401..1b4373f 100644
--- a/cmd/mp.c
+++ b/cmd/mp.c
@@ -66,8 +66,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char cpu_help_text[] =
+U_BOOT_LONGHELP(cpu,
 	    "<num> reset                 - Reset cpu <num>\n"
 	"cpu status                      - Status of all cpus\n"
 	"cpu <num> status                - Status of cpu <num>\n"
@@ -86,8 +85,7 @@
 	"     When cpu <num> is released r4 and r5 = 0.\n" \
 	"     r7 will contain the size of the initial mapped area"
 #endif
-	"";
-#endif
+	);
 
 U_BOOT_CMD(
 	cpu, CONFIG_SYS_MAXARGS, 1, cpu_cmd,
diff --git a/cmd/mtd.c b/cmd/mtd.c
index eb6e2d6..e63c011 100644
--- a/cmd/mtd.c
+++ b/cmd/mtd.c
@@ -541,8 +541,7 @@
 }
 #endif /* CONFIG_AUTO_COMPLETE */
 
-#ifdef CONFIG_SYS_LONGHELP
-static char mtd_help_text[] =
+U_BOOT_LONGHELP(mtd,
 	"- generic operations on memory technology devices\n\n"
 	"mtd list\n"
 	"mtd read[.raw][.oob]                  <name> <addr> [<off> [<size>]]\n"
@@ -563,8 +562,7 @@
 	"\t\t* must be a multiple of a block for erase\n"
 	"\t\t* must be a multiple of a page otherwise (special case: default is a page with dump)\n"
 	"\n"
-	"The .dontskipff option forces writing empty pages, don't use it if unsure.\n";
-#endif
+	"The .dontskipff option forces writing empty pages, don't use it if unsure.\n");
 
 U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils", mtd_help_text,
 		U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mtd_list),
diff --git a/cmd/mtdparts.c b/cmd/mtdparts.c
index 0984158..b31db73 100644
--- a/cmd/mtdparts.c
+++ b/cmd/mtdparts.c
@@ -2079,8 +2079,7 @@
 	"    - change active partition (e.g. part-id = nand0,1) of a MTD device"
 );
 
-#ifdef CONFIG_SYS_LONGHELP
-static char mtdparts_help_text[] =
+U_BOOT_LONGHELP(mtdparts,
 	"\n"
 	"    - list partition table\n"
 	"mtdparts delall\n"
@@ -2122,8 +2121,7 @@
 	"<size>     := standard linux memsize OR '-' to denote all remaining space\n"
 	"<offset>   := partition start offset within the device\n"
 	"<name>     := '(' NAME ')'\n"
-	"<ro-flag>  := when set to 'ro' makes partition read-only (not used, passed to kernel)";
-#endif
+	"<ro-flag>  := when set to 'ro' makes partition read-only (not used, passed to kernel)");
 
 U_BOOT_CMD(
 	mtdparts,	6,	0,	do_mtdparts,
diff --git a/cmd/mux.c b/cmd/mux.c
index c75907a..388fb08 100644
--- a/cmd/mux.c
+++ b/cmd/mux.c
@@ -173,10 +173,10 @@
 	return CMD_RET_SUCCESS;
 }
 
-static char mux_help_text[] =
+U_BOOT_LONGHELP(mux,
 	"list - List all Muxes and their states\n"
 	"select <chip> <id> <state> - Select the given mux state\n"
-	"deselect <chip> <id> - Deselect the given mux and reset it to its idle state";
+	"deselect <chip> <id> - Deselect the given mux and reset it to its idle state");
 
 U_BOOT_CMD_WITH_SUBCMDS(mux, "List, select, and deselect muxes", mux_help_text,
 			U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mux_list),
diff --git a/cmd/nand.c b/cmd/nand.c
index b41e54e..71b8f96 100644
--- a/cmd/nand.c
+++ b/cmd/nand.c
@@ -919,8 +919,7 @@
 	return CMD_RET_USAGE;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char nand_help_text[] =
+U_BOOT_LONGHELP(nand,
 	"info - show available NAND devices\n"
 	"nand device [dev] - show or set current device\n"
 	"nand read - addr off|partition size\n"
@@ -965,8 +964,7 @@
 	"nand env.oob set off|partition - set enviromnent offset\n"
 	"nand env.oob get - get environment offset"
 #endif
-	"";
-#endif
+	);
 
 U_BOOT_CMD(
 	nand, CONFIG_SYS_MAXARGS, 1, do_nand,
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index eaa000b..daf1ad3 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -1238,8 +1238,7 @@
 	return CMD_RET_USAGE;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char env_help_text[] =
+U_BOOT_LONGHELP(env,
 #if defined(CONFIG_CMD_ASKENV)
 	"ask name [message] [size] - ask for environment variable\nenv "
 #endif
@@ -1304,8 +1303,7 @@
 	"env set -e [-nv][-bs][-rt][-at][-a][-i addr:size][-v] name [arg ...]\n"
 	"    - set UEFI variable; unset if '-i' or 'arg' not specified\n"
 #endif
-	"env set [-f] name [arg ...]\n";
-#endif
+	"env set [-f] name [arg ...]\n");
 
 U_BOOT_CMD(
 	env, CONFIG_SYS_MAXARGS, 1, do_env,
diff --git a/cmd/osd.c b/cmd/osd.c
index c8c62d4..210bc5d 100644
--- a/cmd/osd.c
+++ b/cmd/osd.c
@@ -278,12 +278,12 @@
 		return CMD_RET_USAGE;
 }
 
-static char osd_help_text[] =
+U_BOOT_LONGHELP(osd,
 	"show  - show OSD info\n"
 	"osd dev [dev] - show or set current OSD\n"
 	"write [pos_x] [pos_y] [buffer] [count] - write 8-bit hex encoded buffer to osd memory at a given position\n"
 	"print [pos_x] [pos_y] [color] [text] - write ASCII buffer (given by text data and driver-specific color information) to osd memory\n"
-	"size [size_x] [size_y] - set OSD XY size in characters\n";
+	"size [size_x] [size_y] - set OSD XY size in characters\n");
 
 U_BOOT_CMD(
 	osd, 6, 1, do_osd,
diff --git a/cmd/pcap.c b/cmd/pcap.c
index ab5c1a7..a014920 100644
--- a/cmd/pcap.c
+++ b/cmd/pcap.c
@@ -48,7 +48,7 @@
 	return pcap_clear() ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
 }
 
-static char pcap_help_text[] =
+U_BOOT_LONGHELP(pcap,
 	"- network packet capture\n\n"
 	"pcap\n"
 	"pcap init\t\t\t<addr> <max_size>\n"
@@ -60,7 +60,7 @@
 	"With:\n"
 	"\t<addr>: user address to which pcap will be stored (hexedcimal)\n"
 	"\t<max_size>: Maximum size of pcap file (decimal)\n"
-	"\n";
+	"\n");
 
 U_BOOT_CMD_WITH_SUBCMDS(pcap, "pcap", pcap_help_text,
 			U_BOOT_SUBCMD_MKENT(init, 3, 0, do_pcap_init),
diff --git a/cmd/pci.c b/cmd/pci.c
index 78b661d..d89e71c 100644
--- a/cmd/pci.c
+++ b/cmd/pci.c
@@ -620,8 +620,7 @@
 
 /***************************************************/
 
-#ifdef CONFIG_SYS_LONGHELP
-static char pci_help_text[] =
+U_BOOT_LONGHELP(pci,
 	"[bus|*] [long]\n"
 	"    - short or long list of PCI devices on bus 'bus'\n"
 	"pci enum\n"
@@ -639,8 +638,7 @@
 	"pci modify[.b, .w, .l] b.d.f address\n"
 	"    -  modify, auto increment CFG address\n"
 	"pci write[.b, .w, .l] b.d.f address value\n"
-	"    - write to CFG address";
-#endif
+	"    - write to CFG address");
 
 U_BOOT_CMD(
 	pci,	5,	1,	do_pci,
diff --git a/cmd/pci_mps.c b/cmd/pci_mps.c
index 555a5fd..98161da 100644
--- a/cmd/pci_mps.c
+++ b/cmd/pci_mps.c
@@ -152,13 +152,11 @@
 
 /***************************************************/
 
-#ifdef CONFIG_SYS_LONGHELP
-static char pci_mps_help_text[] =
+U_BOOT_LONGHELP(pci_mps,
 	"safe\n"
 	"    - Set PCI Express MPS of all devices to safe values\n"
 	"pci_mps peer2peer\n"
-	"    - Set PCI Express MPS of all devices to support hotplug and peer-to-peer DMA\n";
-#endif
+	"    - Set PCI Express MPS of all devices to support hotplug and peer-to-peer DMA\n");
 
 U_BOOT_CMD(pci_mps, 2, 0, do_pci_mps,
 	   "configure PCI Express MPS", pci_mps_help_text);
diff --git a/cmd/riscv/sbi.c b/cmd/riscv/sbi.c
index 32761c5..940d9bc 100644
--- a/cmd/riscv/sbi.c
+++ b/cmd/riscv/sbi.c
@@ -119,11 +119,8 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char sbi_help_text[] =
-	"- display SBI spec version, implementation, and available extensions";
-
-#endif
+U_BOOT_LONGHELP(sbi,
+	"- display SBI spec version, implementation, and available extensions");
 
 U_BOOT_CMD_COMPLETE(
 	sbi, 1, 0, do_sbi,
diff --git a/cmd/rng.c b/cmd/rng.c
index 81a2396..52f722c 100644
--- a/cmd/rng.c
+++ b/cmd/rng.c
@@ -56,11 +56,9 @@
 	return ret;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char rng_help_text[] =
+U_BOOT_LONGHELP(rng,
 	"[dev [n]]\n"
-	"  - print n random bytes(max 64) read from dev\n";
-#endif
+	"  - print n random bytes(max 64) read from dev\n");
 
 U_BOOT_CMD(
 	rng, 3, 0, do_rng,
diff --git a/cmd/sandbox/exception.c b/cmd/sandbox/exception.c
index 1aa1d67..c082401 100644
--- a/cmd/sandbox/exception.c
+++ b/cmd/sandbox/exception.c
@@ -31,11 +31,10 @@
 			 "", ""),
 };
 
-static char exception_help_text[] =
+U_BOOT_LONGHELP(exception,
 	"<ex>\n"
 	"  The following exceptions are available:\n"
 	"  undefined  - undefined instruction\n"
-	"  sigsegv    - illegal memory access\n"
-	;
+	"  sigsegv    - illegal memory access\n");
 
 #include <exception.h>
diff --git a/cmd/scp03.c b/cmd/scp03.c
index 216c942..2b8d5ae 100644
--- a/cmd/scp03.c
+++ b/cmd/scp03.c
@@ -41,11 +41,12 @@
 	return CMD_RET_SUCCESS;
 }
 
-static char text[] =
+U_BOOT_LONGHELP(scp03,
 	"provides a command to enable SCP03 and provision the SCP03 keys\n"
 	" enable    - enable SCP03 on the TEE\n"
-	" provision - provision SCP03 on the TEE\n";
+	" provision - provision SCP03 on the TEE\n");
 
-U_BOOT_CMD_WITH_SUBCMDS(scp03, "Secure Channel Protocol 03 control", text,
+U_BOOT_CMD_WITH_SUBCMDS(scp03, "Secure Channel Protocol 03 control",
+	scp03_help_text,
 	U_BOOT_SUBCMD_MKENT(enable, 1, 1, do_scp03_enable),
 	U_BOOT_SUBCMD_MKENT(provision, 1, 1, do_scp03_provision));
diff --git a/cmd/sf.c b/cmd/sf.c
index 977ffcb..30b2bd5 100644
--- a/cmd/sf.c
+++ b/cmd/sf.c
@@ -614,8 +614,7 @@
 	return ret;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static const char long_help[] =
+U_BOOT_LONGHELP(sf,
 	"probe [[bus:]cs] [hz] [mode]	- init flash device on given SPI bus\n"
 	"				  and chip select\n"
 	"sf read addr offset|partition len	- read `len' bytes starting at\n"
@@ -635,10 +634,9 @@
 #ifdef CONFIG_CMD_SF_TEST
 	"\nsf test offset len		- run a very basic destructive test"
 #endif
-#endif /* CONFIG_SYS_LONGHELP */
-	;
+	);
 
 U_BOOT_CMD(
 	sf,	5,	1,	do_spi_flash,
-	"SPI flash sub-system", long_help
+	"SPI flash sub-system", sf_help_text
 );
diff --git a/cmd/source.c b/cmd/source.c
index 92c7835..0ba9736 100644
--- a/cmd/source.c
+++ b/cmd/source.c
@@ -54,19 +54,18 @@
 	return rcode;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char source_help_text[] =
+U_BOOT_LONGHELP(source,
 #if defined(CONFIG_FIT)
 	"[<addr>][:[<image>]|#[<config>]]\n"
 	"\t- Run script starting at addr\n"
 	"\t- A FIT config name or subimage name may be specified with : or #\n"
 	"\t  (like bootm). If the image or config name is omitted, the\n"
-	"\t  default is used.";
+	"\t  default is used."
 #else
 	"[<addr>]\n"
-	"\t- Run script starting at addr";
+	"\t- Run script starting at addr"
 #endif
-#endif
+	);
 
 U_BOOT_CMD(
 	source, 2, 0,	do_source,
diff --git a/cmd/ti/Kconfig b/cmd/ti/Kconfig
index db55744..9442c99 100644
--- a/cmd/ti/Kconfig
+++ b/cmd/ti/Kconfig
@@ -2,6 +2,7 @@
 
 config CMD_DDR3
 	bool "command for verifying DDR features"
+	depends on ARCH_KEYSTONE || DRA7XX
 	help
 	   Support for testing ddr3 on TI platforms. This command
 	   supports memory verification, memory comapre and ecc
diff --git a/cmd/ti/Makefile b/cmd/ti/Makefile
index 0455933..87f85b2 100644
--- a/cmd/ti/Makefile
+++ b/cmd/ti/Makefile
@@ -1,9 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0+
 # Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
 
-obj- += dummy.o
-
-ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_CMD_DDR3) += ddr3.o
 obj-$(CONFIG_CMD_PD) += pd.o
-endif
diff --git a/cmd/ti/pd.c b/cmd/ti/pd.c
index a9a182f..a0492a5 100644
--- a/cmd/ti/pd.c
+++ b/cmd/ti/pd.c
@@ -175,11 +175,11 @@
 		return CMD_RET_USAGE;
 }
 
-U_BOOT_CMD(pd, 4, 1, ti_do_pd,
-	   "TI power domain control",
-#if IS_ENABLED(CONFIG_SYS_LONGHELP)
+U_BOOT_LONGHELP(pd,
 	   "dump                 - show power domain status\n"
 	   "enable [psc] [lpsc]  - enable power domain\n"
-	   "disable [psc] [lpsc] - disable power domain\n"
-#endif
+	   "disable [psc] [lpsc] - disable power domain\n");
+
+U_BOOT_CMD(pd, 4, 1, ti_do_pd,
+	   "TI power domain control", pd_help_text
 );
diff --git a/cmd/vbe.c b/cmd/vbe.c
index 6006903..0e84b0e 100644
--- a/cmd/vbe.c
+++ b/cmd/vbe.c
@@ -104,13 +104,11 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char vbe_help_text[] =
+U_BOOT_LONGHELP(vbe,
 	"list   - list VBE bootmeths\n"
 	"vbe select - select a VBE bootmeth by sequence or name\n"
 	"vbe info   - show information about a VBE bootmeth\n"
-	"vbe state  - show VBE state";
-#endif
+	"vbe state  - show VBE state");
 
 U_BOOT_CMD_WITH_SUBCMDS(vbe, "Verified Boot for Embedded", vbe_help_text,
 	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_vbe_list),
diff --git a/cmd/wdt.c b/cmd/wdt.c
index 2741098..b9fdf7a 100644
--- a/cmd/wdt.c
+++ b/cmd/wdt.c
@@ -157,13 +157,13 @@
 	return CMD_RET_SUCCESS;
 }
 
-static char wdt_help_text[] =
+U_BOOT_LONGHELP(wdt,
 	"list - list watchdog devices\n"
 	"wdt dev [<name>] - get/set current watchdog device\n"
 	"wdt start <timeout ms> [flags] - start watchdog timer\n"
 	"wdt stop - stop watchdog timer\n"
 	"wdt reset - reset watchdog timer\n"
-	"wdt expire [flags] - expire watchdog timer immediately\n";
+	"wdt expire [flags] - expire watchdog timer immediately\n");
 
 U_BOOT_CMD_WITH_SUBCMDS(wdt, "Watchdog sub-system", wdt_help_text,
 	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_wdt_list),
diff --git a/cmd/ximg.c b/cmd/ximg.c
index 60ed2c9..a50dd20 100644
--- a/cmd/ximg.c
+++ b/cmd/ximg.c
@@ -258,8 +258,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char imgextract_help_text[] =
+U_BOOT_LONGHELP(imgextract,
 	"addr part [dest]\n"
 	"    - extract <part> from legacy image at <addr> and copy to <dest>"
 #if defined(CONFIG_FIT)
@@ -267,8 +266,7 @@
 	"addr uname [dest]\n"
 	"    - extract <uname> subimage from FIT image at <addr> and copy to <dest>"
 #endif
-	"";
-#endif
+	);
 
 U_BOOT_CMD(
 	imxtract, 4, 1, do_imgextract,
diff --git a/cmd/xxd.c b/cmd/xxd.c
index 742a85c..446ac19 100644
--- a/cmd/xxd.c
+++ b/cmd/xxd.c
@@ -73,11 +73,9 @@
 	return 0;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char xxd_help_text[] =
+U_BOOT_LONGHELP(xxd,
 	"<interface> <dev[:part]> <file>\n"
-	"  - Print file from 'dev' on 'interface' as hexdump to standard output\n";
-#endif
+	"  - Print file from 'dev' on 'interface' as hexdump to standard output\n");
 
 U_BOOT_CMD(xxd, 4, 1, do_xxd,
 	   "Print file as hexdump to standard output",
diff --git a/configs/ad401_defconfig b/configs/ad401_defconfig
index 31752cc..b9aca3a 100644
--- a/configs/ad401_defconfig
+++ b/configs/ad401_defconfig
@@ -51,4 +51,7 @@
 CONFIG_MESON_SERIAL=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
+CONFIG_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_USB_GADGET=y
 CONFIG_WDT=y
diff --git a/configs/ds116_defconfig b/configs/ds116_defconfig
index 0cd546c..2437be7 100644
--- a/configs/ds116_defconfig
+++ b/configs/ds116_defconfig
@@ -28,7 +28,8 @@
 CONFIG_PCI=y
 CONFIG_DEBUG_UART=y
 CONFIG_AHCI=y
-CONFIG_DISTRO_DEFAULTS=y
+CONFIG_BOOTSTD_FULL=y
+CONFIG_BOOTSTD_DEFAULTS=y
 CONFIG_BOOTDELAY=10
 CONFIG_USE_PREBOOT=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
diff --git a/configs/mvebu_ac5_rd_defconfig b/configs/mvebu_ac5_rd_defconfig
index dbf1e31..e8fa22b 100644
--- a/configs/mvebu_ac5_rd_defconfig
+++ b/configs/mvebu_ac5_rd_defconfig
@@ -85,3 +85,4 @@
 CONFIG_USB_ETHER_MCS7830=y
 CONFIG_USB_ETHER_RTL8152=y
 CONFIG_USB_ETHER_SMSC95XX=y
+# CONFIG_SMBIOS is not set
diff --git a/configs/n2350_defconfig b/configs/n2350_defconfig
index 109f0e1..0713574 100644
--- a/configs/n2350_defconfig
+++ b/configs/n2350_defconfig
@@ -29,7 +29,8 @@
 CONFIG_PCI=y
 CONFIG_DEBUG_UART=y
 CONFIG_AHCI=y
-CONFIG_DISTRO_DEFAULTS=y
+CONFIG_BOOTSTD_FULL=y
+CONFIG_BOOTSTD_DEFAULTS=y
 CONFIG_BOOTDELAY=10
 CONFIG_USE_PREBOOT=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
diff --git a/configs/nsa325_defconfig b/configs/nsa325_defconfig
new file mode 100644
index 0000000..d5fe9ca
--- /dev/null
+++ b/configs/nsa325_defconfig
@@ -0,0 +1,81 @@
+CONFIG_ARM=y
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_SYS_DCACHE_OFF=y
+CONFIG_ARCH_CPU_INIT=y
+CONFIG_SYS_THUMB_BUILD=y
+CONFIG_ARCH_KIRKWOOD=y
+CONFIG_SUPPORT_PASSING_ATAGS=y
+CONFIG_CMDLINE_TAG=y
+CONFIG_INITRD_TAG=y
+CONFIG_SYS_KWD_CONFIG="board/zyxel/nsa325/kwbimage.cfg"
+CONFIG_TEXT_BASE=0x600000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_TARGET_NSA325=y
+CONFIG_ENV_SIZE=0x20000
+CONFIG_ENV_OFFSET=0xC0000
+CONFIG_DEFAULT_DEVICE_TREE="kirkwood-nsa325"
+CONFIG_SYS_PROMPT="NSA325> "
+CONFIG_IDENT_STRING="\nZyXEL NSA325 2-Bay Power Media Server"
+CONFIG_SYS_LOAD_ADDR=0x800000
+CONFIG_PCI=y
+CONFIG_LTO=y
+CONFIG_BOOTSTD_FULL=y
+CONFIG_BOOTSTD_DEFAULTS=y
+CONFIG_BOOTSTD_BOOTCOMMAND=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_BOOTSTAGE=y
+CONFIG_SHOW_BOOT_PROGRESS=y
+CONFIG_BOOTDELAY=10
+CONFIG_USE_PREBOOT=y
+CONFIG_BOARD_LATE_INIT=y
+# CONFIG_BOOTM_PLAN9 is not set
+# CONFIG_BOOTM_RTEMS is not set
+# CONFIG_BOOTM_VXWORKS is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MTD=y
+CONFIG_CMD_NAND=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_SATA=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_DNS=y
+# CONFIG_CMD_BLOCK_CACHE is not set
+CONFIG_CMD_JFFS2=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_MTDIDS_DEFAULT="nand0=orion_nand"
+CONFIG_MTDPARTS_DEFAULT="mtdparts=orion_nand:0x100000(uboot),0x80000(stock_uboot_env),0x80000(key_store),0x80000(info),0xA00000(etc),0xA00000(kernel_1),0x2FC0000(rootfs1),0xA00000(kernel_2),0x2FC0000(rootfs2)"
+CONFIG_CMD_UBI=y
+CONFIG_PARTITION_TYPE_GUID=y
+CONFIG_OF_CONTROL=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_NAND=y
+CONFIG_VERSION_VARIABLE=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_NETCONSOLE=y
+# CONFIG_DM_WARN is not set
+CONFIG_SATA_MV=y
+CONFIG_SYS_SATA_MAX_DEVICE=2
+CONFIG_LBA48=y
+CONFIG_SYS_64BIT_LBA=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MVTWSI=y
+# CONFIG_MMC is not set
+CONFIG_MTD=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_PHY_MARVELL=y
+CONFIG_MVGBE=y
+CONFIG_MII=y
+CONFIG_PCI_MVEBU=y
+CONFIG_DM_RTC=y
+CONFIG_RTC_PCF8563=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PCI=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_NAND=y
+CONFIG_UBIFS_SILENCE_MSG=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 01830c7..47417cb 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -280,6 +280,7 @@
 CONFIG_SCSI=y
 CONFIG_DM_SCSI=y
 CONFIG_SANDBOX_SERIAL=y
+CONFIG_SM=y
 CONFIG_SMEM=y
 CONFIG_SANDBOX_SMEM=y
 CONFIG_SOUND=y
diff --git a/configs/x240_defconfig b/configs/x240_defconfig
index 7d2b860..4b1a761 100644
--- a/configs/x240_defconfig
+++ b/configs/x240_defconfig
@@ -42,7 +42,6 @@
 CONFIG_GPIO_HOG=y
 CONFIG_DM_PCA953X=y
 CONFIG_DM_I2C=y
-CONFIG_DM_I2C_GPIO=y
 CONFIG_SYS_I2C_MVTWSI=y
 CONFIG_I2C_MUX=y
 CONFIG_I2C_MUX_PCA954x=y
@@ -84,3 +83,4 @@
 CONFIG_USB_ETHER_RTL8152=y
 CONFIG_USB_ETHER_SMSC95XX=y
 # CONFIG_FAT_WRITE is not set
+# CONFIG_SMBIOS is not set
diff --git a/drivers/Kconfig b/drivers/Kconfig
index a25f6ae..a073230 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -118,6 +118,8 @@
 
 source "drivers/serial/Kconfig"
 
+source "drivers/sm/Kconfig"
+
 source "drivers/smem/Kconfig"
 
 source "drivers/sound/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index efc2a4a..74f940a 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -35,6 +35,7 @@
 obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/
 obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/
 obj-$(CONFIG_$(SPL_)SYSINFO) += sysinfo/
+obj-$(CONFIG_$(SPL_TPL_)SM) += sm/
 obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm/
 obj-$(CONFIG_$(SPL_)NVME) += nvme/
 obj-$(CONFIG_XEN) += xen/
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 1abea0b..94d7369 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -34,6 +34,7 @@
 #include <common.h>
 #include <ahci.h>
 #include <blk.h>
+#include <bootdev.h>
 #include <cpu_func.h>
 #include <dm.h>
 #include <log.h>
@@ -1105,6 +1106,12 @@
 			/* TODO: undo create */
 			continue;
 
+		ret = bootdev_setup_for_sibling_blk(blk, "sata_bootdev");
+		if (ret) {
+			printf("%s: Failed to create bootdev\n", __func__);
+			continue;
+		}
+
 		/* If we got here, the current SATA port was probed
 		 * successfully, so set the probe status to successful.
 		 */
@@ -1117,7 +1124,6 @@
 static int sata_mv_scan(struct udevice *dev)
 {
 	/* Nothing to do here */
-
 	return 0;
 }
 
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index 994b44a..cdc9d6f 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -21,3 +21,11 @@
 	help
 	  Enable clock support for the Amlogic G12A SoC family, such as
 	  the S905X/D2
+
+config CLK_MESON_A1
+	bool "Enable clock support for Amlogic A1"
+	depends on CLK && ARCH_MESON
+	default MESON_A1
+	help
+	  Enable clock support for the Amlogic A1 SoC family, such as
+	  the A113L
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index a486b13..d975f07 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -8,3 +8,4 @@
 obj-$(CONFIG_CLK_MESON_AXG) += axg-ao.o
 obj-$(CONFIG_CLK_MESON_G12A) += g12a.o
 obj-$(CONFIG_CLK_MESON_G12A) += g12a-ao.o
+obj-$(CONFIG_CLK_MESON_A1) += a1.o
diff --git a/drivers/clk/meson/a1.c b/drivers/clk/meson/a1.c
new file mode 100644
index 0000000..1075ba7
--- /dev/null
+++ b/drivers/clk/meson/a1.c
@@ -0,0 +1,729 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2023 SberDevices, Inc.
+ * Author: Igor Prusov <ivprusov@salutedevices.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <regmap.h>
+#include <asm/arch/clock-a1.h>
+#include <dt-bindings/clock/amlogic,a1-pll-clkc.h>
+#include <dt-bindings/clock/amlogic,a1-peripherals-clkc.h>
+#include "clk_meson.h"
+
+/*
+ * This driver supports both PLL and peripherals clock sources.
+ * Following operations are supported:
+ * - calculating clock frequency on a limited tree
+ * - reading muxes and dividers
+ * - enabling/disabling gates without propagation
+ * - reparenting without rate propagation, only on muxes
+ * - setting rates with limited reparenting, only on dividers with mux parent
+ */
+
+#define NR_CLKS				154
+#define NR_PLL_CLKS			11
+
+/* External clock IDs. Those should not overlap with regular IDs */
+#define EXTERNAL_XTAL			(NR_CLKS + 0)
+#define EXTERNAL_FCLK_DIV2		(NR_CLKS + 1)
+#define EXTERNAL_FCLK_DIV3		(NR_CLKS + 2)
+#define EXTERNAL_FCLK_DIV5		(NR_CLKS + 3)
+#define EXTERNAL_FCLK_DIV7		(NR_CLKS + 4)
+
+#define EXTERNAL_FIXPLL_IN		(NR_PLL_CLKS + 1)
+
+#define SET_PARM_VALUE(_priv, _parm, _val)				\
+	regmap_update_bits((_priv)->map, (_parm)->reg_off,		\
+			   SETPMASK((_parm)->width, (_parm)->shift),	\
+			   (_val) << (_parm)->shift)
+
+#define GET_PARM_VALUE(_priv, _parm)					\
+({									\
+	uint _reg;							\
+	regmap_read((_priv)->map, (_parm)->reg_off, &_reg);		\
+	PARM_GET((_parm)->width, (_parm)->shift, _reg);			\
+})
+
+struct meson_clk {
+	struct regmap *map;
+};
+
+/**
+ * enum meson_clk_type - The type of clock
+ * @MESON_CLK_ANY: Special value that matches any clock type
+ * @MESON_CLK_GATE: This clock is a gate
+ * @MESON_CLK_MUX: This clock is a multiplexer
+ * @MESON_CLK_DIV: This clock is a configurable divider
+ * @MESON_CLK_FIXED_DIV: This clock is a configurable divider
+ * @MESON_CLK_EXTERNAL: This is an external clock from different clock provider
+ * @MESON_CLK_PLL: This is a PLL
+ */
+enum meson_clk_type {
+	MESON_CLK_ANY = 0,
+	MESON_CLK_GATE,
+	MESON_CLK_MUX,
+	MESON_CLK_DIV,
+	MESON_CLK_FIXED_DIV,
+	MESON_CLK_EXTERNAL,
+	MESON_CLK_PLL,
+};
+
+/**
+ * struct meson_clk_info - The parameters defining a clock
+ * @name: Name of the clock
+ * @parm: Register bits description for muxes and dividers
+ * @div: Fixed divider value
+ * @parents: List of parent clock IDs
+ * @type: Clock type
+ */
+struct meson_clk_info {
+	const char *name;
+	union {
+		const struct parm *parm;
+		u8 div;
+	};
+	const unsigned int *parents;
+	const enum meson_clk_type type;
+};
+
+/**
+ * struct meson_clk_data - Clocks supported by clock provider
+ * @num_clocks: Number of clocks
+ * @clocks: Array of clock descriptions
+ *
+ */
+struct meson_clk_data {
+	const u8 num_clocks;
+	const struct meson_clk_info **clocks;
+};
+
+/* Clock description initialization macros */
+
+/* A multiplexer */
+#define CLK_MUX(_name, _reg, _shift, _width, ...)			\
+	(&(struct meson_clk_info){					\
+		.parents = (const unsigned int[])__VA_ARGS__,		\
+		.parm = &(struct parm) {				\
+			.reg_off = (_reg),				\
+			.shift = (_shift),				\
+			.width = (_width),				\
+		},							\
+		.name = (_name),					\
+		.type = MESON_CLK_MUX,					\
+	})
+
+/* A divider with an integral divisor */
+#define CLK_DIV(_name, _reg, _shift, _width, _parent)			\
+	(&(struct meson_clk_info){					\
+		.parents = (const unsigned int[]) { (_parent) },	\
+		.parm = &(struct parm) {				\
+			.reg_off = (_reg),				\
+			.shift = (_shift),				\
+			.width = (_width),				\
+		},							\
+		.name = (_name),					\
+		.type = MESON_CLK_DIV,					\
+	})
+
+/* A fixed divider */
+#define CLK_DIV_FIXED(_name, _div, _parent)				\
+	(&(struct meson_clk_info){					\
+		.parents = (const unsigned int[]) { (_parent) },	\
+		.div = (_div),						\
+		.name = (_name),					\
+		.type = MESON_CLK_FIXED_DIV,				\
+	})
+
+/* An external clock */
+#define CLK_EXTERNAL(_name)						\
+	(&(struct meson_clk_info){					\
+		.name = (_name),					\
+		.parents = (const unsigned int[]) { -ENOENT },		\
+		.type = MESON_CLK_EXTERNAL,				\
+	})
+
+/* A clock gate */
+#define CLK_GATE(_name, _reg, _shift, _parent)				\
+	(&(struct meson_clk_info){					\
+		.parents = (const unsigned int[]) { (_parent) },	\
+		.parm = &(struct parm) {				\
+			.reg_off = (_reg),				\
+			.shift = (_shift),				\
+			.width = 1,					\
+		},							\
+		.name = (_name),					\
+		.type = MESON_CLK_GATE,					\
+	})
+
+/* A PLL clock */
+#define CLK_PLL(_name, _parent, ...)					\
+	(&(struct meson_clk_info){					\
+		.name = (_name),					\
+		.parents = (const unsigned int[]) { (_parent) },	\
+		.parm = (const struct parm[])__VA_ARGS__,		\
+		.type = MESON_CLK_PLL,					\
+	})
+
+/* A1 peripherals clocks */
+static const struct meson_clk_info *meson_clocks[] = {
+	[CLKID_SPIFC_SEL] = CLK_MUX("spifc_sel", A1_SPIFC_CLK_CTRL, 9, 2, {
+		EXTERNAL_FCLK_DIV2,
+		EXTERNAL_FCLK_DIV3,
+		EXTERNAL_FCLK_DIV5,
+		-ENOENT,
+	}),
+	[CLKID_SPIFC_SEL2] = CLK_MUX("spifc_sel2", A1_SPIFC_CLK_CTRL, 15, 1, {
+		CLKID_SPIFC_DIV,
+		EXTERNAL_XTAL,
+	}),
+	[CLKID_USB_BUS_SEL] = CLK_MUX("usb_bus_sel", A1_USB_BUSCLK_CTRL, 9, 2, {
+		-ENOENT,
+		CLKID_SYS,
+		EXTERNAL_FCLK_DIV3,
+		EXTERNAL_FCLK_DIV5,
+	}),
+	[CLKID_SYS] = CLK_MUX("sys", A1_SYS_CLK_CTRL0, 31, 1, {
+		CLKID_SYS_A,
+		CLKID_SYS_B,
+	}),
+	[CLKID_SYS_A_SEL] = CLK_MUX("sys_a_sel", A1_SYS_CLK_CTRL0, 10, 3, {
+		-ENOENT,
+		EXTERNAL_FCLK_DIV2,
+		EXTERNAL_FCLK_DIV3,
+		EXTERNAL_FCLK_DIV5,
+		-ENOENT,
+		-ENOENT,
+		-ENOENT,
+		-ENOENT,
+	}),
+	[CLKID_SYS_B_SEL] = CLK_MUX("sys_b_sel", A1_SYS_CLK_CTRL0, 26, 3, {
+		-ENOENT,
+		EXTERNAL_FCLK_DIV2,
+		EXTERNAL_FCLK_DIV3,
+		EXTERNAL_FCLK_DIV5,
+		-ENOENT,
+		-ENOENT,
+		-ENOENT,
+		-ENOENT,
+	}),
+
+	[CLKID_SPIFC_DIV] = CLK_DIV("spifc_div", A1_SPIFC_CLK_CTRL, 0, 8,
+		CLKID_SPIFC_SEL
+	),
+	[CLKID_USB_BUS_DIV] = CLK_DIV("usb_bus_div", A1_USB_BUSCLK_CTRL, 0, 8,
+		CLKID_USB_BUS_SEL
+	),
+	[CLKID_SYS_A_DIV] = CLK_DIV("sys_a_div", A1_SYS_CLK_CTRL0, 0, 10,
+		CLKID_SYS_A_SEL
+	),
+	[CLKID_SYS_B_DIV] = CLK_DIV("sys_b_div", A1_SYS_CLK_CTRL0, 16, 10,
+		CLKID_SYS_B_SEL
+	),
+
+	[CLKID_SPIFC] = CLK_GATE("spifc", A1_SPIFC_CLK_CTRL, 8,
+		CLKID_SPIFC_SEL2
+	),
+	[CLKID_USB_BUS] = CLK_GATE("usb_bus", A1_USB_BUSCLK_CTRL, 8,
+		CLKID_USB_BUS_DIV
+	),
+	[CLKID_SYS_A] = CLK_GATE("sys_a", A1_SYS_CLK_CTRL0, 13,
+		CLKID_SYS_A_DIV
+	),
+	[CLKID_SYS_B] = CLK_GATE("sys_b", A1_SYS_CLK_CTRL0, 29,
+		CLKID_SYS_B_DIV
+	),
+	[CLKID_FIXPLL_IN] = CLK_GATE("fixpll_in", A1_SYS_OSCIN_CTRL, 1,
+		EXTERNAL_XTAL
+	),
+	[CLKID_USB_PHY_IN] = CLK_GATE("usb_phy_in", A1_SYS_OSCIN_CTRL, 2,
+		EXTERNAL_XTAL
+	),
+	[CLKID_USB_PHY] = CLK_GATE("usb_phy", A1_SYS_CLK_EN0, 27,
+		CLKID_SYS
+	),
+	[CLKID_SARADC] = CLK_GATE("saradc", A1_SAR_ADC_CLK_CTR, 8,
+		-ENOENT
+	),
+	[CLKID_SARADC_EN] = CLK_GATE("saradc_en", A1_SYS_CLK_EN0, 13,
+		CLKID_SYS
+	),
+
+	[EXTERNAL_XTAL] = CLK_EXTERNAL("xtal"),
+	[EXTERNAL_FCLK_DIV2] = CLK_EXTERNAL("fclk_div2"),
+	[EXTERNAL_FCLK_DIV3] = CLK_EXTERNAL("fclk_div3"),
+	[EXTERNAL_FCLK_DIV5] = CLK_EXTERNAL("fclk_div5"),
+	[EXTERNAL_FCLK_DIV7] = CLK_EXTERNAL("fclk_div7"),
+};
+
+/* A1 PLL clocks */
+static const struct meson_clk_info *meson_pll_clocks[] = {
+	[EXTERNAL_FIXPLL_IN] = CLK_EXTERNAL("fixpll_in"),
+
+	[CLKID_FIXED_PLL_DCO] = CLK_PLL("fixed_pll_dco", EXTERNAL_FIXPLL_IN, {
+			{A1_ANACTRL_FIXPLL_CTRL0, 0, 8},
+			{A1_ANACTRL_FIXPLL_CTRL0, 10, 5},
+	}),
+
+	[CLKID_FCLK_DIV2_DIV] = CLK_DIV_FIXED("fclk_div2_div", 2,
+		CLKID_FIXED_PLL
+	),
+	[CLKID_FCLK_DIV3_DIV] = CLK_DIV_FIXED("fclk_div3_div", 3,
+		CLKID_FIXED_PLL
+	),
+	[CLKID_FCLK_DIV5_DIV] = CLK_DIV_FIXED("fclk_div5_div", 5,
+		CLKID_FIXED_PLL
+	),
+	[CLKID_FCLK_DIV7_DIV] = CLK_DIV_FIXED("fclk_div7_div", 7,
+		CLKID_FIXED_PLL
+	),
+
+	[CLKID_FIXED_PLL] = CLK_GATE("fixed_pll", A1_ANACTRL_FIXPLL_CTRL0, 20,
+		CLKID_FIXED_PLL_DCO
+	),
+	[CLKID_FCLK_DIV2] = CLK_GATE("fclk_div2", A1_ANACTRL_FIXPLL_CTRL0, 21,
+		CLKID_FCLK_DIV2_DIV
+	),
+	[CLKID_FCLK_DIV3] = CLK_GATE("fclk_div3", A1_ANACTRL_FIXPLL_CTRL0, 22,
+		CLKID_FCLK_DIV3_DIV
+	),
+	[CLKID_FCLK_DIV5] = CLK_GATE("fclk_div5", A1_ANACTRL_FIXPLL_CTRL0, 23,
+		CLKID_FCLK_DIV5_DIV
+	),
+	[CLKID_FCLK_DIV7] = CLK_GATE("fclk_div7", A1_ANACTRL_FIXPLL_CTRL0, 24,
+		CLKID_FCLK_DIV7_DIV
+	),
+};
+
+static const struct meson_clk_info *meson_clk_get_info(struct clk *clk, ulong id,
+						       enum meson_clk_type type)
+{
+	struct meson_clk_data *data;
+	const struct meson_clk_info *info;
+
+	data = (struct meson_clk_data *)dev_get_driver_data(clk->dev);
+	if (id >= data->num_clocks)
+		return ERR_PTR(-EINVAL);
+
+	info = data->clocks[id];
+	if (!info)
+		return ERR_PTR(-ENOENT);
+
+	if (type != MESON_CLK_ANY && type != info->type)
+		return ERR_PTR(-EINVAL);
+
+	return info;
+}
+
+static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id);
+
+static int meson_set_gate(struct clk *clk, bool on)
+{
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	const struct meson_clk_info *info;
+
+	debug("%s: %sabling %lu\n", __func__, on ? "en" : "dis", clk->id);
+
+	info = meson_clk_get_info(clk, clk->id, MESON_CLK_ANY);
+	if (IS_ERR(info))
+		return PTR_ERR(info);
+
+	SET_PARM_VALUE(priv, info->parm, on);
+
+	return 0;
+}
+
+static int meson_clk_enable(struct clk *clk)
+{
+	return meson_set_gate(clk, true);
+}
+
+static int meson_clk_disable(struct clk *clk)
+{
+	return meson_set_gate(clk, false);
+}
+
+static ulong meson_div_get_rate(struct clk *clk, unsigned long id)
+{
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	u16 n;
+	ulong rate;
+	const struct meson_clk_info *info;
+
+	info = meson_clk_get_info(clk, id, MESON_CLK_DIV);
+	if (IS_ERR(info))
+		return PTR_ERR(info);
+
+	/* Actual divider value is (field value + 1), hence the increment */
+	n = GET_PARM_VALUE(priv, info->parm) + 1;
+
+	rate = meson_clk_get_rate_by_id(clk, info->parents[0]);
+
+	return rate / n;
+}
+
+static int meson_clk_get_parent(struct clk *clk, unsigned long id)
+{
+	uint reg = 0;
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	const struct meson_clk_info *info;
+
+	info = meson_clk_get_info(clk, id, MESON_CLK_ANY);
+	if (IS_ERR(info))
+		return PTR_ERR(info);
+
+	/* For muxes we read currently selected parent from register,
+	 * for other types there is always only one element in parents array.
+	 */
+	if (info->type == MESON_CLK_MUX) {
+		reg = GET_PARM_VALUE(priv, info->parm);
+		if (IS_ERR_VALUE(reg))
+			return reg;
+	}
+
+	return info->parents[reg];
+}
+
+static ulong meson_pll_get_rate(struct clk *clk, unsigned long id)
+{
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	const struct meson_clk_info *info;
+	const struct parm *pm, *pn;
+	ulong parent_rate_mhz;
+	unsigned int parent;
+	u16 n, m;
+
+	info = meson_clk_get_info(clk, id, MESON_CLK_ANY);
+	if (IS_ERR(info))
+		return PTR_ERR(info);
+
+	pm = &info->parm[0];
+	pn = &info->parm[1];
+
+	n = GET_PARM_VALUE(priv, pn);
+	m = GET_PARM_VALUE(priv, pm);
+
+	if (n == 0)
+		return -EINVAL;
+
+	parent = info->parents[0];
+	parent_rate_mhz = meson_clk_get_rate_by_id(clk, parent) / 1000000;
+
+	return parent_rate_mhz * m / n * 1000000;
+}
+
+static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id)
+{
+	ulong rate, parent;
+	const struct meson_clk_info *info;
+
+	if (IS_ERR_VALUE(id))
+		return id;
+
+	info = meson_clk_get_info(clk, id, MESON_CLK_ANY);
+	if (IS_ERR(info))
+		return PTR_ERR(info);
+
+	switch (info->type) {
+	case MESON_CLK_PLL:
+		rate = meson_pll_get_rate(clk, id);
+		break;
+	case MESON_CLK_GATE:
+	case MESON_CLK_MUX:
+		parent = meson_clk_get_parent(clk, id);
+		rate = meson_clk_get_rate_by_id(clk, parent);
+		break;
+	case MESON_CLK_DIV:
+		rate = meson_div_get_rate(clk, id);
+		break;
+	case MESON_CLK_FIXED_DIV:
+		parent = meson_clk_get_parent(clk, id);
+		rate = meson_clk_get_rate_by_id(clk, parent) / info->div;
+		break;
+	case MESON_CLK_EXTERNAL: {
+		int ret;
+		struct clk external_clk;
+
+		ret = clk_get_by_name(clk->dev, info->name, &external_clk);
+		if (ret)
+			return ret;
+
+		rate = clk_get_rate(&external_clk);
+		break;
+	}
+	default:
+		rate = -EINVAL;
+		break;
+	}
+
+	return rate;
+}
+
+static ulong meson_clk_get_rate(struct clk *clk)
+{
+	return meson_clk_get_rate_by_id(clk, clk->id);
+}
+
+/* This implements rate propagation for dividers placed after multiplexer:
+ *  ---------|\
+ *     ..... | |---DIV--
+ *  ---------|/
+ */
+static ulong meson_composite_set_rate(struct clk *clk, ulong id, ulong rate)
+{
+	unsigned int i, best_div_val;
+	unsigned long best_delta, best_parent;
+	const struct meson_clk_info *div;
+	const struct meson_clk_info *mux;
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+
+	div = meson_clk_get_info(clk, id, MESON_CLK_DIV);
+	if (IS_ERR(div))
+		return PTR_ERR(div);
+
+	mux = meson_clk_get_info(clk, div->parents[0], MESON_CLK_MUX);
+	if (IS_ERR(mux))
+		return PTR_ERR(mux);
+
+	best_parent = -EINVAL;
+	best_delta = ULONG_MAX;
+	for (i = 0; i < (1 << mux->parm->width); i++) {
+		unsigned long parent_rate, delta;
+		unsigned int div_val;
+
+		parent_rate = meson_clk_get_rate_by_id(clk, mux->parents[i]);
+		if (IS_ERR_VALUE(parent_rate))
+			continue;
+
+		/* If overflow, try to use max divider value */
+		div_val = min(DIV_ROUND_CLOSEST(parent_rate, rate),
+			      (1UL << div->parm->width));
+
+		delta = abs(rate - (parent_rate / div_val));
+		if (delta < best_delta) {
+			best_delta = delta;
+			best_div_val = div_val;
+			best_parent = i;
+		}
+	}
+
+	if (IS_ERR_VALUE(best_parent))
+		return best_parent;
+
+	SET_PARM_VALUE(priv, mux->parm, best_parent);
+	/* Divider is set to (field value + 1), hence the decrement */
+	SET_PARM_VALUE(priv, div->parm, best_div_val - 1);
+
+	return 0;
+}
+
+static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned int id, ulong rate);
+
+static ulong meson_mux_set_rate(struct clk *clk, unsigned long id, ulong rate)
+{
+	int i;
+	ulong ret = -EINVAL;
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	const struct meson_clk_info *info;
+
+	info = meson_clk_get_info(clk, id, MESON_CLK_MUX);
+	if (IS_ERR(info))
+		return PTR_ERR(info);
+
+	for (i = 0; i < (1 << info->parm->width); i++) {
+		ret = meson_clk_set_rate_by_id(clk, info->parents[i], rate);
+		if (!ret) {
+			SET_PARM_VALUE(priv, info->parm, i);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+/* Rate propagation is implemented for a subcection of a clock tree, that is
+ * required at boot stage.
+ */
+static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned int id, ulong rate)
+{
+	switch (id) {
+	case CLKID_SPIFC_DIV:
+	case CLKID_USB_BUS_DIV:
+		return meson_composite_set_rate(clk, id, rate);
+	case CLKID_SPIFC:
+	case CLKID_USB_BUS: {
+		unsigned long parent = meson_clk_get_parent(clk, id);
+
+		return meson_clk_set_rate_by_id(clk, parent, rate);
+	}
+	case CLKID_SPIFC_SEL2:
+		return meson_mux_set_rate(clk, id, rate);
+	}
+
+	return -EINVAL;
+}
+
+static ulong meson_clk_set_rate(struct clk *clk, ulong rate)
+{
+	return meson_clk_set_rate_by_id(clk, clk->id, rate);
+}
+
+static int meson_mux_set_parent_by_id(struct clk *clk, unsigned int parent_id)
+{
+	unsigned int i, parent_index;
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	const struct meson_clk_info *info;
+
+	info = meson_clk_get_info(clk, clk->id, MESON_CLK_MUX);
+	if (IS_ERR(info))
+		return PTR_ERR(info);
+
+	parent_index = -EINVAL;
+	for (i = 0; i < (1 << info->parm->width); i++) {
+		if (parent_id == info->parents[i]) {
+			parent_index = i;
+			break;
+		}
+	}
+
+	if (IS_ERR_VALUE(parent_index))
+		return parent_index;
+
+	SET_PARM_VALUE(priv, info->parm, parent_index);
+
+	return 0;
+}
+
+static int meson_clk_set_parent(struct clk *clk, struct clk *parent_clk)
+{
+	return meson_mux_set_parent_by_id(clk, parent_clk->id);
+}
+
+static struct clk_ops meson_clk_ops = {
+	.disable	= meson_clk_disable,
+	.enable		= meson_clk_enable,
+	.get_rate	= meson_clk_get_rate,
+	.set_rate	= meson_clk_set_rate,
+	.set_parent	= meson_clk_set_parent,
+};
+
+static int meson_clk_probe(struct udevice *dev)
+{
+	struct meson_clk *priv = dev_get_priv(dev);
+
+	return regmap_init_mem(dev_ofnode(dev), &priv->map);
+}
+
+struct meson_clk_data meson_a1_peripherals_info = {
+	.clocks = meson_clocks,
+	.num_clocks = ARRAY_SIZE(meson_clocks),
+};
+
+struct meson_clk_data meson_a1_pll_info = {
+	.clocks = meson_pll_clocks,
+	.num_clocks = ARRAY_SIZE(meson_pll_clocks),
+};
+
+static const struct udevice_id meson_clk_ids[] = {
+	{
+		.compatible = "amlogic,a1-peripherals-clkc",
+		.data = (ulong)&meson_a1_peripherals_info,
+	},
+	{
+		.compatible = "amlogic,a1-pll-clkc",
+		.data = (ulong)&meson_a1_pll_info,
+	},
+	{ }
+};
+
+U_BOOT_DRIVER(meson_clk) = {
+	.name		= "meson-clk-a1",
+	.id		= UCLASS_CLK,
+	.of_match	= meson_clk_ids,
+	.priv_auto	= sizeof(struct meson_clk),
+	.ops		= &meson_clk_ops,
+	.probe		= meson_clk_probe,
+};
+
+static const char *meson_clk_get_name(struct clk *clk, int id)
+{
+	const struct meson_clk_info *info;
+
+	info = meson_clk_get_info(clk, id, MESON_CLK_ANY);
+
+	return IS_ERR(info) ? "unknown" : info->name;
+}
+
+static int meson_clk_dump(struct clk *clk)
+{
+	const struct meson_clk_info *info;
+	struct meson_clk *priv;
+	unsigned long rate;
+	char *state, frequency[80];
+	int parent;
+
+	priv = dev_get_priv(clk->dev);
+
+	info = meson_clk_get_info(clk, clk->id, MESON_CLK_ANY);
+	if (IS_ERR(info) || !info->name)
+		return -EINVAL;
+
+	rate = clk_get_rate(clk);
+	if (IS_ERR_VALUE(rate))
+		sprintf(frequency, "unknown");
+	else
+		sprintf(frequency, "%lu", rate);
+
+	if (info->type == MESON_CLK_GATE)
+		state = GET_PARM_VALUE(priv, info->parm) ? "enabled" : "disabled";
+	else
+		state = "N/A";
+
+	parent = meson_clk_get_parent(clk, clk->id);
+	printf("%15s%20s%20s%15s\n",
+	       info->name,
+	       frequency,
+	       meson_clk_get_name(clk, parent),
+	       state);
+
+	return 0;
+}
+
+static int meson_clk_dump_dev(struct udevice *dev)
+{
+	int i;
+	struct meson_clk_data *data;
+	const char *sep = "--------------------";
+
+	printf("%s:\n", dev->name);
+	printf("%.15s%s%s%.15s\n", sep, sep, sep, sep);
+	printf("%15s%20s%20s%15s\n", "clk", "frequency", "parent", "state");
+	printf("%.15s%s%s%.15s\n", sep, sep, sep, sep);
+
+	data = (struct meson_clk_data *)dev_get_driver_data(dev);
+	for (i = 0; i < data->num_clocks; i++) {
+		meson_clk_dump(&(struct clk){
+			.dev = dev,
+			.id = i
+		});
+	}
+
+	return 0;
+}
+
+int soc_clk_dump(void)
+{
+	struct udevice *dev;
+	int i = 0;
+
+	while (!uclass_get_device(UCLASS_CLK, i++, &dev)) {
+		if (dev->driver == DM_DRIVER_GET(meson_clk)) {
+			meson_clk_dump_dev(dev);
+			printf("\n");
+		}
+	}
+
+	return 0;
+}
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 8ac5769..60138be 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -200,7 +200,7 @@
 
 config MESON_G12A_USB_PHY
 	bool "Amlogic Meson G12A USB PHYs"
-	depends on PHY && ARCH_MESON && MESON_G12A
+	depends on PHY && ARCH_MESON && (MESON_G12A || MESON_A1)
 	imply REGMAP
 	help
 	  This is the generic phy driver for the Amlogic Meson G12A
diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c
index 8b24322..4ba3992 100644
--- a/drivers/phy/meson-g12a-usb2.c
+++ b/drivers/phy/meson-g12a-usb2.c
@@ -19,17 +19,34 @@
 #include <linux/delay.h>
 #include <linux/printk.h>
 #include <power/regulator.h>
+#include <power-domain.h>
 #include <reset.h>
 #include <clk.h>
 
 #include <linux/bitops.h>
 #include <linux/compat.h>
+#include <linux/bitfield.h>
 
 #define PHY_CTRL_R0						0x0
 #define PHY_CTRL_R1						0x4
 #define PHY_CTRL_R2						0x8
+
 #define PHY_CTRL_R3						0xc
+	#define PHY_CTRL_R3_SQUELCH_REF				GENMASK(1, 0)
+	#define PHY_CTRL_R3_HSDIC_REF				GENMASK(3, 2)
+	#define PHY_CTRL_R3_DISC_THRESH				GENMASK(7, 4)
+
 #define PHY_CTRL_R4						0x10
+	#define PHY_CTRL_R4_CALIB_CODE_7_0			GENMASK(7, 0)
+	#define PHY_CTRL_R4_CALIB_CODE_15_8			GENMASK(15, 8)
+	#define PHY_CTRL_R4_CALIB_CODE_23_16			GENMASK(23, 16)
+	#define PHY_CTRL_R4_I_C2L_CAL_EN			BIT(24)
+	#define PHY_CTRL_R4_I_C2L_CAL_RESET_N			BIT(25)
+	#define PHY_CTRL_R4_I_C2L_CAL_DONE			BIT(26)
+	#define PHY_CTRL_R4_TEST_BYPASS_MODE_EN			BIT(27)
+	#define PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0			GENMASK(29, 28)
+	#define PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2			GENMASK(31, 30)
+
 #define PHY_CTRL_R5						0x14
 #define PHY_CTRL_R6						0x18
 #define PHY_CTRL_R7						0x1c
@@ -38,35 +55,131 @@
 #define PHY_CTRL_R10						0x28
 #define PHY_CTRL_R11						0x2c
 #define PHY_CTRL_R12						0x30
+
 #define PHY_CTRL_R13						0x34
+	#define PHY_CTRL_R13_CUSTOM_PATTERN_19			GENMASK(7, 0)
+	#define PHY_CTRL_R13_LOAD_STAT				BIT(14)
+	#define PHY_CTRL_R13_UPDATE_PMA_SIGNALS			BIT(15)
+	#define PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET		GENMASK(20, 16)
+	#define PHY_CTRL_R13_CLEAR_HOLD_HS_DISCONNECT		BIT(21)
+	#define PHY_CTRL_R13_BYPASS_HOST_DISCONNECT_VAL		BIT(22)
+	#define PHY_CTRL_R13_BYPASS_HOST_DISCONNECT_EN		BIT(23)
+	#define PHY_CTRL_R13_I_C2L_HS_EN			BIT(24)
+	#define PHY_CTRL_R13_I_C2L_FS_EN			BIT(25)
+	#define PHY_CTRL_R13_I_C2L_LS_EN			BIT(26)
+	#define PHY_CTRL_R13_I_C2L_HS_OE			BIT(27)
+	#define PHY_CTRL_R13_I_C2L_FS_OE			BIT(28)
+	#define PHY_CTRL_R13_I_C2L_HS_RX_EN			BIT(29)
+	#define PHY_CTRL_R13_I_C2L_FSLS_RX_EN			BIT(30)
+
 #define PHY_CTRL_R14						0x38
 #define PHY_CTRL_R15						0x3c
+
 #define PHY_CTRL_R16						0x40
+	#define PHY_CTRL_R16_MPLL_M				GENMASK(8, 0)
+	#define PHY_CTRL_R16_MPLL_N				GENMASK(14, 10)
+	#define PHY_CTRL_R16_MPLL_TDC_MODE			BIT(20)
+	#define PHY_CTRL_R16_MPLL_SDM_EN			BIT(21)
+	#define PHY_CTRL_R16_MPLL_LOAD				BIT(22)
+	#define PHY_CTRL_R16_MPLL_DCO_SDM_EN			BIT(23)
+	#define PHY_CTRL_R16_MPLL_LOCK_LONG			GENMASK(25, 24)
+	#define PHY_CTRL_R16_MPLL_LOCK_F			BIT(26)
+	#define PHY_CTRL_R16_MPLL_FAST_LOCK			BIT(27)
+	#define PHY_CTRL_R16_MPLL_EN				BIT(28)
+	#define PHY_CTRL_R16_MPLL_RESET				BIT(29)
+	#define PHY_CTRL_R16_MPLL_LOCK				BIT(30)
+	#define PHY_CTRL_R16_MPLL_LOCK_DIG			BIT(31)
+
 #define PHY_CTRL_R17						0x44
+	#define PHY_CTRL_R17_MPLL_FRAC_IN			GENMASK(13, 0)
+	#define PHY_CTRL_R17_MPLL_FIX_EN			BIT(16)
+	#define PHY_CTRL_R17_MPLL_LAMBDA1			GENMASK(19, 17)
+	#define PHY_CTRL_R17_MPLL_LAMBDA0			GENMASK(22, 20)
+	#define PHY_CTRL_R17_MPLL_FILTER_MODE			BIT(23)
+	#define PHY_CTRL_R17_MPLL_FILTER_PVT2			GENMASK(27, 24)
+	#define PHY_CTRL_R17_MPLL_FILTER_PVT1			GENMASK(31, 28)
+
 #define PHY_CTRL_R18						0x48
+	#define PHY_CTRL_R18_MPLL_LKW_SEL			GENMASK(1, 0)
+	#define PHY_CTRL_R18_MPLL_LK_W				GENMASK(5, 2)
+	#define PHY_CTRL_R18_MPLL_LK_S				GENMASK(11, 6)
+	#define PHY_CTRL_R18_MPLL_DCO_M_EN			BIT(12)
+	#define PHY_CTRL_R18_MPLL_DCO_CLK_SEL			BIT(13)
+	#define PHY_CTRL_R18_MPLL_PFD_GAIN			GENMASK(15, 14)
+	#define PHY_CTRL_R18_MPLL_ROU				GENMASK(18, 16)
+	#define PHY_CTRL_R18_MPLL_DATA_SEL			GENMASK(21, 19)
+	#define PHY_CTRL_R18_MPLL_BIAS_ADJ			GENMASK(23, 22)
+	#define PHY_CTRL_R18_MPLL_BB_MODE			GENMASK(25, 24)
+	#define PHY_CTRL_R18_MPLL_ALPHA				GENMASK(28, 26)
+	#define PHY_CTRL_R18_MPLL_ADJ_LDO			GENMASK(30, 29)
+	#define PHY_CTRL_R18_MPLL_ACG_RANGE			BIT(31)
+
 #define PHY_CTRL_R19						0x4c
+
 #define PHY_CTRL_R20						0x50
+	#define PHY_CTRL_R20_USB2_IDDET_EN			BIT(0)
+	#define PHY_CTRL_R20_USB2_OTG_VBUS_TRIM_2_0		GENMASK(3, 1)
+	#define PHY_CTRL_R20_USB2_OTG_VBUSDET_EN		BIT(4)
+	#define PHY_CTRL_R20_USB2_AMON_EN			BIT(5)
+	#define PHY_CTRL_R20_USB2_CAL_CODE_R5			BIT(6)
+	#define PHY_CTRL_R20_BYPASS_OTG_DET			BIT(7)
+	#define PHY_CTRL_R20_USB2_DMON_EN			BIT(8)
+	#define PHY_CTRL_R20_USB2_DMON_SEL_3_0			GENMASK(12, 9)
+	#define PHY_CTRL_R20_USB2_EDGE_DRV_EN			BIT(13)
+	#define PHY_CTRL_R20_USB2_EDGE_DRV_TRIM_1_0		GENMASK(15, 14)
+	#define PHY_CTRL_R20_USB2_BGR_ADJ_4_0			GENMASK(20, 16)
+	#define PHY_CTRL_R20_USB2_BGR_START			BIT(21)
+	#define PHY_CTRL_R20_USB2_BGR_VREF_4_0			GENMASK(28, 24)
+	#define PHY_CTRL_R20_USB2_BGR_DBG_1_0			GENMASK(30, 29)
+	#define PHY_CTRL_R20_BYPASS_CAL_DONE_R5			BIT(31)
+
 #define PHY_CTRL_R21						0x54
+	#define PHY_CTRL_R21_USB2_BGR_FORCE			BIT(0)
+	#define PHY_CTRL_R21_USB2_CAL_ACK_EN			BIT(1)
+	#define PHY_CTRL_R21_USB2_OTG_ACA_EN			BIT(2)
+	#define PHY_CTRL_R21_USB2_TX_STRG_PD			BIT(3)
+	#define PHY_CTRL_R21_USB2_OTG_ACA_TRIM_1_0		GENMASK(5, 4)
+	#define PHY_CTRL_R21_BYPASS_UTMI_CNTR			GENMASK(15, 6)
+	#define PHY_CTRL_R21_BYPASS_UTMI_REG			GENMASK(25, 20)
+
 #define PHY_CTRL_R22						0x58
 #define PHY_CTRL_R23						0x5c
 
 #define RESET_COMPLETE_TIME					1000
 #define PLL_RESET_COMPLETE_TIME					100
 
+enum meson_soc_id {
+	MESON_SOC_A1,
+	MESON_SOC_G12A,
+};
+
 struct phy_meson_g12a_usb2_priv {
 	struct regmap		*regmap;
 #if CONFIG_IS_ENABLED(CLK)
 	struct clk		clk;
 #endif
 	struct reset_ctl	reset;
+#if CONFIG_IS_ENABLED(POWER_DOMAIN)
+	struct power_domain pwrdm;
+#endif
+	int soc_id;
 };
 
 static int phy_meson_g12a_usb2_init(struct phy *phy)
 {
 	struct udevice *dev = phy->dev;
 	struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
+	u32 value;
 	int ret;
 
+#if CONFIG_IS_ENABLED(CLK)
+	ret = clk_enable(&priv->clk);
+	if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
+		pr_err("failed to enable PHY clock\n");
+		return ret;
+	}
+#endif
+
 	ret = reset_assert(&priv->reset);
 	udelay(1);
 	ret |= reset_deassert(&priv->reset);
@@ -79,25 +192,91 @@
 	regmap_update_bits(priv->regmap, PHY_CTRL_R21, BIT(2), 0);
 
 	/* PLL Setup : 24MHz * 20 / 1 = 480MHz */
-	regmap_write(priv->regmap, PHY_CTRL_R16, 0x39400414);
-	regmap_write(priv->regmap, PHY_CTRL_R17, 0x927e0000);
-	regmap_write(priv->regmap, PHY_CTRL_R18, 0xac5f49e5);
+	regmap_write(priv->regmap, PHY_CTRL_R16,
+		FIELD_PREP(PHY_CTRL_R16_MPLL_M, 20) |
+		FIELD_PREP(PHY_CTRL_R16_MPLL_N, 1) |
+		PHY_CTRL_R16_MPLL_LOAD |
+		FIELD_PREP(PHY_CTRL_R16_MPLL_LOCK_LONG, 1) |
+		PHY_CTRL_R16_MPLL_FAST_LOCK |
+		PHY_CTRL_R16_MPLL_EN |
+		PHY_CTRL_R16_MPLL_RESET);
+
+	regmap_write(priv->regmap, PHY_CTRL_R17,
+		FIELD_PREP(PHY_CTRL_R17_MPLL_FRAC_IN, 0) |
+		FIELD_PREP(PHY_CTRL_R17_MPLL_LAMBDA1, 7) |
+		FIELD_PREP(PHY_CTRL_R17_MPLL_LAMBDA0, 7) |
+		FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT2, 2) |
+		FIELD_PREP(PHY_CTRL_R17_MPLL_FILTER_PVT1, 9));
+
+	value = FIELD_PREP(PHY_CTRL_R18_MPLL_LKW_SEL, 1) |
+		FIELD_PREP(PHY_CTRL_R18_MPLL_LK_W, 9) |
+		FIELD_PREP(PHY_CTRL_R18_MPLL_LK_S, 0x27) |
+		FIELD_PREP(PHY_CTRL_R18_MPLL_PFD_GAIN, 1) |
+		FIELD_PREP(PHY_CTRL_R18_MPLL_ROU, 7) |
+		FIELD_PREP(PHY_CTRL_R18_MPLL_DATA_SEL, 3) |
+		FIELD_PREP(PHY_CTRL_R18_MPLL_BIAS_ADJ, 1) |
+		FIELD_PREP(PHY_CTRL_R18_MPLL_BB_MODE, 0) |
+		FIELD_PREP(PHY_CTRL_R18_MPLL_ALPHA, 3) |
+		FIELD_PREP(PHY_CTRL_R18_MPLL_ADJ_LDO, 1) |
+		PHY_CTRL_R18_MPLL_ACG_RANGE;
+
+	if (priv->soc_id == MESON_SOC_A1)
+		value |= PHY_CTRL_R18_MPLL_DCO_CLK_SEL;
+
+	regmap_write(priv->regmap, PHY_CTRL_R18, value);
 
 	udelay(PLL_RESET_COMPLETE_TIME);
 
 	/* UnReset PLL */
-	regmap_write(priv->regmap, PHY_CTRL_R16, 0x19400414);
+	regmap_write(priv->regmap, PHY_CTRL_R16,
+		FIELD_PREP(PHY_CTRL_R16_MPLL_M, 20) |
+		FIELD_PREP(PHY_CTRL_R16_MPLL_N, 1) |
+		PHY_CTRL_R16_MPLL_LOAD |
+		FIELD_PREP(PHY_CTRL_R16_MPLL_LOCK_LONG, 1) |
+		PHY_CTRL_R16_MPLL_FAST_LOCK |
+		PHY_CTRL_R16_MPLL_EN);
 
 	/* PHY Tuning */
-	regmap_write(priv->regmap, PHY_CTRL_R20, 0xfe18);
-	regmap_write(priv->regmap, PHY_CTRL_R4, 0x8000fff);
+	regmap_write(priv->regmap, PHY_CTRL_R20,
+		FIELD_PREP(PHY_CTRL_R20_USB2_OTG_VBUS_TRIM_2_0, 4) |
+		PHY_CTRL_R20_USB2_OTG_VBUSDET_EN |
+		FIELD_PREP(PHY_CTRL_R20_USB2_DMON_SEL_3_0, 15) |
+		PHY_CTRL_R20_USB2_EDGE_DRV_EN |
+		FIELD_PREP(PHY_CTRL_R20_USB2_EDGE_DRV_TRIM_1_0, 3) |
+		FIELD_PREP(PHY_CTRL_R20_USB2_BGR_ADJ_4_0, 0) |
+		FIELD_PREP(PHY_CTRL_R20_USB2_BGR_VREF_4_0, 0) |
+		FIELD_PREP(PHY_CTRL_R20_USB2_BGR_DBG_1_0, 0));
+
+	if (priv->soc_id == MESON_SOC_G12A)
+		regmap_write(priv->regmap, PHY_CTRL_R4,
+			FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_7_0, 0xf) |
+			FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_15_8, 0xf) |
+			FIELD_PREP(PHY_CTRL_R4_CALIB_CODE_23_16, 0xf) |
+			PHY_CTRL_R4_TEST_BYPASS_MODE_EN |
+			FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_1_0, 0) |
+			FIELD_PREP(PHY_CTRL_R4_I_C2L_BIAS_TRIM_3_2, 0));
+	else if (priv->soc_id == MESON_SOC_A1)
+		regmap_write(priv->regmap, PHY_CTRL_R21,
+			PHY_CTRL_R21_USB2_CAL_ACK_EN |
+			PHY_CTRL_R21_USB2_TX_STRG_PD |
+			FIELD_PREP(PHY_CTRL_R21_USB2_OTG_ACA_TRIM_1_0, 2));
 
 	/* Tuning Disconnect Threshold */
-	regmap_write(priv->regmap, PHY_CTRL_R3, 0x34);
+	regmap_write(priv->regmap, PHY_CTRL_R3,
+		FIELD_PREP(PHY_CTRL_R3_SQUELCH_REF, 0) |
+		FIELD_PREP(PHY_CTRL_R3_HSDIC_REF, 1) |
+		FIELD_PREP(PHY_CTRL_R3_DISC_THRESH, 3));
 
 	/* Analog Settings */
-	regmap_write(priv->regmap, PHY_CTRL_R14, 0);
-	regmap_write(priv->regmap, PHY_CTRL_R13, 0x78000);
+	if (priv->soc_id == MESON_SOC_G12A) {
+		regmap_write(priv->regmap, PHY_CTRL_R14, 0);
+		regmap_write(priv->regmap, PHY_CTRL_R13,
+			PHY_CTRL_R13_UPDATE_PMA_SIGNALS |
+			FIELD_PREP(PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET, 7));
+	} else if (priv->soc_id == MESON_SOC_A1) {
+		regmap_write(priv->regmap, PHY_CTRL_R13,
+			FIELD_PREP(PHY_CTRL_R13_MIN_COUNT_FOR_SYNC_DET, 7));
+	}
 
 	return 0;
 }
@@ -108,6 +287,10 @@
 	struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
 	int ret;
 
+#if CONFIG_IS_ENABLED(CLK)
+	clk_disable(&priv->clk);
+#endif
+
 	ret = reset_assert(&priv->reset);
 	if (ret)
 		return ret;
@@ -125,6 +308,8 @@
 	struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev);
 	int ret;
 
+	priv->soc_id = (enum meson_soc_id)dev_get_driver_data(dev);
+
 	ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
 	if (ret)
 		return ret;
@@ -141,24 +326,40 @@
 		return ret;
 	}
 
+#if CONFIG_IS_ENABLED(POWER_DOMAIN)
+	ret = power_domain_get(dev, &priv->pwrdm);
+	if (ret < 0 && ret != -ENODEV) {
+		pr_err("failed to get power domain\n");
+		return ret;
+	}
+
+	if (ret != -ENODEV) {
+		ret = power_domain_on(&priv->pwrdm);
+		if (ret < 0) {
+			pr_err("failed to enable power domain\n");
+			return ret;
+		}
+	}
+#endif
+
 #if CONFIG_IS_ENABLED(CLK)
 	ret = clk_get_by_index(dev, 0, &priv->clk);
 	if (ret < 0)
 		return ret;
-
-	ret = clk_enable(&priv->clk);
-	if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
-		pr_err("failed to enable PHY clock\n");
-		clk_free(&priv->clk);
-		return ret;
-	}
 #endif
 
 	return 0;
 }
 
 static const struct udevice_id meson_g12a_usb2_phy_ids[] = {
-	{ .compatible = "amlogic,g12a-usb2-phy" },
+	{
+		.compatible = "amlogic,g12a-usb2-phy",
+		.data = (ulong)MESON_SOC_G12A,
+	},
+	{
+		.compatible = "amlogic,a1-usb2-phy",
+		.data = (ulong)MESON_SOC_A1,
+	},
 	{ }
 };
 
diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
index 64bc696..9d0c8b3 100644
--- a/drivers/reset/reset-meson.c
+++ b/drivers/reset/reset-meson.c
@@ -13,18 +13,26 @@
 #include <reset-uclass.h>
 #include <regmap.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 
-#define REG_COUNT	8
 #define BITS_PER_REG	32
-#define LEVEL_OFFSET	0x7c
+
+struct meson_reset_drvdata {
+	unsigned int reg_count;
+	unsigned int level_offset;
+};
 
 struct meson_reset_priv {
 	struct regmap *regmap;
+	struct meson_reset_drvdata *drvdata;
 };
 
 static int meson_reset_request(struct reset_ctl *reset_ctl)
 {
-	if (reset_ctl->id > (REG_COUNT * BITS_PER_REG))
+	struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+	struct meson_reset_drvdata *data = priv->drvdata;
+
+	if (reset_ctl->id > (data->reg_count * BITS_PER_REG))
 		return -EINVAL;
 
 	return 0;
@@ -33,9 +41,10 @@
 static int meson_reset_level(struct reset_ctl *reset_ctl, bool assert)
 {
 	struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+	struct meson_reset_drvdata *data = priv->drvdata;
 	uint bank = reset_ctl->id / BITS_PER_REG;
 	uint offset = reset_ctl->id % BITS_PER_REG;
-	uint reg_offset = LEVEL_OFFSET + (bank << 2);
+	uint reg_offset = data->level_offset + (bank << 2);
 	uint val;
 
 	regmap_read(priv->regmap, reg_offset, &val);
@@ -64,15 +73,36 @@
 	.rst_deassert = meson_reset_deassert,
 };
 
+static const struct meson_reset_drvdata meson_gxbb_data = {
+	.reg_count = 8,
+	.level_offset = 0x7c,
+};
+
+static const struct meson_reset_drvdata meson_a1_data = {
+	.reg_count = 3,
+	.level_offset = 0x40,
+};
+
 static const struct udevice_id meson_reset_ids[] = {
-	{ .compatible = "amlogic,meson-gxbb-reset" },
-	{ .compatible = "amlogic,meson-axg-reset" },
+	{
+		.compatible = "amlogic,meson-gxbb-reset",
+		.data = (ulong)&meson_gxbb_data,
+	},
+	{
+		.compatible = "amlogic,meson-axg-reset",
+		.data = (ulong)&meson_gxbb_data,
+	},
+	{
+		.compatible = "amlogic,meson-a1-reset",
+		.data = (ulong)&meson_a1_data,
+	},
 	{ }
 };
 
 static int meson_reset_probe(struct udevice *dev)
 {
 	struct meson_reset_priv *priv = dev_get_priv(dev);
+	priv->drvdata = (struct meson_reset_drvdata *)dev_get_driver_data(dev);
 
 	return regmap_init_mem(dev_ofnode(dev), &priv->regmap);
 }
diff --git a/drivers/rng/meson-rng.c b/drivers/rng/meson-rng.c
index e0a1e8c..fd2988e 100644
--- a/drivers/rng/meson-rng.c
+++ b/drivers/rng/meson-rng.c
@@ -10,10 +10,23 @@
 #include <dm.h>
 #include <rng.h>
 #include <asm/io.h>
+#include <linux/iopoll.h>
+
+#define RNG_DATA	0x00
+#define RNG_S4_DATA	0x08
+#define RNG_S4_CFG	0x00
+
+#define RUN_BIT		BIT(0)
+#define SEED_READY_STS_BIT	BIT(31)
+
+struct meson_rng_priv {
+	u32 (*read)(fdt_addr_t base);
+};
 
 struct meson_rng_plat {
 	fdt_addr_t base;
 	struct clk clk;
+	struct meson_rng_priv *priv;
 };
 
 /**
@@ -27,10 +40,11 @@
 static int meson_rng_read(struct udevice *dev, void *data, size_t len)
 {
 	struct meson_rng_plat *pdata = dev_get_plat(dev);
+	struct meson_rng_priv *priv = pdata->priv;
 	char *buffer = (char *)data;
 
 	while (len) {
-		u32 rand = readl(pdata->base);
+		u32 rand = priv->read(pdata->base);
 		size_t step;
 
 		if (len >= 4)
@@ -44,6 +58,47 @@
 	return 0;
 }
 
+static int meson_rng_wait_status(void __iomem *cfg_addr, int bit)
+{
+	u32 status = 0;
+	int ret;
+
+	ret = readl_relaxed_poll_timeout(cfg_addr,
+					 status, !(status & bit),
+					 10000);
+	if (ret)
+		return -EBUSY;
+
+	return 0;
+}
+
+static u32 meson_common_rng_read(fdt_addr_t base)
+{
+	return readl(base);
+}
+
+static u32 meson_s4_rng_read(fdt_addr_t base)
+{
+	void __iomem *cfg_addr = (void *)base + RNG_S4_CFG;
+	int err;
+
+	writel_relaxed(readl_relaxed(cfg_addr) | SEED_READY_STS_BIT, cfg_addr);
+
+	err = meson_rng_wait_status(cfg_addr, SEED_READY_STS_BIT);
+	if (err) {
+		pr_err("Seed isn't ready, try again\n");
+		return err;
+	}
+
+	err = meson_rng_wait_status(cfg_addr, RUN_BIT);
+	if (err) {
+		pr_err("Can't get random number, try again\n");
+		return err;
+	}
+
+	return readl_relaxed(base + RNG_S4_DATA);
+}
+
 /**
  * meson_rng_probe() - probe rng device
  *
@@ -59,6 +114,8 @@
 	if (err)
 		return err;
 
+	pdata->priv = (struct meson_rng_priv *)dev_get_driver_data(dev);
+
 	return 0;
 }
 
@@ -102,9 +159,22 @@
 	.read = meson_rng_read,
 };
 
+static const struct meson_rng_priv meson_rng_priv = {
+	.read = meson_common_rng_read,
+};
+
+static const struct meson_rng_priv meson_rng_priv_s4 = {
+	.read = meson_s4_rng_read,
+};
+
 static const struct udevice_id meson_rng_match[] = {
 	{
 		.compatible = "amlogic,meson-rng",
+		.data = (ulong)&meson_rng_priv,
+	},
+	{
+		.compatible = "amlogic,meson-s4-rng",
+		.data = (ulong)&meson_rng_priv_s4,
 	},
 	{},
 };
diff --git a/drivers/sm/Kconfig b/drivers/sm/Kconfig
new file mode 100644
index 0000000..f098727
--- /dev/null
+++ b/drivers/sm/Kconfig
@@ -0,0 +1,9 @@
+config SM
+	bool "Enable Secure Monitor driver support"
+
+config MESON_SM
+	bool "Amlogic Secure Monitor driver"
+	select SM
+	default n
+	help
+	  Say y here to enable the Amlogic secure monitor driver.
diff --git a/drivers/sm/Makefile b/drivers/sm/Makefile
new file mode 100644
index 0000000..da81ee8
--- /dev/null
+++ b/drivers/sm/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += sm-uclass.o
+obj-$(CONFIG_SANDBOX) += sandbox-sm.o
+obj-$(CONFIG_MESON_SM) += meson-sm.o
diff --git a/drivers/sm/meson-sm.c b/drivers/sm/meson-sm.c
new file mode 100644
index 0000000..25adaf4
--- /dev/null
+++ b/drivers/sm/meson-sm.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov <avromanov@salutedevices.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <regmap.h>
+#include <sm.h>
+#include <sm-uclass.h>
+#include <stdlib.h>
+#include <syscon.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <meson/sm.h>
+#include <linux/bitfield.h>
+#include <linux/err.h>
+#include <linux/sizes.h>
+
+struct meson_sm_cmd {
+	u32 smc_id;
+};
+
+#define SET_CMD(index, id)	\
+	[index] = {		\
+		.smc_id = (id),	\
+	}
+
+struct meson_sm_data {
+	u32 cmd_get_shmem_in;
+	u32 cmd_get_shmem_out;
+	unsigned int shmem_size;
+	struct meson_sm_cmd cmd[];
+};
+
+struct meson_sm_priv {
+	void *sm_shmem_in;
+	void *sm_shmem_out;
+	const struct meson_sm_data *data;
+};
+
+static unsigned long __meson_sm_call(u32 cmd, const struct pt_regs *args)
+{
+	struct pt_regs r = *args;
+
+	r.regs[0] = cmd;
+	smc_call(&r);
+
+	return r.regs[0];
+};
+
+static u32 meson_sm_get_cmd(const struct meson_sm_data *data,
+			    u32 cmd_index)
+{
+	struct meson_sm_cmd cmd;
+
+	if (cmd_index >= MESON_SMC_CMD_COUNT)
+		return 0;
+
+	cmd = data->cmd[cmd_index];
+	return cmd.smc_id;
+}
+
+static int meson_sm_call(struct udevice *dev, u32 cmd_index, s32 *retval,
+			 struct pt_regs *args)
+{
+	struct meson_sm_priv *priv = dev_get_priv(dev);
+	u32 cmd, ret;
+
+	cmd = meson_sm_get_cmd(priv->data, cmd_index);
+	if (!cmd)
+		return -ENOENT;
+
+	ret = __meson_sm_call(cmd, args);
+	if (retval)
+		*retval = ret;
+
+	return 0;
+}
+
+static int meson_sm_call_read(struct udevice *dev, void *buffer, size_t size,
+			      u32 cmd_index, struct pt_regs *args)
+{
+	struct meson_sm_priv *priv = dev_get_priv(dev);
+	s32 nbytes;
+	int ret;
+
+	if (!buffer || size > priv->data->shmem_size)
+		return -EINVAL;
+
+	ret = meson_sm_call(dev, cmd_index, &nbytes, args);
+	if (ret)
+		return ret;
+
+	if (nbytes < 0 || nbytes > size)
+		return -ENOBUFS;
+
+	/* In some cases (for example GET_CHIP_ID command),
+	 * SMC doesn't return the number of bytes read, even
+	 * though the bytes were actually read into sm_shmem_out.
+	 * So this check is needed.
+	 */
+	ret = nbytes;
+	if (!nbytes)
+		nbytes = size;
+
+	memcpy(buffer, priv->sm_shmem_out, nbytes);
+
+	return ret;
+}
+
+static int meson_sm_call_write(struct udevice *dev, void *buffer, size_t size,
+			       u32 cmd_index, struct pt_regs *args)
+{
+	struct meson_sm_priv *priv = dev_get_priv(dev);
+	s32 nbytes;
+	int ret;
+
+	if (!buffer || size > priv->data->shmem_size)
+		return -EINVAL;
+
+	memcpy(priv->sm_shmem_in, buffer, size);
+
+	ret = meson_sm_call(dev, cmd_index, &nbytes, args);
+	if (ret)
+		return ret;
+
+	if (nbytes <= 0 || nbytes > size)
+		return -EIO;
+
+	return nbytes;
+}
+
+static int meson_sm_probe(struct udevice *dev)
+{
+	struct meson_sm_priv *priv = dev_get_priv(dev);
+	struct pt_regs regs = { 0 };
+
+	priv->data = (struct meson_sm_data *)dev_get_driver_data(dev);
+	if (!priv->data)
+		return -EINVAL;
+
+	priv->sm_shmem_in =
+		(void *)__meson_sm_call(priv->data->cmd_get_shmem_in, &regs);
+
+	if (!priv->sm_shmem_in)
+		return -ENOMEM;
+
+	priv->sm_shmem_out =
+		(void *)__meson_sm_call(priv->data->cmd_get_shmem_out, &regs);
+
+	if (!priv->sm_shmem_out)
+		return -ENOMEM;
+
+	pr_debug("meson sm driver probed\n"
+		 "shmem_in addr: 0x%p, shmem_out addr: 0x%p\n",
+		 priv->sm_shmem_in,
+		 priv->sm_shmem_out);
+
+	return 0;
+}
+
+static const struct meson_sm_data meson_sm_gxbb_data = {
+	.cmd_get_shmem_in  = 0x82000020,
+	.cmd_get_shmem_out = 0x82000021,
+	.shmem_size = SZ_4K,
+	.cmd = {
+		SET_CMD(MESON_SMC_CMD_EFUSE_READ,  0x82000030),
+		SET_CMD(MESON_SMC_CMD_EFUSE_WRITE, 0x82000031),
+		SET_CMD(MESON_SMC_CMD_CHIP_ID_GET, 0x82000044),
+		SET_CMD(MESON_SMC_CMD_PWRDM_SET,   0x82000093),
+	},
+};
+
+static const struct udevice_id meson_sm_ids[] = {
+	{
+		.compatible = "amlogic,meson-gxbb-sm",
+		.data = (ulong)&meson_sm_gxbb_data,
+	},
+	{ }
+};
+
+static const struct sm_ops sm_ops = {
+	.sm_call = meson_sm_call,
+	.sm_call_read = meson_sm_call_read,
+	.sm_call_write = meson_sm_call_write,
+};
+
+U_BOOT_DRIVER(meson_sm) = {
+	.name = "meson_sm",
+	.id = UCLASS_SM,
+	.of_match = meson_sm_ids,
+	.probe = meson_sm_probe,
+	.priv_auto = sizeof(struct meson_sm_priv),
+	.ops = &sm_ops,
+};
diff --git a/drivers/sm/sandbox-sm.c b/drivers/sm/sandbox-sm.c
new file mode 100644
index 0000000..109ddb2
--- /dev/null
+++ b/drivers/sm/sandbox-sm.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov <avromanov@salutedevices.com>
+ */
+
+#include <common.h>
+#include <sm.h>
+#include <sm-uclass.h>
+#include <sandbox-sm.h>
+#include <asm/ptrace.h>
+#include <dm/device.h>
+#include <linux/sizes.h>
+
+static u8 test_buffer[SZ_4K];
+
+static int sandbox_sm_call(struct udevice *dev, u32 cmd_index, s32 *smc_ret,
+			   struct pt_regs *args)
+{
+	if (cmd_index >= SANDBOX_SMC_CMD_COUNT)
+		return -EINVAL;
+
+	if (smc_ret)
+		*smc_ret = 0;
+
+	return 0;
+}
+
+static int sandbox_sm_call_read(struct udevice *dev, void *buffer, size_t size,
+				u32 cmd_index, struct pt_regs *args)
+{
+	if (cmd_index >= SANDBOX_SMC_CMD_COUNT || !buffer)
+		return -EINVAL;
+
+	if (size > sizeof(test_buffer))
+		return -EINVAL;
+
+	memcpy(buffer, test_buffer, size);
+
+	return size;
+}
+
+static int sandbox_sm_call_write(struct udevice *dev, void *buffer, size_t size,
+				 u32 cmd_index, struct pt_regs *args)
+{
+	if (cmd_index >= SANDBOX_SMC_CMD_COUNT || !buffer)
+		return -EINVAL;
+
+	if (size > sizeof(test_buffer))
+		return -EINVAL;
+
+	memcpy(test_buffer, buffer, size);
+
+	return size;
+}
+
+static const struct udevice_id sandbox_sm_ids[] = {
+	{
+		.compatible = "sandbox,sm",
+	},
+	{},
+};
+
+static const struct sm_ops sandbox_sm_ops = {
+	.sm_call = sandbox_sm_call,
+	.sm_call_read = sandbox_sm_call_read,
+	.sm_call_write = sandbox_sm_call_write,
+};
+
+U_BOOT_DRIVER(sm) = {
+	.name = "sm",
+	.id = UCLASS_SM,
+	.of_match = sandbox_sm_ids,
+	.ops = &sandbox_sm_ops,
+};
diff --git a/drivers/sm/sm-uclass.c b/drivers/sm/sm-uclass.c
new file mode 100644
index 0000000..6a8b702
--- /dev/null
+++ b/drivers/sm/sm-uclass.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov <avromanov@salutedevices.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <sm-uclass.h>
+
+static const struct sm_ops *get_sm_ops(struct udevice *dev)
+{
+	return (const struct sm_ops *)dev->driver->ops;
+}
+
+int sm_call(struct udevice *dev, u32 cmd, s32 *ret, struct pt_regs *args)
+{
+	const struct sm_ops *ops = get_sm_ops(dev);
+
+	if (ops->sm_call)
+		return ops->sm_call(dev, cmd, ret, args);
+
+	return -ENOSYS;
+}
+
+int sm_call_read(struct udevice *dev, void *buffer, size_t size,
+		 u32 cmd, struct pt_regs *args)
+{
+	const struct sm_ops *ops = get_sm_ops(dev);
+
+	if (ops->sm_call_read)
+		return ops->sm_call_read(dev, buffer, size, cmd,
+					 args);
+
+	return -ENOSYS;
+}
+
+int sm_call_write(struct udevice *dev, void *buffer, size_t size,
+		   u32 cmd, struct pt_regs *args)
+{
+	const struct sm_ops *ops = get_sm_ops(dev);
+
+	if (ops->sm_call_write)
+		return ops->sm_call_write(dev, buffer, size, cmd,
+					  args);
+
+	return -ENOSYS;
+}
+
+UCLASS_DRIVER(sm) = {
+	.name           = "sm",
+	.id             = UCLASS_SM,
+};
diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
index dc5a976..e0356e6 100644
--- a/drivers/usb/dwc3/dwc3-meson-g12a.c
+++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
@@ -29,6 +29,7 @@
 #include <linux/bitfield.h>
 #include <linux/bitops.h>
 #include <linux/compat.h>
+#include <dt-bindings/clock/amlogic,a1-peripherals-clkc.h>
 
 /* USB2 Ports Control Registers */
 
@@ -103,10 +104,22 @@
 	PHY_COUNT,
 };
 
-static const char *phy_names[PHY_COUNT] = {
+static const char *const dwc3_meson_g12a_phy_names[] = {
 	"usb2-phy0", "usb2-phy1", "usb3-phy0",
 };
 
+static const char *const dwc3_meson_a1_phy_names[] = {
+	"usb2-phy0", "usb2-phy1"
+};
+
+struct dwc3_meson_g12a;
+
+struct dwc3_meson_g12a_drvdata {
+	const char *const *phy_names;
+	unsigned int phy_cnt;
+	int (*clk_init)(struct dwc3_meson_g12a *priv);
+};
+
 struct dwc3_meson_g12a {
 	struct udevice		*dev;
 	struct regmap           *regmap;
@@ -120,6 +133,7 @@
 #if CONFIG_IS_ENABLED(DM_REGULATOR)
 	struct udevice		*vbus_supply;
 #endif
+	struct dwc3_meson_g12a_drvdata *drvdata;
 };
 
 #define U2P_REG_SIZE						0x20
@@ -294,10 +308,11 @@
 
 static int dwc3_meson_g12a_get_phys(struct dwc3_meson_g12a *priv)
 {
+	struct dwc3_meson_g12a_drvdata *data = priv->drvdata;
 	int i, ret;
 
-	for (i = 0 ; i < PHY_COUNT ; ++i) {
-		ret = generic_phy_get_by_name(priv->dev, phy_names[i],
+	for (i = 0 ; i < data->phy_cnt; ++i) {
+		ret = generic_phy_get_by_name(priv->dev, data->phy_names[i],
 					      &priv->phys[i]);
 		if (ret == -ENOENT || ret == -ENODATA)
 			continue;
@@ -355,18 +370,36 @@
 	return 0;
 }
 
+static int dwc3_meson_a1_clk_init(struct dwc3_meson_g12a *priv)
+{
+	int ret;
+
+	ret = clk_get_by_name(priv->dev, "usb_bus", &priv->clk);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(&priv->clk);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static int dwc3_meson_g12a_probe(struct udevice *dev)
 {
 	struct dwc3_meson_g12a *priv = dev_get_plat(dev);
+	struct dwc3_meson_g12a_drvdata *data =
+		(struct dwc3_meson_g12a_drvdata *)dev_get_driver_data(dev);
 	int ret, i;
 
+	priv->drvdata = data;
 	priv->dev = dev;
 
 	ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
 	if (ret)
 		return ret;
 
-	ret = dwc3_meson_g12a_clk_init(priv);
+	ret = data->clk_init(priv);
 	if (ret)
 		return ret;
 
@@ -399,7 +432,7 @@
 	if (ret)
 		return ret;
 
-	for (i = 0 ; i < PHY_COUNT ; ++i) {
+	for (i = 0 ; i < data->phy_cnt; ++i) {
 		if (!priv->phys[i].dev)
 			continue;
 
@@ -408,7 +441,7 @@
 			goto err_phy_init;
 	}
 
-	for (i = 0; i < PHY_COUNT; ++i) {
+	for (i = 0; i < data->phy_cnt; ++i) {
 		if (!priv->phys[i].dev)
 			continue;
 
@@ -420,7 +453,7 @@
 	return 0;
 
 err_phy_init:
-	for (i = 0 ; i < PHY_COUNT ; ++i) {
+	for (i = 0 ; i < data->phy_cnt ; ++i) {
 		if (!priv->phys[i].dev)
 			continue;
 
@@ -433,20 +466,21 @@
 static int dwc3_meson_g12a_remove(struct udevice *dev)
 {
 	struct dwc3_meson_g12a *priv = dev_get_plat(dev);
+	struct dwc3_meson_g12a_drvdata *data = priv->drvdata;
 	int i;
 
 	reset_release_all(&priv->reset, 1);
 
 	clk_release_all(&priv->clk, 1);
 
-	for (i = 0; i < PHY_COUNT; ++i) {
+	for (i = 0; i < data->phy_cnt; ++i) {
 		if (!priv->phys[i].dev)
 			continue;
 
 		 generic_phy_power_off(&priv->phys[i]);
 	}
 
-	for (i = 0 ; i < PHY_COUNT ; ++i) {
+	for (i = 0 ; i < data->phy_cnt; ++i) {
 		if (!priv->phys[i].dev)
 			continue;
 
@@ -456,11 +490,26 @@
 	return dm_scan_fdt_dev(dev);
 }
 
+static const struct dwc3_meson_g12a_drvdata meson_g12a_drvdata = {
+	.phy_names = dwc3_meson_g12a_phy_names,
+	.phy_cnt = ARRAY_SIZE(dwc3_meson_g12a_phy_names),
+	.clk_init = dwc3_meson_g12a_clk_init,
+};
+
+static const struct dwc3_meson_g12a_drvdata meson_a1_drvdata = {
+	.phy_names = dwc3_meson_a1_phy_names,
+	.phy_cnt = ARRAY_SIZE(dwc3_meson_a1_phy_names),
+	.clk_init = dwc3_meson_a1_clk_init,
+};
+
 static int dwc3_meson_g12a_child_pre_probe(struct udevice *dev)
 {
 	if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-g12a-usb"))
 		return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_PERIPHERAL);
 
+	if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-a1-usb"))
+		return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_PERIPHERAL);
+
 	return 0;
 }
 
@@ -469,11 +518,21 @@
 	if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-g12a-usb"))
 		return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_HOST);
 
+	if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-a1-usb"))
+		return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_HOST);
+
 	return 0;
 }
 
 static const struct udevice_id dwc3_meson_g12a_ids[] = {
-	{ .compatible = "amlogic,meson-g12a-usb-ctrl" },
+	{
+		.compatible = "amlogic,meson-g12a-usb-ctrl",
+		.data = (ulong)&meson_g12a_drvdata,
+	},
+	{
+		.compatible = "amlogic,meson-a1-usb-ctrl",
+		.data = (ulong)&meson_a1_drvdata,
+	},
 	{ }
 };
 
diff --git a/include/command.h b/include/command.h
index 1c4ec42..6262365 100644
--- a/include/command.h
+++ b/include/command.h
@@ -328,6 +328,9 @@
 # define _CMD_HELP(x)
 #endif
 
+#define U_BOOT_LONGHELP(_cmdname, text)					\
+	static __maybe_unused const char _cmdname##_help_text[] = text
+
 #define U_BOOT_SUBCMDS_DO_CMD(_cmdname)					\
 	static int do_##_cmdname(struct cmd_tbl *cmdtp, int flag,	\
 				 int argc, char *const argv[],		\
diff --git a/include/configs/ds116.h b/include/configs/ds116.h
index 031f4f6..0883ec4 100644
--- a/include/configs/ds116.h
+++ b/include/configs/ds116.h
@@ -20,15 +20,8 @@
  */
 #include "mv-common.h"
 
-/* Include the common distro boot environment */
 #ifndef CONFIG_SPL_BUILD
 
-#define BOOT_TARGET_DEVICES(func) \
-	func(USB, usb, 0) \
-	func(SCSI, scsi, 0) \
-	func(PXE, pxe, na) \
-	func(DHCP, dhcp, na)
-
 #define KERNEL_ADDR_R	__stringify(0x1000000)
 #define FDT_ADDR_R	__stringify(0x2000000)
 #define RAMDISK_ADDR_R	__stringify(0x2200000)
@@ -42,14 +35,11 @@
 	"scriptaddr=" SCRIPT_ADDR_R "\0" \
 	"pxefile_addr_r=" PXEFILE_ADDR_R "\0"
 
-#include <config_distro_bootcmd.h>
-
 #define CFG_EXTRA_ENV_SETTINGS \
 	RELOCATION_LIMITS_ENV_SETTINGS \
 	LOAD_ADDRESS_ENV_SETTINGS \
 	"fdtfile=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
-	"console=ttyS0,115200\0" \
-	BOOTENV
+	"console=ttyS0,115200\0"
 
 #endif /* CONFIG_SPL_BUILD */
 
diff --git a/include/configs/n2350.h b/include/configs/n2350.h
index 92b2270..d8a9814 100644
--- a/include/configs/n2350.h
+++ b/include/configs/n2350.h
@@ -20,15 +20,8 @@
  */
 #include "mv-common.h"
 
-/* Include the common distro boot environment */
 #ifndef CONFIG_SPL_BUILD
 
-#define BOOT_TARGET_DEVICES(func) \
-	func(SCSI, scsi, 0) \
-	func(USB, usb, 0) \
-	func(PXE, pxe, na) \
-	func(DHCP, dhcp, na)
-
 #define KERNEL_ADDR_R	__stringify(0x1000000)
 #define FDT_ADDR_R	__stringify(0x2000000)
 #define RAMDISK_ADDR_R	__stringify(0x2200000)
@@ -42,14 +35,11 @@
 	"scriptaddr=" SCRIPT_ADDR_R "\0" \
 	"pxefile_addr_r=" PXEFILE_ADDR_R "\0"
 
-#include <config_distro_bootcmd.h>
-
 #define CFG_EXTRA_ENV_SETTINGS \
 	RELOCATION_LIMITS_ENV_SETTINGS \
 	LOAD_ADDRESS_ENV_SETTINGS \
 	"fdtfile=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
-	"console=ttyS0,115200\0" \
-	BOOTENV
+	"console=ttyS0,115200\0"
 
 #endif /* CONFIG_SPL_BUILD */
 
diff --git a/include/configs/nsa325.h b/include/configs/nsa325.h
new file mode 100644
index 0000000..00a148c
--- /dev/null
+++ b/include/configs/nsa325.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2016-2023 Tony Dinh <mibodhi@gmail.com>
+ * (C) Copyright 2014 Jason Plum <jplum@archlinuxarm.org>
+ *
+ * Based on
+ * Copyright (C) 2012  Peter Schildmann <linux@schildmann.info>
+ *
+ * Based on guruplug.h originally written by
+ * Siddarth Gore <gores@marvell.com>
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ */
+
+#ifndef _CONFIG_NSA325_H
+#define _CONFIG_NSA325_H
+
+#include "mv-common.h"
+
+#define KERNEL_ADDR_R	__stringify(0x800000)
+#define FDT_ADDR_R	__stringify(0x2c00000)
+#define RAMDISK_ADDR_R	__stringify(0x01100000)
+#define SCRIPT_ADDR_R	__stringify(0x200000)
+
+#define LOAD_ADDRESS_ENV_SETTINGS \
+	"kernel_addr_r=" KERNEL_ADDR_R "\0" \
+	"fdt_addr_r=" FDT_ADDR_R "\0" \
+	"ramdisk_addr_r=" RAMDISK_ADDR_R "\0" \
+	"scriptaddr=" SCRIPT_ADDR_R "\0"
+
+#define CFG_EXTRA_ENV_SETTINGS \
+	LOAD_ADDRESS_ENV_SETTINGS \
+	"fdtfile=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
+	"mtdparts=" CONFIG_MTDPARTS_DEFAULT "\0" \
+	"console=ttyS0,115200\0"
+
+#endif /* _CONFIG_NSA325_H */
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index ab31580..a6045f5 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -89,6 +89,7 @@
 	UCLASS_MDIO,		/* MDIO bus */
 	UCLASS_MDIO_MUX,	/* MDIO MUX/switch */
 	UCLASS_MEMORY,		/* Memory Controller device */
+	UCLASS_SM,		/* Secure Monitor driver */
 	UCLASS_MISC,		/* Miscellaneous device */
 	UCLASS_MMC,		/* SD / MMC card or chip */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
diff --git a/include/dt-bindings/clock/amlogic,a1-peripherals-clkc.h b/include/dt-bindings/clock/amlogic,a1-peripherals-clkc.h
new file mode 100644
index 0000000..06f198e
--- /dev/null
+++ b/include/dt-bindings/clock/amlogic,a1-peripherals-clkc.h
@@ -0,0 +1,168 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Jian Hu <jian.hu@amlogic.com>
+ *
+ * Copyright (c) 2023, SberDevices. All Rights Reserved.
+ * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
+ */
+
+#ifndef __A1_PERIPHERALS_CLKC_H
+#define __A1_PERIPHERALS_CLKC_H
+
+#define CLKID_XTAL_IN		0
+#define CLKID_FIXPLL_IN		1
+#define CLKID_USB_PHY_IN	2
+#define CLKID_USB_CTRL_IN	3
+#define CLKID_HIFIPLL_IN	4
+#define CLKID_SYSPLL_IN		5
+#define CLKID_DDS_IN		6
+#define CLKID_SYS		7
+#define CLKID_CLKTREE		8
+#define CLKID_RESET_CTRL	9
+#define CLKID_ANALOG_CTRL	10
+#define CLKID_PWR_CTRL		11
+#define CLKID_PAD_CTRL		12
+#define CLKID_SYS_CTRL		13
+#define CLKID_TEMP_SENSOR	14
+#define CLKID_AM2AXI_DIV	15
+#define CLKID_SPICC_B		16
+#define CLKID_SPICC_A		17
+#define CLKID_MSR		18
+#define CLKID_AUDIO		19
+#define CLKID_JTAG_CTRL		20
+#define CLKID_SARADC_EN		21
+#define CLKID_PWM_EF		22
+#define CLKID_PWM_CD		23
+#define CLKID_PWM_AB		24
+#define CLKID_CEC		25
+#define CLKID_I2C_S		26
+#define CLKID_IR_CTRL		27
+#define CLKID_I2C_M_D		28
+#define CLKID_I2C_M_C		29
+#define CLKID_I2C_M_B		30
+#define CLKID_I2C_M_A		31
+#define CLKID_ACODEC		32
+#define CLKID_OTP		33
+#define CLKID_SD_EMMC_A		34
+#define CLKID_USB_PHY		35
+#define CLKID_USB_CTRL		36
+#define CLKID_SYS_DSPB		37
+#define CLKID_SYS_DSPA		38
+#define CLKID_DMA		39
+#define CLKID_IRQ_CTRL		40
+#define CLKID_NIC		41
+#define CLKID_GIC		42
+#define CLKID_UART_C		43
+#define CLKID_UART_B		44
+#define CLKID_UART_A		45
+#define CLKID_SYS_PSRAM		46
+#define CLKID_RSA		47
+#define CLKID_CORESIGHT		48
+#define CLKID_AM2AXI_VAD	49
+#define CLKID_AUDIO_VAD		50
+#define CLKID_AXI_DMC		51
+#define CLKID_AXI_PSRAM		52
+#define CLKID_RAMB		53
+#define CLKID_RAMA		54
+#define CLKID_AXI_SPIFC		55
+#define CLKID_AXI_NIC		56
+#define CLKID_AXI_DMA		57
+#define CLKID_CPU_CTRL		58
+#define CLKID_ROM		59
+#define CLKID_PROC_I2C		60
+#define CLKID_DSPA_SEL		61
+#define CLKID_DSPB_SEL		62
+#define CLKID_DSPA_EN		63
+#define CLKID_DSPA_EN_NIC	64
+#define CLKID_DSPB_EN		65
+#define CLKID_DSPB_EN_NIC	66
+#define CLKID_RTC		67
+#define CLKID_CECA_32K		68
+#define CLKID_CECB_32K		69
+#define CLKID_24M		70
+#define CLKID_12M		71
+#define CLKID_FCLK_DIV2_DIVN	72
+#define CLKID_GEN		73
+#define CLKID_SARADC_SEL	74
+#define CLKID_SARADC		75
+#define CLKID_PWM_A		76
+#define CLKID_PWM_B		77
+#define CLKID_PWM_C		78
+#define CLKID_PWM_D		79
+#define CLKID_PWM_E		80
+#define CLKID_PWM_F		81
+#define CLKID_SPICC		82
+#define CLKID_TS		83
+#define CLKID_SPIFC		84
+#define CLKID_USB_BUS		85
+#define CLKID_SD_EMMC		86
+#define CLKID_PSRAM		87
+#define CLKID_DMC		88
+#define CLKID_SYS_A_SEL		89
+#define CLKID_SYS_A_DIV		90
+#define CLKID_SYS_A		91
+#define CLKID_SYS_B_SEL		92
+#define CLKID_SYS_B_DIV		93
+#define CLKID_SYS_B		94
+#define CLKID_DSPA_A_SEL	95
+#define CLKID_DSPA_A_DIV	96
+#define CLKID_DSPA_A		97
+#define CLKID_DSPA_B_SEL	98
+#define CLKID_DSPA_B_DIV	99
+#define CLKID_DSPA_B		100
+#define CLKID_DSPB_A_SEL	101
+#define CLKID_DSPB_A_DIV	102
+#define CLKID_DSPB_A		103
+#define CLKID_DSPB_B_SEL	104
+#define CLKID_DSPB_B_DIV	105
+#define CLKID_DSPB_B		106
+#define CLKID_RTC_32K_IN	107
+#define CLKID_RTC_32K_DIV	108
+#define CLKID_RTC_32K_XTAL	109
+#define CLKID_RTC_32K_SEL	110
+#define CLKID_CECB_32K_IN	111
+#define CLKID_CECB_32K_DIV	112
+#define CLKID_CECB_32K_SEL_PRE	113
+#define CLKID_CECB_32K_SEL	114
+#define CLKID_CECA_32K_IN	115
+#define CLKID_CECA_32K_DIV	116
+#define CLKID_CECA_32K_SEL_PRE	117
+#define CLKID_CECA_32K_SEL	118
+#define CLKID_DIV2_PRE		119
+#define CLKID_24M_DIV2		120
+#define CLKID_GEN_SEL		121
+#define CLKID_GEN_DIV		122
+#define CLKID_SARADC_DIV	123
+#define CLKID_PWM_A_SEL		124
+#define CLKID_PWM_A_DIV		125
+#define CLKID_PWM_B_SEL		126
+#define CLKID_PWM_B_DIV		127
+#define CLKID_PWM_C_SEL		128
+#define CLKID_PWM_C_DIV		129
+#define CLKID_PWM_D_SEL		130
+#define CLKID_PWM_D_DIV		131
+#define CLKID_PWM_E_SEL		132
+#define CLKID_PWM_E_DIV		133
+#define CLKID_PWM_F_SEL		134
+#define CLKID_PWM_F_DIV		135
+#define CLKID_SPICC_SEL		136
+#define CLKID_SPICC_DIV		137
+#define CLKID_SPICC_SEL2	138
+#define CLKID_TS_DIV		139
+#define CLKID_SPIFC_SEL		140
+#define CLKID_SPIFC_DIV		141
+#define CLKID_SPIFC_SEL2	142
+#define CLKID_USB_BUS_SEL	143
+#define CLKID_USB_BUS_DIV	144
+#define CLKID_SD_EMMC_SEL	145
+#define CLKID_SD_EMMC_DIV	146
+#define CLKID_SD_EMMC_SEL2	147
+#define CLKID_PSRAM_SEL		148
+#define CLKID_PSRAM_DIV		149
+#define CLKID_PSRAM_SEL2	150
+#define CLKID_DMC_SEL		151
+#define CLKID_DMC_DIV		152
+#define CLKID_DMC_SEL2		153
+
+#endif /* __A1_PERIPHERALS_CLKC_H */
diff --git a/include/dt-bindings/clock/amlogic,a1-pll-clkc.h b/include/dt-bindings/clock/amlogic,a1-pll-clkc.h
new file mode 100644
index 0000000..2b660c0
--- /dev/null
+++ b/include/dt-bindings/clock/amlogic,a1-pll-clkc.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Jian Hu <jian.hu@amlogic.com>
+ *
+ * Copyright (c) 2023, SberDevices. All Rights Reserved.
+ * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
+ */
+
+#ifndef __A1_PLL_CLKC_H
+#define __A1_PLL_CLKC_H
+
+#define CLKID_FIXED_PLL_DCO	0
+#define CLKID_FIXED_PLL		1
+#define CLKID_FCLK_DIV2_DIV	2
+#define CLKID_FCLK_DIV3_DIV	3
+#define CLKID_FCLK_DIV5_DIV	4
+#define CLKID_FCLK_DIV7_DIV	5
+#define CLKID_FCLK_DIV2		6
+#define CLKID_FCLK_DIV3		7
+#define CLKID_FCLK_DIV5		8
+#define CLKID_FCLK_DIV7		9
+#define CLKID_HIFI_PLL		10
+
+#endif /* __A1_PLL_CLKC_H */
diff --git a/include/dt-bindings/reset/amlogic,meson-a1-reset.h b/include/dt-bindings/reset/amlogic,meson-a1-reset.h
new file mode 100644
index 0000000..2c749c6
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson-a1-reset.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Xingyu Chen <xingyu.chen@amlogic.com>
+ *
+ * Copyright (c) 2023, SberDevices, Inc.
+ * Author: Alexey Romanov <avromanov@salutedevices.com>
+ */
+
+#ifndef _DT_BINDINGS_AMLOGIC_MESON_A1_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON_A1_RESET_H
+
+/*	RESET0					*/
+/*					0	*/
+#define RESET_AM2AXI_VAD		1
+/*					2-3	*/
+#define RESET_PSRAM			4
+#define RESET_PAD_CTRL			5
+/*					6	*/
+#define RESET_TEMP_SENSOR		7
+#define RESET_AM2AXI_DEV		8
+/*					9	*/
+#define RESET_SPICC_A			10
+#define RESET_MSR_CLK			11
+#define RESET_AUDIO			12
+#define RESET_ANALOG_CTRL		13
+#define RESET_SAR_ADC			14
+#define RESET_AUDIO_VAD			15
+#define RESET_CEC			16
+#define RESET_PWM_EF			17
+#define RESET_PWM_CD			18
+#define RESET_PWM_AB			19
+/*					20	*/
+#define RESET_IR_CTRL			21
+#define RESET_I2C_S_A			22
+/*					23	*/
+#define RESET_I2C_M_D			24
+#define RESET_I2C_M_C			25
+#define RESET_I2C_M_B			26
+#define RESET_I2C_M_A			27
+#define RESET_I2C_PROD_AHB		28
+#define RESET_I2C_PROD			29
+/*					30-31	*/
+
+/*	RESET1					*/
+#define RESET_ACODEC			32
+#define RESET_DMA			33
+#define RESET_SD_EMMC_A			34
+/*					35	*/
+#define RESET_USBCTRL			36
+/*					37	*/
+#define RESET_USBPHY			38
+/*					39-41	*/
+#define RESET_RSA			42
+#define RESET_DMC			43
+/*					44	*/
+#define RESET_IRQ_CTRL			45
+/*					46	*/
+#define RESET_NIC_VAD			47
+#define RESET_NIC_AXI			48
+#define RESET_RAMA			49
+#define RESET_RAMB			50
+/*					51-52	*/
+#define RESET_ROM			53
+#define RESET_SPIFC			54
+#define RESET_GIC			55
+#define RESET_UART_C			56
+#define RESET_UART_B			57
+#define RESET_UART_A			58
+#define RESET_OSC_RING			59
+/*					60-63	*/
+
+/*	RESET2					*/
+/*					64-95	*/
+
+#endif
diff --git a/include/meson/sm.h b/include/meson/sm.h
new file mode 100644
index 0000000..fbaab1f
--- /dev/null
+++ b/include/meson/sm.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov <avromanov@salutedevices.com>
+ */
+
+#ifndef __MESON_SM_CMD_H__
+#define __MESON_SM_CMD_H__
+
+enum meson_smc_cmd {
+	MESON_SMC_CMD_EFUSE_READ,  /* read efuse memory */
+	MESON_SMC_CMD_EFUSE_WRITE, /* write efuse memory */
+	MESON_SMC_CMD_CHIP_ID_GET, /* readh chip unique id */
+	MESON_SMC_CMD_PWRDM_SET,   /* do command at specified power domain */
+	MESON_SMC_CMD_COUNT,
+};
+
+#endif
diff --git a/include/sandbox-sm.h b/include/sandbox-sm.h
new file mode 100644
index 0000000..91c30d5
--- /dev/null
+++ b/include/sandbox-sm.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov <avromanov@salutedevices.com>
+ */
+
+#ifndef __SANDBOX_SM_H__
+#define __SANDBOX_SM_H__
+
+enum sandbox_smc_cmd {
+	SANDBOX_SMC_CMD_READ_MEM,
+	SANDBOX_SMC_CMD_WRITE_MEM,
+	SANDBOX_SMC_CMD_COMMON,
+	SANDBOX_SMC_CMD_COUNT,
+};
+
+#endif
diff --git a/include/sm-uclass.h b/include/sm-uclass.h
new file mode 100644
index 0000000..c114484
--- /dev/null
+++ b/include/sm-uclass.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov <avromanov@salutedevices.com>
+ */
+
+#ifndef __SM_UCLASS_H__
+#define __SM_UCLASS_H__
+
+#include <asm/types.h>
+#include <asm/ptrace.h>
+
+struct udevice;
+
+/**
+ * struct sm_ops - The functions that a SM driver must implement.
+ *
+ * @sm_call: Request a secure monitor call with specified command.
+ *
+ * @sm_call_read: Request a secure monitor call and retrieve data
+ * from secure-monitor (depends on specified command).
+ *
+ * @sm_call_write: Request a secure monitor call and send data
+ * to secure-monitor (depends on specified command).
+ *
+ * The individual methods are described more fully below.
+ */
+struct sm_ops {
+	/**
+	 * sm_call - generic SMC call to the secure-monitor
+	 *
+	 * @dev:	Pointer to UCLASS_SM device
+	 * @cmd_index:	Index of the SMC function ID
+	 * @smc_ret:	Returned value from secure world
+	 * @args:	SMC arguments
+	 *
+	 * @return:	0 on success, a negative value on error
+	 */
+	int (*sm_call)(struct udevice *dev, u32 cmd, s32 *smc_ret,
+		       struct pt_regs *args);
+
+	/**
+	 * sm_call_write - send data to secure-monitor
+	 *
+	 * @dev:	Pointer to UCLASS_SM device
+	 * @buffer:	Buffer containing data to send
+	 * @size:	Size of the buffer
+	 * @cmd:	Index of the SMC function ID
+	 * @args:	SMC arguments
+	 *
+	 * @return:	size of sent data on success, a negative value on error
+	 */
+	int (*sm_call_write)(struct udevice *dev, void *buffer,
+			     size_t size, u32 cmd, struct pt_regs *args);
+
+	/**
+	 * sm_call_read - retrieve data from secure-monitor
+	 *
+	 * @dev:	Pointer to UCLASS_SM device
+	 * @buffer:	Buffer to store the retrieved data
+	 * @size:	Size of the buffer
+	 * @cmd:	Index of the SMC function ID
+	 * @args:	SMC arguments
+	 *
+	 * @return:	size of read data on success, a negative value on error
+	 */
+	int (*sm_call_read)(struct udevice *dev, void *buffer,
+			    size_t size, u32 cmd, struct pt_regs *args);
+};
+
+#endif /* __SM_UCLASS_H__ */
diff --git a/include/sm.h b/include/sm.h
new file mode 100644
index 0000000..afa9c89
--- /dev/null
+++ b/include/sm.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov <avromanov@salutedevices.ru>
+ */
+
+#ifndef __SM_H__
+#define __SM_H__
+
+/*
+ * NOTE: UCLASS_SM is designed with the idea that
+ * each driver should convert @cmd to some raw
+ * value, which is known only for driver, and set this
+ * value to the first element of the @args->regs array.
+ * Therefore, it is necessary to pass the remaining
+ * arguments starting at index = 1. Anyway, driver
+ * implementation may vary, so, please, check the specific
+ * implementation of the driver you are using.
+ */
+
+#include <asm/types.h>
+#include <asm/ptrace.h>
+
+struct udevice;
+
+/**
+ * sm_call - generic SMC call to the secure-monitor
+ *
+ * @dev:	Pointer to UCLASS_SM device
+ * @cmd_index:	Index of the SMC function ID
+ * @smc_ret:	Returned value from secure world
+ * @args:	SMC arguments
+ *
+ * @return:	0 on success, a negative value on error
+ */
+int sm_call(struct udevice *dev, u32 cmd, s32 *ret, struct pt_regs *args);
+
+/**
+ * sm_call_read - retrieve data from secure-monitor
+ *
+ * @dev:	Pointer to UCLASS_MESON_SM device
+ * @buffer:	Buffer to store the retrieved data
+ * @size:	Size of the buffer
+ * @cmd:	Index of the SMC function ID
+ * @args:	SMC arguments
+ *
+ * @return:	size of read data on success, a negative value on error
+ */
+int sm_call_read(struct udevice *dev, void *buffer, size_t size,
+		 u32 cmd, struct pt_regs *args);
+
+/**
+ * sm_call_write - send data to secure-monitor
+ *
+ * @dev:	Pointer to UCLASS_SM device
+ * @buffer:	Buffer containing data to send
+ * @size:	Size of the buffer
+ * @cmd:	Index of the SMC function ID
+ * @args:	SMC arguments
+ *
+ * @return:	size of sent data on success, a negative value on error
+ */
+int sm_call_write(struct udevice *dev, void *buffer, size_t size,
+		  u32 cmd, struct pt_regs *args);
+
+#endif /* __SM_H__ */
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 0f56409..477d475 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -166,8 +166,7 @@
 	return CMD_RET_USAGE;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char ut_help_text[] =
+U_BOOT_LONGHELP(ut,
 	"[-r] [-f] [<suite>] - run unit tests\n"
 	"   -r<runs>   Number of times to run each test\n"
 	"   -f         Force 'manual' tests to run as well\n"
@@ -237,8 +236,7 @@
 	!defined(CONFIG_SPL_BUILD) && !defined(API_BUILD)
 	"\nunicode - Unicode functions"
 #endif
-	;
-#endif /* CONFIG_SYS_LONGHELP */
+	);
 
 U_BOOT_CMD(
 	ut, CONFIG_SYS_MAXARGS, 1, do_ut,
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 7ed0073..02c651a 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -115,6 +115,7 @@
 obj-$(CONFIG_SPMI) += spmi.o
 obj-y += syscon.o
 obj-$(CONFIG_RESET_SYSCON) += syscon-reset.o
+obj-$(CONFIG_SM) += sm.o
 obj-$(CONFIG_SYSINFO) += sysinfo.o
 obj-$(CONFIG_SYSINFO_GPIO) += sysinfo-gpio.o
 obj-$(CONFIG_UT_DM) += tag.o
diff --git a/test/dm/sm.c b/test/dm/sm.c
new file mode 100644
index 0000000..7ebb0c9
--- /dev/null
+++ b/test/dm/sm.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov <avromanov@salutedevices.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <sm.h>
+#include <sandbox-sm.h>
+#include <asm/ptrace.h>
+#include <dm/device-internal.h>
+#include <dm/test.h>
+#include <test/ut.h>
+#include <linux/sizes.h>
+
+static int dm_test_sm(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct pt_regs regs;
+	char buffer[128] = { 0 };
+	char test_string[] = "secure-monitor";
+	int ret, val;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_SM,
+		"secure-monitor", &dev));
+
+	ret = sm_call(dev, SANDBOX_SMC_CMD_COUNT, NULL, &regs);
+	ut_asserteq(ret, -EINVAL);
+
+	ret = sm_call(dev, SANDBOX_SMC_CMD_COMMON, &val, &regs);
+	ut_asserteq(ret, 0);
+	ut_asserteq(val, 0);
+
+	ret = sm_call_write(dev, buffer, sizeof(buffer),
+		SANDBOX_SMC_CMD_COUNT, &regs);
+	ut_asserteq(ret, -EINVAL);
+
+	ret = sm_call_write(dev, buffer, SZ_4K + 1,
+		SANDBOX_SMC_CMD_WRITE_MEM, &regs);
+	ut_asserteq(ret, -EINVAL);
+
+	ret = sm_call_write(dev, buffer, sizeof(buffer),
+		SANDBOX_SMC_CMD_COUNT, &regs);
+	ut_asserteq(ret, -EINVAL);
+
+	ret = sm_call_write(dev, buffer, SZ_4K + 1,
+		SANDBOX_SMC_CMD_READ_MEM, &regs);
+	ut_asserteq(ret, -EINVAL);
+
+	ret = sm_call_write(dev, test_string, sizeof(test_string),
+		SANDBOX_SMC_CMD_WRITE_MEM, &regs);
+	ut_asserteq(ret, sizeof(test_string));
+
+	ret = sm_call_read(dev, buffer, sizeof(buffer),
+		SANDBOX_SMC_CMD_READ_MEM, &regs);
+	ut_asserteq(ret, sizeof(buffer));
+
+	ut_asserteq_str(buffer, test_string);
+
+	return 0;
+}
+
+DM_TEST(dm_test_sm, UT_TESTF_SCAN_FDT);
diff --git a/test/fuzz/cmd_fuzz.c b/test/fuzz/cmd_fuzz.c
index e2f44f3..d0bc7b8 100644
--- a/test/fuzz/cmd_fuzz.c
+++ b/test/fuzz/cmd_fuzz.c
@@ -70,11 +70,8 @@
 	return 1;
 }
 
-#ifdef CONFIG_SYS_LONGHELP
-static char fuzz_help_text[] =
-	"[fuzz-test-name] - execute the named fuzz test\n"
-	;
-#endif /* CONFIG_SYS_LONGHELP */
+U_BOOT_LONGHELP(fuzz,
+	"[fuzz-test-name] - execute the named fuzz test\n");
 
 U_BOOT_CMD(
 	fuzz, CONFIG_SYS_MAXARGS, 1, do_fuzz,