Merge branch '2021-10-31-assorted-platform-updates'

- Revert GIC LPI changes that need to be reworked.
- mvebu SATA booting bugfix
- Samsung Galaxy S9/S9+(SM-G96x0), Samsung Galaxy A and Apple M1
  platform support.
diff --git a/MAINTAINERS b/MAINTAINERS
index 5069f18..9d8cba9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -108,6 +108,15 @@
 F:	doc/device-tree-bindings/mmc/snps,dw-mmc.txt
 F:	drivers/mmc/snps_dw_mmc.c
 
+APPLE M1 SOC SUPPORT
+M:	Mark Kettenis <kettenis@openbsd.org>
+S:	Maintained
+F:	arch/arm/include/asm/arch-m1/
+F:	arch/arm/mach-apple/
+F:	configs/apple_m1_defconfig
+F:	drivers/iommu/apple_dart.c
+F:	include/configs/apple.h
+
 ARM
 M:	Tom Rini <trini@konsulko.com>
 S:	Maintained
@@ -391,7 +400,9 @@
 F:	drivers/mmc/msm_sdhci.c
 F:	drivers/phy/msm8916-usbh-phy.c
 F:	drivers/serial/serial_msm.c
+F:	drivers/serial/serial_msm_geni.c
 F:	drivers/smem/msm_smem.c
+F:	drivers/spmi/spmi-msm.c
 F:	drivers/usb/host/ehci-msm.c
 
 ARM STI
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 02f8306..b4808d4 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -82,8 +82,6 @@
 
 config GIC_V3_ITS
 	bool "ARM GICV3 ITS"
-	select REGMAP
-	select SYSCON
 	select IRQ
 	help
 	  ARM GICV3 Interrupt translation service (ITS).
@@ -922,6 +920,27 @@
 	select DM
 	select GPIO_EXTRA_HEADER
 
+config ARCH_APPLE
+	bool "Apple SoCs"
+	select ARM64
+	select BLK
+	select CLK
+	select CMD_USB
+	select DM
+	select DM_KEYBOARD
+	select DM_SERIAL
+	select DM_USB
+	select DM_VIDEO
+	select IOMMU
+	select LINUX_KERNEL_IMAGE_HEADER
+	select OF_CONTROL
+	select OF_BOARD
+	select POSITION_INDEPENDENT
+	select USB
+	imply CMD_DM
+	imply CMD_GPT
+	imply DISTRO_DEFAULTS
+
 config ARCH_OWL
 	bool "Actions Semi OWL SoCs"
 	select DM
@@ -2018,6 +2037,8 @@
 	  image headers.
 endif
 
+source "arch/arm/mach-apple/Kconfig"
+
 source "arch/arm/mach-aspeed/Kconfig"
 
 source "arch/arm/mach-at91/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 6c9a00c..ad757e9 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -55,6 +55,7 @@
 
 # Machine directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
+machine-$(CONFIG_ARCH_APPLE)		+= apple
 machine-$(CONFIG_ARCH_ASPEED)		+= aspeed
 machine-$(CONFIG_ARCH_AT91)		+= at91
 machine-$(CONFIG_ARCH_BCM283X)		+= bcm283x
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
index 9820d32..a08ed3f 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
@@ -41,27 +41,36 @@
 #endif
 
 #ifdef CONFIG_GIC_V3_ITS
+#define PENDTABLE_MAX_SZ	ALIGN(BIT(ITS_MAX_LPI_NRBITS), SZ_64K)
+#define PROPTABLE_MAX_SZ	ALIGN(BIT(ITS_MAX_LPI_NRBITS) / 8, SZ_64K)
+#define GIC_LPI_SIZE		ALIGN(cpu_numcores() * PENDTABLE_MAX_SZ + \
+				PROPTABLE_MAX_SZ, SZ_1M)
+static int fdt_add_resv_mem_gic_rd_tables(void *blob, u64 base, size_t size)
+{
+	int err;
+	struct fdt_memory gic_rd_tables;
+
+	gic_rd_tables.start = base;
+	gic_rd_tables.end = base + size - 1;
+	err = fdtdec_add_reserved_memory(blob, "gic-rd-tables", &gic_rd_tables,
+					 NULL, 0, NULL, 0);
+	if (err < 0)
+		debug("%s: failed to add reserved memory: %d\n", __func__, err);
+
+	return err;
+}
+
 int ls_gic_rd_tables_init(void *blob)
 {
-	struct fdt_memory lpi_base;
-	fdt_addr_t addr;
-	fdt_size_t size;
-	int offset, ret;
+	u64 gic_lpi_base;
+	int ret;
 
-	offset = fdt_path_offset(gd->fdt_blob, "/syscon@0x80000000");
-	addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, offset, "reg",
-						  0, &size, false);
-
-	lpi_base.start = addr;
-	lpi_base.end = addr + size - 1;
-	ret = fdtdec_add_reserved_memory(blob, "lpi_rd_table", &lpi_base, NULL,
-					 0, NULL, 0);
-	if (ret) {
-		debug("%s: failed to add reserved memory\n", __func__);
+	gic_lpi_base = ALIGN(gd->arch.resv_ram - GIC_LPI_SIZE, SZ_64K);
+	ret = fdt_add_resv_mem_gic_rd_tables(blob, gic_lpi_base, GIC_LPI_SIZE);
+	if (ret)
 		return ret;
-	}
 
-	ret = gic_lpi_tables_init();
+	ret = gic_lpi_tables_init(gic_lpi_base, cpu_numcores());
 	if (ret)
 		debug("%s: failed to init gic-lpi-tables\n", __func__);
 
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index a88aecc..cc34da7 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -28,6 +28,13 @@
 	exynos5800-peach-pi.dtb \
 	exynos5422-odroidxu3.dtb
 dtb-$(CONFIG_EXYNOS7420) += exynos7420-espresso7420.dtb
+dtb-$(CONFIG_TARGET_A5Y17LTE) += exynos78x0-axy17lte.dtb
+dtb-$(CONFIG_TARGET_A3Y17LTE) += exynos78x0-axy17lte.dtb
+dtb-$(CONFIG_TARGET_A7Y17LTE) += exynos78x0-axy17lte.dtb
+
+dtb-$(CONFIG_ARCH_APPLE) += \
+	t8103-j274.dtb \
+	t8103-j293.dtb
 
 dtb-$(CONFIG_ARCH_DAVINCI) += \
 	da850-evm.dtb \
@@ -473,6 +480,7 @@
 
 dtb-$(CONFIG_TARGET_DRAGONBOARD410C) += dragonboard410c.dtb
 dtb-$(CONFIG_TARGET_DRAGONBOARD820C) += dragonboard820c.dtb
+dtb-$(CONFIG_TARGET_STARQLTECHN) += starqltechn.dtb
 
 dtb-$(CONFIG_TARGET_STEMMY) += ste-ux500-samsung-stemmy.dtb
 
diff --git a/arch/arm/dts/exynos78x0-axy17lte.dts b/arch/arm/dts/exynos78x0-axy17lte.dts
new file mode 100644
index 0000000..7fae8db
--- /dev/null
+++ b/arch/arm/dts/exynos78x0-axy17lte.dts
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Samsung Exynos78x0 SoC device tree source
+ *
+ * Copyright (c) 2020 Dzmitry Sankouski (dsankouski@gmail.com)
+ */
+
+/dts-v1/;
+#include "exynos78x0.dtsi"
+/ {
+	compatible = "samsung,exynos78x0", "samsung,exynos7880", "samsung,exynos7870";
+
+	aliases {
+		console = &uart2;
+	};
+
+	chosen {
+		stdout-path = &uart2;
+	};
+};
+
+&gpioi2c0 {
+	status = "okay";
+};
+
+&fin_pll {
+	clock-frequency = <26000000>;
+};
+
diff --git a/arch/arm/dts/exynos78x0-gpio.dtsi b/arch/arm/dts/exynos78x0-gpio.dtsi
new file mode 100644
index 0000000..a7f75c5
--- /dev/null
+++ b/arch/arm/dts/exynos78x0-gpio.dtsi
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Samsung's Exynos7880 SoC pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2020 Dzmitry Sankouski (dsankouski@gmail.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+	/* ALIVE */
+	gpio@139F0000 {
+		etc0: etc0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		etc1: etc1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpa0: gpa0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpa1: gpa1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpa2: gpa2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpa3: gpa3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpq0: gpq0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+
+	/* CCORE */
+	gpio@10630000 {
+		gpm0: gpm0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+
+	/* DISP/AUD */
+	gpio@148C0000 {
+		gpz0: gpz0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpz1: gpz1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpz2: gpz2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+
+	/* FSYS0 */
+	gpio@13750000 {
+		gpr0: gpr0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpr1: gpr1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpr2: gpr2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpr3: gpr3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpr4: gpr4 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+
+	/* TOP */
+	gpio@139B0000 {
+		gpb0: gpb0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpc0: gpc0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpc1: gpc1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpc4: gpc4 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpc5: gpc5 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpc6: gpc6 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpc8: gpc8 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpc9: gpc9 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpd1: gpd1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpd2: gpd2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpd3: gpd3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpd4: gpd4 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpd5: gpd5 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpe0: gpe0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpf0: gpf0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpf1: gpf1 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpf2: gpf2 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpf3: gpf3 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpf4: gpf4 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+};
diff --git a/arch/arm/dts/exynos78x0-pinctrl.dtsi b/arch/arm/dts/exynos78x0-pinctrl.dtsi
new file mode 100644
index 0000000..4958c55
--- /dev/null
+++ b/arch/arm/dts/exynos78x0-pinctrl.dtsi
@@ -0,0 +1,280 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Samsung's Exynos7880 SoC pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2020 Dzmitry Sankouski (dsankouski@gmail.com)
+ *
+ * Samsung's Exynos7880 SoC pin-mux and pin-config options are listed as device
+ * tree nodes are listed in this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+	/* ALIVE */
+	pinctrl@139F0000 {
+		uart2_bus: uart2-bus {
+			samsung,pins = "gpa1-1", "gpa1-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+		};
+
+		dwmmc2_cd_ext_irq: dwmmc2_cd_ext_irq {
+			samsung,pins = "gpa3-3";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <4>;
+		};
+
+		key_power: key-power {
+			samsung,pins = "gpa0-0";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		key_voldown: key-voldown {
+			samsung,pins = "gpa2-1";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		key_volup: key-volup {
+			samsung,pins = "gpa2-0";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		key_home: key-home {
+			samsung,pins = "gpa1-7";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+	};
+
+	/* TOP */
+	pinctrl@139B0000 {
+		i2c0_bus: i2c0-bus {
+			samsung,pins = "gpc1-1", "gpc1-0";
+			samsung,pin-function = <2>;
+		};
+
+		sd0_rst: sd0_rst {
+			samsung,pins = "gpc0-2";
+			samsung,pin-function = <0>;
+		};
+	};
+
+	/* DISP/AUD */
+	pinctrl@148C0000 {
+		i2s_pmic_bus: i2s-pmic-bus {
+			samsung,pins = "gpz1-0", "gpz1-1", "gpz1-2", "gpz1-3", "gpz1-4";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <1>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2s_pmic_bus_idle: i2s-pmic-bus_idle {
+			samsung,pins = "gpz1-0", "gpz1-1", "gpz1-2", "gpz1-3", "gpz1-4";
+			samsung,pin-function = <0>;
+			samsung,pin-pud = <1>;
+			samsung,pin-drv = <0>;
+		};
+	};
+
+	/* FSYS0 */
+	pinctrl@13750000 {
+		sd0_clk: sd0-clk {
+			samsung,pins = "gpr0-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd0_cmd: sd0-cmd {
+			samsung,pins = "gpr0-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd0_rdqs: sd0-rdqs {
+			samsung,pins = "gpr0-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd0_clk_fast_slew_rate_1x: sd0-clk_fast_slew_rate_1x {
+			samsung,pins = "gpr0-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd0_clk_fast_slew_rate_2x: sd0-clk_fast_slew_rate_2x {
+			samsung,pins = "gpr0-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <1>;
+		};
+
+		sd0_clk_fast_slew_rate_3x: sd0-clk_fast_slew_rate_3x {
+			samsung,pins = "gpr0-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd0_clk_fast_slew_rate_4x: sd0-clk_fast_slew_rate_4x {
+			samsung,pins = "gpr0-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+
+		sd0_clk_fast_slew_rate_5x: sd0-clk_fast_slew_rate_5x {
+			samsung,pins = "gpr0-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <4>;
+		};
+
+		sd0_clk_fast_slew_rate_6x: sd0-clk_fast_slew_rate_6x {
+			samsung,pins = "gpr0-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <5>;
+		};
+
+		sd0_bus1: sd0-bus-width1 {
+			samsung,pins = "gpr1-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd0_bus4: sd0-bus-width4 {
+			samsung,pins = "gpr1-1", "gpr1-2", "gpr1-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd0_bus8: sd0-bus-width8 {
+			samsung,pins = "gpr1-4", "gpr1-5", "gpr1-6", "gpr1-7";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd1_clk: sd1-clk {
+			samsung,pins = "gpr2-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd1_cmd: sd1-cmd {
+			samsung,pins = "gpr2-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd1_bus1: sd1-bus-width1 {
+			samsung,pins = "gpr3-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <2>;
+			samsung,pin-con-pdn = <2>;
+			samsung,pin-pud-pdn = <3>;
+		};
+
+		sd1_bus4: sd1-bus-width4 {
+			samsung,pins = "gpr3-1", "gpr3-2", "gpr3-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <2>;
+			samsung,pin-con-pdn = <2>;
+			samsung,pin-pud-pdn = <3>;
+		};
+
+		sd2_clk: sd2-clk {
+			samsung,pins = "gpr4-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd2_cmd: sd2-cmd {
+			samsung,pins = "gpr4-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd2_bus1: sd2-bus-width1 {
+			samsung,pins = "gpr4-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd2_bus4: sd2-bus-width4 {
+			samsung,pins = "gpr4-3", "gpr4-4", "gpr4-5";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd2_clk_output: sd2-clk-output {
+			samsung,pins = "gpr4-0";
+			samsung,pin-function = <1>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd2_cmd_output: sd2-cmd-output {
+			samsung,pins = "gpr4-1";
+			samsung,pin-function = <1>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd2_clk_fast_slew_rate_1x: sd2-clk_fast_slew_rate_1x {
+			samsung,pins = "gpr4-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd2_clk_fast_slew_rate_2x: sd2-clk_fast_slew_rate_2x {
+			samsung,pins = "gpr4-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <1>;
+		};
+
+		sd2_clk_fast_slew_rate_3x: sd2-clk_fast_slew_rate_3x {
+			samsung,pins = "gpr4-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <2>;
+		};
+
+		sd2_clk_fast_slew_rate_4x: sd2-clk_fast_slew_rate_4x {
+			samsung,pins = "gpr4-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <3>;
+		};
+	};
+};
diff --git a/arch/arm/dts/exynos78x0.dtsi b/arch/arm/dts/exynos78x0.dtsi
new file mode 100644
index 0000000..fb9c9cb
--- /dev/null
+++ b/arch/arm/dts/exynos78x0.dtsi
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Samsung Exynos7880 SoC device tree source
+ *
+ * Copyright (c) 2020 Dzmitry Sankouski (dsankouski@gmail.com)
+ */
+
+/dts-v1/;
+#include "skeleton.dtsi"
+#include "exynos78x0-pinctrl.dtsi"
+#include "exynos78x0-gpio.dtsi"
+/ {
+	compatible = "samsung,exynos7880";
+
+	fin_pll: xxti {
+		compatible = "fixed-clock";
+		clock-output-names = "fin_pll";
+		u-boot,dm-pre-reloc;
+		#clock-cells = <0>;
+	};
+
+	/* Dummy clock for uart */
+	fin_uart: uart_dummy_fin {
+		compatible = "fixed-clock";
+		clock-output-names = "fin_uart";
+		clock-frequency = <132710400>;
+		u-boot,dm-pre-reloc;
+		#clock-cells = <0>;
+	};
+
+	uart2: serial@13820000 {
+		compatible = "samsung,exynos4210-uart";
+		reg = <0x13820000 0x100>;
+		u-boot,dm-pre-reloc;
+		clocks = <&fin_uart>, <&fin_uart>; // driver uses 1st clock
+		clock-names = "uart", "clk_uart_baud0";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart2_bus>;
+	};
+
+	gpioi2c0: i2c-0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "i2c-gpio";
+		status = "disabled";
+		gpios = <
+			&gpc1 0 0 /* sda */
+			&gpc1 1 0 /* scl */
+		>;
+		i2c-gpio,delay-us = <5>;
+
+		s2mu004@3d {
+			compatible = "samsung,s2mu004mfd";
+		};
+	};
+
+	/* ALIVE */
+	pinctrl_0: pinctrl@139F0000 {
+		compatible = "samsung,exynos78x0-pinctrl";
+		reg = <0x139F0000 0x1000>;
+	};
+
+	/* DISP/AUD */
+	pinctrl_2: pinctrl@148C0000 {
+		compatible = "samsung,exynos78x0-pinctrl";
+		reg = <0x148C0000 0x1000>;
+	};
+
+	/* FSYS0 */
+	pinctrl_4: pinctrl@13750000 {
+		compatible = "samsung,exynos78x0-pinctrl";
+		reg = <0x13750000 0x1000>;
+	};
+
+	/* ALIVE */
+	gpio_0: gpio@139F0000 {
+		compatible = "samsung,exynos78x0-gpio";
+		reg = <0x139F0000 0x1000>;
+	};
+
+	/* DISP/AUD */
+	gpio_2: gpio@148C0000 {
+		compatible = "samsung,exynos78x0-gpio";
+		reg = <0x148C0000 0x1000>;
+	};
+
+	/* FSYS0 */
+	gpio_4: gpio@13750000 {
+		compatible = "samsung,exynos78x0-gpio";
+		reg = <0x13750000 0x1000>;
+	};
+
+	/* TOP */
+	gpio_6: gpio@139B0000 {
+		compatible = "samsung,exynos78x0-gpio";
+		reg = <0x139B0000 0x1000>;
+	};
+};
diff --git a/arch/arm/dts/fsl-ls1028a.dtsi b/arch/arm/dts/fsl-ls1028a.dtsi
index 50f9b52..53b052e 100644
--- a/arch/arm/dts/fsl-ls1028a.dtsi
+++ b/arch/arm/dts/fsl-ls1028a.dtsi
@@ -44,12 +44,6 @@
 					 IRQ_TYPE_LEVEL_LOW)>;
 	};
 
-	gic_lpi_base: syscon@0x80000000 {
-		compatible = "gic-lpi-base";
-		reg = <0x0 0x80000000 0x0 0x100000>;
-		max-gic-redistributors = <2>;
-	};
-
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) |
diff --git a/arch/arm/dts/fsl-ls1088a.dtsi b/arch/arm/dts/fsl-ls1088a.dtsi
index 64caa60..3a5a50f 100644
--- a/arch/arm/dts/fsl-ls1088a.dtsi
+++ b/arch/arm/dts/fsl-ls1088a.dtsi
@@ -27,12 +27,6 @@
 		interrupts = <1 9 0x4>;
 	};
 
-	gic_lpi_base: syscon@0x80000000 {
-		compatible = "gic-lpi-base";
-		reg = <0x0 0x80000000 0x0 0x100000>;
-		max-gic-redistributors = <8>;
-	};
-
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <1 13 0x8>, /* Physical Secure PPI, active-low */
diff --git a/arch/arm/dts/fsl-ls2080a.dtsi b/arch/arm/dts/fsl-ls2080a.dtsi
index 7374d58..278daee 100644
--- a/arch/arm/dts/fsl-ls2080a.dtsi
+++ b/arch/arm/dts/fsl-ls2080a.dtsi
@@ -27,12 +27,6 @@
 		interrupts = <1 9 0x4>;
 	};
 
-	gic_lpi_base: syscon@0x80000000 {
-		compatible = "gic-lpi-base";
-		reg = <0x0 0x80000000 0x0 0x100000>;
-		max-gic-redistributors = <8>;
-	};
-
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <1 13 0x8>, /* Physical Secure PPI, active-low */
diff --git a/arch/arm/dts/fsl-lx2160a.dtsi b/arch/arm/dts/fsl-lx2160a.dtsi
index a6f0e9b..3b5f0d1 100644
--- a/arch/arm/dts/fsl-lx2160a.dtsi
+++ b/arch/arm/dts/fsl-lx2160a.dtsi
@@ -43,12 +43,6 @@
 		interrupts = <1 9 0x4>;
 	};
 
-	gic_lpi_base: syscon@0x80000000 {
-		compatible = "gic-lpi-base";
-		reg = <0x0 0x80000000 0x0 0x200000>;
-		max-gic-redistributors = <16>;
-	};
-
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <1 13 0x8>, /* Physical Secure PPI, active-low */
diff --git a/arch/arm/dts/sdm845.dtsi b/arch/arm/dts/sdm845.dtsi
new file mode 100644
index 0000000..1185b71
--- /dev/null
+++ b/arch/arm/dts/sdm845.dtsi
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Qualcomm SDM845 chip device tree source
+ *
+ * (C) Copyright 2021 Dzmitry Sankouski <dsankouski@gmail.com>
+ *
+ */
+
+/dts-v1/;
+
+#include "skeleton64.dtsi"
+
+/ {
+	soc: soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0 0 0xffffffff>;
+		compatible = "simple-bus";
+
+		gcc: clock-controller@100000 {
+			u-boot,dm-pre-reloc;
+			compatible = "qcom,gcc-sdm845";
+			reg = <0x100000 0x1f0000>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			#power-domain-cells = <1>;
+		};
+
+		gpio_north: gpio_north@3900000 {
+			u-boot,dm-pre-reloc;
+			#gpio-cells = <2>;
+			compatible = "qcom,sdm845-pinctrl";
+			reg = <0x3900000 0x400000>;
+			gpio-count = <150>;
+			gpio-controller;
+			gpio-ranges = <&gpio_north 0 0 150>;
+			gpio-bank-name = "soc_north.";
+		};
+
+		tlmm_north: pinctrl_north@3900000 {
+			u-boot,dm-pre-reloc;
+			compatible = "qcom,tlmm-sdm845";
+			reg = <0x3900000 0x400000>;
+			gpio-count = <150>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&tlmm_north 0 0 150>;
+
+			/* DEBUG UART */
+			qup_uart9: qup-uart9-default {
+				pinmux {
+					pins = "GPIO_4", "GPIO_5";
+					function = "qup9";
+				};
+			};
+		};
+
+		debug_uart: serial@a84000 {
+			compatible = "qcom,msm-geni-uart";
+			reg = <0xa84000 0x4000>;
+			reg-names = "se_phys";
+			clock-names = "se-clk";
+			clocks = <&gcc 0x58>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&qup_uart9>;
+			qcom,wrapper-core = <0x8a>;
+			status = "disabled";
+		};
+
+		spmi@c440000 {
+			compatible = "qcom,spmi-pmic-arb";
+			reg = <0xc440000 0x1100>,
+			      <0xc600000 0x2000000>,
+			      <0xe600000 0x100000>;
+			reg-names = "cnfg", "core", "obsrvr";
+			#address-cells = <0x1>;
+			#size-cells = <0x1>;
+
+			qcom,revid@100 {
+				compatible = "qcom,qpnp-revid";
+				reg = <0x100 0x100>;
+			};
+
+			pmic0: pm8998@0 {
+				compatible = "qcom,spmi-pmic";
+				reg = <0x0 0x1>;
+				#address-cells = <0x1>;
+				#size-cells = <0x1>;
+
+				pm8998_pon: pm8998_pon@800 {
+					compatible = "qcom,pm8998-pwrkey";
+					reg = <0x800 0x100>;
+					#gpio-cells = <2>;
+					gpio-controller;
+					gpio-bank-name = "pm8998_key.";
+				};
+
+				pm8998_gpios: pm8998_gpios@c000 {
+					compatible = "qcom,pm8998-gpio";
+					reg = <0xc000 0x1a00>;
+					gpio-controller;
+					gpio-count = <21>;
+					#gpio-cells = <2>;
+					gpio-bank-name = "pm8998.";
+				};
+			};
+
+			pmic1: pm8998@1 {
+				compatible = "qcom,spmi-pmic";
+				reg = <0x1 0x0>;
+				#address-cells = <0x2>;
+				#size-cells = <0x0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/starqltechn-uboot.dtsi b/arch/arm/dts/starqltechn-uboot.dtsi
new file mode 100644
index 0000000..d8d75e0
--- /dev/null
+++ b/arch/arm/dts/starqltechn-uboot.dtsi
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * U-Boot addition to handle Samsung S9 SM-G9600 (starqltechn) pins
+ *
+ * (C) Copyright 2021 Dzmitry Sankouski <dsankouski@gmail.com>
+ *
+ */
+
+/
+{
+	soc {
+		u-boot,dm-pre-reloc;
+		gcc {
+			clock-controller@100000 {
+				u-boot,dm-pre-reloc;
+			};
+			serial@0xa84000 {
+				u-boot,dm-pre-reloc;
+			};
+			gpio_north@3900000 {
+				u-boot,dm-pre-reloc;
+			};
+			pinctrl@3900000 {
+				u-boot,dm-pre-reloc;
+			};
+		};
+	};
+};
+
+&pm8998_pon {
+	key_vol_down {
+		gpios = <&pm8998_pon 1 0>;
+		label = "key_vol_down";
+	};
+	key_power {
+		gpios = <&pm8998_pon 0 0>;
+		label = "key_power";
+	};
+};
diff --git a/arch/arm/dts/starqltechn.dts b/arch/arm/dts/starqltechn.dts
new file mode 100644
index 0000000..387420f
--- /dev/null
+++ b/arch/arm/dts/starqltechn.dts
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Samsung S9 SM-G9600 (starqltechn) board device tree source
+ *
+ * (C) Copyright 2021 Dzmitry Sankouski <dsankouski@gmail.com>
+ *
+ */
+
+/dts-v1/;
+
+#include "sdm845.dtsi"
+
+/ {
+	model = "Samsung S9 (SM-G9600)";
+	compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	chosen {
+		stdout-path = "serial0:921600n8";
+	};
+
+	aliases {
+		serial0 = &debug_uart;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x80000000 0 0xfe1bffff>;
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	soc: soc {
+		serial@0xa84000 {
+			status = "ok";
+		};
+
+		pinctrl@3900000 {
+			muic_i2c: muic_i2c {
+				pins = "GPIO_33", "GPIO_34";
+				drive-strength = <0x2>;
+				function = "gpio";
+				bias-disable;
+			};
+		};
+	};
+};
+
+#include "starqltechn-uboot.dtsi"
diff --git a/arch/arm/dts/t8103-j274.dts b/arch/arm/dts/t8103-j274.dts
new file mode 100644
index 0000000..aef1ae2
--- /dev/null
+++ b/arch/arm/dts/t8103-j274.dts
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple Mac mini (M1, 2020)
+ *
+ * target-type: J274
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t8103.dtsi"
+
+/ {
+	compatible = "apple,j274", "apple,t8103", "apple,arm-platform";
+	model = "Apple Mac mini (M1, 2020)";
+
+	aliases {
+		serial0 = &serial0;
+		ethernet0 = &eth0;
+		wifi0 = &wifi0;
+	};
+
+	chosen {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		stdout-path = "serial0";
+
+		framebuffer0: framebuffer@0 {
+			compatible = "apple,simple-framebuffer", "simple-framebuffer";
+			reg = <0 0 0 0>; /* To be filled by loader */
+			/* Format properties will be added by loader */
+			status = "disabled";
+		};
+	};
+
+	memory@800000000 {
+		device_type = "memory";
+		reg = <0x8 0 0x2 0>; /* To be filled by loader */
+	};
+};
+
+&serial0 {
+	status = "okay";
+};
+
+&pcie0_dart_0 {
+	status = "okay";
+};
+
+&pcie0_dart_1 {
+	status = "okay";
+};
+
+&pcie0_dart_2 {
+	status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+
+	pci0: pci@0,0 {
+		device_type = "pci";
+		reg = <0x0 0x0 0x0 0x0 0x0>;
+		pwren-gpios = <&smc 13 0>;
+		reset-gpios = <&pinctrl_ap 152 0>;
+		max-link-speed = <2>;
+
+		#address-cells = <3>;
+		#size-cells = <2>;
+		ranges;
+	};
+
+	pci1: pci@1,0 {
+		device_type = "pci";
+		reg = <0x800 0x0 0x0 0x0 0x0>;
+		reset-gpios = <&pinctrl_ap 153 0>;
+		max-link-speed = <2>;
+
+		#address-cells = <3>;
+		#size-cells = <2>;
+		ranges;
+	};
+
+	pci2: pci@2,0 {
+		device_type = "pci";
+		reg = <0x1000 0x0 0x0 0x0 0x0>;
+		reset-gpios = <&pinctrl_ap 33 0>;
+		max-link-speed = <1>;
+
+		#address-cells = <3>;
+		#size-cells = <2>;
+		ranges;
+	};
+};
+
+&pci0 {
+	wifi0: network@0,0 {
+		reg = <0x10000 0x0 0x0 0x0 0x0>;
+		local-mac-address = [00 00 00 00 00 00];
+	};
+};
+
+&pci2 {
+	eth0: ethernet@0,0 {
+		reg = <0x30000 0x0 0x0 0x0 0x0>;
+		local-mac-address = [00 00 00 00 00 00];
+	};
+};
+
+&dwc3_0_dart_0 {
+	status = "okay";
+};
+
+&dwc3_0_dart_1 {
+	status = "okay";
+};
+
+&dwc3_0 {
+	status = "okay";
+};
+
+&dwc3_1_dart_0 {
+	status = "okay";
+};
+
+&dwc3_1_dart_1 {
+	status = "okay";
+};
+
+&dwc3_1 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/t8103-j293.dts b/arch/arm/dts/t8103-j293.dts
new file mode 100644
index 0000000..4a22596
--- /dev/null
+++ b/arch/arm/dts/t8103-j293.dts
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple Macbook Pro (M1, 2020)
+ *
+ * target-type: J293
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t8103.dtsi"
+
+/ {
+	compatible = "apple,j293", "apple,t8103", "apple,arm-platform";
+	model = "Apple Macbook Pro (M1, 2020)";
+
+	aliases {
+		serial0 = &serial0;
+		wifi0 = &wifi0;
+	};
+
+	chosen {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		stdout-path = "serial0";
+
+		framebuffer0: framebuffer@0 {
+			compatible = "apple,simple-framebuffer", "simple-framebuffer";
+			reg = <0 0 0 0>; /* To be filled by loader */
+			/* Format properties will be added by loader */
+			status = "disabled";
+		};
+	};
+
+	memory@800000000 {
+		device_type = "memory";
+		reg = <0x8 0 0x2 0>; /* To be filled by loader */
+	};
+};
+
+&serial0 {
+	status = "okay";
+};
+
+&pcie0_dart_0 {
+	status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+
+	pci0: pci@0,0 {
+		device_type = "pci";
+		reg = <0x0 0x0 0x0 0x0 0x0>;
+		pwren-gpios = <&smc 13 0>;
+		reset-gpios = <&pinctrl_ap 152 0>;
+		max-link-speed = <2>;
+
+		#address-cells = <3>;
+		#size-cells = <2>;
+		ranges;
+	};
+};
+
+&pci0 {
+	wifi0: network@0,0 {
+		reg = <0x10000 0x0 0x0 0x0 0x0>;
+		local-mac-address = [00 00 00 00 00 00];
+	};
+};
+
+&dwc3_0_dart_0 {
+	status = "okay";
+};
+
+&dwc3_0_dart_1 {
+	status = "okay";
+};
+
+&dwc3_0 {
+	status = "okay";
+};
+
+&dwc3_1_dart_0 {
+	status = "okay";
+};
+
+&dwc3_1_dart_1 {
+	status = "okay";
+};
+
+&dwc3_1 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/t8103.dtsi b/arch/arm/dts/t8103.dtsi
new file mode 100644
index 0000000..7d9cb27
--- /dev/null
+++ b/arch/arm/dts/t8103.dtsi
@@ -0,0 +1,560 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple T8103 "M1" SoC
+ *
+ * Other names: H13G, "Tonga"
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/apple-aic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/apple.h>
+#include <dt-bindings/spmi/spmi.h>
+
+/ {
+	compatible = "apple,t8103", "apple,arm-platform";
+
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			compatible = "apple,icestorm";
+			device_type = "cpu";
+			reg = <0x0 0x0>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0 0>; /* To be filled by loader */
+		};
+
+		cpu1: cpu@1 {
+			compatible = "apple,icestorm";
+			device_type = "cpu";
+			reg = <0x0 0x1>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0 0>; /* To be filled by loader */
+		};
+
+		cpu2: cpu@2 {
+			compatible = "apple,icestorm";
+			device_type = "cpu";
+			reg = <0x0 0x2>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0 0>; /* To be filled by loader */
+		};
+
+		cpu3: cpu@3 {
+			compatible = "apple,icestorm";
+			device_type = "cpu";
+			reg = <0x0 0x3>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0 0>; /* To be filled by loader */
+		};
+
+		cpu4: cpu@10100 {
+			compatible = "apple,firestorm";
+			device_type = "cpu";
+			reg = <0x0 0x10100>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0 0>; /* To be filled by loader */
+		};
+
+		cpu5: cpu@10101 {
+			compatible = "apple,firestorm";
+			device_type = "cpu";
+			reg = <0x0 0x10101>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0 0>; /* To be filled by loader */
+		};
+
+		cpu6: cpu@10102 {
+			compatible = "apple,firestorm";
+			device_type = "cpu";
+			reg = <0x0 0x10102>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0 0>; /* To be filled by loader */
+		};
+
+		cpu7: cpu@10103 {
+			compatible = "apple,firestorm";
+			device_type = "cpu";
+			reg = <0x0 0x10103>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0 0>; /* To be filled by loader */
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupt-parent = <&aic>;
+		interrupt-names = "hyp-phys", "hyp-virt", "phys", "virt";
+		interrupts = <AIC_FIQ AIC_TMR_HV_PHYS IRQ_TYPE_LEVEL_HIGH>,
+			     <AIC_FIQ AIC_TMR_HV_VIRT IRQ_TYPE_LEVEL_HIGH>,
+			     <AIC_FIQ AIC_TMR_GUEST_PHYS IRQ_TYPE_LEVEL_HIGH>,
+			     <AIC_FIQ AIC_TMR_GUEST_VIRT IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	clkref: clock-ref {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "clkref";
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		ranges;
+		dma-ranges;
+		dma-coherent;
+		nonposted-mmio;
+
+		serial0: serial@235200000 {
+			compatible = "apple,s5l-uart";
+			reg = <0x2 0x35200000 0x0 0x1000>;
+			reg-io-width = <4>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 605 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clkref>, <&clkref>, <&clkref>;
+			clock-names = "uart", "clk_uart_baud0", "clk_uart_baud1";
+			power-domains = <&ps_uart0>;
+			status = "disabled";
+		};
+
+		serial2: serial@235208000 {
+			compatible = "apple,s5l-uart";
+			reg = <0x2 0x35208000 0x0 0x1000>;
+			reg-io-width = <4>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 607 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clkref>, <&clkref>, <&clkref>;
+			clock-names = "uart", "clk_uart_baud0", "clk_uart_baud1";
+			power-domains = <&ps_uart2>;
+			status = "disabled";
+		};
+
+		aic: interrupt-controller@23b100000 {
+			compatible = "apple,t8103-aic", "apple,aic";
+			#interrupt-cells = <3>;
+			interrupt-controller;
+			reg = <0x2 0x3b100000 0x0 0x8000>;
+		};
+
+		pmgr: power-controller@23b700000 {
+			compatible = "apple,t8103-pmgr", "apple,pmgr", "syscon", "simple-mfd";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			reg = <0x2 0x3b700000 0x0 0x14000>;
+
+			ps_pcie_ref: power-controller@1a0 {
+				compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
+				reg = <0x1a0>;
+				#power-domain-cells = <0>;
+				#reset-cells = <0>;
+				apple,domain-name = "pcie_ref";
+			};
+
+			ps_imx: power-controller@1b8 {
+				compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
+				reg = <0x1b8>;
+				#power-domain-cells = <0>;
+				#reset-cells = <0>;
+				apple,domain-name = "imx";
+				apple,always-on;
+			};
+
+			ps_sio: power-controller@1c0 {
+				compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
+				reg = <0x1c0>;
+				#power-domain-cells = <0>;
+				#reset-cells = <0>;
+				apple,domain-name = "sio";
+			};
+
+			ps_uart_p: power-controller@220 {
+				compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
+				reg = <0x220>;
+				#power-domain-cells = <0>;
+				#reset-cells = <0>;
+				power-domains = <&ps_sio>;
+				apple,domain-name = "uart_p";
+			};
+
+			ps_uart0: power-controller@270 {
+				compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
+				reg = <0x270>;
+				#power-domain-cells = <0>;
+				#reset-cells = <0>;
+				power-domains = <&ps_uart_p>;
+				apple,domain-name = "uart0";
+			};
+
+			ps_uart1: power-controller@278 {
+				compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
+				reg = <0x278>;
+				#power-domain-cells = <0>;
+				#reset-cells = <0>;
+				apple,domain-name = "uart1";
+				power-domains = <&ps_uart_p>;
+			};
+
+			ps_uart2: power-controller@280 {
+				compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
+				reg = <0x280>;
+				#power-domain-cells = <0>;
+				#reset-cells = <0>;
+				apple,domain-name = "uart2";
+				power-domains = <&ps_uart_p>;
+			};
+
+			ps_uart3: power-controller@288 {
+				compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
+				reg = <0x288>;
+				#power-domain-cells = <0>;
+				#reset-cells = <0>;
+				apple,domain-name = "uart3";
+				power-domains = <&ps_uart_p>;
+			};
+
+			ps_apcie: power-controller@348 {
+				compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
+				reg = <0x348>;
+				#power-domain-cells = <0>;
+				#reset-cells = <0>;
+				apple,domain-name = "apcie";
+				power-domains = <&ps_imx>;
+			};
+
+			ps_apcie_gp: power-controller@3e8 {
+				compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
+				reg = <0x3e8>;
+				#power-domain-cells = <0>;
+				#reset-cells = <0>;
+				apple,domain-name = "apcie_gp";
+				power-domains = <&ps_apcie>;
+			};
+
+			ps_ans2: power-controller@3f0 {
+				compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
+				reg = <0x3f0>;
+				#power-domain-cells = <0>;
+				#reset-cells = <0>;
+				apple,domain-name = "ans2";
+				power-domains = <&ps_apcie_st>;
+			};
+
+			ps_apcie_st: power-controller@418 {
+				compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate";
+				reg = <0x418>;
+				#power-domain-cells = <0>;
+				#reset-cells = <0>;
+				apple,domain-name = "apcie_st";
+				power-domains = <&ps_apcie>;
+			};
+		};
+
+		pinctrl_ap: pinctrl@23c100000 {
+			compatible = "apple,t8103-pinctrl", "apple,pinctrl";
+			reg = <0x2 0x3c100000 0x0 0x100000>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl_ap 0 0 212>;
+
+			interrupt-controller;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 190 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 191 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 192 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 193 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 194 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 195 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 196 IRQ_TYPE_LEVEL_HIGH>;
+
+			i2c0_pins: i2c0_pins {
+				pinmux = <APPLE_PINMUX(188, 1)>,
+					 <APPLE_PINMUX(192, 1)>;
+			};
+
+			pcie_pins: pcie-pins {
+				pinmux = <APPLE_PINMUX(150, 1)>,
+				         <APPLE_PINMUX(151, 1)>,
+					 <APPLE_PINMUX(32, 1)>;
+			};
+		};
+
+		pinctrl_aop: pinctrl@24a820000 {
+			compatible = "apple,t8103-pinctrl", "apple,pinctrl";
+			reg = <0x2 0x4a820000 0x0 0x4000>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl_aop 0 0 42>;
+
+			interrupt-controller;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 268 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 269 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 270 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 271 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 272 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 273 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 274 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pinctrl_nub: pinctrl@23d1f0000 {
+			compatible = "apple,t8103-pinctrl", "apple,pinctrl";
+			reg = <0x2 0x3d1f0000 0x0 0x4000>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl_nub 0 0 23>;
+
+			interrupt-controller;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 330 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 331 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 332 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 333 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 334 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 335 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 336 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pinctrl_smc: pinctrl@23e820000 {
+			compatible = "apple,t8103-pinctrl", "apple,pinctrl";
+			reg = <0x2 0x3e820000 0x0 0x4000>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl_smc 0 0 16>;
+
+			interrupt-controller;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 391 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 392 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 393 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 394 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 395 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 396 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 397 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		i2c0: i2c@20a110000 {
+			compatible = "apple,i2c-v0";
+			reg = <0x2 0x35010000 0x0 0x4000>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 627 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clkref>;
+			pinctrl-0 = <&i2c0_pins>;
+			pinctrl-names = "default";
+			#address-cells = <0x1>;
+			#size-cells = <0x0>;
+
+			hpm0: hpm@38 {
+				compatible = "ti,tps6598x";
+				reg = <0x38>;
+			};
+
+			hpm1: hpm@3f {
+				compatible = "ti,tps6598x";
+				reg = <0x3f>;
+			};
+                };
+
+		ans_mbox: mbox@277400000 {
+			compatible = "apple,iop-mailbox-m1";
+			reg = <0x2 0x77400000 0x0 0x20000>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 583 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 586 IRQ_TYPE_LEVEL_HIGH>;
+			power-domains = <&ps_ans2>;
+			#mbox-cells = <1>;
+			endpoints = <32>;
+		};
+
+		ans@27bcc0000 {
+			compatible = "apple,nvme-m1";
+			reg = <0x2 0x7bcc0000 0x0 0x40000>,
+			      <0x2 0x7bc50000 0x0 0x4000>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 590 IRQ_TYPE_LEVEL_HIGH>;
+			power-domains = <&ps_apcie_st>;
+			mboxes = <&ans_mbox 32>;
+		};
+
+		pcie0_dart_0: iommu@681008000 {
+			compatible = "apple,t8103-dart", "apple,dart-m1";
+			reg = <0x6 0x81008000 0x0 0x4000>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 696 IRQ_TYPE_LEVEL_HIGH>;
+			#iommu-cells = <1>;
+			status = "disabled";
+		};
+
+		pcie0_dart_1: iommu@682008000 {
+			compatible = "apple,t8103-dart", "apple,dart-m1";
+			reg = <0x6 0x82008000 0x0 0x4000>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 699 IRQ_TYPE_LEVEL_HIGH>;
+			#iommu-cells = <1>;
+			status = "disabled";
+		};
+
+		pcie0_dart_2: iommu@683008000 {
+			compatible = "apple,t8103-dart", "apple,dart-m1";
+			reg = <0x6 0x83008000 0x0 0x4000>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 702 IRQ_TYPE_LEVEL_HIGH>;
+			#iommu-cells = <1>;
+			status = "disabled";
+		};
+
+		smc_mbox: mbox@23e400000 {
+			compatible = "apple,iop-mailbox-m1";
+			reg = <0x2 0x3e400000 0x0 0x20000>;
+			#mbox-cells = <1>;
+			endpoints = <32>;
+		};
+
+		smc: smc@23e050000 {
+			compatible = "apple,smc-m1";
+			reg = <0x2 0x3e050000 0x0 0x4000>;
+			mboxes = <&smc_mbox 32>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-13 = <0x00800000>;
+		};
+
+		pcie0: pcie@690000000 {
+			compatible = "apple,t8103-pcie", "apple,pcie";
+
+			reg = <0x6 0x90000000 0x0 0x1000000>,
+			      <0x6 0x80000000 0x0 0x4000>,
+			      <0x6 0x81000000 0x0 0x8000>,
+			      <0x6 0x82000000 0x0 0x8000>,
+			      <0x6 0x83000000 0x0 0x8000>;
+			reg-names = "config", "rc", "port0", "port1", "port2";
+
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 695 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 698 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 701 IRQ_TYPE_LEVEL_HIGH>;
+
+			msi-controller;
+			msi-parent = <&pcie0>;
+			msi-ranges = <&aic AIC_IRQ 704 IRQ_TYPE_EDGE_RISING 32>;
+
+			iommu-map = <0x100 &pcie0_dart_0 1 1>,
+				    <0x200 &pcie0_dart_1 1 1>,
+				    <0x300 &pcie0_dart_2 1 1>;
+			iommu-map-mask = <0xff00>;
+
+			bus-range = <0 3>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges = <0x43000000 0x6 0xa0000000 0x6 0xa0000000
+			          0x0 0x20000000>,
+				 <0x02000000 0x0 0xc0000000 0x6 0xc0000000
+				  0x0 0x40000000>;
+
+			power-domains = <&ps_apcie>, <&ps_apcie_gp>, <&ps_pcie_ref>;
+			pinctrl-0 = <&pcie_pins>;
+			pinctrl-names = "default";
+
+			device_type = "pci";
+			status = "disabled";
+		};
+
+		dwc3_0_dart_0: iommu@382f00000 {
+			compatible = "apple,t8103-dart";
+			reg = <0x3 0x82f00000 0x0 0x4000>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 781 IRQ_TYPE_LEVEL_HIGH>;
+			#iommu-cells = <1>;
+			status = "disabled";
+		};
+
+		dwc3_0_dart_1: iommu@382f80000 {
+			compatible = "apple,t8103-dart";
+			reg = <0x3 0x82f80000 0x0 0x4000>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 781 IRQ_TYPE_LEVEL_HIGH>;
+			#iommu-cells = <1>;
+			status = "disabled";
+		};
+
+		dwc3_0: usb@382280000{
+			compatible = "snps,dwc3";
+			reg = <0x3 0x82280000 0x0 0x100000>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 777 IRQ_TYPE_LEVEL_HIGH>;
+			dr_mode = "host";
+			iommus = <&dwc3_0_dart_0 0>, <&dwc3_0_dart_1 1>;
+			status = "disabled";
+		};
+
+		dwc3_1_dart_0: iommu@502f00000 {
+			compatible = "apple,t8103-dart";
+			reg = <0x5 0x02f00000 0x0 0x4000>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 861 IRQ_TYPE_LEVEL_HIGH>;
+			#iommu-cells = <1>;
+			status = "disabled";
+		};
+
+		dwc3_1_dart_1: iommu@502f80000 {
+			compatible = "apple,t8103-dart";
+			reg = <0x5 0x02f80000 0x0 0x4000>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 861 IRQ_TYPE_LEVEL_HIGH>;
+			#iommu-cells = <1>;
+			status = "disabled";
+		};
+
+		dwc3_1: usb@502280000{
+			compatible = "snps,dwc3";
+			reg = <0x5 0x02280000 0x0 0x100000>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 857 IRQ_TYPE_LEVEL_HIGH>;
+			dr_mode = "host";
+			iommus = <&dwc3_1_dart_0 0>, <&dwc3_1_dart_1 1>;
+			status = "disabled";
+		};
+
+		reboot@23d2b0000 {
+			compatible = "apple,reboot-v0";
+			reg = <0x2 0x3d2b0000 0x0 0x4000>;
+		};
+
+		spi@23510c000 {
+			compatible = "apple,t8103-spi", "apple,spi";
+			reg = <0x2 0x3510c000 0x0 0x4000>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 617 IRQ_TYPE_LEVEL_HIGH>;
+			cs-gpios = <&pinctrl_ap 49 GPIO_ACTIVE_HIGH>;
+		};
+
+		spmi@23d0d8000 {
+			compatible = "apple,t8103-spmi", "apple,spmi";
+			reg = <0x2 0x3d0d9300 0x0 0x100>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 343 IRQ_TYPE_LEVEL_HIGH>;
+
+			#address-cells = <2>;
+			#size-cells = <0>;
+
+			pmu@f {
+				compatible = "apple,sera-pmu";
+				reg = <0xf SPMI_USID>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/include/asm/arch-m1/uart.h b/arch/arm/include/asm/arch-m1/uart.h
new file mode 100644
index 0000000..d2a17a2
--- /dev/null
+++ b/arch/arm/include/asm/arch-m1/uart.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2009 Samsung Electronics
+ * Minkyu Kang <mk7.kang@samsung.com>
+ * Heungjun Kim <riverful.kim@samsung.com>
+ */
+
+#ifndef __ASM_ARCH_UART_H_
+#define __ASM_ARCH_UART_H_
+
+#ifndef __ASSEMBLY__
+/* baudrate rest value */
+union br_rest {
+	unsigned short	slot;		/* udivslot */
+	unsigned char	value;		/* ufracval */
+};
+
+struct s5p_uart {
+	unsigned int	ulcon;
+	unsigned int	ucon;
+	unsigned int	ufcon;
+	unsigned int	umcon;
+	unsigned int	utrstat;
+	unsigned int	uerstat;
+	unsigned int	ufstat;
+	unsigned int	umstat;
+	unsigned int	utxh;
+	unsigned int	urxh;
+	unsigned int	ubrdiv;
+	union br_rest	rest;
+	unsigned char	res3[0x3fd0];
+};
+
+static inline int s5p_uart_divslot(void)
+{
+	return 0;
+}
+
+#endif	/* __ASSEMBLY__ */
+
+#endif
diff --git a/arch/arm/include/asm/gic-v3.h b/arch/arm/include/asm/gic-v3.h
index 35efec7..5131fab 100644
--- a/arch/arm/include/asm/gic-v3.h
+++ b/arch/arm/include/asm/gic-v3.h
@@ -127,9 +127,9 @@
 #define GIC_REDISTRIBUTOR_OFFSET 0x20000
 
 #ifdef CONFIG_GIC_V3_ITS
-int gic_lpi_tables_init(void);
+int gic_lpi_tables_init(u64 base, u32 max_redist);
 #else
-int gic_lpi_tables_init(void)
+int gic_lpi_tables_init(u64 base, u32 max_redist)
 {
 	return 0;
 }
diff --git a/arch/arm/lib/gic-v3-its.c b/arch/arm/lib/gic-v3-its.c
index 2d3fdb6..f6211a2 100644
--- a/arch/arm/lib/gic-v3-its.c
+++ b/arch/arm/lib/gic-v3-its.c
@@ -5,8 +5,6 @@
 #include <common.h>
 #include <cpu_func.h>
 #include <dm.h>
-#include <regmap.h>
-#include <syscon.h>
 #include <asm/gic.h>
 #include <asm/gic-v3.h>
 #include <asm/io.h>
@@ -19,22 +17,15 @@
 #define LPI_PROPBASE_SZ		ALIGN(BIT(LPI_NRBITS), SZ_64K)
 #define LPI_PENDBASE_SZ		ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)
 
-/* Number of GIC re-distributors */
-#define MAX_GIC_REDISTRIBUTORS	8
-
 /*
  * gic_v3_its_priv - gic details
  *
  * @gicd_base: gicd base address
  * @gicr_base: gicr base address
- * @lpi_base: gic lpi base address
- * @num_redist: number of gic re-distributors
  */
 struct gic_v3_its_priv {
 	ulong gicd_base;
 	ulong gicr_base;
-	ulong lpi_base;
-	u32 num_redist;
 };
 
 static int gic_v3_its_get_gic_addr(struct gic_v3_its_priv *priv)
@@ -68,39 +59,13 @@
 	return 0;
 }
 
-static int gic_v3_its_get_gic_lpi_addr(struct gic_v3_its_priv *priv)
-{
-	struct regmap *regmap;
-	struct udevice *dev;
-	int ret;
-
-	ret = uclass_get_device_by_driver(UCLASS_SYSCON,
-					  DM_DRIVER_GET(gic_lpi_syscon), &dev);
-	if (ret) {
-		pr_err("%s: failed to get %s syscon device\n", __func__,
-		       DM_DRIVER_GET(gic_lpi_syscon)->name);
-		return ret;
-	}
-
-	regmap = syscon_get_regmap(dev);
-	if (!regmap) {
-		pr_err("%s: failed to regmap for %s syscon device\n", __func__,
-		       DM_DRIVER_GET(gic_lpi_syscon)->name);
-		return -ENODEV;
-	}
-	priv->lpi_base = regmap->ranges[0].start;
-
-	priv->num_redist = dev_read_u32_default(dev, "max-gic-redistributors",
-						MAX_GIC_REDISTRIBUTORS);
-
-	return 0;
-}
-
 /*
  * Program the GIC LPI configuration tables for all
  * the re-distributors and enable the LPI table
+ * base: Configuration table address
+ * num_redist: number of redistributors
  */
-int gic_lpi_tables_init(void)
+int gic_lpi_tables_init(u64 base, u32 num_redist)
 {
 	struct gic_v3_its_priv priv;
 	u32 gicd_typer;
@@ -109,15 +74,12 @@
 	int i;
 	u64 redist_lpi_base;
 	u64 pend_base;
-	ulong pend_tab_total_sz;
+	ulong pend_tab_total_sz = num_redist * LPI_PENDBASE_SZ;
 	void *pend_tab_va;
 
 	if (gic_v3_its_get_gic_addr(&priv))
 		return -EINVAL;
 
-	if (gic_v3_its_get_gic_lpi_addr(&priv))
-		return -EINVAL;
-
 	gicd_typer = readl((uintptr_t)(priv.gicd_base + GICD_TYPER));
 	/* GIC support for Locality specific peripheral interrupts (LPI's) */
 	if (!(gicd_typer & GICD_TYPER_LPIS)) {
@@ -130,7 +92,7 @@
 	 * Once the LPI table is enabled, can not program the
 	 * LPI configuration tables again, unless the GIC is reset.
 	 */
-	for (i = 0; i < priv.num_redist; i++) {
+	for (i = 0; i < num_redist; i++) {
 		u32 offset = i * GIC_REDISTRIBUTOR_OFFSET;
 
 		if ((readl((uintptr_t)(priv.gicr_base + offset))) &
@@ -146,7 +108,7 @@
 			    ITS_MAX_LPI_NRBITS);
 
 	/* Set PropBase */
-	val = (priv.lpi_base |
+	val = (base |
 	       GICR_PROPBASER_INNERSHAREABLE |
 	       GICR_PROPBASER_RAWAWB |
 	       ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK));
@@ -163,8 +125,7 @@
 		}
 	}
 
-	redist_lpi_base = priv.lpi_base + LPI_PROPBASE_SZ;
-	pend_tab_total_sz = priv.num_redist * LPI_PENDBASE_SZ;
+	redist_lpi_base = base + LPI_PROPBASE_SZ;
 	pend_tab_va = map_physmem(redist_lpi_base, pend_tab_total_sz,
 				  MAP_NOCACHE);
 	memset(pend_tab_va, 0, pend_tab_total_sz);
@@ -172,7 +133,7 @@
 	unmap_physmem(pend_tab_va, MAP_NOCACHE);
 
 	pend_base = priv.gicr_base + GICR_PENDBASER;
-	for (i = 0; i < priv.num_redist; i++) {
+	for (i = 0; i < num_redist; i++) {
 		u32 offset = i * GIC_REDISTRIBUTOR_OFFSET;
 
 		val = ((redist_lpi_base + (i * LPI_PENDBASE_SZ)) |
@@ -207,14 +168,3 @@
 	.id		= UCLASS_IRQ,
 	.of_match	= gic_v3_its_ids,
 };
-
-static const struct udevice_id gic_lpi_syscon_ids[] = {
-	{ .compatible = "gic-lpi-base" },
-	{}
-};
-
-U_BOOT_DRIVER(gic_lpi_syscon) = {
-	.name		= "gic-lpi-base",
-	.id		= UCLASS_SYSCON,
-	.of_match	= gic_lpi_syscon_ids,
-};
diff --git a/arch/arm/mach-apple/Kconfig b/arch/arm/mach-apple/Kconfig
new file mode 100644
index 0000000..66cab91
--- /dev/null
+++ b/arch/arm/mach-apple/Kconfig
@@ -0,0 +1,18 @@
+if ARCH_APPLE
+
+config SYS_TEXT_BASE
+	default 0x00000000
+
+config SYS_CONFIG_NAME
+	default "apple"
+
+config SYS_SOC
+	default "m1"
+
+config SYS_MALLOC_LEN
+	default 0x4000000
+
+config SYS_MALLOC_F_LEN
+	default 0x4000
+
+endif
diff --git a/arch/arm/mach-apple/Makefile b/arch/arm/mach-apple/Makefile
new file mode 100644
index 0000000..e74a8c9
--- /dev/null
+++ b/arch/arm/mach-apple/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += board.o
+obj-y += lowlevel_init.o
diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c
new file mode 100644
index 0000000..0bfbc47
--- /dev/null
+++ b/arch/arm/mach-apple/board.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021 Mark Kettenis <kettenis@openbsd.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <efi_loader.h>
+
+#include <asm/armv8/mmu.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct mm_region apple_mem_map[] = {
+	{
+		/* I/O */
+		.virt = 0x200000000,
+		.phys = 0x200000000,
+		.size = 8UL * SZ_1G,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* I/O */
+		.virt = 0x500000000,
+		.phys = 0x500000000,
+		.size = 2UL * SZ_1G,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* I/O */
+		.virt = 0x680000000,
+		.phys = 0x680000000,
+		.size = SZ_512M,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* PCIE */
+		.virt = 0x6a0000000,
+		.phys = 0x6a0000000,
+		.size = SZ_512M,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
+			 PTE_BLOCK_INNER_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* PCIE */
+		.virt = 0x6c0000000,
+		.phys = 0x6c0000000,
+		.size = SZ_1G,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
+			 PTE_BLOCK_INNER_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* RAM */
+		.virt = 0x800000000,
+		.phys = 0x800000000,
+		.size = 8UL * SZ_1G,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		/* Empty entry for framebuffer */
+		0,
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = apple_mem_map;
+
+int board_init(void)
+{
+	return 0;
+}
+
+int dram_init(void)
+{
+	ofnode node;
+	int index, ret;
+	fdt_addr_t base;
+	fdt_size_t size;
+
+	ret = fdtdec_setup_mem_size_base();
+	if (ret)
+		return ret;
+
+	/* Update RAM mapping */
+	index = ARRAY_SIZE(apple_mem_map) - 3;
+	apple_mem_map[index].virt = gd->ram_base;
+	apple_mem_map[index].phys = gd->ram_base;
+	apple_mem_map[index].size = gd->ram_size;
+
+	node = ofnode_path("/chosen/framebuffer");
+	if (!ofnode_valid(node))
+		return 0;
+
+	base = ofnode_get_addr_size(node, "reg", &size);
+	if (base == FDT_ADDR_T_NONE)
+		return 0;
+
+	/* Add framebuffer mapping */
+	index = ARRAY_SIZE(apple_mem_map) - 2;
+	apple_mem_map[index].virt = base;
+	apple_mem_map[index].phys = base;
+	apple_mem_map[index].size = size;
+	apple_mem_map[index].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) |
+		PTE_BLOCK_INNER_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN;
+
+	return 0;
+}
+
+int dram_init_banksize(void)
+{
+	return fdtdec_setup_memory_banksize();
+}
+
+#define APPLE_WDT_BASE		0x23d2b0000ULL
+
+#define APPLE_WDT_SYS_CTL_ENABLE	BIT(2)
+
+typedef struct apple_wdt {
+	u32	reserved0[3];
+	u32	chip_ctl;
+	u32	sys_tmr;
+	u32	sys_cmp;
+	u32	reserved1;
+	u32	sys_ctl;
+} apple_wdt_t;
+
+void reset_cpu(void)
+{
+	apple_wdt_t *wdt = (apple_wdt_t *)APPLE_WDT_BASE;
+
+	writel(0, &wdt->sys_cmp);
+	writel(APPLE_WDT_SYS_CTL_ENABLE, &wdt->sys_ctl);
+
+	while(1)
+		wfi();
+}
+
+extern long fw_dtb_pointer;
+
+void *board_fdt_blob_setup(int *err)
+{
+	/* Return DTB pointer passed by m1n1 */
+	*err = 0;
+	return (void *)fw_dtb_pointer;
+}
+
+ulong board_get_usable_ram_top(ulong total_size)
+{
+	/*
+	 * Top part of RAM is used by firmware for things like the
+	 * framebuffer.  This gives us plenty of room to play with.
+	 */
+	return 0x980000000;
+}
diff --git a/arch/arm/mach-apple/lowlevel_init.S b/arch/arm/mach-apple/lowlevel_init.S
new file mode 100644
index 0000000..e1c0d91
--- /dev/null
+++ b/arch/arm/mach-apple/lowlevel_init.S
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2021 Mark Kettenis <kettenis@openbsd.org>
+ */
+
+.align 8
+.global fw_dtb_pointer
+fw_dtb_pointer:
+	.quad	0
+
+.global save_boot_params
+save_boot_params:
+	/* Stash DTB pointer passed by m1n1 */
+	adr	x1, fw_dtb_pointer
+	str	x0, [x1]
+
+	b	save_boot_params_ret
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 7df0e17..7f3aee5 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -151,6 +151,33 @@
 	select PINCTRL_EXYNOS7420
 	select SUPPORT_SPL
 
+config  TARGET_A5Y17LTE
+	bool "Samsung SM-A520F board"
+	select ARM64
+	select CLK_EXYNOS
+	select OF_CONTROL
+	select PINCTRL
+	select PINCTRL_EXYNOS78x0
+	select SUPPORT_SPL
+
+config  TARGET_A7Y17LTE
+	bool "Samsung SM-A520F board"
+	select ARM64
+	select CLK_EXYNOS
+	select OF_CONTROL
+	select PINCTRL
+	select PINCTRL_EXYNOS78x0
+	select SUPPORT_SPL
+
+config  TARGET_A3Y17LTE
+	bool "Samsung SM-A520F board"
+	select ARM64
+	select CLK_EXYNOS
+	select OF_CONTROL
+	select PINCTRL
+	select PINCTRL_EXYNOS7880
+	select SUPPORT_SPL
+
 endchoice
 endif
 
@@ -167,6 +194,7 @@
 source "board/samsung/smdk5250/Kconfig"
 source "board/samsung/smdk5420/Kconfig"
 source "board/samsung/espresso7420/Kconfig"
+source "board/samsung/axy17lte/Kconfig"
 
 config SPL_LDSCRIPT
 	default "board/samsung/common/exynos-uboot-spl.lds" if ARCH_EXYNOS5 || ARCH_EXYNOS4
diff --git a/arch/arm/mach-exynos/mmu-arm64.c b/arch/arm/mach-exynos/mmu-arm64.c
index 46b8169..e3bd995 100644
--- a/arch/arm/mach-exynos/mmu-arm64.c
+++ b/arch/arm/mach-exynos/mmu-arm64.c
@@ -29,3 +29,69 @@
 
 struct mm_region *mem_map = exynos7420_mem_map;
 #endif
+
+#ifdef CONFIG_EXYNOS7870
+static struct mm_region exynos7870_mem_map[] = {
+	{
+		.virt	= 0x10000000UL,
+		.phys	= 0x10000000UL,
+		.size	= 0x10000000UL,
+		.attrs	= PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+				PTE_BLOCK_NON_SHARE |
+				PTE_BLOCK_PXN | PTE_BLOCK_UXN,
+	},
+	{
+		.virt	= 0x40000000UL,
+		.phys	= 0x40000000UL,
+		.size	= 0x3E400000UL,
+		.attrs	= PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+				PTE_BLOCK_INNER_SHARE,
+	},
+	{
+		.virt	= 0x80000000UL,
+		.phys	= 0x80000000UL,
+		.size	= 0x40000000UL,
+		.attrs	= PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+				PTE_BLOCK_INNER_SHARE,
+	},
+
+	{
+		/* List terminator */
+	},
+};
+
+struct mm_region *mem_map = exynos7870_mem_map;
+#endif
+
+#ifdef CONFIG_EXYNOS7880
+static struct mm_region exynos7880_mem_map[] = {
+	{
+		.virt	= 0x10000000UL,
+		.phys	= 0x10000000UL,
+		.size	= 0x10000000UL,
+		.attrs	= PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+				PTE_BLOCK_NON_SHARE |
+				PTE_BLOCK_PXN | PTE_BLOCK_UXN,
+	},
+	{
+		.virt	= 0x40000000UL,
+		.phys	= 0x40000000UL,
+		.size	= 0x3E400000UL,
+		.attrs	= PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+				PTE_BLOCK_INNER_SHARE,
+	},
+	{
+		.virt	= 0x80000000UL,
+		.phys	= 0x80000000UL,
+		.size	= 0x80000000UL,
+		.attrs	= PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+				PTE_BLOCK_INNER_SHARE,
+	},
+
+	{
+		/* List terminator */
+	},
+};
+
+struct mm_region *mem_map = exynos7880_mem_map;
+#endif
diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c
index cad3f0a..73c4b9a 100644
--- a/arch/arm/mach-mvebu/spl.c
+++ b/arch/arm/mach-mvebu/spl.c
@@ -199,8 +199,8 @@
 		return BOOT_DEVICE_MMC1;
 #endif
 #ifdef CONFIG_SPL_SATA
-	case BOOT_FROM_SATA:
-		return BOOT_FROM_SATA;
+	case BOOT_DEVICE_SATA:
+		return BOOT_DEVICE_SATA;
 #endif
 #ifdef CONFIG_SPL_SPI_FLASH_SUPPORT
 	case BOOT_DEVICE_SPI:
diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig
index 0ec74fa..12cf02a 100644
--- a/arch/arm/mach-snapdragon/Kconfig
+++ b/arch/arm/mach-snapdragon/Kconfig
@@ -9,6 +9,14 @@
 config SPL_SYS_MALLOC_F_LEN
 	default 0x2000
 
+config SDM845
+	bool "Qualcomm Snapdragon 845 SoC"
+	default n
+	select LINUX_KERNEL_IMAGE_HEADER
+
+config LNX_KRNL_IMG_TEXT_OFFSET_BASE
+	default 0x80000000
+
 choice
 	prompt "Snapdragon board select"
 
@@ -36,9 +44,22 @@
 	  - 3GiB RAM
 	  - 32GiB UFS drive
 
+config TARGET_STARQLTECHN
+	bool "Samsung S9 SM-G9600(starqltechn)"
+	help
+	  Support for Samsung S9 SM-G9600(starqltechn) board.
+	  Features:
+	  - Qualcomm Snapdragon SDM845 SoC
+	  - 4GiB RAM
+	  - 64GiB UFS drive
+	select MISC_INIT_R
+	select SDM845
+	select DM_ETH if NET
+
 endchoice
 
 source "board/qualcomm/dragonboard410c/Kconfig"
 source "board/qualcomm/dragonboard820c/Kconfig"
+source "board/samsung/starqltechn/Kconfig"
 
 endif
diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile
index 709919f..962855e 100644
--- a/arch/arm/mach-snapdragon/Makefile
+++ b/arch/arm/mach-snapdragon/Makefile
@@ -2,6 +2,9 @@
 #
 # (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
 
+obj-$(CONFIG_SDM845) += clock-sdm845.o
+obj-$(CONFIG_SDM845) += sysmap-sdm845.o
+obj-$(CONFIG_SDM845) += init_sdm845.o
 obj-$(CONFIG_TARGET_DRAGONBOARD820C) += clock-apq8096.o
 obj-$(CONFIG_TARGET_DRAGONBOARD820C) += sysmap-apq8096.o
 obj-$(CONFIG_TARGET_DRAGONBOARD410C) += clock-apq8016.o
@@ -12,3 +15,4 @@
 obj-y += pinctrl-snapdragon.o
 obj-y += pinctrl-apq8016.o
 obj-y += pinctrl-apq8096.o
+obj-$(CONFIG_SDM845) += pinctrl-sdm845.o
diff --git a/arch/arm/mach-snapdragon/clock-sdm845.c b/arch/arm/mach-snapdragon/clock-sdm845.c
new file mode 100644
index 0000000..9572639
--- /dev/null
+++ b/arch/arm/mach-snapdragon/clock-sdm845.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Clock drivers for Qualcomm SDM845
+ *
+ * (C) Copyright 2017 Jorge Ramirez Ortiz <jorge.ramirez-ortiz@linaro.org>
+ * (C) Copyright 2021 Dzmitry Sankouski <dsankouski@gmail.com>
+ *
+ * Based on Little Kernel driver, simplified
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+#include "clock-snapdragon.h"
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+struct freq_tbl {
+	uint freq;
+	uint src;
+	u8 pre_div;
+	u16 m;
+	u16 n;
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
+	F(7372800, CFG_CLK_SRC_GPLL0_EVEN, 1, 384, 15625),
+	F(14745600, CFG_CLK_SRC_GPLL0_EVEN, 1, 768, 15625),
+	F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0),
+	F(29491200, CFG_CLK_SRC_GPLL0_EVEN, 1, 1536, 15625),
+	F(32000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 75),
+	F(48000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 25),
+	F(64000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 16, 75),
+	F(80000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 15),
+	F(96000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 25),
+	F(100000000, CFG_CLK_SRC_GPLL0_EVEN, 3, 0, 0),
+	F(102400000, CFG_CLK_SRC_GPLL0_EVEN, 1, 128, 375),
+	F(112000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 28, 75),
+	F(117964800, CFG_CLK_SRC_GPLL0_EVEN, 1, 6144, 15625),
+	F(120000000, CFG_CLK_SRC_GPLL0_EVEN, 2.5, 0, 0),
+	F(128000000, CFG_CLK_SRC_GPLL0, 1, 16, 75),
+	{ }
+};
+
+static const struct bcr_regs uart2_regs = {
+	.cfg_rcgr = SE9_UART_APPS_CFG_RCGR,
+	.cmd_rcgr = SE9_UART_APPS_CMD_RCGR,
+	.M = SE9_UART_APPS_M,
+	.N = SE9_UART_APPS_N,
+	.D = SE9_UART_APPS_D,
+};
+
+const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, uint rate)
+{
+	if (!f)
+		return NULL;
+
+	if (!f->freq)
+		return f;
+
+	for (; f->freq; f++)
+		if (rate <= f->freq)
+			return f;
+
+	/* Default to our fastest rate */
+	return f - 1;
+}
+
+static int clk_init_uart(struct msm_clk_priv *priv, uint rate)
+{
+	const struct freq_tbl *freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s0_clk_src, rate);
+
+	clk_rcg_set_rate_mnd(priv->base, &uart2_regs,
+						freq->pre_div, freq->m, freq->n, freq->src);
+
+	return 0;
+}
+
+ulong msm_set_rate(struct clk *clk, ulong rate)
+{
+	struct msm_clk_priv *priv = dev_get_priv(clk->dev);
+
+	switch (clk->id) {
+	case 0x58: /*UART2*/
+		return clk_init_uart(priv, rate);
+	default:
+		return 0;
+	}
+}
diff --git a/arch/arm/mach-snapdragon/clock-snapdragon.c b/arch/arm/mach-snapdragon/clock-snapdragon.c
index 2b76371..3deb08a 100644
--- a/arch/arm/mach-snapdragon/clock-snapdragon.c
+++ b/arch/arm/mach-snapdragon/clock-snapdragon.c
@@ -135,6 +135,7 @@
 	{ .compatible = "qcom,gcc-apq8016" },
 	{ .compatible = "qcom,gcc-msm8996" },
 	{ .compatible = "qcom,gcc-apq8096" },
+	{ .compatible = "qcom,gcc-sdm845" },
 	{ }
 };
 
diff --git a/arch/arm/mach-snapdragon/clock-snapdragon.h b/arch/arm/mach-snapdragon/clock-snapdragon.h
index 58fab40..2ac53b5 100644
--- a/arch/arm/mach-snapdragon/clock-snapdragon.h
+++ b/arch/arm/mach-snapdragon/clock-snapdragon.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * Qualcomm APQ8016, APQ8096
+ * Qualcomm APQ8016, APQ8096, SDM845
  *
  * (C) Copyright 2017 Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
  */
@@ -9,6 +9,7 @@
 
 #define CFG_CLK_SRC_CXO   (0 << 8)
 #define CFG_CLK_SRC_GPLL0 (1 << 8)
+#define CFG_CLK_SRC_GPLL0_EVEN (6 << 8)
 #define CFG_CLK_SRC_MASK  (7 << 8)
 
 struct pll_vote_clk {
diff --git a/arch/arm/mach-snapdragon/include/mach/sysmap-sdm845.h b/arch/arm/mach-snapdragon/include/mach/sysmap-sdm845.h
new file mode 100644
index 0000000..7165985
--- /dev/null
+++ b/arch/arm/mach-snapdragon/include/mach/sysmap-sdm845.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Qualcomm SDM845 sysmap
+ *
+ * (C) Copyright 2021 Dzmitry Sankouski <dsankouski@gmail.com>
+ */
+#ifndef _MACH_SYSMAP_SDM845_H
+#define _MACH_SYSMAP_SDM845_H
+
+#define TLMM_BASE_ADDR			(0x1010000)
+
+/* Strength (sdc1) */
+#define SDC1_HDRV_PULL_CTL_REG		(TLMM_BASE_ADDR + 0x0012D000)
+
+/* Clocks: (from CLK_CTL_BASE)  */
+#define GPLL0_STATUS			(0x0000)
+#define APCS_GPLL_ENA_VOTE		(0x52000)
+#define APCS_CLOCK_BRANCH_ENA_VOTE	(0x52004)
+
+#define SDCC2_BCR			(0x14000) /* block reset */
+#define SDCC2_APPS_CBCR			(0x14004) /* branch control */
+#define SDCC2_AHB_CBCR			(0x14008)
+#define SDCC2_CMD_RCGR			(0x1400c)
+#define SDCC2_CFG_RCGR			(0x14010)
+#define SDCC2_M				(0x14014)
+#define SDCC2_N				(0x14018)
+#define SDCC2_D				(0x1401C)
+
+#define RCG2_CFG_REG			0x4
+#define M_REG			0x8
+#define N_REG			0xc
+#define D_REG			0x10
+
+#define SE9_AHB_CBCR			(0x25004)
+#define SE9_UART_APPS_CBCR		(0x29004)
+#define SE9_UART_APPS_CMD_RCGR	(0x18148)
+#define SE9_UART_APPS_CFG_RCGR	(0x1814C)
+#define SE9_UART_APPS_M		(0x18150)
+#define SE9_UART_APPS_N		(0x18154)
+#define SE9_UART_APPS_D		(0x18158)
+
+#endif
diff --git a/arch/arm/mach-snapdragon/init_sdm845.c b/arch/arm/mach-snapdragon/init_sdm845.c
new file mode 100644
index 0000000..5f53c21
--- /dev/null
+++ b/arch/arm/mach-snapdragon/init_sdm845.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Common init part for boards based on SDM845
+ *
+ * (C) Copyright 2021 Dzmitry Sankouski <dsankouski@gmail.com>
+ */
+
+#include <init.h>
+#include <env.h>
+#include <common.h>
+#include <asm/system.h>
+#include <asm/gpio.h>
+#include <dm.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+	return fdtdec_setup_mem_size_base();
+}
+
+void reset_cpu(void)
+{
+	psci_system_reset();
+}
+
+__weak int board_init(void)
+{
+	return 0;
+}
+
+/* Check for vol- and power buttons */
+__weak int misc_init_r(void)
+{
+	struct udevice *pon;
+	struct gpio_desc resin;
+	int node, ret;
+
+	ret = uclass_get_device_by_name(UCLASS_GPIO, "pm8998_pon@800", &pon);
+	if (ret < 0) {
+		printf("Failed to find PMIC pon node. Check device tree\n");
+		return 0;
+	}
+
+	node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(pon),
+				  "key_vol_down");
+	if (node < 0) {
+		printf("Failed to find key_vol_down node. Check device tree\n");
+		return 0;
+	}
+	if (gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0,
+				       &resin, 0)) {
+		printf("Failed to request key_vol_down button.\n");
+		return 0;
+	}
+	if (dm_gpio_get_value(&resin)) {
+		env_set("key_vol_down", "1");
+		printf("Volume down button pressed\n");
+	} else {
+		env_set("key_vol_down", "0");
+	}
+
+	node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(pon),
+				  "key_power");
+	if (node < 0) {
+		printf("Failed to find key_power node. Check device tree\n");
+		return 0;
+	}
+	if (gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0,
+				       &resin, 0)) {
+		printf("Failed to request key_power button.\n");
+		return 0;
+	}
+	if (dm_gpio_get_value(&resin)) {
+		env_set("key_power", "1");
+		printf("Power button pressed\n");
+	} else {
+		env_set("key_power", "0");
+	}
+
+	return 0;
+}
diff --git a/arch/arm/mach-snapdragon/pinctrl-sdm845.c b/arch/arm/mach-snapdragon/pinctrl-sdm845.c
new file mode 100644
index 0000000..40f2f01
--- /dev/null
+++ b/arch/arm/mach-snapdragon/pinctrl-sdm845.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Qualcomm SDM845 pinctrl
+ *
+ * (C) Copyright 2021 Dzmitry Sankouski <dsankouski@gmail.com>
+ *
+ */
+
+#include "pinctrl-snapdragon.h"
+#include <common.h>
+
+#define MAX_PIN_NAME_LEN 32
+static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
+
+static const struct pinctrl_function msm_pinctrl_functions[] = {
+	{"qup9", 1},
+	{"gpio", 0},
+};
+
+static const char *sdm845_get_function_name(struct udevice *dev,
+					     unsigned int selector)
+{
+	return msm_pinctrl_functions[selector].name;
+}
+
+static const char *sdm845_get_pin_name(struct udevice *dev,
+					unsigned int selector)
+{
+	snprintf(pin_name, MAX_PIN_NAME_LEN, "GPIO_%u", selector);
+	return pin_name;
+}
+
+static unsigned int sdm845_get_function_mux(unsigned int selector)
+{
+	return msm_pinctrl_functions[selector].val;
+}
+
+struct msm_pinctrl_data sdm845_data = {
+	.pin_count = 150,
+	.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
+	.get_function_name = sdm845_get_function_name,
+	.get_function_mux = sdm845_get_function_mux,
+	.get_pin_name = sdm845_get_pin_name,
+};
diff --git a/arch/arm/mach-snapdragon/pinctrl-snapdragon.c b/arch/arm/mach-snapdragon/pinctrl-snapdragon.c
index e6b87c3..d1c560d 100644
--- a/arch/arm/mach-snapdragon/pinctrl-snapdragon.c
+++ b/arch/arm/mach-snapdragon/pinctrl-snapdragon.c
@@ -116,6 +116,9 @@
 static const struct udevice_id msm_pinctrl_ids[] = {
 	{ .compatible = "qcom,tlmm-apq8016", .data = (ulong)&apq8016_data },
 	{ .compatible = "qcom,tlmm-apq8096", .data = (ulong)&apq8096_data },
+#ifdef CONFIG_SDM845
+	{ .compatible = "qcom,tlmm-sdm845", .data = (ulong)&sdm845_data },
+#endif
 	{ }
 };
 
diff --git a/arch/arm/mach-snapdragon/pinctrl-snapdragon.h b/arch/arm/mach-snapdragon/pinctrl-snapdragon.h
index 61d466f..ea52431 100644
--- a/arch/arm/mach-snapdragon/pinctrl-snapdragon.h
+++ b/arch/arm/mach-snapdragon/pinctrl-snapdragon.h
@@ -27,5 +27,6 @@
 
 extern struct msm_pinctrl_data apq8016_data;
 extern struct msm_pinctrl_data apq8096_data;
+extern struct msm_pinctrl_data sdm845_data;
 
 #endif
diff --git a/arch/arm/mach-snapdragon/sysmap-sdm845.c b/arch/arm/mach-snapdragon/sysmap-sdm845.c
new file mode 100644
index 0000000..721ac41
--- /dev/null
+++ b/arch/arm/mach-snapdragon/sysmap-sdm845.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Qualcomm SDM845 memory map
+ *
+ * (C) Copyright 2021 Dzmitry Sankouski <dsankousk@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/armv8/mmu.h>
+
+static struct mm_region sdm845_mem_map[] = {
+	{
+		.virt = 0x0UL, /* Peripheral block */
+		.phys = 0x0UL, /* Peripheral block */
+		.size = 0x10000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		.virt = 0x80000000UL, /* DDR */
+		.phys = 0x80000000UL, /* DDR */
+		.size = 0x200000000UL, /* 8GiB - maximum allowed memory */
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = sdm845_mem_map;
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index e27d106..8cd688e 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -764,6 +764,11 @@
 		vss-microvolts = <0>;
 	};
 
+	iommu: iommu@0 {
+		compatible = "sandbox,iommu";
+		#iommu-cells = <0>;
+	};
+
 	irq: irq {
 		compatible = "sandbox,irq";
 		interrupt-controller;
@@ -1226,6 +1231,7 @@
 
 	usb_1: usb@1 {
 		compatible = "sandbox,usb";
+		iommus = <&iommu>;
 		hub {
 			compatible = "usb-hub";
 			usb,device-class = <9>;
diff --git a/board/broadcom/bcmns3/ns3.c b/board/broadcom/bcmns3/ns3.c
index 758a358..32acf36 100644
--- a/board/broadcom/bcmns3/ns3.c
+++ b/board/broadcom/bcmns3/ns3.c
@@ -196,7 +196,8 @@
 {
 	u32 chimp_hs = CHIMP_HANDSHAKE_WAIT_TIMEOUT;
 
-	gic_lpi_tables_init();
+	/* FIXME: Need to call gic_lpi_tables_init correctly now */
+	printf("%s: failed to init gic-lpi-tables\n", __func__);
 
 	/*
 	 * Check for chimp handshake status.
diff --git a/board/samsung/axy17lte/Kconfig b/board/samsung/axy17lte/Kconfig
new file mode 100644
index 0000000..2abf8e7
--- /dev/null
+++ b/board/samsung/axy17lte/Kconfig
@@ -0,0 +1,58 @@
+config SYS_CONFIG_NAME
+	string "Board configuration name"
+	default "exynos78x0-common.h"
+	help
+	  This option contains information about board configuration name.
+	  Based on this option include/configs/<CONFIG_SYS_CONFIG_NAME>.h header
+	  will be used for board configuration.
+
+if TARGET_A5Y17LTE
+config SYS_BOARD
+	default "axy17lte"
+	help
+	  a5y17lte is a production board for SM-A520F phone on Exynos7880 SoC.
+
+config SYS_VENDOR
+	default "samsung"
+
+config SYS_CONFIG_NAME
+	default "a5y17lte"
+
+config EXYNOS7880
+    bool "Exynos 7880 SOC support"
+    default y
+endif
+
+if TARGET_A7Y17LTE
+config SYS_BOARD
+	default "axy17lte"
+	help
+	  a5y17lte is a production board for SM-A520F phone on Exynos7880 SoC.
+
+config SYS_VENDOR
+	default "samsung"
+
+config SYS_CONFIG_NAME
+	default "a5y17lte"
+
+config EXYNOS7880
+    bool "Exynos 7880 SOC support"
+    default y
+endif
+
+if TARGET_A3Y17LTE
+config SYS_BOARD
+	default "axy17lte"
+	help
+	  a3y17lte is a production board for SM-A520F phone on Exynos7880 SoC.
+
+config SYS_VENDOR
+	default "samsung"
+
+config SYS_CONFIG_NAME
+	default "a3y17lte"
+
+config EXYNOS7870
+    bool "Exynos 7870 SOC support"
+    default y
+endif
diff --git a/board/samsung/axy17lte/MAINTAINERS b/board/samsung/axy17lte/MAINTAINERS
new file mode 100644
index 0000000..13feba6
--- /dev/null
+++ b/board/samsung/axy17lte/MAINTAINERS
@@ -0,0 +1,8 @@
+Samsung A series 2017 phones Board
+M:	Dzmitry Sankouski <dsankouski@gmail.com>
+S:	Maintained
+F:	board/samsung/axy17lte/
+F:	include/configs/exynos78x0-common.h
+F:	configs/a3y17lte_defconfig
+F:	configs/a5y17lte_defconfig
+F:	configs/a7y17lte_defconfig
diff --git a/board/samsung/axy17lte/Makefile b/board/samsung/axy17lte/Makefile
new file mode 100644
index 0000000..4e11f28
--- /dev/null
+++ b/board/samsung/axy17lte/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+obj-y	+= axy17lte.o
diff --git a/board/samsung/axy17lte/axy17lte.c b/board/samsung/axy17lte/axy17lte.c
new file mode 100644
index 0000000..c38297a
--- /dev/null
+++ b/board/samsung/axy17lte/axy17lte.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Samsung A5Y17 and A3Y17 LTE boards based on Exynos 7880 and Exynos 7870 SoCs
+ */
+
+#include <common.h>
+
+int exynos_init(void)
+{
+	return 0;
+}
diff --git a/board/samsung/starqltechn/Kconfig b/board/samsung/starqltechn/Kconfig
new file mode 100644
index 0000000..0eea666
--- /dev/null
+++ b/board/samsung/starqltechn/Kconfig
@@ -0,0 +1,22 @@
+if TARGET_STARQLTECHN
+
+config SYS_BOARD
+	default "starqltechn"
+	help
+	  starqltechn is a production board for S9 and S9+ phones(SM-G96x0) phones based on SDM845 SoC.
+
+config SYS_CONFIG_NAME
+	string "Board configuration name"
+	default "sdm845"
+	help
+	  This option contains information about board configuration name.
+	  Based on this option include/configs/<CONFIG_SYS_CONFIG_NAME>.h header
+	  will be used for board configuration.
+
+config SYS_VENDOR
+	default "samsung"
+
+config SYS_CONFIG_NAME
+	default "starqltechn"
+
+endif
diff --git a/board/samsung/starqltechn/MAINTAINERS b/board/samsung/starqltechn/MAINTAINERS
new file mode 100644
index 0000000..135cafd
--- /dev/null
+++ b/board/samsung/starqltechn/MAINTAINERS
@@ -0,0 +1,6 @@
+Samsung S9 (SM-G9600)(starqltechn)  Board
+M:	Dzmitry Sankouski <dsankouski@gmail.com>
+S:	Maintained
+F:	board/samsung/starqltechn/
+F:	include/configs/starqltechn.h
+F:	configs/starqltechn_defconfig
diff --git a/board/samsung/starqltechn/Makefile b/board/samsung/starqltechn/Makefile
new file mode 100644
index 0000000..c38c0b4
--- /dev/null
+++ b/board/samsung/starqltechn/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2021 Dzmitry Sankouski <dsankouski@gmail.com>
+#
+# This empty file prevents make error.
+# Board logic defined in board/qualcomm/common/sdm845.c, no custom logic for starqltechn so far.
+#
+
+obj-y += starqltechn.o
diff --git a/board/samsung/starqltechn/starqltechn.c b/board/samsung/starqltechn/starqltechn.c
new file mode 100644
index 0000000..f2cdb4e
--- /dev/null
+++ b/board/samsung/starqltechn/starqltechn.c
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * This empty file prevents make linking error.
+ * No custom logic for starqltechn so far.
+ *
+ * (C) Copyright 2021 Dzmitry Sankouski <dsankouski@gmail.com>
+ *
+ */
+
+void nooop(void) {}
diff --git a/configs/a3y17lte_defconfig b/configs/a3y17lte_defconfig
new file mode 100644
index 0000000..36404d1
--- /dev/null
+++ b/configs/a3y17lte_defconfig
@@ -0,0 +1,24 @@
+CONFIG_ARM=y
+CONFIG_ARCH_EXYNOS=y
+CONFIG_ARCH_EXYNOS7=y
+CONFIG_S5P=y
+CONFIG_TARGET_A3Y17LTE=y
+# This option is a number of 256MB DRAM banks, i.e. (ram size) / 256MB.
+# Used in samsung common board dram_init function.
+CONFIG_NR_DRAM_BANKS=8
+CONFIG_SYS_CONFIG_NAME="exynos78x0-common"
+CONFIG_DEFAULT_DEVICE_TREE="exynos78x0-axy17lte"
+CONFIG_SYS_TEXT_BASE=0x40001000
+CONFIG_SYS_LOAD_ADDR=0x40001000
+CONFIG_HUSH_PARSER=y
+CONFIG_FIT=y
+CONFIG_BOARD_EARLY_INIT_F=n
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_CMD_GPIO=y
+CONFIG_DISPLAY_CPUINFO=n
+CONFIG_CMD_I2C=y
+CONFIG_DM_I2C_GPIO=y
+CONFIG_PINCTRL_EXYNOS78x0=y
+CONFIG_PINCTRL_EXYNOS=y
+# CONFIG_DEBUG_UART_S5P=y
+# CONFIG_DEBUG_UART_BASE=0x13820000
\ No newline at end of file
diff --git a/configs/a5y17lte_defconfig b/configs/a5y17lte_defconfig
new file mode 100644
index 0000000..273ad10
--- /dev/null
+++ b/configs/a5y17lte_defconfig
@@ -0,0 +1,24 @@
+CONFIG_ARM=y
+CONFIG_ARCH_EXYNOS=y
+CONFIG_ARCH_EXYNOS7=y
+CONFIG_S5P=y
+CONFIG_TARGET_A5Y17LTE=y
+# This option is a number of 256MB DRAM banks, i.e. (ram size) / 256MB.
+# Used in samsung common board dram_init function.
+CONFIG_NR_DRAM_BANKS=12
+CONFIG_SYS_CONFIG_NAME="exynos78x0-common"
+CONFIG_DEFAULT_DEVICE_TREE="exynos78x0-axy17lte"
+CONFIG_SYS_TEXT_BASE=0x40001000
+CONFIG_SYS_LOAD_ADDR=0x40001000
+CONFIG_HUSH_PARSER=y
+CONFIG_FIT=y
+CONFIG_BOARD_EARLY_INIT_F=n
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_CMD_GPIO=y
+CONFIG_DISPLAY_CPUINFO=n
+CONFIG_CMD_I2C=y
+CONFIG_DM_I2C_GPIO=y
+CONFIG_PINCTRL_EXYNOS78x0=y
+CONFIG_PINCTRL_EXYNOS=y
+# CONFIG_DEBUG_UART_S5P=y
+# CONFIG_DEBUG_UART_BASE=0x13820000
\ No newline at end of file
diff --git a/configs/a7y17lte_defconfig b/configs/a7y17lte_defconfig
new file mode 100644
index 0000000..f544f62
--- /dev/null
+++ b/configs/a7y17lte_defconfig
@@ -0,0 +1,24 @@
+CONFIG_ARM=y
+CONFIG_ARCH_EXYNOS=y
+CONFIG_ARCH_EXYNOS7=y
+CONFIG_S5P=y
+CONFIG_TARGET_A7Y17LTE=y
+# This option is a number of 256MB DRAM banks, i.e. (ram size) / 256MB.
+# Used in samsung common board dram_init function.
+CONFIG_NR_DRAM_BANKS=12
+CONFIG_SYS_CONFIG_NAME="exynos78x0-common"
+CONFIG_DEFAULT_DEVICE_TREE="exynos78x0-axy17lte"
+CONFIG_SYS_TEXT_BASE=0x40001000
+CONFIG_SYS_LOAD_ADDR=0x40001000
+CONFIG_HUSH_PARSER=y
+CONFIG_FIT=y
+CONFIG_BOARD_EARLY_INIT_F=n
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_CMD_GPIO=y
+CONFIG_DISPLAY_CPUINFO=n
+CONFIG_CMD_I2C=y
+CONFIG_DM_I2C_GPIO=y
+CONFIG_PINCTRL_EXYNOS78x0=y
+CONFIG_PINCTRL_EXYNOS=y
+# CONFIG_DEBUG_UART_S5P=y
+# CONFIG_DEBUG_UART_BASE=0x13820000
\ No newline at end of file
diff --git a/configs/apple_m1_defconfig b/configs/apple_m1_defconfig
new file mode 100644
index 0000000..d71cbfd
--- /dev/null
+++ b/configs/apple_m1_defconfig
@@ -0,0 +1,20 @@
+CONFIG_ARM=y
+CONFIG_ARCH_APPLE=y
+CONFIG_DEFAULT_DEVICE_TREE="t8103-j274"
+# CONFIG_DISPLAY_CPUINFO is not set
+# CONFIG_MMC is not set
+# CONFIG_NET is not set
+CONFIG_VIDEO_SIMPLE=y
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USE_PREBOOT=y
+CONFIG_PREBOOT="usb start"
+CONFIG_SYS_LOAD_ADDR=0x880000000
+# CONFIG_GENERATE_SMBIOS_TABLE is not set
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_DEBUG_UART_BASE=0x235200000
+CONFIG_DEBUG_UART_CLOCK=240000
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 838280e..4582889 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -130,6 +130,7 @@
 CONFIG_I2C_ARB_GPIO_CHALLENGE=y
 CONFIG_CROS_EC_KEYB=y
 CONFIG_I8042_KEYB=y
+CONFIG_IOMMU=y
 CONFIG_LED=y
 CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index d07a7f3..9385857 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -168,6 +168,7 @@
 CONFIG_I2C_ARB_GPIO_CHALLENGE=y
 CONFIG_CROS_EC_KEYB=y
 CONFIG_I8042_KEYB=y
+CONFIG_IOMMU=y
 CONFIG_LED=y
 CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index 5980c86..edfdac8 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -107,6 +107,7 @@
 CONFIG_I2C_ARB_GPIO_CHALLENGE=y
 CONFIG_CROS_EC_KEYB=y
 CONFIG_I8042_KEYB=y
+CONFIG_IOMMU=y
 CONFIG_LED=y
 CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig
index 238604f..ab37849 100644
--- a/configs/sandbox_noinst_defconfig
+++ b/configs/sandbox_noinst_defconfig
@@ -128,6 +128,7 @@
 CONFIG_I2C_ARB_GPIO_CHALLENGE=y
 CONFIG_CROS_EC_KEYB=y
 CONFIG_I8042_KEYB=y
+CONFIG_IOMMU=y
 CONFIG_LED=y
 CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index b9da8dc..9a0a678 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -130,6 +130,7 @@
 CONFIG_I2C_ARB_GPIO_CHALLENGE=y
 CONFIG_CROS_EC_KEYB=y
 CONFIG_I8042_KEYB=y
+CONFIG_IOMMU=y
 CONFIG_LED=y
 CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
diff --git a/configs/starqltechn_defconfig b/configs/starqltechn_defconfig
new file mode 100644
index 0000000..f57bb85
--- /dev/null
+++ b/configs/starqltechn_defconfig
@@ -0,0 +1,24 @@
+CONFIG_ARM=y
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_POSITION_INDEPENDENT=y
+CONFIG_ARCH_SNAPDRAGON=y
+CONFIG_SYS_TEXT_BASE=0x80000000
+CONFIG_SYS_MALLOC_LEN=0x81f000
+CONFIG_DEFAULT_DEVICE_TREE="starqltechn"
+CONFIG_TARGET_STARQLTECHN=y
+CONFIG_IDENT_STRING="\nSamsung S9 SM-G9600"
+CONFIG_SYS_LOAD_ADDR=0x80000000
+CONFIG_USE_PREBOOT=y
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_GPIO=y
+# CONFIG_NET is not set
+# CONFIG_DM_STDIO is not set
+CONFIG_CLK=y
+CONFIG_MSM_GPIO=y
+CONFIG_PM8916_GPIO=y
+CONFIG_PINCTRL=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_PM8916=y
+CONFIG_MSM_GENI_SERIAL=y
+CONFIG_SPMI_MSM=y
diff --git a/doc/board/apple/index.rst b/doc/board/apple/index.rst
new file mode 100644
index 0000000..8446847
--- /dev/null
+++ b/doc/board/apple/index.rst
@@ -0,0 +1,9 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Apple
+=====
+
+.. toctree::
+   :maxdepth: 2
+
+   m1
diff --git a/doc/board/apple/m1.rst b/doc/board/apple/m1.rst
new file mode 100644
index 0000000..9fa2176
--- /dev/null
+++ b/doc/board/apple/m1.rst
@@ -0,0 +1,59 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+U-Boot for Apple Silicon Macs
+=============================
+
+Allows Apple Silicon Macs to boot U-Boot via the m1n1 bootloader
+developed by the Asahi Linux project.  At this point the machines with
+the following SoCs work:
+
+ - Apple M1 SoC
+
+On these SoCs the following hardware is supported:
+
+ - S5L serial port
+ - Framebuffer
+ - USB 3.1 Type-C ports
+
+Device trees are currently provided for the M1 Mac mini (2020, J274)
+and M1 MacBook Pro 13" (2020, J293).  The M1 MacBook Air (2020) is
+expected to work with the J293 device tree.  The M1 iMac (2021) may
+work with the J274 device tree.
+
+Building U-Boot
+---------------
+
+.. code-block:: bash
+
+    $ export CROSS_COMPILE=aarch64-none-elf-
+    $ make apple_m1_defconfig
+    $ make
+
+This will build ``u-boot-nodtb.bin`` as well as devices trees for some
+of the supported machines.  These device trees can be found in the
+``arch/arm/dts`` subdirectory of your build.
+
+Image creation
+--------------
+
+In order to run U-Boot on an Apple Silicon Mac, U-Boot has to be used
+as a payload for the m1n1 bootloader.  Instructions for building m1n1
+can be found here:
+
+    https://github.com/AsahiLinux/docs/wiki/SW%3Am1n1
+
+.. code-block:: bash
+
+    $ cat m1n1.macho t8103-j274.dtb u-boot-nodtb.bin > u-boot.macho
+
+This uses ``u-boot-nodtb.bin`` as the device tree is passed to U-Boot
+by m1n1 after making some adjustments.
+
+Image installation
+------------------
+
+Instructions on how to install U-Boot on your Mac can be found at:
+
+    https://github.com/AsahiLinux/docs/wiki/Developer-Quickstart
+
+Just replace ``m1n1.macho`` with ``u-boot.macho`` in the instructions.
diff --git a/doc/board/index.rst b/doc/board/index.rst
index aa397ab..74ea33e 100644
--- a/doc/board/index.rst
+++ b/doc/board/index.rst
@@ -10,6 +10,7 @@
    advantech/index
    AndesTech/index
    amlogic/index
+   apple/index
    atmel/index
    congatec/index
    coreboot/index
@@ -22,6 +23,7 @@
    openpiton/index
    qualcomm/index
    rockchip/index
+   samsung/index
    siemens/index
    sifive/index
    sipeed/index
diff --git a/doc/board/qualcomm/index.rst b/doc/board/qualcomm/index.rst
index f7e0aa9..10b9821 100644
--- a/doc/board/qualcomm/index.rst
+++ b/doc/board/qualcomm/index.rst
@@ -7,3 +7,4 @@
    :maxdepth: 2
 
    dragonboard410c
+   sdm845
diff --git a/doc/board/qualcomm/sdm845.rst b/doc/board/qualcomm/sdm845.rst
new file mode 100644
index 0000000..cd46cbe
--- /dev/null
+++ b/doc/board/qualcomm/sdm845.rst
@@ -0,0 +1,38 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. sectionauthor:: Dzmitry Sankouski <dsankouski@gmail.com>
+
+Snapdragon 845
+================
+
+About this
+----------
+This document describes the information about Qualcomm Snapdragon 845
+supported boards and it's usage steps.
+
+SDM845 - hi-end qualcomm chip, introduced in late 2017.
+Mostly used in flagship phones and tablets of 2018.
+
+U-Boot can be used as a replacement for Qualcomm's original ABL (UEFI) bootloader.
+It is loaded as an Android boot image through ABL
+
+Installation
+------------
+First, setup ``CROSS_COMPILE`` for aarch64. Then, build U-Boot for your board::
+
+	$ export CROSS_COMPILE=<aarch64 toolchain prefix>
+	$ make <your board name here, see Boards section>_defconfig
+	$ make
+
+This will build ``u-boot.bin`` in the configured output directory.
+
+Boards
+------------
+starqlte
+^^^^^^^^^^^^
+
+The starqltechn is a production board for Samsung S9 (SM-G9600) phone,
+based on the Qualcomm SDM845 SoC.
+
+More information can be found on the `Samsung S9 page`_.
+
+.. _Samsung S9 page: https://en.wikipedia.org/wiki/Samsung_Galaxy_S9
diff --git a/doc/board/samsung/axy17lte.rst b/doc/board/samsung/axy17lte.rst
new file mode 100644
index 0000000..511cd57
--- /dev/null
+++ b/doc/board/samsung/axy17lte.rst
@@ -0,0 +1,94 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. sectionauthor:: Dzmitry Sankouski <dsankouski@gmail.com>
+
+Samsung 2017 A series phones
+============================
+
+About this
+----------
+This document describes the information about Samsung A(7/5/3) 2017 midrange
+phones and u-boot usage steps.
+
+U-Boot can be used as a chain-loaded bootloader to replace Samsung's original SBOOT bootloader.
+It is loaded as an Android boot image through SBOOT.
+
+Phone specs
+-----------
+A3 (SM-320) (a3y17lte)
+^^^^^^^^^^^^^^^^^^^^^^
+- 4.7 AMOLED display
+- Exynos 7870 SoC
+- 16GB flash
+- 2GB RAM
+
+.. A3 2017 wiki page: https://en.wikipedia.org/wiki/Samsung_Galaxy_A3_(2017)
+
+A5 (SM-520) (a5y17lte)
+^^^^^^^^^^^^^^^^^^^^^^
+- 5.2 AMOLED display
+- Exynos 7880 SoC
+- 32GB flash
+- 3GB RAM
+
+.. A5 2017 wiki page: https://en.wikipedia.org/wiki/Samsung_Galaxy_A5_(2017)
+
+A7 (SM-720) (a5y17lte)
+^^^^^^^^^^^^^^^^^^^^^^
+- 5.7 AMOLED display
+- Exynos 7880 SoC
+- 32GB flash
+- 3GB RAM
+
+.. A7 2017 wiki page: https://en.wikipedia.org/wiki/Samsung_Galaxy_A7_(2017)
+
+Installation
+------------
+
+Building u-boot
+^^^^^^^^^^^^^^^
+
+First, setup ``CROSS_COMPILE`` for aarch64.
+Then, build U-Boot for your phone, for example ``a5y17lte``::
+
+  $ export CROSS_COMPILE=<aarch64 toolchain prefix>
+  $ make a5y17lte_defconfig
+  $ make
+
+This will build ``u-boot.bin`` in the configured output directory.
+
+Payload
+^^^^^^^
+What is a payload?
+""""""""""""""""""
+A payload file is a file to be used instead of linux kernel in android boot image.
+This file will be loaded into memory, and executed by SBOOT,
+and is therefore SBOOT's payload.
+It may be pure u-boot (with loading u-boot's payload from flash in mind),
+or u-boot + u-boot's payload.
+
+It should be kept in mind, that SBOOT binary patches it's payload after loading
+in address range 0x401f8550-0x401f9280. Given SBOOT loads payload to 0x40001000,
+a range of 0x1f7550-0x1f8280 (2061648-2065024) in a payload file
+will be corrupted after loading to RAM.
+
+Creating payload file
+"""""""""""""""""""""
+- Assemble FIT image for your kernel
+- Create a file for u-boot payload ``touch sboot-payload``
+- Write zeroes till 0x200000 address to be sure SBOOT won't corrupt your info
+  ``dd if=/dev/zero of=sboot-payload bs=$((0x200000)) count=1``
+- Write u-boot to the start of the payload ``dd if=<u-boot.bin path> of=sboot-payload``
+- Write FIT image to payload from 0x200000 address
+  ``dd if=<FIT image path> of=sboot-payload seek=1 bs=2M``
+
+Creating android boot image
+"""""""""""""""""""""""""""
+Once payload created, it's time for android image::
+
+  mkbootimg --base 0x40000000 --kernel_offset 0x00000000 --ramdisk_offset 0x01000000 --tags_offset 0x00000100 --pagesize 2048 --second_offset 0x00f00000 --kernel <sboot-payload path> -o uboot.img
+
+Note, that stock Samsung bootloader ignores offsets, set in mkbootimg.
+
+Flashing
+""""""""
+Flash like regular android boot image.
diff --git a/doc/board/samsung/index.rst b/doc/board/samsung/index.rst
new file mode 100644
index 0000000..c904372
--- /dev/null
+++ b/doc/board/samsung/index.rst
@@ -0,0 +1,9 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Samsung
+========
+
+.. toctree::
+   :maxdepth: 2
+
+   axy17lte
diff --git a/doc/device-tree-bindings/iommu/iommu.txt b/doc/device-tree-bindings/iommu/iommu.txt
new file mode 100644
index 0000000..26ba9e5
--- /dev/null
+++ b/doc/device-tree-bindings/iommu/iommu.txt
@@ -0,0 +1,206 @@
+This document describes the generic device tree binding for IOMMUs and their
+master(s).
+
+
+IOMMU device node:
+==================
+
+An IOMMU can provide the following services:
+
+* Remap address space to allow devices to access physical memory ranges that
+  they otherwise wouldn't be capable of accessing.
+
+  Example: 32-bit DMA to 64-bit physical addresses
+
+* Implement scatter-gather at page level granularity so that the device does
+  not have to.
+
+* Provide system protection against "rogue" DMA by forcing all accesses to go
+  through the IOMMU and faulting when encountering accesses to unmapped
+  address regions.
+
+* Provide address space isolation between multiple contexts.
+
+  Example: Virtualization
+
+Device nodes compatible with this binding represent hardware with some of the
+above capabilities.
+
+IOMMUs can be single-master or multiple-master. Single-master IOMMU devices
+typically have a fixed association to the master device, whereas multiple-
+master IOMMU devices can translate accesses from more than one master.
+
+The device tree node of the IOMMU device's parent bus must contain a valid
+"dma-ranges" property that describes how the physical address space of the
+IOMMU maps to memory. An empty "dma-ranges" property means that there is a
+1:1 mapping from IOMMU to memory.
+
+Required properties:
+--------------------
+- #iommu-cells: The number of cells in an IOMMU specifier needed to encode an
+  address.
+
+The meaning of the IOMMU specifier is defined by the device tree binding of
+the specific IOMMU. Below are a few examples of typical use-cases:
+
+- #iommu-cells = <0>: Single master IOMMU devices are not configurable and
+  therefore no additional information needs to be encoded in the specifier.
+  This may also apply to multiple master IOMMU devices that do not allow the
+  association of masters to be configured. Note that an IOMMU can by design
+  be multi-master yet only expose a single master in a given configuration.
+  In such cases the number of cells will usually be 1 as in the next case.
+- #iommu-cells = <1>: Multiple master IOMMU devices may need to be configured
+  in order to enable translation for a given master. In such cases the single
+  address cell corresponds to the master device's ID. In some cases more than
+  one cell can be required to represent a single master ID.
+- #iommu-cells = <4>: Some IOMMU devices allow the DMA window for masters to
+  be configured. The first cell of the address in this may contain the master
+  device's ID for example, while the second cell could contain the start of
+  the DMA window for the given device. The length of the DMA window is given
+  by the third and fourth cells.
+
+Note that these are merely examples and real-world use-cases may use different
+definitions to represent their individual needs. Always refer to the specific
+IOMMU binding for the exact meaning of the cells that make up the specifier.
+
+
+IOMMU master node:
+==================
+
+Devices that access memory through an IOMMU are called masters. A device can
+have multiple master interfaces (to one or more IOMMU devices).
+
+Required properties:
+--------------------
+- iommus: A list of phandle and IOMMU specifier pairs that describe the IOMMU
+  master interfaces of the device. One entry in the list describes one master
+  interface of the device.
+
+When an "iommus" property is specified in a device tree node, the IOMMU will
+be used for address translation. If a "dma-ranges" property exists in the
+device's parent node it will be ignored. An exception to this rule is if the
+referenced IOMMU is disabled, in which case the "dma-ranges" property of the
+parent shall take effect. Note that merely disabling a device tree node does
+not guarantee that the IOMMU is really disabled since the hardware may not
+have a means to turn off translation. But it is invalid in such cases to
+disable the IOMMU's device tree node in the first place because it would
+prevent any driver from properly setting up the translations.
+
+Optional properties:
+--------------------
+- pasid-num-bits: Some masters support multiple address spaces for DMA, by
+  tagging DMA transactions with an address space identifier. By default,
+  this is 0, which means that the device only has one address space.
+
+- dma-can-stall: When present, the master can wait for a transaction to
+  complete for an indefinite amount of time. Upon translation fault some
+  IOMMUs, instead of aborting the translation immediately, may first
+  notify the driver and keep the transaction in flight. This allows the OS
+  to inspect the fault and, for example, make physical pages resident
+  before updating the mappings and completing the transaction. Such IOMMU
+  accepts a limited number of simultaneous stalled transactions before
+  having to either put back-pressure on the master, or abort new faulting
+  transactions.
+
+  Firmware has to opt-in stalling, because most buses and masters don't
+  support it. In particular it isn't compatible with PCI, where
+  transactions have to complete before a time limit. More generally it
+  won't work in systems and masters that haven't been designed for
+  stalling. For example the OS, in order to handle a stalled transaction,
+  may attempt to retrieve pages from secondary storage in a stalled
+  domain, leading to a deadlock.
+
+
+Notes:
+======
+
+One possible extension to the above is to use an "iommus" property along with
+a "dma-ranges" property in a bus device node (such as PCI host bridges). This
+can be useful to describe how children on the bus relate to the IOMMU if they
+are not explicitly listed in the device tree (e.g. PCI devices). However, the
+requirements of that use-case haven't been fully determined yet. Implementing
+this is therefore not recommended without further discussion and extension of
+this binding.
+
+
+Examples:
+=========
+
+Single-master IOMMU:
+--------------------
+
+	iommu {
+		#iommu-cells = <0>;
+	};
+
+	master {
+		iommus = <&{/iommu}>;
+	};
+
+Multiple-master IOMMU with fixed associations:
+----------------------------------------------
+
+	/* multiple-master IOMMU */
+	iommu {
+		/*
+		 * Masters are statically associated with this IOMMU and share
+		 * the same address translations because the IOMMU does not
+		 * have sufficient information to distinguish between masters.
+		 *
+		 * Consequently address translation is always on or off for
+		 * all masters at any given point in time.
+		 */
+		#iommu-cells = <0>;
+	};
+
+	/* static association with IOMMU */
+	master@1 {
+		reg = <1>;
+		iommus = <&{/iommu}>;
+	};
+
+	/* static association with IOMMU */
+	master@2 {
+		reg = <2>;
+		iommus = <&{/iommu}>;
+	};
+
+Multiple-master IOMMU:
+----------------------
+
+	iommu {
+		/* the specifier represents the ID of the master */
+		#iommu-cells = <1>;
+	};
+
+	master@1 {
+		/* device has master ID 42 in the IOMMU */
+		iommus = <&{/iommu} 42>;
+	};
+
+	master@2 {
+		/* device has master IDs 23 and 24 in the IOMMU */
+		iommus = <&{/iommu} 23>, <&{/iommu} 24>;
+	};
+
+Multiple-master IOMMU with configurable DMA window:
+---------------------------------------------------
+
+	/ {
+		iommu {
+			/*
+			 * One cell for the master ID and one cell for the
+			 * address of the DMA window. The length of the DMA
+			 * window is encoded in two cells.
+			 *
+			 * The DMA window is the range addressable by the
+			 * master (i.e. the I/O virtual address space).
+			 */
+			#iommu-cells = <4>;
+		};
+
+		master {
+			/* master ID 42, 4 GiB DMA window starting at 0 */
+			iommus = <&{/iommu}  42  0  0x1 0x0>;
+		};
+	};
diff --git a/doc/device-tree-bindings/serial/msm-geni-serial.txt b/doc/device-tree-bindings/serial/msm-geni-serial.txt
new file mode 100644
index 0000000..9eadc25
--- /dev/null
+++ b/doc/device-tree-bindings/serial/msm-geni-serial.txt
@@ -0,0 +1,6 @@
+Qualcomm GENI UART
+
+Required properties:
+- compatible: must be "qcom,msm-geni-uart"
+- reg: start address and size of the registers
+- clock: interface clock (must accept baudrate as a frequency)
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 417d6f8..b26ca8c 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -50,6 +50,8 @@
 
 source "drivers/input/Kconfig"
 
+source "drivers/iommu/Kconfig"
+
 source "drivers/led/Kconfig"
 
 source "drivers/mailbox/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 4cbc407..4e7cf28 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -102,6 +102,7 @@
 obj-y += pwm/
 obj-y += reset/
 obj-y += input/
+obj-y += iommu/
 # SOC specific infrastructure drivers.
 obj-y += smem/
 obj-y += thermal/
diff --git a/drivers/core/device.c b/drivers/core/device.c
index d7a778a..efd0717 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -28,6 +28,7 @@
 #include <dm/uclass.h>
 #include <dm/uclass-internal.h>
 #include <dm/util.h>
+#include <iommu.h>
 #include <linux/err.h>
 #include <linux/list.h>
 #include <power-domain.h>
@@ -543,6 +544,13 @@
 			goto fail;
 	}
 
+	if (CONFIG_IS_ENABLED(IOMMU) && dev->parent &&
+	    (device_get_uclass_id(dev) != UCLASS_IOMMU)) {
+		ret = dev_iommu_enable(dev);
+		if (ret)
+			goto fail;
+	}
+
 	ret = device_get_dma_constraints(dev);
 	if (ret)
 		goto fail;
diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c
index e1ff84c..a3c3cd7 100644
--- a/drivers/gpio/msm_gpio.c
+++ b/drivers/gpio/msm_gpio.c
@@ -120,6 +120,7 @@
 	{ .compatible = "qcom,msm8916-pinctrl" },
 	{ .compatible = "qcom,apq8016-pinctrl" },
 	{ .compatible = "qcom,ipq4019-pinctrl" },
+	{ .compatible = "qcom,sdm845-pinctrl" },
 	{ }
 };
 
diff --git a/drivers/gpio/pm8916_gpio.c b/drivers/gpio/pm8916_gpio.c
index 40b0f25..7ad9578 100644
--- a/drivers/gpio/pm8916_gpio.c
+++ b/drivers/gpio/pm8916_gpio.c
@@ -202,6 +202,7 @@
 static const struct udevice_id pm8916_gpio_ids[] = {
 	{ .compatible = "qcom,pm8916-gpio" },
 	{ .compatible = "qcom,pm8994-gpio" },	/* 22 GPIO's */
+	{ .compatible = "qcom,pm8998-gpio" },
 	{ }
 };
 
@@ -266,7 +267,7 @@
 		return log_msg_ret("bad type", -ENXIO);
 
 	reg = pmic_reg_read(dev->parent, priv->pid + REG_SUBTYPE);
-	if (reg != 0x1)
+	if ((reg & 0x5) == 0)
 		return log_msg_ret("bad subtype", -ENXIO);
 
 	return 0;
@@ -287,11 +288,12 @@
 static const struct udevice_id pm8941_pwrkey_ids[] = {
 	{ .compatible = "qcom,pm8916-pwrkey" },
 	{ .compatible = "qcom,pm8994-pwrkey" },
+	{ .compatible = "qcom,pm8998-pwrkey" },
 	{ }
 };
 
-U_BOOT_DRIVER(pwrkey_pm8941) = {
-	.name	= "pwrkey_pm8916",
+U_BOOT_DRIVER(pwrkey_pm89xx) = {
+	.name	= "pwrkey_pm89xx",
 	.id	= UCLASS_GPIO,
 	.of_match = pm8941_pwrkey_ids,
 	.of_to_plat = pm8941_pwrkey_of_to_plat,
diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c
index 76f35ac..06ed585 100644
--- a/drivers/gpio/s5p_gpio.c
+++ b/drivers/gpio/s5p_gpio.c
@@ -357,6 +357,7 @@
 	{ .compatible = "samsung,exynos4x12-pinctrl" },
 	{ .compatible = "samsung,exynos5250-pinctrl" },
 	{ .compatible = "samsung,exynos5420-pinctrl" },
+	{ .compatible = "samsung,exynos78x0-gpio" },
 	{ }
 };
 
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
new file mode 100644
index 0000000..dabc1f9
--- /dev/null
+++ b/drivers/iommu/Kconfig
@@ -0,0 +1,27 @@
+#
+# IOMMU devices
+#
+
+menu "IOMMU device drivers"
+
+config IOMMU
+	bool "Enable Driver Model for IOMMU drivers"
+	depends on DM
+	help
+	  Enable driver model for IOMMU devices. An IOMMU maps device
+	  virtiual memory addresses to physical addresses. Devices
+	  that sit behind an IOMMU can typically only access physical
+	  memory if the IOMMU has been programmed to allow access to
+	  that memory.
+
+config APPLE_DART
+	bool "Apple DART support"
+	depends on IOMMU && ARCH_APPLE
+	default y
+	help
+	  Enable support for the DART on Apple SoCs.  The DART is Apple's
+	  IOMMU implementation.  The driver performs the necessary
+	  configuration to put the DART into bypass mode such that it can
+	  be used transparently by U-Boot.
+
+endmenu
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
new file mode 100644
index 0000000..e3e0900
--- /dev/null
+++ b/drivers/iommu/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_IOMMU) += iommu-uclass.o
+
+obj-$(CONFIG_APPLE_DART) += apple_dart.o
+obj-$(CONFIG_SANDBOX) += sandbox_iommu.o
diff --git a/drivers/iommu/apple_dart.c b/drivers/iommu/apple_dart.c
new file mode 100644
index 0000000..ff8c5fa
--- /dev/null
+++ b/drivers/iommu/apple_dart.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <asm/io.h>
+
+#define DART_PARAMS2		0x0004
+#define  DART_PARAMS2_BYPASS_SUPPORT	BIT(0)
+#define DART_TLB_OP		0x0020
+#define  DART_TLB_OP_OPMASK	(0xfff << 20)
+#define  DART_TLB_OP_FLUSH	(0x001 << 20)
+#define  DART_TLB_OP_BUSY	BIT(2)
+#define DART_TLB_OP_SIDMASK	0x0034
+#define DART_ERROR_STATUS	0x0040
+#define DART_TCR(sid)		(0x0100 + 4 * (sid))
+#define  DART_TCR_TRANSLATE_ENABLE	BIT(7)
+#define  DART_TCR_BYPASS_DART		BIT(8)
+#define  DART_TCR_BYPASS_DAPF		BIT(12)
+#define DART_TTBR(sid, idx)	(0x0200 + 16 * (sid) + 4 * (idx))
+#define  DART_TTBR_VALID	BIT(31)
+#define  DART_TTBR_SHIFT	12
+
+static int apple_dart_probe(struct udevice *dev)
+{
+	void *base;
+	int sid, i;
+
+	base = dev_read_addr_ptr(dev);
+	if (!base)
+		return -EINVAL;
+
+	u32 params2 = readl(base + DART_PARAMS2);
+	if (params2 & DART_PARAMS2_BYPASS_SUPPORT) {
+		for (sid = 0; sid < 16; sid++) {
+			writel(DART_TCR_BYPASS_DART | DART_TCR_BYPASS_DAPF,
+			       base + DART_TCR(sid));
+			for (i = 0; i < 4; i++)
+				writel(0, base + DART_TTBR(sid, i));
+		}
+	}
+
+	return 0;
+}
+
+static const struct udevice_id apple_dart_ids[] = {
+	{ .compatible = "apple,t8103-dart" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(apple_dart) = {
+	.name = "apple_dart",
+	.id = UCLASS_IOMMU,
+	.of_match = apple_dart_ids,
+	.probe = apple_dart_probe
+};
diff --git a/drivers/iommu/iommu-uclass.c b/drivers/iommu/iommu-uclass.c
new file mode 100644
index 0000000..ed917b3
--- /dev/null
+++ b/drivers/iommu/iommu-uclass.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
+ */
+
+#define LOG_CATEGORY UCLASS_IOMMU
+
+#include <common.h>
+#include <dm.h>
+
+#if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA))
+int dev_iommu_enable(struct udevice *dev)
+{
+	struct ofnode_phandle_args args;
+	struct udevice *dev_iommu;
+	int i, count, ret = 0;
+
+	count = dev_count_phandle_with_args(dev, "iommus",
+					    "#iommu-cells", 0);
+	for (i = 0; i < count; i++) {
+		ret = dev_read_phandle_with_args(dev, "iommus",
+						 "#iommu-cells", 0, i, &args);
+		if (ret) {
+			debug("%s: dev_read_phandle_with_args failed: %d\n",
+			      __func__, ret);
+			return ret;
+		}
+
+		ret = uclass_get_device_by_ofnode(UCLASS_IOMMU, args.node,
+						  &dev_iommu);
+		if (ret) {
+			debug("%s: uclass_get_device_by_ofnode failed: %d\n",
+			      __func__, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+#endif
+
+UCLASS_DRIVER(iommu) = {
+	.id		= UCLASS_IOMMU,
+	.name		= "iommu",
+};
diff --git a/drivers/iommu/sandbox_iommu.c b/drivers/iommu/sandbox_iommu.c
new file mode 100644
index 0000000..c8161a4
--- /dev/null
+++ b/drivers/iommu/sandbox_iommu.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+
+static const struct udevice_id sandbox_iommu_ids[] = {
+	{ .compatible = "sandbox,iommu" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(sandbox_iommu) = {
+	.name = "sandbox_iommu",
+	.id = UCLASS_IOMMU,
+	.of_match = sandbox_iommu_ids,
+};
diff --git a/drivers/pinctrl/exynos/Kconfig b/drivers/pinctrl/exynos/Kconfig
index 84b6aaa..a60f498 100644
--- a/drivers/pinctrl/exynos/Kconfig
+++ b/drivers/pinctrl/exynos/Kconfig
@@ -8,3 +8,11 @@
 	help
 	  Support pin multiplexing and pin configuration control on
 	  Samsung's Exynos7420 SoC.
+
+config PINCTRL_EXYNOS78x0
+	bool "Samsung Exynos78x0 pinctrl driver"
+	depends on ARCH_EXYNOS && PINCTRL_FULL
+	select PINCTRL_EXYNOS
+	help
+	  Support pin multiplexing and pin configuration control on
+	  Samsung's Exynos78x0 SoC.
diff --git a/drivers/pinctrl/exynos/Makefile b/drivers/pinctrl/exynos/Makefile
index 6a14a47..07db970 100644
--- a/drivers/pinctrl/exynos/Makefile
+++ b/drivers/pinctrl/exynos/Makefile
@@ -5,3 +5,4 @@
 
 obj-$(CONFIG_PINCTRL_EXYNOS)		+= pinctrl-exynos.o
 obj-$(CONFIG_PINCTRL_EXYNOS7420)	+= pinctrl-exynos7420.o
+obj-$(CONFIG_PINCTRL_EXYNOS78x0)	+= pinctrl-exynos78x0.o
diff --git a/drivers/pinctrl/exynos/pinctrl-exynos.c b/drivers/pinctrl/exynos/pinctrl-exynos.c
index 2640c8f..8981854 100644
--- a/drivers/pinctrl/exynos/pinctrl-exynos.c
+++ b/drivers/pinctrl/exynos/pinctrl-exynos.c
@@ -5,6 +5,7 @@
  * Thomas Abraham <thomas.ab@samsung.com>
  */
 
+#include <log.h>
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
@@ -38,9 +39,9 @@
 						u32 *pin)
 {
 	struct exynos_pinctrl_priv *priv = dev_get_priv(dev);
-	const struct samsung_pin_ctrl *pin_ctrl = priv->pin_ctrl;
-	const struct samsung_pin_bank_data *bank_data = pin_ctrl->pin_banks;
-	u32 nr_banks = pin_ctrl->nr_banks, idx = 0;
+	const struct samsung_pin_ctrl *pin_ctrl_array = priv->pin_ctrl;
+	const struct samsung_pin_bank_data *bank_data;
+	u32 nr_banks, pin_ctrl_idx = 0, idx = 0, bank_base;
 	char bank[10];
 
 	/*
@@ -55,11 +56,26 @@
 	*pin = pin_name[++idx] - '0';
 
 	/* lookup the pin bank data using the pin bank name */
-	for (idx = 0; idx < nr_banks; idx++)
-		if (!strcmp(bank, bank_data[idx].name))
+	while (true) {
+		const struct samsung_pin_ctrl *pin_ctrl = &pin_ctrl_array[pin_ctrl_idx];
+
+		nr_banks = pin_ctrl->nr_banks;
+		if (!nr_banks)
 			break;
 
-	return priv->base + bank_data[idx].offset;
+		bank_data = pin_ctrl->pin_banks;
+		for (idx = 0; idx < nr_banks; idx++) {
+			debug("pinctrl[%d] bank_data[%d] name is: %s\n",
+					pin_ctrl_idx, idx, bank_data[idx].name);
+			if (!strcmp(bank, bank_data[idx].name)) {
+				bank_base = priv->base + bank_data[idx].offset;
+				break;
+			}
+		}
+		pin_ctrl_idx++;
+	}
+
+	return bank_base;
 }
 
 /**
diff --git a/drivers/pinctrl/exynos/pinctrl-exynos78x0.c b/drivers/pinctrl/exynos/pinctrl-exynos78x0.c
new file mode 100644
index 0000000..01e9a4f
--- /dev/null
+++ b/drivers/pinctrl/exynos/pinctrl-exynos78x0.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Exynos78x0 pinctrl driver.
+ *
+ * Copyright (c) 2020 Dzmitry Sankouski (dsankouski@gmail.com)
+ *
+ * based on drivers/pinctrl/exynos/pinctrl-exynos7420.c :
+ * Copyright (C) 2016 Samsung Electronics
+ * Thomas Abraham <thomas.ab@samsung.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+#include <fdtdec.h>
+#include <asm/arch/pinmux.h>
+#include "pinctrl-exynos.h"
+
+static struct pinctrl_ops exynos78x0_pinctrl_ops = {
+	.set_state	= exynos_pinctrl_set_state
+};
+
+/* pin banks of exynos78x0 pin-controller 0 (ALIVE) */
+static struct samsung_pin_bank_data exynos78x0_pin_banks0[] = {
+	EXYNOS_PIN_BANK(6, 0x000, "etc0"),
+	EXYNOS_PIN_BANK(3, 0x020, "etc1"),
+	EXYNOS_PIN_BANK(8, 0x040, "gpa0"),
+	EXYNOS_PIN_BANK(8, 0x060, "gpa1"),
+	EXYNOS_PIN_BANK(8, 0x080, "gpa2"),
+	EXYNOS_PIN_BANK(5, 0x0a0, "gpa3"),
+	EXYNOS_PIN_BANK(2, 0x0c0, "gpq0"),
+};
+
+/* pin banks of exynos78x0 pin-controller 1 (CCORE) */
+static struct samsung_pin_bank_data exynos78x0_pin_banks1[] = {
+	EXYNOS_PIN_BANK(2, 0x000, "gpm0"),
+};
+
+/* pin banks of exynos78x0 pin-controller 2 (DISPAUD) */
+static struct samsung_pin_bank_data exynos78x0_pin_banks2[] = {
+	EXYNOS_PIN_BANK(4, 0x000, "gpz0"),
+	EXYNOS_PIN_BANK(6, 0x020, "gpz1"),
+	EXYNOS_PIN_BANK(4, 0x040, "gpz2"),
+};
+
+/* pin banks of exynos78x0 pin-controller 4 (FSYS) */
+static struct samsung_pin_bank_data exynos78x0_pin_banks4[] = {
+	EXYNOS_PIN_BANK(3, 0x000, "gpr0"),
+	EXYNOS_PIN_BANK(8, 0x020, "gpr1"),
+	EXYNOS_PIN_BANK(2, 0x040, "gpr2"),
+	EXYNOS_PIN_BANK(4, 0x060, "gpr3"),
+	EXYNOS_PIN_BANK(6, 0x080, "gpr4"),
+};
+
+/* pin banks of exynos78x0 pin-controller 6 (TOP) */
+static struct samsung_pin_bank_data exynos78x0_pin_banks6[] = {
+	EXYNOS_PIN_BANK(4, 0x000, "gpb0"),
+	EXYNOS_PIN_BANK(3, 0x020, "gpc0"),
+	EXYNOS_PIN_BANK(4, 0x040, "gpc1"),
+	EXYNOS_PIN_BANK(4, 0x060, "gpc4"),
+	EXYNOS_PIN_BANK(2, 0x080, "gpc5"),
+	EXYNOS_PIN_BANK(4, 0x0a0, "gpc6"),
+	EXYNOS_PIN_BANK(2, 0x0c0, "gpc8"),
+	EXYNOS_PIN_BANK(2, 0x0e0, "gpc9"),
+	EXYNOS_PIN_BANK(7, 0x100, "gpd1"),
+	EXYNOS_PIN_BANK(6, 0x120, "gpd2"),
+	EXYNOS_PIN_BANK(8, 0x140, "gpd3"),
+	EXYNOS_PIN_BANK(7, 0x160, "gpd4"),
+	EXYNOS_PIN_BANK(5, 0x180, "gpd5"),
+	EXYNOS_PIN_BANK(3, 0x1a0, "gpe0"),
+	EXYNOS_PIN_BANK(4, 0x1c0, "gpf0"),
+	EXYNOS_PIN_BANK(2, 0x1e0, "gpf1"),
+	EXYNOS_PIN_BANK(2, 0x200, "gpf2"),
+	EXYNOS_PIN_BANK(4, 0x220, "gpf3"),
+	EXYNOS_PIN_BANK(5, 0x240, "gpf4"),
+};
+
+struct samsung_pin_ctrl exynos78x0_pin_ctrl[] = {
+	{
+		/* pin-controller instance 0 Alive data */
+		.pin_banks	= exynos78x0_pin_banks0,
+		.nr_banks	= ARRAY_SIZE(exynos78x0_pin_banks0),
+	}, {
+		/* pin-controller instance 1 CCORE data */
+		.pin_banks	= exynos78x0_pin_banks1,
+		.nr_banks	= ARRAY_SIZE(exynos78x0_pin_banks1),
+	}, {
+		/* pin-controller instance 2 DISPAUD data */
+		.pin_banks	= exynos78x0_pin_banks2,
+		.nr_banks	= ARRAY_SIZE(exynos78x0_pin_banks2),
+	}, {
+		/* pin-controller instance 4 FSYS data */
+		.pin_banks	= exynos78x0_pin_banks4,
+		.nr_banks	= ARRAY_SIZE(exynos78x0_pin_banks4),
+	}, {
+		/* pin-controller instance 6 TOP data */
+		.pin_banks	= exynos78x0_pin_banks6,
+		.nr_banks	= ARRAY_SIZE(exynos78x0_pin_banks6),
+	},
+	{/* list terminator */}
+};
+
+static const struct udevice_id exynos78x0_pinctrl_ids[] = {
+	{ .compatible = "samsung,exynos78x0-pinctrl",
+		.data = (ulong)exynos78x0_pin_ctrl },
+	{ }
+};
+
+U_BOOT_DRIVER(pinctrl_exynos78x0) = {
+	.name		= "pinctrl_exynos78x0",
+	.id		= UCLASS_PINCTRL,
+	.of_match	= exynos78x0_pinctrl_ids,
+	.priv_auto = sizeof(struct exynos_pinctrl_priv),
+	.ops		= &exynos78x0_pinctrl_ops,
+	.probe		= exynos_pinctrl_probe,
+};
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 122a397..6c8fdda 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -290,12 +290,20 @@
 
 config DEBUG_UART_S5P
 	bool "Samsung S5P"
-	depends on ARCH_EXYNOS || ARCH_S5PC1XX
+	depends on ARCH_APPLE || ARCH_EXYNOS || ARCH_S5PC1XX
 	help
 	  Select this to enable a debug UART using the serial_s5p driver. You
 	  will need to provide parameters to make this work. The driver will
 	  be available until the real driver-model serial is running.
 
+config DEBUG_UART_MSM_GENI
+	bool "Qualcomm snapdragon"
+	depends on ARCH_SNAPDRAGON
+	help
+	  Select this to enable a debug UART using the serial_msm driver. You
+	  will need to provide parameters to make this work. The driver will
+	  be available until the real driver-model serial is running.
+
 config DEBUG_UART_MESON
 	bool "Amlogic Meson"
 	depends on MESON_SERIAL
@@ -737,7 +745,7 @@
 
 config S5P_SERIAL
 	bool "Support for Samsung S5P UART"
-	depends on ARCH_EXYNOS || ARCH_S5PC1XX
+	depends on ARCH_APPLE || ARCH_EXYNOS || ARCH_S5PC1XX
 	default y
 	help
 	  Select this to enable Samsung S5P UART support.
@@ -801,6 +809,16 @@
 	  for example APQ8016 and MSM8916.
 	  Single baudrate is supported in current implementation (115200).
 
+config MSM_GENI_SERIAL
+	bool "Qualcomm on-chip GENI UART"
+	help
+	  Support UART based on Generic Interface (GENI) Serial Engine (SE),
+	  used on Qualcomm Snapdragon SoCs. Should support all qualcomm SOCs
+	  with Qualcomm Universal Peripheral (QUP) Wrapper cores,
+	  i.e. newer ones, starting from SDM845.
+	  Driver works in FIFO mode.
+	  Multiple baudrates supported.
+
 config OCTEON_SERIAL_BOOTCMD
 	bool "MIPS Octeon PCI remote bootcmd input"
 	depends on ARCH_OCTEON
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 4edd2aa..8168af6 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -63,6 +63,7 @@
 obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o
 obj-$(CONFIG_BCM283X_PL011_SERIAL) += serial_bcm283x_pl011.o
 obj-$(CONFIG_MSM_SERIAL) += serial_msm.o
+obj-$(CONFIG_MSM_GENI_SERIAL) += serial_msm_geni.o
 obj-$(CONFIG_MVEBU_A3700_UART) += serial_mvebu_a3700.o
 obj-$(CONFIG_MPC8XX_CONS) += serial_mpc8xx.o
 obj-$(CONFIG_NULLDEV_SERIAL) += serial_nulldev.o
diff --git a/drivers/serial/serial_msm_geni.c b/drivers/serial/serial_msm_geni.c
new file mode 100644
index 0000000..3e255a9
--- /dev/null
+++ b/drivers/serial/serial_msm_geni.c
@@ -0,0 +1,613 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Qualcomm GENI serial engine UART driver
+ *
+ * (C) Copyright 2021 Dzmitry Sankouski <dsankouski@gmail.com>
+ *
+ * Based on Linux driver.
+ */
+
+#include <asm/io.h>
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <errno.h>
+#include <linux/compiler.h>
+#include <log.h>
+#include <linux/delay.h>
+#include <malloc.h>
+#include <serial.h>
+#include <watchdog.h>
+#include <linux/bug.h>
+
+#define UART_OVERSAMPLING	32
+#define STALE_TIMEOUT	160
+
+#define USEC_PER_SEC	1000000L
+
+/* Registers*/
+#define GENI_FORCE_DEFAULT_REG	0x20
+#define GENI_SER_M_CLK_CFG	0x48
+#define GENI_SER_S_CLK_CFG	0x4C
+#define SE_HW_PARAM_0	0xE24
+#define SE_GENI_STATUS	0x40
+#define SE_GENI_S_CMD0	0x630
+#define SE_GENI_S_CMD_CTRL_REG	0x634
+#define SE_GENI_S_IRQ_CLEAR	0x648
+#define SE_GENI_S_IRQ_STATUS	0x640
+#define SE_GENI_S_IRQ_EN	0x644
+#define SE_GENI_M_CMD0	0x600
+#define SE_GENI_M_CMD_CTRL_REG	0x604
+#define SE_GENI_M_IRQ_CLEAR	0x618
+#define SE_GENI_M_IRQ_STATUS	0x610
+#define SE_GENI_M_IRQ_EN	0x614
+#define SE_GENI_TX_FIFOn	0x700
+#define SE_GENI_RX_FIFOn	0x780
+#define SE_GENI_TX_FIFO_STATUS	0x800
+#define SE_GENI_RX_FIFO_STATUS	0x804
+#define SE_GENI_TX_WATERMARK_REG	0x80C
+#define SE_GENI_TX_PACKING_CFG0	0x260
+#define SE_GENI_TX_PACKING_CFG1	0x264
+#define SE_GENI_RX_PACKING_CFG0	0x284
+#define SE_GENI_RX_PACKING_CFG1	0x288
+#define SE_UART_RX_STALE_CNT	0x294
+#define SE_UART_TX_TRANS_LEN	0x270
+#define SE_UART_TX_STOP_BIT_LEN	0x26c
+#define SE_UART_TX_WORD_LEN	0x268
+#define SE_UART_RX_WORD_LEN	0x28c
+#define SE_UART_TX_TRANS_CFG	0x25c
+#define SE_UART_TX_PARITY_CFG	0x2a4
+#define SE_UART_RX_TRANS_CFG	0x280
+#define SE_UART_RX_PARITY_CFG	0x2a8
+
+#define M_TX_FIFO_WATERMARK_EN	(BIT(30))
+#define DEF_TX_WM	2
+/* GENI_FORCE_DEFAULT_REG fields */
+#define FORCE_DEFAULT	(BIT(0))
+
+#define S_CMD_ABORT_EN	(BIT(5))
+
+#define UART_START_READ	0x1
+
+/* GENI_M_CMD_CTRL_REG */
+#define M_GENI_CMD_CANCEL	(BIT(2))
+#define M_GENI_CMD_ABORT	(BIT(1))
+#define M_GENI_DISABLE	(BIT(0))
+
+#define M_CMD_ABORT_EN	(BIT(5))
+#define M_CMD_DONE_EN	(BIT(0))
+#define M_CMD_DONE_DISABLE_MASK	(~M_CMD_DONE_EN)
+
+#define S_GENI_CMD_ABORT	(BIT(1))
+
+/* GENI_S_CMD0 fields */
+#define S_OPCODE_MSK	(GENMASK(31, 27))
+#define S_PARAMS_MSK	(GENMASK(26, 0))
+
+/* GENI_STATUS fields */
+#define M_GENI_CMD_ACTIVE	(BIT(0))
+#define S_GENI_CMD_ACTIVE	(BIT(12))
+#define M_CMD_DONE_EN	(BIT(0))
+#define S_CMD_DONE_EN	(BIT(0))
+
+#define M_OPCODE_SHIFT	27
+#define S_OPCODE_SHIFT	27
+#define M_TX_FIFO_WATERMARK_EN	(BIT(30))
+#define UART_START_TX	0x1
+#define UART_CTS_MASK	(BIT(1))
+#define M_SEC_IRQ_EN	(BIT(31))
+#define TX_FIFO_WC_MSK	(GENMASK(27, 0))
+#define RX_FIFO_WC_MSK	(GENMASK(24, 0))
+
+#define S_RX_FIFO_WATERMARK_EN	(BIT(26))
+#define S_RX_FIFO_LAST_EN	(BIT(27))
+#define M_RX_FIFO_WATERMARK_EN	(BIT(26))
+#define M_RX_FIFO_LAST_EN	(BIT(27))
+
+/* GENI_SER_M_CLK_CFG/GENI_SER_S_CLK_CFG */
+#define SER_CLK_EN	(BIT(0))
+#define CLK_DIV_MSK	(GENMASK(15, 4))
+#define CLK_DIV_SHFT	4
+
+/* SE_HW_PARAM_0 fields */
+#define TX_FIFO_WIDTH_MSK	(GENMASK(29, 24))
+#define TX_FIFO_WIDTH_SHFT	24
+#define TX_FIFO_DEPTH_MSK	(GENMASK(21, 16))
+#define TX_FIFO_DEPTH_SHFT	16
+
+/*
+ * Predefined packing configuration of the serial engine (CFG0, CFG1 regs)
+ * for uart mode.
+ *
+ * Defines following configuration:
+ * - Bits of data per transfer word             8
+ * - Number of words per fifo element           4
+ * - Transfer from MSB to LSB or vice-versa     false
+ */
+#define UART_PACKING_CFG0   0xf
+#define UART_PACKING_CFG1   0x0
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct msm_serial_data {
+	phys_addr_t base;
+	u32 baud;
+};
+
+unsigned long root_freq[] = {7372800,  14745600, 19200000, 29491200,
+					 32000000, 48000000, 64000000, 80000000,
+					 96000000, 100000000};
+
+/**
+ * get_clk_cfg() - Get clock rate to apply on clock supplier.
+ * @clk_freq:	Desired clock frequency after build-in divider.
+ *
+ * Return: frequency, supported by clock supplier, multiple of clk_freq.
+ */
+static int get_clk_cfg(unsigned long clk_freq)
+{
+	for (int i = 0; i < ARRAY_SIZE(root_freq); i++) {
+		if (!(root_freq[i] % clk_freq))
+			return root_freq[i];
+	}
+	return 0;
+}
+
+/**
+ * get_clk_div_rate() - Find clock supplier frequency, and calculate divisor.
+ * @baud:	        Baudrate.
+ * @sampling_rate:	Clock ticks per character.
+ * @clk_div:	    Pointer to calculated divisor.
+ *
+ * This function searches for suitable frequency for clock supplier,
+ * calculates divisor for internal divider, based on found frequency,
+ * and stores divisor under clk_div pointer.
+ *
+ * Return: frequency, supported by clock supplier, multiple of clk_freq.
+ */
+static int get_clk_div_rate(u32 baud,
+							u64 sampling_rate, u32 *clk_div)
+{
+	unsigned long ser_clk;
+	unsigned long desired_clk;
+
+	desired_clk = baud * sampling_rate;
+	ser_clk = get_clk_cfg(desired_clk);
+	if (!ser_clk) {
+		pr_err("%s: Can't find matching DFS entry for baud %d\n",
+								__func__, baud);
+		return ser_clk;
+	}
+
+	*clk_div = ser_clk / desired_clk;
+	return ser_clk;
+}
+
+static int geni_serial_set_clock_rate(struct udevice *dev, u64 rate)
+{
+	struct clk *clk;
+	int ret;
+
+	clk = devm_clk_get(dev, "se-clk");
+	if (!clk)
+		return -EINVAL;
+
+	ret = clk_set_rate(clk, rate);
+	return ret;
+}
+
+/**
+ * geni_se_get_tx_fifo_depth() - Get the TX fifo depth of the serial engine
+ * @base:	Pointer to the concerned serial engine.
+ *
+ * This function is used to get the depth i.e. number of elements in the
+ * TX fifo of the serial engine.
+ *
+ * Return: TX fifo depth in units of FIFO words.
+ */
+static inline u32 geni_se_get_tx_fifo_depth(long base)
+{
+	u32 tx_fifo_depth;
+
+	tx_fifo_depth = ((readl(base + SE_HW_PARAM_0) & TX_FIFO_DEPTH_MSK) >>
+			 TX_FIFO_DEPTH_SHFT);
+	return tx_fifo_depth;
+}
+
+/**
+ * geni_se_get_tx_fifo_width() - Get the TX fifo width of the serial engine
+ * @base:	Pointer to the concerned serial engine.
+ *
+ * This function is used to get the width i.e. word size per element in the
+ * TX fifo of the serial engine.
+ *
+ * Return: TX fifo width in bits
+ */
+static inline u32 geni_se_get_tx_fifo_width(long base)
+{
+	u32 tx_fifo_width;
+
+	tx_fifo_width = ((readl(base + SE_HW_PARAM_0) & TX_FIFO_WIDTH_MSK) >>
+			 TX_FIFO_WIDTH_SHFT);
+	return tx_fifo_width;
+}
+
+static inline void geni_serial_baud(phys_addr_t base_address, u32 clk_div,
+									int baud)
+{
+	u32 s_clk_cfg = 0;
+
+	s_clk_cfg |= SER_CLK_EN;
+	s_clk_cfg |= (clk_div << CLK_DIV_SHFT);
+
+	writel(s_clk_cfg, base_address + GENI_SER_M_CLK_CFG);
+	writel(s_clk_cfg, base_address + GENI_SER_S_CLK_CFG);
+}
+
+int msm_serial_setbrg(struct udevice *dev, int baud)
+{
+	struct msm_serial_data *priv = dev_get_priv(dev);
+
+	priv->baud = baud;
+	u32 clk_div;
+	u64 clk_rate;
+
+	clk_rate = get_clk_div_rate(baud, UART_OVERSAMPLING, &clk_div);
+	geni_serial_set_clock_rate(dev, clk_rate);
+	geni_serial_baud(priv->base, clk_div, baud);
+
+	return 0;
+}
+
+/**
+ * qcom_geni_serial_poll_bit() - Poll reg bit until desired value or timeout.
+ * @base:	Pointer to the concerned serial engine.
+ * @offset:	Offset to register address.
+ * @field:	AND bitmask for desired bit.
+ * @set:	Desired bit value.
+ *
+ * This function is used to get the width i.e. word size per element in the
+ * TX fifo of the serial engine.
+ *
+ * Return: true, when register bit equals desired value, false, when timeout
+ * reached.
+ */
+static bool qcom_geni_serial_poll_bit(const struct udevice *dev, int offset,
+					  int field, bool set)
+{
+	u32 reg;
+	struct msm_serial_data *priv = dev_get_priv(dev);
+	unsigned int baud;
+	unsigned int tx_fifo_depth;
+	unsigned int tx_fifo_width;
+	unsigned int fifo_bits;
+	unsigned long timeout_us = 10000;
+
+	baud = 115200;
+
+	if (priv) {
+		baud = priv->baud;
+		if (!baud)
+			baud = 115200;
+		tx_fifo_depth = geni_se_get_tx_fifo_depth(priv->base);
+		tx_fifo_width = geni_se_get_tx_fifo_width(priv->base);
+		fifo_bits = tx_fifo_depth * tx_fifo_width;
+		/*
+		 * Total polling iterations based on FIFO worth of bytes to be
+		 * sent at current baud. Add a little fluff to the wait.
+		 */
+		timeout_us = ((fifo_bits * USEC_PER_SEC) / baud) + 500;
+	}
+
+	timeout_us = DIV_ROUND_UP(timeout_us, 10) * 10;
+	while (timeout_us) {
+		reg = readl(priv->base + offset);
+		if ((bool)(reg & field) == set)
+			return true;
+		udelay(10);
+		timeout_us -= 10;
+	}
+	return false;
+}
+
+static void qcom_geni_serial_setup_tx(u64 base, u32 xmit_size)
+{
+	u32 m_cmd;
+
+	writel(xmit_size, base + SE_UART_TX_TRANS_LEN);
+	m_cmd = UART_START_TX << M_OPCODE_SHIFT;
+	writel(m_cmd, base + SE_GENI_M_CMD0);
+}
+
+static inline void qcom_geni_serial_poll_tx_done(const struct udevice *dev)
+{
+	struct msm_serial_data *priv = dev_get_priv(dev);
+	int done = 0;
+	u32 irq_clear = M_CMD_DONE_EN;
+
+	done = qcom_geni_serial_poll_bit(dev, SE_GENI_M_IRQ_STATUS,
+					 M_CMD_DONE_EN, true);
+	if (!done) {
+		writel(M_GENI_CMD_ABORT, priv->base + SE_GENI_M_CMD_CTRL_REG);
+		irq_clear |= M_CMD_ABORT_EN;
+		qcom_geni_serial_poll_bit(dev, SE_GENI_M_IRQ_STATUS,
+					  M_CMD_ABORT_EN, true);
+	}
+	writel(irq_clear, priv->base + SE_GENI_M_IRQ_CLEAR);
+}
+
+static u32 qcom_geni_serial_tx_empty(u64 base)
+{
+	return !readl(base + SE_GENI_TX_FIFO_STATUS);
+}
+
+/**
+ * geni_se_setup_s_cmd() - Setup the secondary sequencer
+ * @se:		Pointer to the concerned serial engine.
+ * @cmd:	Command/Operation to setup in the secondary sequencer.
+ * @params:	Parameter for the sequencer command.
+ *
+ * This function is used to configure the secondary sequencer with the
+ * command and its associated parameters.
+ */
+static inline void geni_se_setup_s_cmd(u64 base, u32 cmd, u32 params)
+{
+	u32 s_cmd;
+
+	s_cmd = readl(base + SE_GENI_S_CMD0);
+	s_cmd &= ~(S_OPCODE_MSK | S_PARAMS_MSK);
+	s_cmd |= (cmd << S_OPCODE_SHIFT);
+	s_cmd |= (params & S_PARAMS_MSK);
+	writel(s_cmd, base + SE_GENI_S_CMD0);
+}
+
+static void qcom_geni_serial_start_tx(u64 base)
+{
+	u32 irq_en;
+	u32 status;
+
+	status = readl(base + SE_GENI_STATUS);
+	if (status & M_GENI_CMD_ACTIVE)
+		return;
+
+	if (!qcom_geni_serial_tx_empty(base))
+		return;
+
+	irq_en = readl(base + SE_GENI_M_IRQ_EN);
+	irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN;
+
+	writel(DEF_TX_WM, base + SE_GENI_TX_WATERMARK_REG);
+	writel(irq_en, base + SE_GENI_M_IRQ_EN);
+}
+
+static void qcom_geni_serial_start_rx(struct udevice *dev)
+{
+	u32 status;
+	struct msm_serial_data *priv = dev_get_priv(dev);
+
+	status = readl(priv->base + SE_GENI_STATUS);
+
+	geni_se_setup_s_cmd(priv->base, UART_START_READ, 0);
+
+	setbits_le32(priv->base + SE_GENI_S_IRQ_EN, S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN);
+	setbits_le32(priv->base + SE_GENI_M_IRQ_EN, M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
+}
+
+static void qcom_geni_serial_abort_rx(struct udevice *dev)
+{
+	struct msm_serial_data *priv = dev_get_priv(dev);
+
+	u32 irq_clear = S_CMD_DONE_EN | S_CMD_ABORT_EN;
+
+	writel(S_GENI_CMD_ABORT, priv->base + SE_GENI_S_CMD_CTRL_REG);
+	qcom_geni_serial_poll_bit(dev, SE_GENI_S_CMD_CTRL_REG,
+					S_GENI_CMD_ABORT, false);
+	writel(irq_clear, priv->base + SE_GENI_S_IRQ_CLEAR);
+	writel(FORCE_DEFAULT, priv->base + GENI_FORCE_DEFAULT_REG);
+}
+
+static void msm_geni_serial_setup_rx(struct udevice *dev)
+{
+	struct msm_serial_data *priv = dev_get_priv(dev);
+
+	qcom_geni_serial_abort_rx(dev);
+
+	writel(UART_PACKING_CFG0, priv->base + SE_GENI_RX_PACKING_CFG0);
+	writel(UART_PACKING_CFG1, priv->base + SE_GENI_RX_PACKING_CFG1);
+
+	geni_se_setup_s_cmd(priv->base, UART_START_READ, 0);
+
+	setbits_le32(priv->base + SE_GENI_S_IRQ_EN, S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN);
+	setbits_le32(priv->base + SE_GENI_M_IRQ_EN, M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
+}
+
+static int msm_serial_putc(struct udevice *dev, const char ch)
+{
+	struct msm_serial_data *priv = dev_get_priv(dev);
+
+	writel(DEF_TX_WM, priv->base + SE_GENI_TX_WATERMARK_REG);
+	qcom_geni_serial_setup_tx(priv->base, 1);
+
+	qcom_geni_serial_poll_bit(dev, SE_GENI_M_IRQ_STATUS,
+				  M_TX_FIFO_WATERMARK_EN, true);
+
+	writel(ch, priv->base + SE_GENI_TX_FIFOn);
+	writel(M_TX_FIFO_WATERMARK_EN, priv->base + SE_GENI_M_IRQ_CLEAR);
+
+	qcom_geni_serial_poll_tx_done(dev);
+
+	return 0;
+}
+
+static int msm_serial_getc(struct udevice *dev)
+{
+	struct msm_serial_data *priv = dev_get_priv(dev);
+	u32 rx_fifo;
+	u32 m_irq_status;
+	u32 s_irq_status;
+
+	writel(1 << S_OPCODE_SHIFT, priv->base + SE_GENI_S_CMD0);
+
+	qcom_geni_serial_poll_bit(dev, SE_GENI_M_IRQ_STATUS, M_SEC_IRQ_EN,
+				  true);
+
+	m_irq_status = readl(priv->base + SE_GENI_M_IRQ_STATUS);
+	s_irq_status = readl(priv->base + SE_GENI_S_IRQ_STATUS);
+	writel(m_irq_status, priv->base + SE_GENI_M_IRQ_CLEAR);
+	writel(s_irq_status, priv->base + SE_GENI_S_IRQ_CLEAR);
+	qcom_geni_serial_poll_bit(dev, SE_GENI_RX_FIFO_STATUS, RX_FIFO_WC_MSK,
+				  true);
+
+	if (!readl(priv->base + SE_GENI_RX_FIFO_STATUS))
+		return 0;
+
+	rx_fifo = readl(priv->base + SE_GENI_RX_FIFOn);
+	return rx_fifo & 0xff;
+}
+
+static int msm_serial_pending(struct udevice *dev, bool input)
+{
+	struct msm_serial_data *priv = dev_get_priv(dev);
+
+	if (input)
+		return readl(priv->base + SE_GENI_RX_FIFO_STATUS) &
+			   RX_FIFO_WC_MSK;
+	else
+		return readl(priv->base + SE_GENI_TX_FIFO_STATUS) &
+			   TX_FIFO_WC_MSK;
+
+	return 0;
+}
+
+static const struct dm_serial_ops msm_serial_ops = {
+	.putc = msm_serial_putc,
+	.pending = msm_serial_pending,
+	.getc = msm_serial_getc,
+	.setbrg = msm_serial_setbrg,
+};
+
+static inline void geni_serial_init(struct udevice *dev)
+{
+	struct msm_serial_data *priv = dev_get_priv(dev);
+	phys_addr_t base_address = priv->base;
+	u32 tx_trans_cfg;
+	u32 tx_parity_cfg = 0; /* Disable Tx Parity */
+	u32 rx_trans_cfg = 0;
+	u32 rx_parity_cfg = 0; /* Disable Rx Parity */
+	u32 stop_bit_len = 0;  /* Default stop bit length - 1 bit */
+	u32 bits_per_char;
+
+	/*
+	 * Ignore Flow control.
+	 * n = 8.
+	 */
+	tx_trans_cfg = UART_CTS_MASK;
+	bits_per_char = BITS_PER_BYTE;
+
+	/*
+	 * Make an unconditional cancel on the main sequencer to reset
+	 * it else we could end up in data loss scenarios.
+	 */
+	qcom_geni_serial_poll_tx_done(dev);
+	qcom_geni_serial_abort_rx(dev);
+
+	writel(UART_PACKING_CFG0, base_address + SE_GENI_TX_PACKING_CFG0);
+	writel(UART_PACKING_CFG1, base_address + SE_GENI_TX_PACKING_CFG1);
+	writel(UART_PACKING_CFG0, base_address + SE_GENI_RX_PACKING_CFG0);
+	writel(UART_PACKING_CFG1, base_address + SE_GENI_RX_PACKING_CFG1);
+
+	writel(tx_trans_cfg, base_address + SE_UART_TX_TRANS_CFG);
+	writel(tx_parity_cfg, base_address + SE_UART_TX_PARITY_CFG);
+	writel(rx_trans_cfg, base_address + SE_UART_RX_TRANS_CFG);
+	writel(rx_parity_cfg, base_address + SE_UART_RX_PARITY_CFG);
+	writel(bits_per_char, base_address + SE_UART_TX_WORD_LEN);
+	writel(bits_per_char, base_address + SE_UART_RX_WORD_LEN);
+	writel(stop_bit_len, base_address + SE_UART_TX_STOP_BIT_LEN);
+}
+
+static int msm_serial_probe(struct udevice *dev)
+{
+	struct msm_serial_data *priv = dev_get_priv(dev);
+
+	/* No need to reinitialize the UART after relocation */
+	if (gd->flags & GD_FLG_RELOC)
+		return 0;
+
+	geni_serial_init(dev);
+	msm_geni_serial_setup_rx(dev);
+	qcom_geni_serial_start_rx(dev);
+	qcom_geni_serial_start_tx(priv->base);
+
+	return 0;
+}
+
+static int msm_serial_ofdata_to_platdata(struct udevice *dev)
+{
+	struct msm_serial_data *priv = dev_get_priv(dev);
+
+	priv->base = dev_read_addr(dev);
+	if (priv->base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct udevice_id msm_serial_ids[] = {
+	{.compatible = "qcom,msm-geni-uart"}, {}};
+
+U_BOOT_DRIVER(serial_msm_geni) = {
+	.name = "serial_msm_geni",
+	.id = UCLASS_SERIAL,
+	.of_match = msm_serial_ids,
+	.of_to_plat = msm_serial_ofdata_to_platdata,
+	.priv_auto = sizeof(struct msm_serial_data),
+	.probe = msm_serial_probe,
+	.ops = &msm_serial_ops,
+};
+
+#ifdef CONFIG_DEBUG_UART_MSM_GENI
+
+static struct msm_serial_data init_serial_data = {
+	.base = CONFIG_DEBUG_UART_BASE
+};
+
+/* Serial dumb device, to reuse driver code */
+static struct udevice init_dev = {
+	.priv_ = &init_serial_data,
+};
+
+#include <debug_uart.h>
+
+#define CLK_DIV (CONFIG_DEBUG_UART_CLOCK / \
+					(CONFIG_BAUDRATE * UART_OVERSAMPLING))
+#if (CONFIG_DEBUG_UART_CLOCK % (CONFIG_BAUDRATE * UART_OVERSAMPLING) > 0)
+#error Clocks cannot be set at early debug. Change CONFIG_BAUDRATE
+#endif
+
+static inline void _debug_uart_init(void)
+{
+	phys_addr_t base = CONFIG_DEBUG_UART_BASE;
+
+	geni_serial_init(&init_dev);
+	geni_serial_baud(base, CLK_DIV, CONFIG_BAUDRATE);
+	qcom_geni_serial_start_tx(base);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+	phys_addr_t base = CONFIG_DEBUG_UART_BASE;
+
+	writel(DEF_TX_WM, base + SE_GENI_TX_WATERMARK_REG);
+	qcom_geni_serial_setup_tx(base, 1);
+	qcom_geni_serial_poll_bit(&init_dev, SE_GENI_M_IRQ_STATUS,
+				  M_TX_FIFO_WATERMARK_EN, true);
+
+	writel(ch, base + SE_GENI_TX_FIFOn);
+	writel(M_TX_FIFO_WATERMARK_EN, base + SE_GENI_M_IRQ_CLEAR);
+	qcom_geni_serial_poll_tx_done(&init_dev);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c
index 6d09952..de420d2 100644
--- a/drivers/serial/serial_s5p.c
+++ b/drivers/serial/serial_s5p.c
@@ -14,24 +14,45 @@
 #include <asm/global_data.h>
 #include <linux/compiler.h>
 #include <asm/io.h>
+#if !CONFIG_IS_ENABLED(ARCH_APPLE)
 #include <asm/arch/clk.h>
+#endif
 #include <asm/arch/uart.h>
 #include <serial.h>
 #include <clk.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define RX_FIFO_COUNT_SHIFT	0
-#define RX_FIFO_COUNT_MASK	(0xff << RX_FIFO_COUNT_SHIFT)
-#define RX_FIFO_FULL		(1 << 8)
-#define TX_FIFO_COUNT_SHIFT	16
-#define TX_FIFO_COUNT_MASK	(0xff << TX_FIFO_COUNT_SHIFT)
-#define TX_FIFO_FULL		(1 << 24)
+enum {
+	PORT_S5P = 0,
+	PORT_S5L
+};
+
+#define S5L_RX_FIFO_COUNT_SHIFT	0
+#define S5L_RX_FIFO_COUNT_MASK	(0xf << S5L_RX_FIFO_COUNT_SHIFT)
+#define S5L_RX_FIFO_FULL	(1 << 8)
+#define S5L_TX_FIFO_COUNT_SHIFT	4
+#define S5L_TX_FIFO_COUNT_MASK	(0xf << S5L_TX_FIFO_COUNT_SHIFT)
+#define S5L_TX_FIFO_FULL	(1 << 9)
+
+#define S5P_RX_FIFO_COUNT_SHIFT	0
+#define S5P_RX_FIFO_COUNT_MASK	(0xff << S5P_RX_FIFO_COUNT_SHIFT)
+#define S5P_RX_FIFO_FULL	(1 << 8)
+#define S5P_TX_FIFO_COUNT_SHIFT	16
+#define S5P_TX_FIFO_COUNT_MASK	(0xff << S5P_TX_FIFO_COUNT_SHIFT)
+#define S5P_TX_FIFO_FULL	(1 << 24)
 
 /* Information about a serial port */
 struct s5p_serial_plat {
 	struct s5p_uart *reg;  /* address of registers in physical memory */
+	u8 reg_width;	/* register width */
 	u8 port_id;     /* uart port number */
+	u8 rx_fifo_count_shift;
+	u8 tx_fifo_count_shift;
+	u32 rx_fifo_count_mask;
+	u32 tx_fifo_count_mask;
+	u32 rx_fifo_full;
+	u32 tx_fifo_full;
 };
 
 /*
@@ -71,8 +92,8 @@
 	writel(0x245, &uart->ucon);
 }
 
-static void __maybe_unused s5p_serial_baud(struct s5p_uart *uart, uint uclk,
-					   int baudrate)
+static void __maybe_unused s5p_serial_baud(struct s5p_uart *uart, u8 reg_width,
+					   uint uclk, int baudrate)
 {
 	u32 val;
 
@@ -82,6 +103,8 @@
 
 	if (s5p_uart_divslot())
 		writew(udivslot[val % 16], &uart->rest.slot);
+	else if (reg_width == 4)
+		writel(val % 16, &uart->rest.value);
 	else
 		writeb(val % 16, &uart->rest.value);
 }
@@ -93,7 +116,7 @@
 	struct s5p_uart *const uart = plat->reg;
 	u32 uclk;
 
-#ifdef CONFIG_CLK_EXYNOS
+#if CONFIG_IS_ENABLED(CLK_EXYNOS) || CONFIG_IS_ENABLED(ARCH_APPLE)
 	struct clk clk;
 	u32 ret;
 
@@ -105,7 +128,7 @@
 	uclk = get_uart_clk(plat->port_id);
 #endif
 
-	s5p_serial_baud(uart, uclk, baudrate);
+	s5p_serial_baud(uart, plat->reg_width, uclk, baudrate);
 
 	return 0;
 }
@@ -144,11 +167,14 @@
 	struct s5p_serial_plat *plat = dev_get_plat(dev);
 	struct s5p_uart *const uart = plat->reg;
 
-	if (!(readl(&uart->ufstat) & RX_FIFO_COUNT_MASK))
+	if (!(readl(&uart->ufstat) & plat->rx_fifo_count_mask))
 		return -EAGAIN;
 
 	serial_err_check(uart, 0);
-	return (int)(readb(&uart->urxh) & 0xff);
+	if (plat->reg_width == 4)
+		return (int)(readl(&uart->urxh) & 0xff);
+	else
+		return (int)(readb(&uart->urxh) & 0xff);
 }
 
 static int s5p_serial_putc(struct udevice *dev, const char ch)
@@ -156,10 +182,13 @@
 	struct s5p_serial_plat *plat = dev_get_plat(dev);
 	struct s5p_uart *const uart = plat->reg;
 
-	if (readl(&uart->ufstat) & TX_FIFO_FULL)
+	if (readl(&uart->ufstat) & plat->tx_fifo_full)
 		return -EAGAIN;
 
-	writeb(ch, &uart->utxh);
+	if (plat->reg_width == 4)
+		writel(ch, &uart->utxh);
+	else
+		writeb(ch, &uart->utxh);
 	serial_err_check(uart, 1);
 
 	return 0;
@@ -171,15 +200,19 @@
 	struct s5p_uart *const uart = plat->reg;
 	uint32_t ufstat = readl(&uart->ufstat);
 
-	if (input)
-		return (ufstat & RX_FIFO_COUNT_MASK) >> RX_FIFO_COUNT_SHIFT;
-	else
-		return (ufstat & TX_FIFO_COUNT_MASK) >> TX_FIFO_COUNT_SHIFT;
+	if (input) {
+		return (ufstat & plat->rx_fifo_count_mask) >>
+			plat->rx_fifo_count_shift;
+	} else {
+		return (ufstat & plat->tx_fifo_count_mask) >>
+			plat->tx_fifo_count_shift;
+	}
 }
 
 static int s5p_serial_of_to_plat(struct udevice *dev)
 {
 	struct s5p_serial_plat *plat = dev_get_plat(dev);
+	const ulong port_type = dev_get_driver_data(dev);
 	fdt_addr_t addr;
 
 	addr = dev_read_addr(dev);
@@ -187,8 +220,26 @@
 		return -EINVAL;
 
 	plat->reg = (struct s5p_uart *)addr;
+	plat->reg_width = dev_read_u32_default(dev, "reg-io-width", 1);
 	plat->port_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 					"id", dev_seq(dev));
+
+	if (port_type == PORT_S5L) {
+		plat->rx_fifo_count_shift = S5L_RX_FIFO_COUNT_SHIFT;
+		plat->rx_fifo_count_mask = S5L_RX_FIFO_COUNT_MASK;
+		plat->rx_fifo_full = S5L_RX_FIFO_FULL;
+		plat->tx_fifo_count_shift = S5L_TX_FIFO_COUNT_SHIFT;
+		plat->tx_fifo_count_mask = S5L_TX_FIFO_COUNT_MASK;
+		plat->tx_fifo_full = S5L_TX_FIFO_FULL;
+	} else {
+		plat->rx_fifo_count_shift = S5P_RX_FIFO_COUNT_SHIFT;
+		plat->rx_fifo_count_mask = S5P_RX_FIFO_COUNT_MASK;
+		plat->rx_fifo_full = S5P_RX_FIFO_FULL;
+		plat->tx_fifo_count_shift = S5P_TX_FIFO_COUNT_SHIFT;
+		plat->tx_fifo_count_mask = S5P_TX_FIFO_COUNT_MASK;
+		plat->tx_fifo_full = S5P_TX_FIFO_FULL;
+	}
+
 	return 0;
 }
 
@@ -200,7 +251,8 @@
 };
 
 static const struct udevice_id s5p_serial_ids[] = {
-	{ .compatible = "samsung,exynos4210-uart" },
+	{ .compatible = "samsung,exynos4210-uart",	.data = PORT_S5P },
+	{ .compatible = "apple,s5l-uart",		.data = PORT_S5L },
 	{ }
 };
 
@@ -221,19 +273,30 @@
 
 static inline void _debug_uart_init(void)
 {
+	if (IS_ENABLED(CONFIG_DEBUG_UART_SKIP_INIT))
+		return;
+
 	struct s5p_uart *uart = (struct s5p_uart *)CONFIG_DEBUG_UART_BASE;
 
 	s5p_serial_init(uart);
-	s5p_serial_baud(uart, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
+#if CONFIG_IS_ENABLED(ARCH_APPLE)
+	s5p_serial_baud(uart, 4, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
+#else
+	s5p_serial_baud(uart, 1, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
+#endif
 }
 
 static inline void _debug_uart_putc(int ch)
 {
 	struct s5p_uart *uart = (struct s5p_uart *)CONFIG_DEBUG_UART_BASE;
 
-	while (readl(&uart->ufstat) & TX_FIFO_FULL);
-
+#if CONFIG_IS_ENABLED(ARCH_APPLE)
+	while (readl(&uart->ufstat) & S5L_TX_FIFO_FULL);
+	writel(ch, &uart->utxh);
+#else
+	while (readl(&uart->ufstat) & S5P_TX_FIFO_FULL);
 	writeb(ch, &uart->utxh);
+#endif
 }
 
 DEBUG_UART_FUNCS
diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c
index 5a335e5..27a035c 100644
--- a/drivers/spmi/spmi-msm.c
+++ b/drivers/spmi/spmi-msm.c
@@ -19,39 +19,63 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 /* PMIC Arbiter configuration registers */
-#define PMIC_ARB_VERSION		0x0000
-#define PMIC_ARB_VERSION_V2_MIN		0x20010000
+#define PMIC_ARB_VERSION 0x0000
+#define PMIC_ARB_VERSION_V2_MIN 0x20010000
+#define PMIC_ARB_VERSION_V3_MIN 0x30000000
+#define PMIC_ARB_VERSION_V5_MIN 0x50000000
 
-#define ARB_CHANNEL_OFFSET(n)		(0x4 * (n))
-#define SPMI_CH_OFFSET(chnl)		((chnl) * 0x8000)
+#define APID_MAP_OFFSET_V1_V2_V3 (0x800)
+#define APID_MAP_OFFSET_V5 (0x900)
+#define ARB_CHANNEL_OFFSET(n) (0x4 * (n))
+#define SPMI_CH_OFFSET(chnl) ((chnl) * 0x8000)
+#define SPMI_V5_OBS_CH_OFFSET(chnl) ((chnl) * 0x80)
+#define SPMI_V5_RW_CH_OFFSET(chnl) ((chnl) * 0x10000)
 
-#define SPMI_REG_CMD0			0x0
-#define SPMI_REG_CONFIG			0x4
-#define SPMI_REG_STATUS			0x8
-#define SPMI_REG_WDATA			0x10
-#define SPMI_REG_RDATA			0x18
+#define SPMI_REG_CMD0 0x0
+#define SPMI_REG_CONFIG 0x4
+#define SPMI_REG_STATUS 0x8
+#define SPMI_REG_WDATA 0x10
+#define SPMI_REG_RDATA 0x18
 
-#define SPMI_CMD_OPCODE_SHIFT		27
-#define SPMI_CMD_SLAVE_ID_SHIFT		20
-#define SPMI_CMD_ADDR_SHIFT		12
-#define SPMI_CMD_ADDR_OFFSET_SHIFT	4
-#define SPMI_CMD_BYTE_CNT_SHIFT		0
+#define SPMI_CMD_OPCODE_SHIFT 27
+#define SPMI_CMD_SLAVE_ID_SHIFT 20
+#define SPMI_CMD_ADDR_SHIFT 12
+#define SPMI_CMD_ADDR_OFFSET_SHIFT 4
+#define SPMI_CMD_BYTE_CNT_SHIFT 0
 
-#define SPMI_CMD_EXT_REG_WRITE_LONG	0x00
-#define SPMI_CMD_EXT_REG_READ_LONG	0x01
+#define SPMI_CMD_EXT_REG_WRITE_LONG 0x00
+#define SPMI_CMD_EXT_REG_READ_LONG 0x01
 
-#define SPMI_STATUS_DONE		0x1
+#define SPMI_STATUS_DONE 0x1
 
-#define SPMI_MAX_CHANNELS	128
-#define SPMI_MAX_SLAVES		16
-#define SPMI_MAX_PERIPH		256
+#define SPMI_MAX_CHANNELS 128
+#define SPMI_MAX_SLAVES 16
+#define SPMI_MAX_PERIPH 256
+
+enum arb_ver {
+	V1 = 1,
+	V2,
+	V3,
+	V5 = 5
+};
+
+/*
+ * PMIC arbiter version 5 uses different register offsets for read/write vs
+ * observer channels.
+ */
+enum pmic_arb_channel {
+	PMIC_ARB_CHANNEL_RW,
+	PMIC_ARB_CHANNEL_OBS,
+};
 
 struct msm_spmi_priv {
-	phys_addr_t arb_chnl; /* ARB channel mapping base */
+	phys_addr_t arb_chnl;  /* ARB channel mapping base */
 	phys_addr_t spmi_core; /* SPMI core */
-	phys_addr_t spmi_obs; /* SPMI observer */
+	phys_addr_t spmi_obs;  /* SPMI observer */
 	/* SPMI channel map */
 	uint8_t channel_map[SPMI_MAX_SLAVES][SPMI_MAX_PERIPH];
+	/* SPMI bus arbiter version */
+	u32 arb_ver;
 };
 
 static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off,
@@ -59,6 +83,7 @@
 {
 	struct msm_spmi_priv *priv = dev_get_priv(dev);
 	unsigned channel;
+	unsigned int ch_offset;
 	uint32_t reg = 0;
 
 	if (usid >= SPMI_MAX_SLAVES)
@@ -69,8 +94,8 @@
 	channel = priv->channel_map[usid][pid];
 
 	/* Disable IRQ mode for the current channel*/
-	writel(0x0, priv->spmi_core + SPMI_CH_OFFSET(channel) +
-	       SPMI_REG_CONFIG);
+	writel(0x0,
+	       priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CONFIG);
 
 	/* Write single byte */
 	writel(val, priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_WDATA);
@@ -82,6 +107,11 @@
 	reg |= (off << SPMI_CMD_ADDR_OFFSET_SHIFT);
 	reg |= 1; /* byte count */
 
+	if (priv->arb_ver == V5)
+		ch_offset = SPMI_V5_RW_CH_OFFSET(channel);
+	else
+		ch_offset = SPMI_CH_OFFSET(channel);
+
 	/* Send write command */
 	writel(reg, priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0);
 
@@ -104,6 +134,7 @@
 {
 	struct msm_spmi_priv *priv = dev_get_priv(dev);
 	unsigned channel;
+	unsigned int ch_offset;
 	uint32_t reg = 0;
 
 	if (usid >= SPMI_MAX_SLAVES)
@@ -113,8 +144,13 @@
 
 	channel = priv->channel_map[usid][pid];
 
+	if (priv->arb_ver == V5)
+		ch_offset = SPMI_V5_OBS_CH_OFFSET(channel);
+	else
+		ch_offset = SPMI_CH_OFFSET(channel);
+
 	/* Disable IRQ mode for the current channel*/
-	writel(0x0, priv->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_CONFIG);
+	writel(0x0, priv->spmi_obs + ch_offset + SPMI_REG_CONFIG);
 
 	/* Prepare read command */
 	reg |= SPMI_CMD_EXT_REG_READ_LONG << SPMI_CMD_OPCODE_SHIFT;
@@ -124,13 +160,12 @@
 	reg |= 1; /* byte count */
 
 	/* Request read */
-	writel(reg, priv->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0);
+	writel(reg, priv->spmi_obs + ch_offset + SPMI_REG_CMD0);
 
 	/* Wait till CMD DONE status */
 	reg = 0;
 	while (!reg) {
-		reg = readl(priv->spmi_obs + SPMI_CH_OFFSET(channel) +
-			    SPMI_REG_STATUS);
+		reg = readl(priv->spmi_obs + ch_offset + SPMI_REG_STATUS);
 	}
 
 	if (reg ^ SPMI_STATUS_DONE) {
@@ -139,8 +174,8 @@
 	}
 
 	/* Read the data */
-	return readl(priv->spmi_obs + SPMI_CH_OFFSET(channel) +
-		     SPMI_REG_RDATA) & 0xFF;
+	return readl(priv->spmi_obs + ch_offset +
+				SPMI_REG_RDATA) & 0xFF;
 }
 
 static struct dm_spmi_ops msm_spmi_ops = {
@@ -150,31 +185,50 @@
 
 static int msm_spmi_probe(struct udevice *dev)
 {
-	struct udevice *parent = dev->parent;
 	struct msm_spmi_priv *priv = dev_get_priv(dev);
-	int node = dev_of_offset(dev);
+	phys_addr_t config_addr;
 	u32 hw_ver;
-	bool is_v1;
+	u32 version;
 	int i;
+	int err;
 
-	priv->arb_chnl = dev_read_addr(dev);
-	priv->spmi_core = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
-			dev_of_offset(parent), node, "reg", 1, NULL, false);
-	priv->spmi_obs = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
-			dev_of_offset(parent), node, "reg", 2, NULL, false);
+	config_addr = dev_read_addr_index(dev, 0);
+	priv->spmi_core = dev_read_addr_index(dev, 1);
+	priv->spmi_obs = dev_read_addr_index(dev, 2);
 
-	hw_ver = readl(priv->arb_chnl + PMIC_ARB_VERSION - 0x800);
-	is_v1  = (hw_ver < PMIC_ARB_VERSION_V2_MIN);
+	hw_ver = readl(config_addr + PMIC_ARB_VERSION);
 
-	dev_dbg(dev, "PMIC Arb Version-%d (0x%x)\n", (is_v1 ? 1 : 2), hw_ver);
+	if (hw_ver < PMIC_ARB_VERSION_V3_MIN) {
+		priv->arb_ver = V2;
+		version = 2;
+		priv->arb_chnl = config_addr + APID_MAP_OFFSET_V1_V2_V3;
+	} else if (hw_ver < PMIC_ARB_VERSION_V5_MIN) {
+		priv->arb_ver = V3;
+		version = 3;
+		priv->arb_chnl = config_addr + APID_MAP_OFFSET_V1_V2_V3;
+	} else {
+		priv->arb_ver = V5;
+		version = 5;
+		priv->arb_chnl = config_addr + APID_MAP_OFFSET_V5;
+
+		if (err) {
+			dev_err(dev, "could not read APID->PPID mapping table, rc= %d\n", err);
+			return -1;
+		}
+	}
+
+	dev_dbg(dev, "PMIC Arb Version-%d (0x%x)\n", version, hw_ver);
 
 	if (priv->arb_chnl == FDT_ADDR_T_NONE ||
 	    priv->spmi_core == FDT_ADDR_T_NONE ||
 	    priv->spmi_obs == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
+	dev_dbg(dev, "priv->arb_chnl address (%llu)\n", priv->arb_chnl);
+	dev_dbg(dev, "priv->spmi_core address (%llu)\n", priv->spmi_core);
+	dev_dbg(dev, "priv->spmi_obs address (%llu)\n", priv->spmi_obs);
 	/* Scan peripherals connected to each SPMI channel */
-	for (i = 0; i < SPMI_MAX_PERIPH ; i++) {
+	for (i = 0; i < SPMI_MAX_PERIPH; i++) {
 		uint32_t periph = readl(priv->arb_chnl + ARB_CHANNEL_OFFSET(i));
 		uint8_t slave_id = (periph & 0xf0000) >> 16;
 		uint8_t pid = (periph & 0xff00) >> 8;
@@ -195,5 +249,5 @@
 	.of_match = msm_spmi_ids,
 	.ops = &msm_spmi_ops,
 	.probe = msm_spmi_probe,
-	.priv_auto	= sizeof(struct msm_spmi_priv),
+	.priv_auto = sizeof(struct msm_spmi_priv),
 };
diff --git a/include/configs/apple.h b/include/configs/apple.h
new file mode 100644
index 0000000..b1f6043
--- /dev/null
+++ b/include/configs/apple.h
@@ -0,0 +1,36 @@
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <linux/sizes.h>
+
+#define CONFIG_SYS_SDRAM_BASE	0x880000000
+
+#define CONFIG_LNX_KRNL_IMG_TEXT_OFFSET_BASE	CONFIG_SYS_TEXT_BASE
+
+/* Environment */
+#define ENV_DEVICE_SETTINGS \
+	"stdin=serial,usbkbd\0" \
+	"stdout=serial,vidconsole\0" \
+	"stderr=serial,vidconsole\0"
+
+#define ENV_MEM_LAYOUT_SETTINGS \
+	"fdt_addr_r=0x960100000\0" \
+	"kernel_addr_r=0x960200000\0"
+
+#if CONFIG_IS_ENABLED(CMD_USB)
+	#define BOOT_TARGET_USB(func) func(USB, usb, 0)
+#else
+	#define BOOT_TARGET_USB(func)
+#endif
+
+#define BOOT_TARGET_DEVICES(func) \
+	BOOT_TARGET_USB(func)
+
+#include <config_distro_bootcmd.h>
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	ENV_DEVICE_SETTINGS \
+	ENV_MEM_LAYOUT_SETTINGS \
+	BOOTENV
+
+#endif
diff --git a/include/configs/exynos78x0-common.h b/include/configs/exynos78x0-common.h
new file mode 100644
index 0000000..478a0c4
--- /dev/null
+++ b/include/configs/exynos78x0-common.h
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Configuration settings for the EXYNOS 78x0 based boards.
+ *
+ * Copyright (c) 2020 Dzmitry Sankouski (dsankouski@gmail.com)
+ * based on include/exynos7420-common.h
+ * Copyright (C) 2016 Samsung Electronics
+ * Thomas Abraham <thomas.ab@samsung.com>
+ */
+
+#ifndef __CONFIG_EXYNOS78x0_COMMON_H
+#define __CONFIG_EXYNOS78x0_COMMON_H
+
+/* High Level Configuration Options */
+#define CONFIG_SAMSUNG			/* in a SAMSUNG core */
+#define CONFIG_S5P
+
+#include <asm/arch/cpu.h>		/* get chip and board defs */
+#include <linux/sizes.h>
+
+/* Miscellaneous configurable options */
+#define CONFIG_SYS_CBSIZE		1024	/* Console I/O Buffer Size */
+#define CONFIG_SYS_PBSIZE		1024	/* Print Buffer Size */
+
+/* Boot Argument Buffer Size */
+#define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE
+
+/* Timer input clock frequency */
+#define COUNTER_FREQUENCY		26000000
+
+/* Device Tree */
+#define CONFIG_DEVICE_TREE_LIST "EXYNOS78x0-a5y17lte"
+
+#define CPU_RELEASE_ADDR		secondary_boot_addr
+
+#define CONFIG_SYS_BAUDRATE_TABLE \
+	{9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600}
+
+#define CONFIG_BOARD_COMMON
+
+#define CONFIG_SYS_SDRAM_BASE		0x40000000
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_TEXT_BASE + SZ_2M - GENERATED_GBL_DATA_SIZE)
+/* DRAM Memory Banks */
+#define SDRAM_BANK_SIZE		(256UL << 20UL)	/* 256 MB */
+#define PHYS_SDRAM_1		CONFIG_SYS_SDRAM_BASE
+#define PHYS_SDRAM_1_SIZE	SDRAM_BANK_SIZE
+#define PHYS_SDRAM_2		(CONFIG_SYS_SDRAM_BASE + SDRAM_BANK_SIZE)
+#define PHYS_SDRAM_2_SIZE	SDRAM_BANK_SIZE
+#define PHYS_SDRAM_3		(CONFIG_SYS_SDRAM_BASE + (2 * SDRAM_BANK_SIZE))
+#define PHYS_SDRAM_3_SIZE	SDRAM_BANK_SIZE
+#define PHYS_SDRAM_4		(CONFIG_SYS_SDRAM_BASE + (3 * SDRAM_BANK_SIZE))
+#define PHYS_SDRAM_4_SIZE	SDRAM_BANK_SIZE
+#define PHYS_SDRAM_5		(CONFIG_SYS_SDRAM_BASE + (4 * SDRAM_BANK_SIZE))
+#define PHYS_SDRAM_5_SIZE	SDRAM_BANK_SIZE
+#define PHYS_SDRAM_6		(CONFIG_SYS_SDRAM_BASE + (5 * SDRAM_BANK_SIZE))
+#define PHYS_SDRAM_6_SIZE	SDRAM_BANK_SIZE
+#define PHYS_SDRAM_7		(CONFIG_SYS_SDRAM_BASE + (6 * SDRAM_BANK_SIZE))
+#define PHYS_SDRAM_7_SIZE	SDRAM_BANK_SIZE
+#define PHYS_SDRAM_8		(CONFIG_SYS_SDRAM_BASE + (7 * SDRAM_BANK_SIZE))
+#define PHYS_SDRAM_8_SIZE	SDRAM_BANK_SIZE
+#define PHYS_SDRAM_9		(CONFIG_SYS_SDRAM_BASE + (8 * SDRAM_BANK_SIZE))
+#define PHYS_SDRAM_9_SIZE	SDRAM_BANK_SIZE
+#define PHYS_SDRAM_10		(CONFIG_SYS_SDRAM_BASE + (9 * SDRAM_BANK_SIZE))
+#define PHYS_SDRAM_10_SIZE	SDRAM_BANK_SIZE
+#define PHYS_SDRAM_11		(CONFIG_SYS_SDRAM_BASE + (10 * SDRAM_BANK_SIZE))
+#define PHYS_SDRAM_11_SIZE	SDRAM_BANK_SIZE
+#define PHYS_SDRAM_12		(CONFIG_SYS_SDRAM_BASE + (11 * SDRAM_BANK_SIZE))
+#define PHYS_SDRAM_12_SIZE	SDRAM_BANK_SIZE
+
+#define CONFIG_DEBUG_UART_CLOCK	132710400
+
+#define CONFIG_PREBOOT \
+"echo Read pressed buttons status;" \
+"KEY_VOLUMEUP=gpa20;" \
+"KEY_HOME=gpa17;" \
+"KEY_VOLUMEDOWN=gpa21;" \
+"KEY_POWER=gpa00;" \
+"PRESSED=0;" \
+"RELEASED=1;" \
+"if gpio input $KEY_VOLUMEUP; then setenv VOLUME_UP $PRESSED; " \
+"else setenv VOLUME_UP $RELEASED; fi;" \
+"if gpio input $KEY_VOLUMEDOWN; then setenv VOLUME_DOWN $PRESSED; " \
+"else setenv VOLUME_DOWN $RELEASED; fi;" \
+"if gpio input $KEY_HOME; then setenv HOME $PRESSED; else setenv HOME $RELEASED; fi;" \
+"if gpio input $KEY_POWER; then setenv POWER $PRESSED; else setenv POWER $RELEASED; fi;"
+
+#ifndef MEM_LAYOUT_ENV_SETTINGS
+#define MEM_LAYOUT_ENV_SETTINGS \
+	"bootm_size=0x10000000\0" \
+	"bootm_low=0x40000000\0"
+#endif
+
+#ifndef EXYNOS_DEVICE_SETTINGS
+#define EXYNOS_DEVICE_SETTINGS \
+	"stdin=serial\0" \
+	"stdout=serial\0" \
+	"stderr=serial\0"
+#endif
+
+#ifndef EXYNOS_FDTFILE_SETTING
+#define EXYNOS_FDTFILE_SETTING
+#endif
+
+#define EXTRA_ENV_SETTINGS \
+	EXYNOS_DEVICE_SETTINGS \
+	EXYNOS_FDTFILE_SETTING \
+	MEM_LAYOUT_ENV_SETTINGS
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	EXTRA_ENV_SETTINGS
+
+#endif	/* __CONFIG_EXYNOS78x0_COMMON_H */
diff --git a/include/configs/sdm845.h b/include/configs/sdm845.h
new file mode 100644
index 0000000..af9ba19
--- /dev/null
+++ b/include/configs/sdm845.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Configuration file for boards, based on Qualcomm SDM845 chip
+ *
+ * (C) Copyright 2021 Dzmitry Sankouski <dsankouski@gmail.com>
+ */
+
+#ifndef __CONFIGS_SDM845_H
+#define __CONFIGS_SDM845_H
+
+#include <linux/sizes.h>
+#include <asm/arch/sysmap-sdm845.h>
+
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 115200, 230400, 460800, 921600 }
+
+/* Generic Timer Definitions */
+#define COUNTER_FREQUENCY	19000000
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_BOOTM_LEN	SZ_64M
+
+/* Monitor Command Prompt */
+#define CONFIG_SYS_CBSIZE	512
+#define CONFIG_SYS_MAXARGS	64
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 3768432..fd139b9 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -62,6 +62,7 @@
 	UCLASS_I2C_MUX,		/* I2C multiplexer */
 	UCLASS_I2S,		/* I2S bus */
 	UCLASS_IDE,		/* IDE device */
+	UCLASS_IOMMU,		/* IOMMU */
 	UCLASS_IRQ,		/* Interrupt controller */
 	UCLASS_KEYBOARD,	/* Keyboard input device */
 	UCLASS_LED,		/* Light-emitting diode (LED) */
diff --git a/include/dt-bindings/interrupt-controller/apple-aic.h b/include/dt-bindings/interrupt-controller/apple-aic.h
new file mode 100644
index 0000000..9ac56a7
--- /dev/null
+++ b/include/dt-bindings/interrupt-controller/apple-aic.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
+#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_APPLE_AIC_H
+#define _DT_BINDINGS_INTERRUPT_CONTROLLER_APPLE_AIC_H
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#define AIC_IRQ	0
+#define AIC_FIQ	1
+
+#define AIC_TMR_HV_PHYS		0
+#define AIC_TMR_HV_VIRT		1
+#define AIC_TMR_GUEST_PHYS	2
+#define AIC_TMR_GUEST_VIRT	3
+
+#endif
diff --git a/include/dt-bindings/pinctrl/apple.h b/include/dt-bindings/pinctrl/apple.h
new file mode 100644
index 0000000..ea0a6f4
--- /dev/null
+++ b/include/dt-bindings/pinctrl/apple.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR MIT */
+/*
+ * This header provides constants for Apple pinctrl bindings.
+ */
+
+#ifndef _DT_BINDINGS_PINCTRL_APPLE_H
+#define _DT_BINDINGS_PINCTRL_APPLE_H
+
+#define APPLE_PINMUX(pin, func) ((pin) | ((func) << 16))
+#define APPLE_PIN(pinmux) ((pinmux) & 0xffff)
+#define APPLE_FUNC(pinmux) ((pinmux) >> 16)
+
+#endif /* _DT_BINDINGS_PINCTRL_APPLE_H */
diff --git a/include/dt-bindings/spmi/spmi.h b/include/dt-bindings/spmi/spmi.h
new file mode 100644
index 0000000..ad4a434
--- /dev/null
+++ b/include/dt-bindings/spmi/spmi.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ */
+#ifndef __DT_BINDINGS_SPMI_H
+#define __DT_BINDINGS_SPMI_H
+
+#define SPMI_USID	0
+#define SPMI_GSID	1
+
+#endif
diff --git a/include/iommu.h b/include/iommu.h
new file mode 100644
index 0000000..6c46adf
--- /dev/null
+++ b/include/iommu.h
@@ -0,0 +1,16 @@
+#ifndef _IOMMU_H
+#define _IOMMU_H
+
+struct udevice;
+
+#if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) && \
+	CONFIG_IS_ENABLED(IOMMU)
+int dev_iommu_enable(struct udevice *dev);
+#else
+static inline int dev_iommu_enable(struct udevice *dev)
+{
+	return 0;
+}
+#endif
+
+#endif
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 55162e9..7de013f 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -48,6 +48,7 @@
 obj-$(CONFIG_SOUND) += i2s.o
 obj-y += irq.o
 obj-$(CONFIG_CLK_K210_SET_RATE) += k210_pll.o
+obj-$(CONFIG_IOMMU) += iommu.o
 obj-$(CONFIG_LED) += led.o
 obj-$(CONFIG_DM_MAILBOX) += mailbox.o
 obj-$(CONFIG_DM_MDIO) += mdio.o
diff --git a/test/dm/iommu.c b/test/dm/iommu.c
new file mode 100644
index 0000000..94174a7
--- /dev/null
+++ b/test/dm/iommu.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <dm/uclass-internal.h>
+#include <iommu.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+static int dm_test_iommu(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+
+	ut_assertok(uclass_find_device(UCLASS_IOMMU, 0, &dev));
+	ut_assert(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED));
+
+	/* Probing USB probes the IOMMU through the "iommus" property */
+	ut_assertok(uclass_probe_all(UCLASS_USB));
+	ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED);
+
+	return 0;
+}
+
+DM_TEST(dm_test_iommu, UT_TESTF_SCAN_FDT);